大家好,我是小木,我又回来了,今天我们要讲一些算法,这些算法可以把物体和它的背景分离。这些算法最常用的有两种,一种叫做GrabCut
我们今天不讲推导过程,原因是本人还没有看明白,所以第九节课给大家普及。这节课我只讲东西是怎么用的。
GrabCutNB36040
BB
首先我们有一张图:
额,又是小熊,为啥博主总是用它呢?很简单,我喜欢这个娃娃啊!我们想要把小熊后边的背景都给干掉,那么怎么办呢?
第一种方法叫做矩形框选法:
首先我们在这个图片上面把前景部分用矩形给圈起来:
接下来,我们假定在红色框框里面的东西一部分可能是前景、一部分可能是背景。而框框外面的物体全部都是背景。
X,Y
PS00123OPENCV
GCD_BGD=0
GCD_FGD=1
GCD_PR_BGD=2
GCD_PR_FGD=3
165=13*5
GrabCut
0~342~32003为1101
OK
OPENCV
#导入类库 import numpy as np import cv2 #画图类库,很好用,不用自己从头编写了 from matplotlib import pyplot as plt #导入图像(小熊) img = cv2.imread('D:/xiaomu/opencv7-1.png') #建立一个和img图像一样大的蒙版 mask = np.zeros(img.shape[:2],np.uint8) #画一个矩形框框,选出前景物体(小熊) rect = (50,10,250,440) #建立背景模型和前景模型,大小为1*65 bgdModel = np.zeros((1,65),np.float64) fgdModel = np.zeros((1,65),np.float64) #把上面的数据导入GrabCut算法中,进行计算, #该方法参数为:1.原始图像 2.蒙版 3.矩形框框 4.背景模型 5.前景模型 6.迭代次数 7.方法选择(矩形框选法) cv2.grabCut(img.copy(),mask,rect,bgdModel,fgdModel,10,cv2.GC_INIT_WITH_RECT) #把2变为0,把3变为1 mask2 = np.where((mask==2)|(mask==0),0,1).astype('uint8') #将蒙版与原图做点对点乘积 img = img*mask2[:,:,np.newaxis] #绘制出分离背景后的图像 plt.subplot(121), plt.imshow(img) plt.title("grabcut"), plt.xticks([]), plt.yticks([]) #绘制出原图 plt.subplot(122), plt.imshow(cv2.cvtColor(cv2.imread('D:/xiaomu/opencv7-1.png'), cv2.COLOR_BGR2RGB)) plt.title("original"), plt.xticks([]), plt.yticks([]) #在窗口中显示图像 plt.show() #保存图像 cv2.imwrite('D:/xiaomu/opencv7-2.png',img)
我们运行后的结果如下所示:
GrabCut
这种算法中,我们不是用矩形框框把某个前景物体圈起来了,而是我们画一个自定义的轮廓,接着我们上面的结果再次进行背景分离:
我们这次的图片是:
也就是我们上次矩形框框分离后的图图。
PS
在新图层中,我们用白色的刷子,把那些本来应该是前景,但是却没算成前景的地方给标记出来,然后把应该是背景的地方,但是却搞错的用黑色标记,剩下不改变的地方用灰色标记。
最后我们的,我们得到的蒙版为:
在蒙版中,我为了说明不同颜色的用途,所以我才随意画了一个白色的圈圈。
OPENCVOPENCV
#导入类库 import numpy as np import cv2 #画图类库,很好用,不用自己从头编写了 from matplotlib import pyplot as plt #导入图像(小熊) img = cv2.imread('D:/xiaomu/opencv7-1.png') #建立一个和img图像一样大的蒙版 mask = np.zeros(img.shape[:2],np.uint8) #画一个矩形框框,选出前景物体(小熊) rect = (50,10,250,440) #建立背景模型和前景模型,大小为1*65 bgdModel = np.zeros((1,65),np.float64) fgdModel = np.zeros((1,65),np.float64) #矩形框选法 #把上面的数据导入GrabCut算法中,进行计算, #该方法参数为:1.原始图像 2.蒙版 3.矩形框框 4.背景模型 5.前景模型 6.迭代次数 7.方法选择(矩形框选法) cv2.grabCut(img.copy(),mask,rect,bgdModel,fgdModel,10,cv2.GC_INIT_WITH_RECT) #把2变为0,把3变为1 mask2 = np.where((mask==2)|(mask==0),0,1).astype('uint8') #将蒙版与原图做点对点乘积 img = img*mask2[:,:,np.newaxis] #非矩形框,蒙版法再处理 img2 = cv2.imread('D:/xiaomu/opencv7-1.png') #导入蒙版 img3 = cv2.imread('D:/xiaomu/opencv7-3.png',0) #把蒙版中白色地方置为1,作为确定前景。黑色地方置为0,作为确定背景 mask[img3 == 0] = 0 mask[img3 == 255] = 1 #把上面的数据导入GrabCut算法中,进行计算, #该方法参数为:1.原始图像 2.蒙版 3.矩形框框(无) 4.背景模型 5.前景模型 6.迭代次数 7.方法选择(蒙版法) cv2.grabCut(img2,mask,None,bgdModel,fgdModel,5,cv2.GC_INIT_WITH_MASK) #把2变为0,把3变为1 mask3 = np.where((mask==2)|(mask==0),0,1).astype('uint8') #将蒙版与原图做点对点乘积 img2 = img2*mask3[:,:,np.newaxis] #绘制出蒙版法处理后的图像 plt.subplot(121), plt.imshow(img2) plt.title("grabcut-mask"), plt.xticks([]), plt.yticks([]) #绘制出矩形框法处理后的图像 plt.subplot(122), plt.imshow(img) plt.title("grabcut-rect"), plt.xticks([]), plt.yticks([]) #在窗口中显示图像 plt.show() cv2.waitKey() cv2.destroyAllWindows()
我们运行后的结果如下所示:
我们可以看出,我们把白色的地方都变成了前景(前面的小圆),黑色的地方成背景(小熊与背景分开的更好了)
这样我们的第一种算法就讲解完成了。
第二种算法我们做的是分水岭算法,下节课我们继续讲解。
文章来源: 白话文讲计算机视觉-第七讲-GrabCut算法