【笔记】OpenCV3 图像分割-用grabCut做前景检测
2019-06-04 13:07
519 查看
版权声明:qdwork https://blog.csdn.net/hopena/article/details/90766386
grabCut算法的大致思路,摘抄。。。。
- 在图片中定义(一个或者多个)包含物体的矩形。
- 矩形外的区域被自动认为是背景。
- 对于用户定义的矩形区域,可用背景中的数据来区分它里面的前景和背景区域。
- 用高斯混合模型(GMM)来对背景和前景建模,并将未定义的像素标记为可能的前景或者背景。
- 图像中的每一个像素都被看做通过虚拟边与周围像素相连接,而每条边都有一个属于前景或者背景的概率,这是基于它与周边像素颜色上的相似性。
- 每一个像素(即算法中的节点)会与一个前景或背景节点连接。
- 在节点完成连接后(可能与背景或前景连接),若节点之间的边属于不同终端(即一个节点属于前景,另一个节点属于背景),则会切断他们之间的边,这就能将图像各部分分割出来
[code]def grabCut(img, mask, rect, bgdModel, fgdModel, iterCount, mode=None)
输入参数:
img: 输入图像
mask: 掩码图像,用来确定哪些区域是背景、前景,哪些可能是前景/背景
[code]0 GC_BGD 定义了明显的背景像素。 1 GC_FGD 定义了一个明显的前景(对象)像素。 2 GC_PR_BGD 定义了可能的背景像素。 3 GC_PR_FGD 定义了可能的前景像素。
rect: mode为rect模式时有效 包含前景的矩形(x,y,w,h),以外的部分为背景
bgdModel、fgdModel:背景、前景数组,算法用
itterCount: 算法迭代的次数
mode: cv2.GC_INIT_WITH_RECT,cv2.GC_INIT_WITH_MASK两种模式
测试下试试,在代码中加入了鼠标事件,来获取在图形绘制的rect,用来给算法限定前景的范围
- 鼠标按下时,设置绘制边框模式setrect_flag为True,且记录下点击的点
- 鼠标左键按下,并拖动时,记录鼠标点坐标,用于在移动时绘制矩形框
- 鼠标左键松开时,记录下坐标点,完成矩形框绘制
[code]file_name = 'img/renma.jpg' setrect_flag = False has_rect = False set_rect = [1,1,1,1] cut_flag = False def onMouse(event,x,y,flags, param): global setrect_flag,has_rect,set_rect,cut_flag if event == cv2.EVENT_LBUTTONDOWN: print("left mouse click...") setrect_flag = True has_rect = False set_rect[0] = x set_rect[1] = y set_rect[2] = x set_rect[3] = y if event == cv2.EVENT_MOUSEMOVE and flags == cv2.EVENT_FLAG_LBUTTON: if setrect_flag: set_rect[2] = x set_rect[3] = y elif event == cv2.EVENT_LBUTTONUP: print("left mouse up...") if setrect_flag: setrect_flag = False has_rect = True cut_flag = True set_rect[2] = x set_rect[3] = y print(x,y) elif event == cv2.EVENT_RBUTTONDOWN: print("right mouse down...") has_rect = False setrect_flag = False
- 在main处绘制出原图,并记录
- 循环判断,当为绘制矩形框模式时,绘制出矩形框
- cut_flag 用来判断是否已经完成剪切,如果已完成,就不用处理,不然会一直处理。。。
- 在里面判断鼠标按下与松开的位置,来确定最终的前景确认框的rect ,左上角坐标,及宽高
[code]if __name__ == "__main__": cv2.namedWindow('pic', cv2.WINDOW_AUTOSIZE) cv2.setMouseCallback('pic', onMouse) img = cv2.imread(file_name, cv2.IMREAD_COLOR) imgold = img.copy() cv2.imshow('pic', img) while True: # 画区域中 if setrect_flag: img = imgold.copy() cv2.rectangle(img,(set_rect[0],set_rect[1]),(set_rect[2],set_rect[3]),(255,0,0),1) cv2.imshow('pic',img) else: if cut_flag: if has_rect and (set_rect[0] - set_rect[2]) != 0 and (set_rect[1] - set_rect[3]) != 0: # 默认往右下拖动 rect = [set_rect[0],set_rect[1],abs(set_rect[2]-set_rect[0]),abs(set_rect[3]-set_rect[1])] if set_rect[2] < set_rect[0] and set_rect[3] < set_rect[1]:#往左上拖动 rect[0] = set_rect[2] rect[1] = set_rect[3] elif set_rect[2] < set_rect[0] and set_rect[3] > set_rect[1]:#往左下拖动 rect[0] = set_rect[2] rect[1] = set_rect[1] elif set_rect[2] > set_rect[0] and set_rect[3] < set_rect[1]:#往右上拖动 rect[0] = set_rect[0] rect[1] = set_rect[3] img = imgold.copy() st = time.time() print('begin cut pic...') cuppic(img,rect) print("cut over , it takes {:.3f}".format(time.time()-st)) cut_flag = False else: cv2.imshow('pic', imgold) pressKey = cv2.waitKey(20) if cv2.getWindowProperty('pic', cv2.WND_PROP_AUTOSIZE) < 1: break if pressKey == 27: # ESC print('退出。。。。。') break cv2.destroyAllWindows()
调用分隔算法
- 用图像等大的数据初始化掩码
- 创建以0填充的前景和背景模型, 输入必须是单通道的浮点型图像, 1行, 13x5 = 65的列 即(1,65)
- 自定义区域
- 分割
- 将0,2合并为0, 1,3合并为1
- 与图像合并,取出前景
[code]def cuppic(img, rect): print("set rect to ",rect) mask = np.zeros(img.shape[:2], np.uint8) bgdModel = np.zeros((1,65), np.float64) fgdModel = np.zeros((1,65), np.float64) bgrect = tuple(rect) cv2.grabCut(img, mask, bgrect, bgdModel, fgdModel, 16, cv2.GC_INIT_WITH_RECT) mask2 = np.where((mask == 2)|(mask==0),0,1).astype('uint8') imgnew = img*mask2[:,:,np.newaxis] cv2.imshow('new',imgnew)
效果
相关文章推荐
- 利用OpenCV的Grabcut()函数实现图像的前景与背景的分割-并对Grabcut()作详细介绍
- OpenCv学习笔记4--图像分割之GrabCut算法
- OpenCV(EmguCV)2.1新特性介绍之图像分割GrabCut(GrabCut Of OpenCV 2.1)
- OpenCV图像分割实战C++(一)Grabcut抠图与证件照背景替换
- OpenCV(EmguCV)2.1新特性介绍之图像分割GrabCut(GrabCut Of OpenCV 2.1)
- OpenCV3.0 Examples学习笔记(10)-grabcut.cpp-grabcut函数实现人机交互高效分割图像前景背景
- OpenCV图像分割cv::grabCut()函数
- 图像分割之(五)OpenCV的GrabCut调用
- [转载]OpenCV(EmguCV)2.1新特性介绍之图像分割GrabCut(GrabCut Of OpenCV 2.1)
- GrabCut in One Cut(基于图割算法grabcut的一次快速图像分割的OpenCV实现)----目前效果最好的图割
- OpenCV(EmguCV)2.1新特性介绍之图像分割GrabCut
- Python OpenCV学习笔记之:使用Grabcut算法进行图像背景和前景分割
- Opencv 利用分割的图像掩膜来完善检测前景
- 学习OpenCV范例(二十二)—GrabCut图像分割
- OpenCV(EmguCV)2.1新特性介绍之图像分割GrabCut(GrabCut Of OpenCV 2.1)
- GrabCut in One Cut(基于图割算法grabcut的一次快速图像分割的OpenCV实现)----目前效果最好的图割
- GrabCut in One Cut(基于图割算法grabcut的一次快速图像分割的OpenCV实现)----目前效果最好的图割
- 【图像处理】图像分割之(一~四)GraphCut,GrabCut函数使用和源码解读(OpenCV)
- 图像分割学习笔记_1(opencv自带meanshift分割例子)
- 图像处理(十四)图像分割(4)grab cut的图割实现-Siggraph 2004