计算机视觉(四)

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:待续



















  • 2
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

HySmiley

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值