计算机视觉(四)
Grabcut
Grabcut算法详解
http://blog.csdn.net/zouxy09/article/details/8534954
原理:
首先用矩形将要选择的前景区域选定,其中前景区域应该完全包含在矩形框当中。然后算法进行迭代式分割,知道达到效果最佳。但是有时分割结果不好,例如前景当成背景,背景当成前景。测试需要用户修改。用户只需要在非前景区域用鼠标划一下即可。
首先,输入矩形框,矩形框外部区域都是背景。内部一定包含前景。电脑对输入图像进行初始化,标记前景和背景的像素。使用高斯混合模型(GMM)对前景和背景建模。根据输入,GMM会学习并创建新的像素分布。对未知的像素(前景或背景不确定),根据他们与已知的分类像素关系进行分类。(类似聚类操作)这样会根据像素的分布创建一幅图,图中节点是像素。除了像素点是节点以外,还有Source\_node和Sink\_node两个节点。所有的前景图像斗鱼Source\_node相连。背景与Sink\_node相连。像素是否连接到Source\_node/end\_node依赖于权值,这个权值由像素属于同一类,也就是前景或者背景的概率来决定。如果像素的颜色有很大区别,那么他们之间的权重就很小。使用mincut算法对图像进行分割。它会根据最小代价方程对图像分成source\_node和sink\_node。代价方程是指裁剪所有边上权重的和。裁剪完成后,所有连接到source\_node的判定为前景,sink\_node上的为背景。继续此过程,直到分类收敛。
def grabCut(img, mask, rect, bgdModel, fgdModel, iterCount, mode=None): # real signature unknown; restored from __doc__ """ grabCut(img, mask, rect, bgdModel, fgdModel, iterCount[, mode]) -> mask, bgdModel, fgdModel """ pass
cv2.grabCut()函数参数
- img 输入图像,图像的类型必须为:CV_8UC3
mask 掩模图像,确定前景区域,背景区域,不确定区域,可以设置为cv2.GC_BGD,cv2.GC_FGD,cv2.GC_PR_BGD,cv2.GC_PR_FGD,也可以输入0,1,2,3它的大小和image一样,但是它的格式为CV_8UC1,只能是单通道的,grabcut算法的结果就保存在该图像中。
mask图像的值只能为下面下面4个值(PR,probably表示可能的):计算完成后mask里面值为0到3,其中0表示背景,1表示前景,2表示可能是背景,3表示可能是前景 ,代码中将0和2合并为背景 1和3合并为前景
GC_BGD = 0, //背景
GC_FGD = 1, //前景
GC_PR_BGD = 2, //可能背景GC_PR_FGD = 3 //可能前景
代码中将0和2合并为背景 1和3合并为前景
根据rectangle生成的mask图像规则为:四边形外面的部分一定是背景,所以在mask图中对应的像素值为GC\_BGD,而四边形内部的的值可能为前景,所以对应的像素值为GC\_PR\_FGD。
- rect 前景的矩形,格式为(x,y,w,h),分别为左上角坐标和宽度,高度
- bdgModel, fgdModel)**临时矩阵变量**,只需要创建两个大小为(1,65)np.float64的数组。
- bgdModel(background背景)——背景模型,如果为null,函数内部会自动创建一个bgdModel;bgdModel必须是单通道浮点型(CV_32FC1)图像,且行数只能为1,列数只能为13x5;
fgdModel(foreground前景——前景模型,如果为null,函数内部会自动创建一个fgdModel;fgdModel必须是单通道浮点型(CV_32FC1)图像,且行数只能为1,列数只能为13x5; - iterCount 迭代次数,迭代越多,效果越好,但划时间也越长。
- mode cv2.GC_INIT_WITH_RECT 或 cv2.GC_INIT_WITH_MASK,使用矩阵模式还是掩模模式。
- mode——用于指示grabCut函数进行什么操作,可选的值有:
GC_INIT_WITH_RECT(=0),用矩形窗初始化GrabCut;
GC_INIT_WITH_MASK(=1),用掩码图像初始化GrabCut;
GC_EVAL(=2),执行分割。 - 参数为GC_INIT_WITH_MASK,这时第三个参数rectangle没有使用,我们必须在调用grabcut函数之前,手工设置mask图像
1、自定义(自设区域选定)
静态图像:
import numpy as np
from cv2 import *
from matplotlib import pyplot as plt
filename="D:/temp/6.jpg"
img=imread(filename)
mask=np.zeros(img.shape[:2],np.uint8)
bgdmodel=np.zeros((1,65),np.float64)
fgdmodel=np.zeros((1,65),np.float64)
#img.shape[0],img.shape[1],表图像的高度和宽度
rect=(2,2,img.shape[0]-1,img.shape[1]-1)
grabCut(img,mask,rect,bgdmodel,fgdmodel,6,GC_INIT_WITH_RECT)
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(cvtColor(imread(filename),COLOR_BGR2RGB))
plt.title('original'),plt.xticks([]),plt.yticks([])
plt.show()
C++代码参考:
http://blog.csdn.net/l1l2l3q1q2q3/article/details/51181975
http://blog.csdn.net/wangyaninglm/article/details/50074613
http://blog.csdn.net/zxc024000/article/details/51243629
http://blog.csdn.net/roslei/article/details/52221975
(Java)http://blog.csdn.net/huohuxingxing1987/article/details/13278375
摄像(动态):
import numpy as np
from cv2 import *
from matplotlib import pyplot as plt
videocapture=VideoCapture(0)
ret,img=videocapture.read()
while ret:
image = img
mask=np.zeros(img.shape[:2],np.uint8)
bgdmodel=np.zeros((1,65),np.float64)
fgdmodel=np.zeros((1,65),np.float64)
rect=(1,1,image.shape[0],image.shape[1])
grabCut(img,mask,rect,bgdmodel,fgdmodel,2,GC_INIT_WITH_RECT)
mask2=np.where((mask==2)|(mask==0),0,1).astype('uint8')
img=img*mask2[:,:,np.newaxis]
imshow('Grabcut',img)
imshow('Image',image)
waitKey(1)
ret, img = videocapture.read()
destroyAllWindows()
运行非常慢。
2、交互模式
参考:http://blog.topspeedsnail.com/archives/2080
http://blog.csdn.net/tengfei461807914/article/details/62438959
鼠标画笔 setMouseCallback():http://blog.csdn.net/qton\_csdn/article/details/70193884
创建一个鼠标回调函数,在指定事件发生时执行。
使用如下代码查看鼠标事件:
import cv2
events=[i for i in dir(cv2)if 'EVENT' in i]
print events
事件:[‘EVENT_FLAG_ALTKEY’, ‘EVENT_FLAG_CTRLKEY’, ‘EVENT_FLAG_LBUTTON’, ‘EVENT_FLAG_MBUTTON’, ‘EVENT_FLAG_RBUTTON’, ‘EVENT_FLAG_SHIFTKEY’, ‘EVENT_LBUTTONDBLCLK’, ‘EVENT_LBUTTONDOWN’, ‘EVENT_LBUTTONUP’, ‘EVENT_MBUTTONDBLCLK’, ‘EVENT_MBUTTONDOWN’, ‘EVENT_MBUTTONUP’, ‘EVENT_MOUSEHWHEEL’, ‘EVENT_MOUSEMOVE’, ‘EVENT_MOUSEWHEEL’, ‘EVENT_RBUTTONDBLCLK’, ‘EVENT_RBUTTONDOWN’, ‘EVENT_RBUTTONUP’]
C++参考:http://blog.csdn.net/my\_lord\_/article/details/53927865
python:待续
还没有评论,来说两句吧...