使用分水岭和GrabCut算法进行物体分割

用GrabCut算法进行图像分割

在OpenCV中,实现了grabcut分割算法,该算法可以方便的分割出前景图像,操作简单,而且分割的效果很好。算法的原理参见papaer:“GrabCut” — Interactive Foreground Extraction using Iterated Graph Cuts

比如下面的一副图,我们只要选定一个四边形框,把框中的图像作为grabcut的一个输入参数,表示该框中的像素可能属于前景,但框外的部分一定属于背景。

GrabCut算法实现步骤为:

1.在图片中定义含有(一个或多个)物体的矩形

2.矩形外的区域被自动认为是背景

3.对于用户定义的矩形区域,可用背景中的数据来区别它里面的前景和背景区域

4.用高斯混合模型(GMM)来对背景和前景建模,并将未定义的像素标记为可能的前景或背景。

5.图像中的每一个像素都被看作通过虚拟边与周围像素相连接,而每条边都有一个属于前景或背景的概率,这基于它与周围像素颜色上的相似性。

6.每一个像素(即算法中的节点)会与一个前景或背景节点连接

7.在节点完成连接后(可能与背景或前景连接),若节点之间的边属于不同终端(即一个节点属于前景,另一个节点属于背景),则会切断它们之间的边(这就是算法名中的切割部分),这就能将图像各部分分割出来。

import numpy as np
import cv2
from matplotlib import pyplot as plt img=cv2.imread('1.jpg')
mask=np.zeros(img.shape[:2],np.uint8)#创建一个掩模

#创建以0填充的前景和背景模型
bgdModel=np.zeros((1,65),np.float64)
fgdModel=np.zeros((1,65),np.float64) rect=(100,160,400,670)#创建矩形
cv2.grabCut(img,mask,rect,bgdModel,fgdModel,5,cv2.GC_INIT_WITH_RECT)#使用了指定的空模型和掩模来运行GrabCut,并且实际上是用一个矩形来初始化这个操作
#做完这些后,我们的掩模已经变成包含0~3之间的值。值为0和2的将转为0,值为1,3的将转为1.然后保存在mask2中。这样就可以用mask2过滤出所有的0值像素(理论上会完整保留所有前景像素)
mask2=np.where((mask==0)|(mask==2),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("1.jpg"),cv2.COLOR_BGR2RGB))
plt.title("original"),plt.xticks([]),plt.yticks([])
plt.show()

使用分水岭算法进行图像分割

把图像中的低密度的区域(变化很少)想象成山谷,图像中高密度的区域(变化很多)想象成山峰。开始向山谷中注入水直到不同的山谷中的水开始汇聚。为了阻止不同山谷的水汇聚,可以设置一些栅栏,最后得到的栅栏就是图像分割。

import numpy as np
import cv2
from matplotlib import pyplot as plt
img=cv2.imread("1.jpg")
gray=cv2.cvtColor(img,cv2.COLOR_BGR2GRAY)#颜色转为灰度
ret,thresh=cv2.threshold(gray,0,255,cv2.THRESH_BINARY_INV+cv2.THRESH_OTSU)#可为图像设一个阈值
kernel=np.ones((3,3),np.uint8)
opening=cv2.morphologyEx(thresh,cv2.MORPH_OPEN,kernel,iterations=2)#去除噪声
sure_bg=cv2.dilate(opening,kernel,iterations=3) dist_transform=cv2.distanceTransform(opening,cv2.DIST_L2,5)#可以通过distanceTransform来获取确定的前景区域。也就是说,这是图像中最可能是前景的区域,越是远离背景区域的边界点越可能属于前景,这里用了阈值来决定那些区域是前景
ret,sure_fg=cv2.threshold(dist_transform,0.7*dist_transform.max(),255,0)
#这个阶段之后,所得到的前景和背景中有重合的部分该怎么办?首先需要确定这些区域,这可从sure_bg与sure_fg的集合相减得到
sure_fg=np.uint8(sure_fg)
unknown=cv2.subtract(sure_bg,sure_fg)
#现在有了这些区域,就可以设定栅栏来阻止水汇聚,这是通过connectedComponents函数完成。
ret,markers=cv2.connectedComponents(sure_fg) markers=markers+1
markers[unknown==255]=0
#把栅栏绘制成红色
markers=cv2.watershed(img,markers)
img[markers==-1]=[255,0,0]
plt.imshow(img)
plt.show()

opencv3计算机视觉+Python(四)的更多相关文章

  1. 《OpenCV3 计算机视觉--Python语言实现 第二版》源代码及纠错

    1.源代码下载地址 <OpenCV3 计算机视觉--Python语言实现 第二版>由我们翻译,英文书名<Learning OpenCV3 Computer Vision with P ...

  2. OpenCV3计算机视觉Python语言实现笔记(四)

    1. Canny边缘检测 OpenCV提供了Canny函数来识别边缘.Canny边缘检测算法有5个步骤:使用高斯滤波器对图像进行去噪.计算梯度.在边缘上使用非最大抑制(NMS).在检测到的边缘上使用双 ...

  3. OpenCV3计算机视觉+python(三)

    使用OpenCV3处理图像 下面要介绍的内容都与图像处理有关,这时需要修改图像,比如要使用具有艺术性的滤镜.外插(extrapolate)某些部分.分割.粘贴或其他需要的操作. 不同色彩空间的转换 O ...

  4. OpenCV3计算机视觉Python语言实现笔记(三)

    一.使用OpenCV处理图像 1.不同颜色空间的转换 OpenCV中有数百种关于在不同色彩空间之间转换的方法.当前,在计算机视觉中有三种常用的色彩空间:灰度.BGR以及HSV(Hue, Saturat ...

  5. OpenCV3计算机视觉Python语言实现笔记(二)

    1. 图像与原始字节之间的转换 从概念上讲,一个字节能表示0到255的整数.目前,对于多有的实时图像应用而言,虽然有其他的表示形式,但一个像素通常由每个通道的一个字节表示. 一个OpenCV图像是.a ...

  6. OpenCV3计算机视觉+Python(五)

    人脸检测和识别 本章将介绍Haar级联分类器,通过对比分析相邻图像区域来判断给定图像或子图像与已知对象是否匹配.本章将考虑如何将多个Haar级联分类器构成一个层次结构,即一个分类器能识别整体区域(如人 ...

  7. OpenCV3计算机视觉+python(二)

    不同色彩空间的转换 当前,在计算机视觉中有三种常用的色彩空间:灰度.BGR以及HSV 1.灰度色彩空间是通过去除彩色信息来将其转换为灰阶,灰度色彩空间对中间处理特别有效,比如人脸检测 2.BGR,即蓝 ...

  8. opencv3计算机视觉+Python(一)

    基本I/O脚本 读/写图像文件 OpenCV的imread函数和imwrite函数能支持各种静态图像文件格式.不同系统支持的文件格式不一样,但都支持BMP格式,通常还应该支持PNG.JPEG和TIFF ...

  9. OpenCV3计算机视觉Python语言实现笔记(五)

    图像的几何变换主要包括:平移.扩大与缩小.旋转.仿射.透视等等.图像变换是建立在矩阵运算基础上的,通过矩阵运算可以很快的找到对应关系. 1. 图像的平移 图像的平移,沿着x方向tx距离,y方向ty距离 ...

随机推荐

  1. es模板

    Index Templatesedit Index templates allow you to define templates that will automatically be applied ...

  2. Codeforces Round #297 (Div. 2) 525C Ilya and Sticks(脑洞)

    C. Ilya and Sticks time limit per test 2 seconds memory limit per test 256 megabytes input standard ...

  3. atitit.atiLinq v2新特性attilax大总结 q326

    atitit.atiLinq v2新特性attilax大总结 q326 1. V3规划 (分开sql2obj sql2sql sql2xml)1 2. V2新特性 Url linq的定义1 3. V1 ...

  4. Java时间类总结

    java.util.Date 包含有年月日时分秒,精确到毫秒级别. 官方解释: // The class Date represents a specific instant in time, wit ...

  5. rpm安装路径

    安装xxx.rpm包,以relocate 参数进行安装,安装到/opt/temp目录: rpm -ivh --relocate /=/opt/temp xxx.rpm: 以prefix进行安装: rp ...

  6. dp解Codeforces Round #260 (Div. 2)C. Boredom

    #include<iostream> #include<map> #include<string> #include<cstring> #include ...

  7. Python eval 作用和风险 (string 转为dict list tuple)建议用“ast.literal_eval”

    a = "[[1,2], [3,4], [5,6], [7,8], [9,0]]" b = eval(a) print b [[1, 2], [3, 4], [5, 6], [7, ...

  8. hdu 2586(最近公共祖先LCA)

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=2586 思路:在求解最近公共祖先的问题上,用到的是Tarjan的思想,从根结点开始形成一棵深搜树,非常好 ...

  9. filter、map函数的区别

    def even(num): if num%2==0: return True return False lis = [1,2,3,4,5,6,7,8,9] res = filter(even,lis ...

  10. c++包含头文件好还是重新定义好

    A.h struct A { int a; int b; }; B.cpp 在B.cpp里面用到这个结构体 有两种方法 .自己定义一个一模一样的结构体 struct A { }; .包含A.h头文件 ...