win10+Python3.7.3+OpenCV3.4.1⼊门学习(⼗七图像分割与提取)—。。。Python版本是Python3.7.3,OpenCV版本OpenCV 3.4.1,开发环境为PyCharm
17.2 相关函数介绍
在OpenCV中,可以使⽤函数cv2.watershed()实现分⽔岭算法。在具体的实现过程中,还需要借助于形态学函数、距离变换函数
cv2.distanceTransform()、tedComponents()来完成图像分割。下⾯对分⽔岭算法中⽤到的函数进⾏简单的说明。1.形态学函数回顾
在使⽤分⽔岭算法对图像进⾏分割前,需要对图像进⾏简单的形态学处理。先回顾⼀下形态学⾥的基本操作。
(1)开运算
开运算是先腐蚀、后膨胀的操作,开运算能够去除图像内的噪声。例如,在下图中,先对左图进⾏腐蚀操作,会得到中间的图像,再对中间的图像进⾏膨胀操作,会得到右侧的图像。对左图进⾏开运算(先腐蚀、后膨胀)后,我们得到了右图。通过观察可知,左图在经过开运算后变成右图以后,上⾯的⽑刺(噪声信息)已经被去除了。
对图像进⾏开运算,能够去除图像内的噪声。在⽤分⽔岭算法处理图像前,要先使⽤开运算去除图像内的噪声,以避免噪声对图像分割可能造成的⼲扰。
(2)获取图像边界
通过形态学操作和减法运算能够获取图像的边界。例如,在下图中,左图是原始图像,中间的图是对其进⾏腐蚀⽽得到的图像,对⼆者进⾏减法运算,就会得到右侧的图像。通过观察可知,右图是左图的边界。
eg1:使⽤形态学变换,获取⼀幅图像的边界信息,并观察效果。
代码如下:
pycharm安装教程win10import cv2
import numpy as np
import matplotlib.pyplot as plt
o=cv2.imread("rice.png",cv2.IMREAD_UNCHANGED)
s((5,5),np.uint8)
de(o,k)
b=cv2.subtract(o,e)
plt.subplot(131)
plt.imshow(o)
plt.axis('off')
plt.subplot(132)
plt.imshow(e)
plt.axis('off')
plt.subplot(133)
plt.imshow(b)
plt.axis('off')
plt.show()
运⾏上述程序,得到结果如下图所⽰,其中左图是原始图像,中间的图是对其进⾏腐蚀⽽得到的图像,右图是原始图像减去腐蚀图像后得到的边界图像。可以看到,右图⽐较准确地显⽰出了左图内前景对象的边界信息。
通过以上分析可知,使⽤形态学操作和减法运算能够获取图像的边界信息。但是,形态学操作仅适⽤于⽐较简单的图像。如果图像内的前景对象存在连接的情况,使⽤形态学操作就⽆法准确获取各个⼦图像的边界了。
2.距离变换函数distanceTransform
当图像内的各个⼦图没有连接时,可以直接使⽤形态学的腐蚀操作确定前景对象,但是如果图像内的⼦图连接在⼀起时,就很难确定前景对象了。此时,借助于距离变换函数cv2.distanceTransform()可以⽅便地将前景对象提取出来。
距离变换函数cv2.distanceTransform()计算⼆值图像内任意点到最近背景点的距离。⼀般情况下,该函数计算的是图像内⾮零值像素点到最近的零值像素点的距离,即计算⼆值图像中所有像素点距离其最近的值为0的像素点的距离。当然,如果像素点本⾝的值为0,则这个距离也为0。
距离变换函数cv2.distanceTransform()的计算结果反映了各个像素与背景(值为0的像素点)的距离关系。通常情况下:
● 如果前景对象的中⼼(质⼼)距离值为0的像素点距离较远,会得到⼀个较⼤的值。
● 如果前景对象的边缘距离值为0的像素点较近,会得到⼀个较⼩的值。
如果对上述计算结果进⾏阈值化,就可以得到图像内⼦图的中⼼、⾻架等信息。距离变换函数cv2.distanceTransform()可以⽤于计算对象的中⼼,还能细化轮廓、获取图像前景等,有多种功能。
距离变换函数cv2.distanceTransform()的语法格式为:
dst=cv2.distanceTransform(src, distanceType, maskSize[, dstType]])
式中:
● src是8位单通道的⼆值图像。
● distanceType为距离类型参数,其具体值和含义如下表所⽰。
● maskSize为掩模的尺⼨,其可能的值如下表所⽰。需要注意,当distanceType=cv2.DIST_L1或cv2.DIST_C时,maskSize强制为
3(因为设置为3和设置为5及更⼤值没有什么区别)。
● dstType为⽬标图像的类型,默认值为CV_32F。
● dst表⽰计算得到的⽬标图像,可以是8位或32位浮点数,尺⼨和src相同。
eg2:使⽤距离变换函数cv2.distanceTransform(),计算⼀幅图像的确定前景,并观察效果。
代码如下:
import numpy as np
import cv2
import matplotlib.pyplot as plt
img = cv2.imread('water_coins.jpg')
gray = cv2.cvtColor(img,cv2.COLOR_BGR2GRAY)
img=cv2.cvtColor(img,cv2.COLOR_BGR2RGB)
py()
ret, thresh = cv2.threshold(gray,0,255,cv2.THRESH_BINARY_INV+cv2.THRESH_OTSU)
kernel = np.ones((3,3),np.uint8)
opening = phologyEx(thresh,cv2.MORPH_OPEN,kernel, iterations = 2)
dist_transform = cv2.distanceTransform(opening,cv2.DIST_L2,5)
ret, fore = cv2.threshold(dist_transform,0.7*dist_transform.max(),255,0)
plt.subplot(131)
plt.imshow(ishow)
plt.axis('off')
plt.subplot(132)
plt.imshow(dist_transform)
plt.axis('off')
plt.subplot(133)
plt.imshow(fore)
plt.axis('off')
plt.show()
运⾏上述程序,得到结果如下图所⽰。其中:
● 左图是原始图像。
● 中间的是距离变换函数cv2.distanceTransform()计算得到的距离图像。
● 右图是对距离图像进⾏阈值化处理后的结果图像。
从下图可以看到,右图⽐较准确地显⽰出左图内的“确定前景”。这⾥的确定前景,通常是指前景对象的
中⼼。之所以认为这些点是确定前景,是因为它们距离背景点的距离⾜够远,都是距离⼤于⾜够⼤的固定阈值(0.7*dist_transform.max())的点。
3.确定未知区域
使⽤形态学的膨胀操作能够将图像内的前景“膨胀放⼤”。当图像内的前景被放⼤后,背景就会被“压缩”,所以此时得到的背景信息⼀定⼩于实际背景的,不包含前景的“确定背景”。以下为了⽅便说明将确定背景称为B。
距离变换函数cv2.distanceTransform()能够获取图像的“中⼼”,得到“确定前景”。为了⽅便说明,将确定前景称为F。
图像中有了确定前景F和确定背景B,剩下区域的就是未知区域UN了。这部分区域正是分⽔岭算法要进⼀步明确的区域。
针对⼀幅图像O,通过以下关系能够得到未知区域UN:
未知区域UN=图像O-确定背景B-确定前景F
对上述表达式进⾏整理,可以得到:
未知区域UN=(图像O-确定背景B)- 确定前景F
上式中的“图像O-确定背景B”,可以通过对图像进⾏形态学的膨胀操作得到。
eg3:标注⼀幅图像的确定前景、确定背景及未知区域。
代码如下:
import numpy as np
import cv2
import matplotlib.pyplot as plt
img = cv2.imread('water_coins.jpg')
gray = cv2.cvtColor(img,cv2.COLOR_BGR2GRAY)
img=cv2.cvtColor(img,cv2.COLOR_BGR2RGB)
py()
ret, thresh = cv2.threshold(gray,0,255,cv2.THRESH_BINARY_INV+cv2.THRESH_OTSU)
kernel = np.ones((3,3),np.uint8)
opening = phologyEx(thresh,cv2.MORPH_OPEN,kernel, iterations = 2)
bg= cv2.dilate(opening,kernel,iterations=3)
dist = cv2.distanceTransform(opening,cv2.DIST_L2,5)
ret, fore = cv2.threshold(dist,0.7*dist.max(),255,0)
fore = np.uint8(fore)
un = cv2.subtract(bg,fore)
plt.subplot(221)
plt.imshow(ishow)
plt.axis('off')
plt.subplot(222)
plt.imshow(bg)
plt.axis('off')
plt.subplot(223)
plt.imshow(fore)
plt.axis('off')
plt.subplot(224)
plt.imshow(un)
plt.axis('off')
plt.show()
运⾏上述程序,得到的结果如下图所⽰。其中:
● 左上⾓是原始图像ishow。
● 右上⾓是对图像ishow进⾏膨胀后得到的图像bg,其背景图像是确定背景,前景图像是“原始图像-确定背景”。
● 左下⾓是确定前景图像fore。
● 右下⾓图像中的⼩圆环就是未知区域图像un,是由图像bg和图像fore相减得到的。也就是说,未知区域图像un来源于“原始图像-确定背景-确定前景”。
值得注意的是,在图下右上⾓的图像bg中:
● 前景的⼀个个⼩圆是“原始图像-确定背景”部分,⽽不是“确定背景”。
● 其背景图像才是“确定背景”。
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。
发表评论