版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领
文档简介
第9章图像分割与测量9.1概述图像分析过程图像图像识别图像预处理图像理解图像分割图像分割与测量是图像识别工作的基础。图像分割将图像分为一些有意义的区域,然后可以对这些区域进行描述,相当于提取出某些目标区域图像的特征,判断图像中是否有感兴趣的目标。图像分割的基础是像素间的相似性和跳变性。图像分割的概念分成若干个互不相交的小区域的过程,小区域是某种意义下具有共同属性的像素的连通集合。各区域对某种性质,如灰度,纹理等有相似性。区域内部是连通的,没有过多小孔。区域边界是明确的,相邻区域对分割所依据的性质有明显的差异。图像分割的概念图像分割图像分割:把图像分成各具特性的区域,如目标或前景与背景,选择性地定位感兴趣目标在图像中的位置和范围,提取出感兴趣目标的技术和过程。
人的视觉系统对图像分割是十分复杂的,也是相当有效的。但分割原理和模型都未搞清楚。图像分割的基本思路:从简到难,逐级分割控制背景环境,降低分割难度把焦点放在增强感兴趣对象,缩小不相干图像成分的干扰上。图像分割边缘检测:检测出边缘,再将边缘像素连接,构成边界形成分割,找出目标物体的轮廓,进行目标的分析、识别、测量等。阈值分割:最常用法。有直方图门限选择,半阈值选择图像分割,迭代阈值。边界方法:直接确定区域边界,实现分割;有边界跟踪法,轮廓提取法。区域法:将各像素划归到相应物体或区域的像素聚类方法;有区域增长法等。图像分割四种不同的方法概述分割的目的是将图像分为一些有意义的区域,如目标或前景,然后可以对这些区域进行描述。图像分割的基本思路:从简到难,逐级分割;控制背景环境,降低分割难度,把焦点放在增强感兴趣的对象,缩小不相干图像成分的干扰上。图像分割的方法有多种,依据工作对像来分,可分为点相关分割和区域相关分割;按算法分类,可分为阀值法,界限检测法,匹配法,跟踪法等。9.2阈值法分割12基本原理原始图像——f(x,y)灰度阈值——T阈值运算得二值图像——g(x,y)阈值分割9.2.1直方图门限选择法9.2.1直方图阈值选择
阈值T可通过分析边缘检测输出的直方图来确定。假设,一幅图像只有物体和背景两部分组成,其灰度级直方图成明显的双峰值。255f(i,j)16人工阈值人工选择法是通过人眼的观察,应用人对图像的知识,在分析图像直方图的基础上,人工选出合适的阈值。也可以在人工选出阈值后,根据分割效果,不断的交互操作,从而选择出最佳的阈值。17直方图阈值选择阈值选择直接影响分割效果,利用灰度直方图求两峰之间的谷底作为阈值。18T=70的二值化图像原始图像直方图人工阈值255如果f(i,j)≥Tf(i,j)=
0如果f(i,j)<T或:
0如果f(i,j)≥Tf(i,j)=
255如果f(i,j)<T直方图阈值选择
若直方图呈现多个明显的峰值,如三个峰值,可取两个峰谷处的灰度值T1,T2作为阈值。同样,可将阈值化后的图像变成二值化图像。
f(i,j)T1T22550直方图阈值选择其数学表达式为:
0如果T1≤f(i,j)≤T2f(i,j)=
255其它或
255如果T1≤f(i,j)≤T2f(i,j)=
0其它
直方图阈值选择1)获得原图像的首地址,图像的宽和高。2)开辟一块内存空间,初始化为255。3)图像灰度统计,显示灰度直方图。4)通过对话框选取一个峰谷作为阈值。5)像素灰度值小于阈值,将像素置为0,否则置为255。6)将结果复制到原图像数据区。实现步骤效果图(a)根据直方图选择阈值(b)原图(c)二值化效果展示根据直方图9-3所示,将两峰之间的谷底140作为阈值。
图9-3直方图19.2.2半阈值选择法9.2.2半阈值选择分割不论图像的直方图具有双峰还是多峰值,阈值化后将原多值图像变成二值图像,若希望只把图像的背景表示成二值图像(即背景不是最白就是最黑),而物体为多值图像。此时,可采用半阈值技术,把物体从背景中分离出来。半阈值化表示为:
f(i,j)如果f(i,j)≥Tf(i,j)=
0或者255如果f(i,j)<T
或
f(i,j)如果f(i,j)≤Tf(i,j)=
0或者255其它半阈值选择分割1)获得原图像的首地址,图像的宽和高。2)开辟一块内存空间,并初始化为255。3)进行图像灰度统计,显示灰度直方图。4)选取一个峰谷作为阈值。5)像素灰度值小于阈值,将像素置为0,否则保持灰度值不变。实现步骤(a)根据直方图选择阈值
(b)半阈值选择分割效果图cv2.calcHist()函数用于统计图像直方图信息hist=cv2.calcHist(image,channel,mask,histSize,range,accumulate)hist:表示返回的统计直方图,数组内的元素是各个灰度级的像素个数;image:表示原始图像,该图像需要用“[]”括起来;channel:表示指定通道编号,通道编号需要用“[]”括起来;mask:表示掩模图像,当统计整幅图像的直方图时,将这个值设为None;当统计图像某一部分的直方图时,需要用到掩模图像;histSize:表示BINS的值,该值需要用“[]”括起来;range:表示像素值范围;accumulate:表示累计标识,默认值为False。如果被设置为True,则直方图在开始计算时不会被清零,计算的是多个直方图的累计结果,用于对一组图像计算直方图。该参数是可选的,一般情况下不需要设置。函数说明效果展示根据直方图9-5所示,将两峰之间的谷底140作为阈值。
图9-5直方图2效果展示
图9-6半阈值选择图像分割处理效果图9.2.3迭代阈值法34基本思想:选择一个阈值作为初始值,按某种策略不断地迭代改进,直到满足给定的准则。自动输出一个阈值。在迭代过程中,关键是阈值改进策略,阈值改进策略要求:快速收敛,新产生阈值优于上一次的阈值。9.2.3迭代阈值分割迭代阈值法
1)选择图像灰度的中值作为初始阈值Ti=T0。2)利用阈值Ti把图像分割成两部分区域,R1和R2,并计算其灰度均值。3)计算新的阈值Ti+14)重复步骤2、3,直到Ti+1和Ti的阈值差别小于某个给定值。1)获得原图像的首地址,图像的高和宽。2)进行直方图统计。3)设定初始阈值T=127。4)分别计算图像中小于T和大于T的两组平均灰度值。5)迭代计算阈值,直至两个阈值相等。7)根据计算出的阈值,对图像进行二值化处理。实现步骤37原始图像迭代阈值二值化效果图函数说明matplotlib模块可以使用其中的hist()函数来直接绘制图像的直方图。n,bins,patches=matplotlib.pyplot.hist(src,bins=10,normed=False,histtype=u'bar',**kwargs)返回值:
n:直方图向量,是否归一化由参数normed设定。当normed取默认值时,n即为直方图各组内元素的数量(各组频数);
bins:返回各个bin的区间范围;
patches:返回每个bin里面包含的数据,是一个list;参数:
src:表示原始图像数据,必须将其转换为一维数据;
bins:直方图的柱数,可选项,默认为10;
normed:是否将得到的直方图向量归一化。默认为0;
histtype:直方图类型,这些类型有:'bar','barstacked','step','stepfilled'。效果展示9.2.4Otsu阈值法小结Otsu算法主要采用最大类间方差法,将图像分成背景和前景两部分,要求这两个部分的类内离散度最小,类间离散度最大,使两类间方差最大来确定最佳阈值。根据阈值T将图像中的像素点分为C1和C2两类,则:ω0=N0/M×Nω1=N1/M×NN0+N1=M×Nω0+ω1=1μ=ω0*μ0+ω1*μ1(9-12)
g=ω0(μ0-μ)^2+ω1(μ1-μ)^2(9-13)
将式(9-12)代入式(9-13),得到等价公式:
g=ω0ω1(μ0-μ1)^2在从0到255的范围内,不断调整阈值T;分别计算上式,找到上述最大的g(T),则对应的T即为Otsu算法自动选取的阈值。函数说明在threshold()函数传递type参数时,多传递一个参数cv2.THRESH_OTSU即可,必须把阈值设置为0。retval,dst=cv2.threshold(src,thresh,maxval,type)retval:表示返回的阈值;dst:表示输出的图像;src:表示要进行阈值分割的图像,可以是多通道的图像;thresh:表示设定的阈值;maxval:表示type参数,cv2.THRESH_OTSU;效果展示图像Ostu算法阈值处理效果如图9-8所示。左侧为原始图像,右侧为处理后的图像。图9-8Ostu算法阈值处理效果图9.2.5自适应阈值法小结自适应阈值可以看成一种局部性的阈值,通过规定一个区域大小,比较处理像素点与区域大小里面像素点的平均值—阈值(或者其他特征)的大小关系确定这个像素点是黑还是白。理想的情况下,色彩均衡的图像,对整个图像使用单个阈值进行阈值化就会成功。但是,受到多种因素的影响,图像的色彩并不会很均衡,在这种情况下,使用局部值(又称自适应值)进行分割可以产生好的结果。函数说明在OpenCV中提供函数cv2.adaptiveThreshold()来实现自适应阈值处理,其一般格式为:dst=cv2.adaptiveThreshold(src,maxValue,adaptiveMethod,thresholdType,blockSize,c)dst:输出的图像;src:输入图,只能输入单通道图像,通常来说为灰度图;maxval:当像素值超过了阈值(或者小于阈值,根据type来决定)时,所赋予的值adaptiveMethod:阈值的计算方法,包含以下2种类型:
cv2.ADAPTIVE_THRESH_MEAN_C:区域内均值;
cv2.ADAPTIVE_THRESH_GAUSSIAN_C:区域内像素点加权和,权重为一个高斯窗口;thresholdType:二值化操作的类型BlockSize:图片中区域的大小;C:阈值计算方法中的常数项。效果展示图像自适应阈值分割处理效果如图9-9所示。图9-9(a)为原始图像,图9-9(b)为采用权重相等方式的局部阈值处理;图9-9(c)为采用权重为高斯分布的局部阈值处理。可以看出图9-9(c)相对于图9-9(b)保留了大量的细节信息。9.2.6分水岭算法是一种分割方法;在分割中,与邻近相似性作为参考依据;将空间位置上相近和灰度值相近的像素点,连接起来构成一个封闭的轮廓;比喻为地理学上的地形表面实现分割。9.1分水岭算法9.1.1算法原理灰度值高的区域看成山峰,灰度值低的区域看成山谷。由于噪声,存在过度分割的现象;为了解决过度分割的问题,使用基于标记(mark)图像的分水岭算法。通常的mark图像都是在某个区域定义了一些灰度层级,在这个区域的洪水淹没过程中,水平面都是从定义的高度开始的,这样可以避免一些很小的噪声极值区域的分割。9.1.2OpenCV中的相关函数完成分水岭分割还需要:对灰度图进行OTSU二值化阈值处理;形态学函数;距离变换函数cv2.distanceTransform();计算结果进行阈值化处理,得到图像内子图的一些形状信息;对目标进行标注,函数cv2.connectedComponent()使用cv2.watershed()函数实现分水岭算法。1.形态学函数开运算:先腐蚀后膨胀的操作。去除图像内的噪声。在用分水岭算法处理图像前,要先使用开运算去除图像内的噪声,以避免噪声对图像分割可能造成的干扰。2.距离变换函数distanceTransform二值图像内任意点到最近背景点的距离。一般计算非零值像素点到最近的零值像素点的距离。其计算结果反映了各个像素与背景(值为0的像素点)的距离关系。如果对上述计算结果进行阈值化处理,就可以得到图像内子图的一些形状信息。距离变换函数实现步骤①将输入图片转换为二值图像,前景设置为1,背景设置为0②先遍历图像:左,左上,上,左下公式计算:D表示距离包括欧式距离,棋盘距离和麦哈顿距离;掩膜模板mask为maskL;f(p)为像素点p的像素值;③再次遍历图像,右,右上,右下,下;④根据模板maskL和maskR的扫描,得到最终的距离变换图像。为了减少计算了量,采用了一种倒角模版的算法,只需要对图像进行两次扫描,可以实现距离变换,该方法被称为chamfer倒角距离变换,该模版如下:距离变换函数实现步骤函数介绍dst=cv2.distanceTransform(src,distanceType,maskSize[,dstType])·dst表示计算得到目标函数图像。·src表示原始图像,必须是8通道的二值图像。·distanceType表示距离类型。·maskSize表示掩模的尺寸大小。·dstType表示目标函数的类型,默认为CV_F。distanceType表示的是选取距离的类型,可以设置为CV_DIST_L1,CV_DIST_L2,CV_DIST_C等,具体如下:DIST_L1=1,distance=|x1-x2|+|y1-y2|DIST_L2=2,thesimple欧式distanceDIST_C=3,distance=max(|x1-x2|,|y1-y2|)DIST_L12=4,L1-L2metric:distance=2(sqrt(1+x*x/2)-1))DIST_FAIR=5,distance=c^2(|x|/c-log(1+|x|/c)),c=1.3998DIST_WELSCH=6,distance=c^2/2(1-exp(-(x/c)^2)),c=2.9846DIST_HUBER=7distance=|x|<c?x^2/2:c(|x|-c/2),c=1.345maskSize表示的是距离变换的掩膜模板,可以设置为3,5或CV_DIST_MASK_PRECISE,对CV_DIST_L1或CV_DIST_C的情况,参数值被强制设定为3,因为3×3mask给出5×5mask一样的结果,而且速度还更快。labels表示可选输出2维数组;labelType表示的是输出二维数组的类型;defcalcEuclideanDistance(x1,y1,x2,y2): returnmath.sqrt(float((x1-x2)*(x1-x2)+(y1-y2)*(y1-y2)));defdistanceTrans(src,x1):rows=src.shape[0]cols=src.shape[1]#第一遍遍历图像,使用左模板foriinrange(1,rows-1):forjinrange(1,cols-1):ifi==x1:disPara=calcEuclideanDistance(i,j,i,j-1)fDisMin=min(float(src[i][j]),src[i][j-1]+disPara)disPara=calcEuclideanDistance(i,j,i-1,j-1)fDisMin=min(fDisMin,src[i-1][j-1]+disPara)disPara=calcEuclideanDistance(i,j,i-1,j)fDisMin=min(fDisMin,src[i-1][j]+disPara)disPara=calcEuclideanDistance(i,j,i-1,j+1)fDisMin=min(fDisMin,src[i-1][j+1]+disPara)src[i][j]=fDisMin
#第二遍使用右模板,从右下角开始foriinrange(rows-2,0,-1):forjinrange(cols-2,0,-1):ifi==x1:disPara=calcEuclideanDistance(i,j,i,j+1)fDisMin=min(float(src[i][j]),src[i][j+1]+disPara)disPara=calcEuclideanDistance(i,j,i+1,j+1)fDisMin=min(fDisMin,src[i+1][j+1]+disPara)disPara=calcEuclideanDistance(i,j,i+1,j)
fDisMin=min(fDisMin,src[i+1][j]+disPara)disPara=calcEuclideanDistance(i,j,i+1,j-1)fDisMin=min(fDisMin,src[i+1][j-1]+disPara)src[i][j]=fDisMinreturnsrc[[000000][02552552552550][02552552552550][02552552552550][02552552552550][000000]][[000000][011110][02552552552550][02552552552550][02552552552550][000000]][[000000][011110][012210][02552552552550][02552552552550][000000]][[000000][011110][012210][012210][02552552552550][000000]]9-1-0观察距离变换函数cv2.distanceTransform()
[[000000][011110][012210][012210][011110][000000]]1.原图2.第一行距离3.第二行距离4.第三行距离5.第四行距离img=cv2.imread("F:/picture/coin.jpg")imageGray=cv.cvtColor(img,cv.COLOR_BGR2GRAY)#对灰度图进行OTSU阈值处理ret,thresh=cv.threshold(imageGray,0,255,cv.THRESH_BINARY_INV+cv.THRESH_OTSU)kernel=np.ones((3,3),np.uint8)#设定开运算的卷积核#对二值图像进行开运算imageOpen=cv.morphologyEx(thresh,cv.MORPH_OPEN,kernel,iterations=2)distTransform=cv.distanceTransform(imageOpen,cv.DIST_L2,5)#计算欧氏距离#对距离图像进行阈值处理ret,fore=cv.threshold(distTransform,0.4*distTransform.max(),255,0)cv.imwrite("result.jpg",fore)使用距离变换函数cv2.distanceTransform()确定一幅图像的前景图像
a是原始的灰度图像;b是经过开运算处理的图像;c是距离变换函数cv2.distanceTransform()计算得到的图像;d是对距离图像经过阈值处理后的图像。d可以较为准确地确定图a的前景图像。未知区域的确定开运算是先膨胀后腐蚀,得到背景信息小于实际的背景信息,距离变换函数cv2.distanceTransform()只是得到了图像的“中心信息”,即确定前景。对于一幅图像来说,除去这两种区域之外所剩的就是未知区域。imageGray=cv.imread("F:/picture/coin.jpg",0)#读图像#进行Otsu阈值处理ret,thresh=cv.threshold(imageGray,0,255,cv.THRESH_BINARY_INV+cv.THRESH_OTSU)kernel=np.ones((3,3),np.uint8)#设定开运算的卷积核#对二值图像进行开运算imageOpen=cv.morphologyEx(thresh,cv.MORPH_OPEN,kernel,iterations=2)#对开运算后的图像进行膨胀操作,得到确定背景bg=cv.dilate(imageOpen,kernel,iterations=3)distTransform=cv.distanceTransform(imageOpen,cv.DIST_L2,5)#计算欧氏距离#对距离图像进行阈值处理ret,fore=cv.threshold(distTransform,0.4*distTransform.max(),255,0)fore=np.uint8(fore)#调整对距离图像阈值处理的结果un=cv.subtract(bg,fore)#确定未知区域cv.imshow("imageGray",imageGray)#显示原始灰度图cv.imshow("bg",bg)#显示确定背景图像cv.imshow("distTransfom",distTransform)#显示距离图像cv.imshow("un",un)#显示未知区域a:原始的灰度图像;b:距离变换函数cv2.distanceTransform()计算得到的确定前景图像;c:对原始图像经过膨胀操作得到的图像,其背景图像是确定背景;d是未知区域的图像。由c减去b得到。1连通域是指图像中具有相同像素值且位置相邻的前景像素点组成的区域。2.连通区域分析:指将图像中的各个连通区域找出并标记。通常连通区域分析处理的对象是二值化后的图像。l图像的标注图像的标注确定前景图像后,cv2.connectedComponents()函数对图像进行标注。将背景标记为0,其他使用从1开始的整数标记。
ret,labels=cv2.connectedComponents(image)·ret表示标注的数量。·labels表示标注的结果图像。·image表示原始图像,必须是8通道的图像。补充:cv2.connectedComponentsWithStats()num_labels,labels,stats,centroids=cv2.connectedComponentsWithStats(image,connectivity=8,ltype=None)image:必须是二值图,8位单通道图像。connectivity:可选值为4或8,也就是使用4连通还是8连通。ltype:输出图像标记的类型,目前支持CV_32S和CV_16U。
返回值:num_labels:所有连通域的数目labels:图像上每一像素的标记,用数字1、2、3…表示(不同的数字表示不同的连通域)对原始图中的每一个像素都打上标签,背景为0,连通域打上1,2,3。。。的标签,同一个连通域的像素打上同样的标签。stats:每一个标记的统计信息,5列矩阵,每行对应每个区域外接矩形的x、y、width、height和面积,表示每个连通区域的外接矩形(起始点的x、y、宽和高)和面积centroids:连通域的中心点左边是确定的前景图像,右边是标注的图像,共标注了20个结果。分水岭分割在经过上述操作后,cv2.watershed()函数实现图像的分水岭操作。img=cv2.watershed(image,markers)·img表示分水岭操作的结果。·image表示输入的8位三通道图像。·markers表示32位单通道标注结果。【例9-4】使用cv2.watershed()函数对一幅图像进行分水岭演示。小结分水岭分割是基于自然的启发算法来模拟水流通过地形起伏的现象,从而研究总结出来的一种分割方法,其基本原理是将图像特征看作地理上的地貌特征,在分割中,它会把与邻近像素间的相似性作为重要的参考依据,从而将在空间位置上相近和灰度值相近的像素点互相连接起来构成一个封闭的轮廓。具体实现方案如下:(1)对灰度图进行二值化处理,增强目标前景,去除无用背景(2)利用形态学函数,找到背景并标记背景;确定背景信息B(3)利用距离变换函数cv2.distanceTransform()函数,确定前景信息F距离变换函数实现步骤:小结①将输入图片转换为二值图像,前景设置为1,背景设置为0。②Chamfer倒角模版遍历像素顺序如图9-10所示,需要对图像进行两次扫描。依次选取左、左上、上、右下,等像素计算见(9-20)式,实现距离变换。其中,D表示距离包括欧式距离,棋盘距离和麦哈顿距离;小结掩膜模板mask为maskL;f(p)为像素点p的像素值。③依据图9-10(b)所示的后向模板maskR再次遍历图像,依次选取右、右下、下、左下等像素计算(9-20)式,实现距离变换。④根据模板maskL和maskR的扫描,得到最终的距离变换图像。(4)获取边缘,确定未知区域UN图像中有了确定前景F和确定背景B,剩下的区域就是未知区域UN了。未知区域UN=
图像O
-
确定背景B
-
确定前景F未知区域UN=(图像O
-
确定背景B)-
确定前景F上式中的“图像O
-
确定背景B”,可以通过对图像进行形态学的开运算操作得到。(5)利用函数cv2.connectedComponent(),构建标记图像(marker),对目标进行标注使用函数cv2.connectedComponents()进行标注,该函数会将背景标注为0,将其他的对象使用从1开始的正整数标注。函数说明使用cv2.watershed()函数实现分水岭算法,(1)距离变换函数distanceTransformdst=cv2.distanceTransform(src,distanceType,maskSize[,dstType])dst:表示计算得到目标函数图像。可以是8位或32位浮点数,尺寸和src相同;src:表示原始图像,必须是8通道的二值图像;DistanceType:表示距离类型。常用距离类型标识符和含义如表9-1所示。(2)图像的标注cv2.connectedComponents()函数对图像进行标注。ret,markers=cv2.connectedComponents(image)ret:连通域的数目,表示标注的数量;markers:表示标注的结果图像,图像上每一个像素的标记,用数字1、2、3、…表示(不同的数字表示不同的连通域),0表示背景;image:表示原始图像,必须是8通道的图像。函数说明(3)分水岭分割cv2.watershed()函数实现图像的分水岭操作。img=cv2.watershed(image,markers)img:表示分水岭操作的结果;image:表示输入图像;markers:表示32位单通道标注结果。效果展示图像分水岭算法处理效果如图9-20所示,左面的图像是原始的灰度图,右边的图像是对其进行分水岭操作后的图像。
图9-20分水岭算法处理效果图9.3投影法分割水平投影量的计算1.水平投影实现步骤:①图像二值化,物体为黑,背景为白。②循环各行,依次判断每一列的像素值是否为黑,统计该行所有黑像素的个数。设该行共有M个黑像素,则把该行从第一列到第M列置为黑。实现步骤:①图像二值化,物体为黑,背景为白。②循环各列,依次判断每一行的像素值是否为黑,统计该列所有黑像素的个数。设该列共有M个黑像素,则把该列从第一行到第M行置为黑。垂直投影投影量的计算(a)原图(b)水平投影(c)垂直投影效果图9.3.1水平投影分割小结水平投影分割是沿着图像水平方向,统计水平方向像素的累加计算量的集合,通过水平投影可以取得目标物体所在的行数。实现步骤:①将图像二值化,使物体为黑,背景为白。②循环各行,依次判断每一列的像素值是否为黑,统计该行所有黑像素的个数。设该行共有M个黑像素,则把该行从第一列到第M列置为黑。③显示该图。效果展示通过水平投影可以取得汉字所在的行数,图像投影处理效果如图9-21所示。图9-21水平投影可分割汉字所在的行数9.3.2垂直投影分割小结垂直投影分割是沿着图像垂直方向,统计垂直方向像素的累加计算量的集合,通过垂直投影可以取得目标物体所在的列数。实现步骤:①将图像二值化,使物体为黑,背景为白。②循环各列,依次判断每一行的像素值是否为黑,统计该列所有黑像素的个数。设该列共有M个黑像素,则把该列从第一行到第M行置为黑。③显示该图。效果展示图像投影处理效果如图9-22所示,垂直投影可获得汉字所在的列数,因此,垂直投影可以分割每个汉字。图9-22垂直投影可以分割每个汉字9.4轮廓检测9.4.1邻域判断法
掏空内部点轮廓提取图像边缘是图像局部特性不连续性(灰度突变、颜色突变等)的反映,它标志着一个区域的终结和另一个区域的开始。二值图像的轮廓提取采用掏空内部点法:如果原图中有一点为黑,且它的8个相邻点皆为黑,则将该点删除。对于非二值图像,要先进行二值化处理。1)获取原图像的首地址,图像的高和宽。2)开辟一块内存缓冲区。3)将像素点的8邻域像素读入数组中,如果8个邻域像素都和中心点相同,在内存缓冲区中将该像素点置白,否则保持不变。4)重复执行3),对每一个像素进行处理。实现步骤(a)原图(b)轮廓提取效果图效果图9.4.2边界跟踪法
从图像中一个边界点出发,然后根据某种判别准则搜索下一个边界点,以此跟踪出目标边界。边界跟踪法小结中心像素可以跟踪的方向有8个,对每个方向制订了方向编号及偏移量,当找到起始点,把该点记录下来,定义初始的跟踪方向是左上方0方向,判断该点是否为目标点,若是则把该目标点作为跟踪的起始点,逆时针旋转90度作为新的跟踪方向,继续检测该新的跟踪方向上的点;若不是则沿顺时针旋转45度,直至找到目标点。找到目标点后,在当前跟踪方向的基础上,逆时针旋转90度作为新的跟踪方向,用同样的方法跟踪下一个边界点,直到回到起始点为止。小结边界跟踪的基本方法是:先根据某些严格的“探测准则”找出目标物体轮廓上的像素,再根据这些像素的某些特征用一定的“跟踪准则”找出目标物体上的其他像素。图9-24边界跟踪示意图确定边界的起始搜索点,起始点的选择很关键,对某些图像,选择不同的起始点会导致不同的结果。
确定合适边界判别准则和搜索准则,判别准则用于判断一个点是不是边界点,搜索准则则指导如何搜索下一个边缘点。
确定搜索的终止条件。边界跟踪法1)从左下角开始逐点扫描,当遇到边缘点时,则跟踪,直至跟后续点回到起始点(对于闭合线),或其后续点再没有新的后续点(对于非闭合线)为止。2)如果为非闭合线,则跟踪一侧后,需从起始点开始朝相反的方向跟踪到另一尾点。3)如果不止一个后续点,则按上述连接准则选择距离最近的点为后续点,另一次要的后续点作为新的边缘跟踪起点另行跟踪。4)一条线跟踪完后,接着扫描下一个未跟踪点,直至所有边缘都跟踪完毕。边界跟踪法--跟踪准则(a)中心像素跟踪的8个方向编号及偏移量(b)边界跟踪示意图(-1,-1)(0,-1)(1,-1)(-1,0)(1,0)(-1,1)(0,1)(1,1)边界跟踪法--跟踪准则
中心像素可以跟踪的方向有8个,对每个方向制定了方向编号及偏移量,选取图像的最左下方的像素点作为起始点。边界跟踪法--跟踪准则当找到起始点,把该点记录下来;初始跟踪方向是:左上方0方向;判断该点是否为目标点,是则把该点为跟踪的起始点;逆时针旋转90度,作为新的跟踪方向,继续检测该新的跟踪方向上的点。边界跟踪法--跟踪准则若不是是目标点则沿顺时针旋转45度,一直到找到目标点。找到目标点后,在当前跟踪方向的基础上,逆时针旋转90度作为新的跟踪方向,用同样的方法跟踪下一个边界点;直到回到起始点为止。
边界跟踪法--跟踪准则1)获得图像的首地址,图像的高和宽。2)开辟一块内存缓冲区,初始化为255。3)将图像进行二值化处理。4)跟踪边界点,找到1个边界点,就将内存缓冲区中该点置0。5)按照跟踪准则,重复执行(4),直到回到初始点。实现步骤(a)原图(b)外边界跟踪效果图
效果图9.4.3区域增长法阈值分割法:很少考虑空间关系,使多阈值选择受到限制。区域分割法:弥补这点不足,利用空间性质,认为属于同一区域的像素应具有相似性。传统的区域分割算法有:区域增长法和区域分裂合并法。该类方法在先验知识不足的图像进行分割,有较好的性能。但是,空间和时间开销比较大。区域增长法
依次用图像的每一个像素的灰度值和种子点相减,判断结果是否小于标准差,是则将该点和种子点合并,不是则保持像素点的灰度值不变。这样处理后的图像就是用区域分割法处理后的边缘分割图像。区域增长法考虑空间邻域象素之间的关系。开始时确定一个或多个象素点作为种子,按某种相似性准则,增长区域,逐步生成具有某种均匀性的空间区域,将相邻的具有相似性质的象素或区域归并,从而逐步增长区域,直至没有可以归并的点或其它小区域为止。区域内象素的相似性度量可以包括平均灰度值、纹理、颜色等信息。区域增长法选择合适的种子点确定相似性准则(生长准则)确定生长停止条件区域增长法区域增长法示意图区域增长法1)获取原图像的首地址,及高和宽。2)依次用图像的每一个像素的灰度值减去种子点,判断结果的绝对值是否小于阈值,阈值为10。如果小于则将种子点赋给该像素点,否则灰度值保持不变。实现步骤(a)选择生长点
(b)按右键点击黑处效果图效果图小结将具有相似性质的像素集合起来构成区域。先找一个种子像素作为生长起点,然后将与种子像素有相同或相似性质的像素合所在的区域中。将这些新像素当作新的种子继续上面的过程,直到没有满足条件
区域增长法示意图函数说明(1)None=dWindow(winname[,flags])该函数是OpenCV中用于创建窗口的函数,窗口通常用来显示图像。Winname:窗口名称;Flags:可选参数,例如有cv2.WINDOW_NORMAL、cv.WINDOW_AUTOSIZE等。(2)None=cv2.setMouseCallback(winname,onMouse,userdata)该函数是OpenCV中常需要用到的鼠标回调函数,以此实现人机交互。Winname:绑定的窗口名称;OnMouse:鼠标的回调函数;Userdata:可选参数。函数说明(3)在OpenCV中提供了cv2.circle()函数来绘制圆image=cv2.circle(image,center,radius,color[,thickness[,lineType]])image:表示绘制的载体图像;center:表示圆心;radius:表示圆的半径;color:表示绘制圆的线条的颜色;thickness:表示绘制圆的线条的粗细;lineType:表示绘制圆的线条的类型。函数说明(4)在OpenCV中提供了cv2.putText()函数,用于在图形上绘制文字mage=cv2.putText(image,text,org,fontFace,fontScale,color[,thickness[,lineType[,bottomLeftOrigin]]])image:表示绘制的载体图像;text:表示要绘制的字体;org:表示绘制字体的位置;fontFace:表示字体类型;fontScale:表示字体大小;color:表示绘制文字的线条的颜色;thickness:表示绘制文字的线条的粗细;lineType:表示绘制文字的线条的类型;bottomLeftOrigin:表示文字的方向。效果展示
图9-27鼠标单击效果图9.4.4轮廓检测与拟合图像的轮廓由一系列的点组成,这些点以某种方式表示图像中的一条曲线。所以,图像轮廓的绘制就是将检测到的边缘信息和图像的前景信息进行拟合,从而得到图像的轮廓。在OpenCV中提供了cv2.findContours()和cv2.drawContours()函数来实现对图像轮廓的查找与绘制,OpenCV中轮廓的查找与绘制函数说明在OpenCV中提供了cv2.findContours()和cv2.drawContours()函数来实现对图像轮廓的查找与绘制。(1)cv2.findContours()函数一般格式为:image,contours,hierarchy=cv2.findContours(image,mode,method)image:表示8位单通道原始图像。mode:表示轮廓检索模式。(2)cv2.drawContours()函数一般格式为:image=cv2.drawContours(image,contours,contourIdx,color[,thickness[,lineTypehierarchy[,maxLevel[,offset]]]]])函数说明image:表示待绘制轮廓的图像。contours:表示需要绘制的轮廓。contourIdx:表示需要绘制的边缘索引。color:表示绘制的轮廓颜色。绘制的颜色,用BGR格式表示。thickness:表示绘制轮廓的粗细。如将该值设置为“-1”,则表示要绘制实心轮廓。lineType:表示绘制轮廓所选用的线型。hierarchy:对应函数cv2.findContours()所输出的层次信息。maxLevel:控制所绘制轮廓层次的深度。offset:表示轮廓的偏移程度。该参数使轮廓偏移到不同的位置展示出来。函数介绍cv2.findContours()函数的一般格式为:image,contours,hierarchy=cv2.findContours(image,mode,method)其中:·image表示8位单通道原始图像。·contours表示返回的轮廓。·hierarchy表示轮廓的层次信息。·mode表示轮廓检索模式。·method表示轮廓的近似方法。cv2.drawContours()函数的一般格式为:image=cv2.drawContours(image,contours,contourIdx,color[,thickness[,lineTypehierarchy[,maxLevel[,offset]]]]])函数介绍cv2.drawContours()函数的一般格式为:image=cv2.drawContours(image,contours,contourIdx,color[,thickness[,lineTypehierarchy[,maxLevel[,offset]]]]])其中:·image表示待绘制轮廓的图像。·contours表示需要绘制的轮廓。·contourIdx表示需要绘制的边缘索引。·color表示绘制的轮廓颜色。·thickness表示绘制轮廓的粗细。·lineType表示绘制轮廓所选用的线型。·hierarchy对应cv2.findContours()函数中同样参数的信息。·maxLevel控制所绘制轮廓层次的深度。
绘制轮廓实例【例】绘制一幅图像内的轮廓。效果分析a是原始图像;b是绘制图1a中轮廓的结果;c是轮廓的信息。可以看出,图像共有8个轮廓信息,类型是列表。由于本书是黑白打印,为了观察轮廓绘制效果,请上机测试。【例2】利用查找绘制轮廓的方法提取出一幅图像的前景信息。效果分析a是原始图像;b是通过cv.findContours()函数和cv.draw-Contours()函数绘制的轮廓;c是通过掩模提取的前景信息。效果展示
(a)原图(b)轮廓绘制(c)Mask图
效果展示
(d)提取的前景(e)Canny检测的边缘(f)绘制的边缘信息
9.5目标物体测量9.5.1区域标记二值图像区域标记在二值图像中,相互联结的黑像素集合成为一个(黑)区域。通过对图像内每个区域进行标记操作,求得区域的数目。处理前的f是二值的,像素要么为0(黑),要么为255(白),处理后每个像素的值即为其所处理区域的区域标号(1,2,3,…)。从左到右,从上倒下逐个像素扫描。若该点的左上、正上、右上及左前点都不为物体,则标号加1。优先级依次为右上点,正上点,左上点及左前点。右上点的优先级最高,左前的优先级最低。若右上点为物体,则当前点标记和右上点相同的值。若右上点不为物体,则判断正上点。标记准则其中特别调整:当前点的右上点及左前点为不同标记,正上点和左上点不为物体,则当前点标记同右上点置相同的值。此时,从头到尾扫描图像,把所有标记相同的像素值都标记成与右上点同样的值。标记准则1)读入原图数据,存放在缓冲区内。2)根据输入的阈值进行二值化。3)从左到右,从上倒下,依次检测每个像素,如果发现某像素点像素值为0,则依次检测该点的右上、正上、左上及左前点共四个点的像素值,根据前面介绍的8个准则进行连通性的判断,并标识物体,将物体的像素值改为标号。4)依次逐行检测至扫描结束。实现步骤(a)原图
(b)对物体加标记图
效果图函数说明(1)在OpenCV中可以通过cv2.moments()函数来获取图像的轮廓特征moments=cv2.moments(img,binaryImage=False)img:可以是灰度图像或者二值图像;binaryImage:表示输入的二值图像是否已经是经过二值化处理的。如果是,则传入True,否则传入False。moments:返回的矩特征。cv2.moments函数的返回值为一个字典,包含了图像矩及其他信息。字典的键与矩的特征有关,例如中心矩、二阶矩等。m00=moments['m00'] #面积cx=moments['m10']/moments['m00'] #x坐标cy=moments['m01']/moments['m00'] #y坐标其中,m00表示图像的面积,cx和cy分别表示图像的重心。效果展示9.5.2面积测量9.4.2二值图像的区域面积测量在二值图像f中,通过对图像f内每个像素进行标记操作,将物体的像素值改为标号,求各种标号的总和,即求得不同区域的面积数目。1)调用标记统计函数,对图像进行标记,划分成不同的连通区域。2)循环取得各点像素值,像素值就是标号。3)根据不同的标号,加到对应的数组。4)弹出对话框,输出各个连通区域的面积(像素个数)。实现步骤面积测量效果图在OpenCV中,cv2.contourArea()函数可以用于计算轮廓的面积,其一般格式为:retval=cv2.contourArea(contour[,booled])retval:表示返回的轮廓面积;contour:表示输入的轮廓;booled:表示轮廓的封闭性。函数说明效果展示9.5.3周长测量9.4.3二值图像的周长测量在二值图像区域标记的基础上,物体的像素值改为标号,再采用边界跟踪法,跟踪各封闭区域边界线(轮廓线)的每个黑像素的标号,记录二值图像物体边界。1)调用biaoji()函数,对图像进行标记,划分成不同的连通区域。2)根据不同的像素值,即不同的连通区,循环取得各点像素值的标号,搜索出一个发点,利用7.3.2节介绍的边界跟踪法,采用Lunkuogenzong()函数,找到出发点后,记录其坐标,再跟踪下一像素。保留循环得到的边界点,其余都置255(白点)。实现步骤3)根据不同的像素值,即不同的连通区,依次执行第2步。4)把缓冲区的数据返回到原数据区。5)调整连通边界区,计算每个连通边界区的周长(像素个数)。6)弹出对话框,输出各个边界连通区域的像素个数。实现步骤周长计算效果图
(a)原图
(b)对不同区域体标识图(c)区域面积测量图(d)区域周长测量图效果图函数说明在OpenCV中,函数cv2.arcLength()可以用于计算轮廓的长度,其一般格式为:retval=cv2.arcLength(contour,booled)其中:retval:表示返回的轮廓周长;contour:表示输入的轮廓;booled:表示轮廓的封闭性。效果展示图9-35周长计算效果图在OpenCV中,当查找并绘制出图像的轮廓后,可以通过cv2.arcLength()函数和cv2.contourArea()函数计算轮廓的周长与面积。在OpenCV中,函数cv2.arcLength()可以用于计算轮廓的长度,其一般格式为:ret=cv2.arcLength(contour,booled)其中:·ret表示返回的轮廓周长。·contour表示输入的轮廓。·booled表示轮廓的封闭性。OpenCV中轮廓的周长与面积9.2.1
周长计算:cv2.arcLength()函数【】计算并显示一幅图像中的轮廓长度。运行结果a是原始图像,其中有8个各种各样的图形;b是原始图像中各个图形的周长。面积计算:cv2.contourArea()函数在OpenCV中,cv2.contourArea()函数可以用于计算轮廓的面积,其一般格式为:ret=cv2.contourArea(contour[,booled])其中:·ret表示返回的轮廓面积。·contour表示输入的轮廓。·booled表示轮廓的封闭性。【例5】计算并显示一幅图像中的轮廓面积。运行结果a是原始图像,其中有8个图形;b是原始图像中各个图形的面积。9.6最小外包形状检测在通过之前的阈值分割和边缘检测后,可以获得一幅图像的前景或边缘。接下来,一般是通过拟合的方式获取可以近似这些图像轮廓的多边形或者最小外包,为之后的模板匹配打下一定的基础。几何图形的最小外包与拟合9.6.1最小外包矩形cv2.minAreaRect()函数用来绘制轮廓的最小外包矩形框,其一般格式为:ret=cv2.minAreaRect(points)其中:·ret表示返回的矩形特征信息。·points表示输入的轮廓。注意返回值ret的结构不符合cv2.drawContours()函数的参数结构要求。因此必须用cv2.boxPoints()函数将上述返回值ret转换为符合要求的结构。cv2.boxPoints()函数的一般格式是:points=cv2.boxPoints(box)其中:·box表示cv2.minAreaRect()函数返回值类型的值。·points表示返回的符合结构的矩形特征信息。【例6】利用cv2.minAreaRect()函数得到图像的最小外包矩形框。运行结果图6a是原始图像;图6b是在原始图像上绘制的最小矩形外包的图像。9.6.2最小外包圆形在OpenCV中提供了cv2.minEnclosingCircle()函数来绘制轮廓的最小外包圆形,其一般格式为:center,radius=cv2.minEnclosingCircle(points)其中:·center表示最小外包圆形的中心。·radius表示最小外包圆形的半径。·points表示输入的轮廓。【例7】利用cv2.minEnclosingCircle()函数得到图像的最小外包圆形。运行结果9.6.3最小外包三角形在OpenCV中提供了cv2.minEnclosingTriangle()函数来绘制轮廓的最小外包三角形,其一般格式为:ret,triangle=cv2.minEnclosingTriangle(points)其中:·ret表示最小外包三角形的面积。·triangle表示最小外包三角形的三个顶点集。·points表示输入的轮廓。【例8】利用cv2.minEnclosingTriangle()函数得到图像的最小外包三角形。运行结果9.6.4最小外包椭圆在OpenCV中提供了cv2.fitEllipse()函数来绘制轮廓的最小外包椭圆,其一般格式为:ret=cv2.fitEllipse(points)其中:·ret表示返回的椭圆特征信息,包括中心点、轴长度和旋转角等。·points表示输入的轮廓。【例9】利用cv2.fitEllipse()函数得到图像的最小外包椭圆。运行结果9.3.5最优拟合直线在OpenCV中提供了cv2.fitLine()函数来绘制轮廓的最优拟合直线,其一般格式为:line=cv2.fitLine(points,distType,param,reps,aeps)其中:·line表示返回的最优拟合直线参数。·points表示输入的轮廓。·distType表示距离类型。·param表示距离参数,与所用距离类型相关。·reps表示最优拟合直线的径向精度,一般为0.01。·aeps表示最优拟合直线的角度精度,一般为0.01。【例10】利用cv2.fitLine()函数得到图像的最优拟合直线。运行结果9.7霍夫检测霍夫变换于1962年由PaulHough首次提出,霍夫变换运用两个坐标空间之间的变换将在一个空间中具有相同形状的曲线或直线映射到另一个坐标空间的一个点上形成峰值,从而把检测任意形状的问题转化为统计峰值问题。9.7霍夫检测9.7.1霍夫直线检测小结霍夫变换(HoughTransform)的原理是将特定图形上的点变换到一组参数空间上,根据参数空间点的累计结果找到一个极大值对应的解,那么这个解就对应着要寻找的几何形状的。图9-40极坐标系下的直线方程(1)极坐标系下的直线方程ρ
=
xcosθ
+
ysinθ(9-21)(2)极坐标系中的一点对应θ从0~2π变化的直线(3)θ角度由1°逐渐递增可获取对应的直线参数ρ(4)同一条直线上的点,对应相同的(ρ,θ)图9-40极坐标系下的直线方程(5)参数空间(θ,ρ)量化,构建累加器矩阵,统计相同(θ,ρ)的出现次数霍夫直线检测,就是将参数空间(θ,ρ)量化成m×n(m为θ的等份数,n为ρ的等份数)个单元。小结算法流程:①首先就是对图像进行Canny边缘提取;②将参数空间(θ,ρ)量化成m×n个单元,并设置累加器矩阵Q[m×n],并把累加器的初始值置为零;③将每一个边缘点的直角坐标系代入式ρ=xcosθ+ysinθ,然后将θ0~θm−1也都代入其中,分别计算出相应的值ρj;④在参数空间中,找到每一个Q(θi,ρj)所对应的单元,并将该单元的累加器加1;⑤待图像xy坐标系中的所有点都进行运算之后,检查参数空间的累加器,指定一个阈值,输出多条直线。函数说明(1)cv2.HoughLines()函数来实现标准霍夫直线检测,lines=cv2.HoughLines(image,rho,theta,threshold)lines:表示函数的返回值,是检测到的直线参数;image:表示输入的8位单通道二值图像;rho:表示距离的精度,一般为1;theta:表示角度的精度,一般为π/180;threshold:表示判断阈值。效果展示
(a)原图(b)Canny边缘检测
(c)霍夫直线检测结果
温馨提示
- 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
- 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
- 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
- 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
- 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
- 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
- 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。
最新文档
- 设备维修与保养合同书
- 设计师室内设计收费标准
- 语文能力大学专升本提升
- 货物买卖与购销合同
- 质量保证诚信施工
- 购房卖房中介合同示例示例示例
- 购销合同封面模版
- 购销合同简单范本模版
- 贷款合同签订条件说明
- 赴台保证书共筑美好未来
- 2022年特种作业人员的管理制度
- GB∕T 37566-2019 圆钢超声检测方法
- 鼻腔鼻窦基本病变影像学表现
- 马凡氏综合征护理查房ppt课件(PPT 25页)
- 教学课件·光学测量技术
- 03-习题考点一现金流量折现模型
- 标准化基础知识
- 口算伴我成长自动出题系统v2.9-万以内整数加减
- 地质学专业英语词汇
- 2022年新课标完整解读新版义务教育课程方案和课程标准(2022年版)简约(PPT课件)
- 《线段的垂直平分线的性质》课件(共17张PPT)
评论
0/150
提交评论