在OpenCV里使用GrabCut算法抽取前景

版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接: https://blog.csdn.net/caimouse/article/details/102622705

前面学习过分水岭算法来分离背景与前景,现在来学习另一个标记算法GrabCut,它也是通过标记来抽取前景的算法。这个算法与分水岭算法标记不一样,比如只要简单地标记一个前景的方框,就可以抽取出来,不过计算量就有点大了。如下图:

在这里使用红色的矩形把中间的烧鸭选出来,就这样就可以把它放到OpenCV里的函数grabCut去处理,就会把烧鸭分离出来,既然分离出来了,你就可以进行各种处理了。整个代码如下:

#python 3.7.4,opencv4.1
#蔡军生 https://blog.csdn.net/caimouse/article/details/51749579
#
import numpy as np
import cv2
from matplotlib import pyplot as plt

img = cv2.imread('yaze1.png')
mask = np.zeros(img.shape[:2],np.uint8)

bgdModel = np.zeros((1,65),np.float64)
fgdModel = np.zeros((1,65),np.float64)

rect = (75,103,700,520)
cv2.grabCut(img,mask,rect,bgdModel,fgdModel,5,cv2.GC_INIT_WITH_RECT)

mask2 = np.where((mask==2)|(mask==0),0,1).astype('uint8')
img1 = img*mask2[:,:,np.newaxis]

imgRGB = cv2.cvtColor(img1,cv2.COLOR_BGR2RGB)
plt.imshow(imgRGB)
plt.show()

结果输出如下:

从结果里看到,本来想只要烧鸭的,结果还多了一朵花出来。如果还想更加完美的分离,就需要进一步标注,比如把这朵花的区域标记为黑色,烧鸭上面的白色要保留,于是就可以把上图修改成这样:

花朵已经变成黑色,保留的白色已经被标记为纯白。然后再来做一次grabCut处理,就可以得下面完美的图片:

 

到这里就完成了。完整的代码如下:

#python 3.7.4,opencv4.1
#蔡军生 https://blog.csdn.net/caimouse/article/details/51749579
#
import numpy as np
import cv2
from matplotlib import pyplot as plt

img = cv2.imread('yaze1.png')
mask = np.zeros(img.shape[:2],np.uint8)

bgdModel = np.zeros((1,65),np.float64)
fgdModel = np.zeros((1,65),np.float64)

rect = (75,103,700,520)
cv2.grabCut(img,mask,rect,bgdModel,fgdModel,5,cv2.GC_INIT_WITH_RECT)

mask2 = np.where((mask==2)|(mask==0),0,1).astype('uint8')
img1 = img*mask2[:,:,np.newaxis]

imgRGB = cv2.cvtColor(img1,cv2.COLOR_BGR2RGB)
plt.imshow(imgRGB)
plt.show()

#
cv2.imwrite('mask2.png', img1)

#
newmask = cv2.imread('mask3.png',0)
mask[newmask == 0] = 0
mask[newmask == 255] = 1

mask, bgdModel, fgdModel = cv2.grabCut(img,mask,None,bgdModel,fgdModel,5,cv2.GC_INIT_WITH_MASK)

mask = np.where((mask==2)|(mask==0),0,1).astype('uint8')
img = img*mask[:,:,np.newaxis]
imgRGB1 = cv2.cvtColor(img,cv2.COLOR_BGR2RGB)
plt.imshow(imgRGB1)
plt.show()

           
cv2.waitKey(0)
cv2.destroyAllWindows()

想要了解更多内容参考下面网站:

https://blog.csdn.net/qq_31145049/article/details/84876366

https://blog.csdn.net/l_zqxs_/article/details/79434907

https://blog.csdn.net/caimouse/article/details/51749579

猜你喜欢

转载自blog.csdn.net/caimouse/article/details/102622705