OpenCv形态学(一)

2024-06-23 01:04
文章标签 opencv 形态学

本文主要是介绍OpenCv形态学(一),希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

目录

形态学转换

结构元素

腐蚀

膨胀

开运算

闭运算

形态学梯度

顶帽

黑帽

图像轮廓

查找轮廓

绘制轮廓


形态学转换

·形态变换是一些基于图像形状的简单操作。通常在二值图像上执行。它需要两个输入,一个是我们的原始图像,第二个是决定操作性质的结构元素或内核。两种基本的形态学算子是侵蚀和膨胀。然后,它的变体形式(如“打开”,“关闭”等)也开始起作用。形态变换是一些基于图像形状的简单操作。通常在二值图像上执行。它需要两个输入,一个是我们的原始图像,第二个是决定操作性质的结构元素或内核。两种基本的形态学算子是侵蚀和膨胀。然后,它的变体形式(如“打开”,“关闭”等)也开始起作用。基本思想:使用具有一定形状的结构元素去度量和提取图像中对应的形状,以达到对图像进行处理的目的。

形态学操作图像的数学基础是集合论

集合的交集和并集

集合的补集和差集

集合的反射

集合的平移

结构元素

二值图像形态学处理的运算对象是集合

设A为像素集合,B为结构元素(本身也是一个像素集合,其元素是感兴趣目标的像素),处理过程就是用B对A进行操作。结构元素B对A的具体操作

  • 通过让B在A上平移,以便B的原点访问A的每一个元素,以此得到一个新的像素集合

    结构元素必须指定一个原点

  • 结构元素的原点就是形态学运算的参考点(当结果元素对称且未显示原点时,通常将原点假定在对称中心处)

    当对图像操作时,要求结构元素时矩形阵列(通过添加最小可能数量的背景元素组成一个矩阵阵列来实现)

    注意:形态学处理中,只考虑图像和结构元素中有效像素点,也就是只考虑感兴趣的前景部分,背景部分不予考虑

    为什么结构元素是奇数:

    旋转180°不变,反射之后还是他本身

    原点方便定位中心点

cv2.getStructuringElement(shape, ksize, anchor)

函数用于返回一个指定形状和尺寸的结构元素,该结构元素可用于形态学操作,如腐蚀、膨胀、开运算和闭运算等。其语法参数说明:

  • shape:表示结构元素的形状,可以是以下几种取值:

  • cv2.MORPH_RECT:矩形结构元素

  • cv2.MORPH_CROSS:十字形结构元素

  • cv2.MORPH_ELLIPSE:椭圆形结构元素

  • ksize:表示结构元素的大小

  • anchor:表示结构元素的锚点位置,默认为(-1,-1),表示结构元素的中心

在图像处理中,使用cv2.getStructuringElement函数创建结构元素时,将ksize参数设置为奇数有以下几个原因:

  • 对称性:奇数尺寸的结构元素具有对称性,这在一些形态学操作中是很重要的。例如,在腐蚀和膨胀操作中,使用对称的结构元素可以确保操作的结果在图像的不同位置上具有相似的效果。

  • 中心性:奇数尺寸的结构元素有一个明确的中心像素。这个中心像素在形态学操作中起着重要的作用,例如在腐蚀操作中

  1. 边界处理的便利性:在处理图像边界时,奇数尺寸的结构元素可以更方便地处理边界像素。对于奇数尺寸,能够以更对称和一致的方式处理靠近图像边缘的部分,减少边界效应带来的不一致性。

  2. 更好的局部特征提取:在一些应用中,奇数尺寸的结构元素可以更准确地捕捉图像的局部特征。这是因为其中心像素能够更精确地定位在目标区域内,从而对局部结构的描述更加准确。

  3. 数学计算的简洁性:在某些形态学运算的数学实现中,奇数尺寸的结构元素可能会使计算更加简洁和高效,减少计算过程中的复杂性和可能出现的错误。

腐蚀

.Common Names: Erode, Shrink, Reduce(常用名称:腐蚀,侵蚀,收缩,减少)。侵蚀是数学形态学领域的两个基本算子之一,另一个是膨胀算子。

·侵蚀通常适用于二值图像,但也有适用于灰度图像的版本。算子对二值图像的基本作用是侵蚀掉前景像素(即白色像素)区域的边界。因此,前景像素的区域缩小了。

效果:缩小图像中的物体

定义:假设A是原始的二值图像,B是结构元素,则A被B腐蚀的定义为:将结构元素B相对于集合A进行平移,只要平移后结构元素都包含在集合A中,则这些位移Z的点(前景像素点)的集合即为腐蚀后的结果

def erode(src, kernel, dst=None, anchor=None, iterations=None, borderType=None, borderValue=None):

  • src:输入图像,可以是多通道图像,深度应为CV_8UCV_16UCV_16SCV_32FCV_64F之一。

  • dst:输出与输入图像相同大小和类型的图像。

  • kernel:用于腐蚀的结构元素。如果kernel=Mat(),则使用3x3矩形结构元素。可以使用getStructuringElement()函数创建内核。

  • anchor:锚点在元素内的位置,默认值为(-1,-1),表示锚点位于元素中心。

  • iterations:腐蚀的次数,默认值为1。

  • borderType:像素外推方法,可选项包括BORDER_CONSTANTBORDER_REPLICATE等。

  • borderValue:边界不变的边界值。

腐蚀的过程

 eg:去掉两个物体之间连接的细线

im=np.zeros((200,200),np.uint8)
im[20:23,20:23]=255# 获取一个3*3的结构元素
# 第一个参数:结果元素的形状,矩阵还是十字型
# 第二个参数:结构元素的大小
kernel=cv2.getStructuringElement(cv2.MORPH_RECT,(3,3))
dst=cv2.erode(im,kernel)
cv2.imshow("im",im)
cv2.imshow("dst",dst)
cv2.waitKey(0)
cv2.destroyAllWindows()

用3*3的卷积核腐蚀3*3的矩阵(原图--右,效果图--左)

膨胀

·效果:扩大图像中的物体,在二值图中扩大白色的部分,收缩黑色的部分

·定义:假设A是原始的二值图像,B是结构元素,则A被B膨胀的定义为:

又被定义为:

也就是,A被B膨胀的结果是满足上面公式的所有位移z的点(前景像素点)的集合。

dilation = cv.dilate(img,kernel,iterations =1)

  • img:要进行膨胀操作的输入图像。

  • kernel:用于膨胀操作的结构元素,通常通过 cv2.getStructuringElement 函数获取。

  • iterations:膨胀操作的迭代次数。默认值为 1,表示执行一次膨胀操作。如果设置为大于 1 的值,则会连续执行指定次数的膨胀操作,使得膨胀效果更加强烈。

开运算

效果: 断开较窄的粘连线,消除较细的突出物和噪音,使图像的轮廓变得光滑(去除白点)

定义: 假设A是原始的二值图像,B是结构元素,则A被B开运算的定义为:

也就是,先用B对A继续腐蚀,然后再用B对腐蚀的结果进行膨胀

opening = cv2.morphologyEx(img, cv.MORPH_OPEN, kernel)

 

闭运算

效果:关闭前景对象内部的小孔或对象上的小黑点时很有用。使图像的

轮廓变得光滑(去除黑点)

定义:假设A是原始的二值图像,B是结构元素,则A被B闭运算的定义

为:   先用B对A继续膨胀,然后再用B对膨胀的结果进行腐蚀

closing = cv.morphologyEx(img, cv.MORPH_CLOSE, kernel)

形态学梯度

效果:

图像边界提取

·定义:假设A是原始的二值图像,B是结构元素,则定义为:

也就是,腐蚀的部分

·gradient = cv.morphologyEx(img, cv.MORPH_GRADIENT, kernel)

示例:获取图像边界

import cv2
im = cv2.imread("grad.png")
kernel = cv2.getStructuringElement(cv2.MORPH_RECT, (3, 3))
im2 = cv2.morphologyEx(im, cv2.MORPH_GRADIENT, kernel)
cv2.imshow("im", im)
cv2.imshow("gradient", im2)
# cv2.imshow("im3", im3)
cv2.waitKey(0)
cv2.destroyAllWindows()

顶帽

顶帽是输入图像和图像开运算之差

  • tophat = cv.morphologyEx(img, cv.MORPH_TOPHAT, kernel)

    细小结构。因此,顶帽运算能够突出原始图像中比周围环境更亮的区域

    或者斑点,有助于分离出这些亮区域,比如寻找图像中的亮点物体或者

    高亮细节。这对于背景相对均匀而前景目标较亮的图像特别有用,例如,

    在医学成像或文本识别中强调局部高亮区域。(找小白点)

  • ·开运算由先腐蚀后膨胀组成,能够去除图像中的小亮点(比如噪声)

黑帽

     是输入图像和图像闭运算之差

  • blackhat = cv.morphologyEx(img, cv.MORPH_BLACKHAT,kernel)

    闭运算由先膨胀后腐蚀组成,能够填充图像中的小暗点和细小缝隙。因此,黑帽运算能突出显示原始图像中比周围环境更暗的区域或者斑块,有助于发现图像中的暗区域或者阴影部分,对于背景去除或者凸显图像中的暗结构非常有效。在一些应用场景下,如检测路面坑洞或寻找图像中的暗色目标时非常有用。

图像轮廓

图像轮廓是具有相同颜色或灰度的连续点的曲线,轮廓在形状分析和物

体的检测和识别中很有用。

·轮廓的作用:

    -图形分析-物体的检测和识别

.注意点:

函数返回两个值:轮廓列表 contours 和轮廓的层次结构 hierarchy

.Mode查找轮廓的模式:

RETR EXTERNAL=0这是最简单的检索模式,只检索最外层的轮廓,即不包括任何嵌套轮廓。如果你只关心物体的外部边界,而不考虑其内部结构或孔洞,这个模式就很适用。

RETR LIST=1该模式检索所有轮廓,并将其作为列表返回,但不创建任何层次结构。每个轮廓都是独立的,没有父子关系信息。适用于需要所有轮廓但不需要它们之间关系的场景。

RETR CCOMP =2在这种模式下,检索到的轮廓被组织成两层层次结构。顶层是外部边界,第二层是孔和内部边界。如果一个对象内有多个孔,则孔被视为同一层级。这对于需要区分外边界和内部孔洞的场景很有用。

RETR_TREE =3这是最复杂的检索模式,构建了一个完整的轮廓层次树。每个轮廓都有一个层次信息,可以区分出父轮廓和子轮廓(内部轮廓),非常适合于需要分析复杂结构和多级嵌套轮廓的场景。(常用这个)

  • 需要先对图像进行二值化处理

  • 画轮廓会修改原始图像,如果后面像继续使用原始图像,应该设置原始图像副本

  • 查找轮廓

    findContours(image, mode, method[, contours[,hierarchy[ offset]]]) -> contours, hierarchy

    图片只能是单通道u8的

    cv2.findContours 函数用于在二值图像中查找轮廓,其参数如下:

  • image:输入的 8 位单通道图像,可以是二值图像。

  • mode:轮廓的检索模式,常见的取值有:

  • cv2.RETR_EXTERNAL:只检测最外层轮廓。

  • cv2.RETR_LIST:检测所有轮廓,不建立层次关系。

  • cv2.RETR_CCOMP:检测所有轮廓,并将其组织为两层的层次结构。

  • cv2.RETR_TREE:检测所有轮廓,并重建完整的层次结构。

  • method:轮廓的近似方法,常见的取值有:

  • cv2.CHAIN_APPROX_NONE:存储所有的轮廓点。

  • cv2.CHAIN_APPROX_SIMPLE:压缩水平、垂直和对角线段,只保留其端点。

  • 函数返回两个值:轮廓列表 contours 和轮廓的层次结构 hierarchy

    .Mode查找轮廓的模式:

    RETR EXTERNAL=0这是最简单的检索模式,只检索最外层的轮廓,即不包括任何嵌套轮廓。如果你只关心物体的外部边界,而不考虑其内部结构或孔洞,这个模式就很适用。

    RETR LIST=1该模式检索所有轮廓,并将其作为列表返回,但不创建任何层次结构。每个轮廓都是独立的,没有父子关系信息。适用于需要所有轮廓但不需要它们之间关系的场景。

    RETR CCOMP =2在这种模式下,检索到的轮廓被组织成两层层次结构。顶层是外部边界,第二层是孔和内部边界。如果一个对象内有多个孔,则孔被视为同一层级。这对于需要区分外边界和内部孔洞的场景很有用。

    RETR_TREE =3这是最复杂的检索模式,构建了一个完整的轮廓层次树。每个轮廓都有一个层次信息,可以区分出父轮廓和子轮廓(内部轮廓),非常适合于需要分析复杂结构和多级嵌套轮廓的场景。(常用这个)

    findContours(image, mode, method[, contours[,hierarchy[,offset]]]) -> contours(轮廓), hierarchy(层级)

    ·Method:

  • CHAIN APPROX NONE=1:轮廓中的每一点都会被精确保存下来

  • CHAIN APPROX SIMPLE = 2: 仅保留轮廓的端点和具有拐角的点来简化轮廓表示

绘制轮廓

drawContours(image, contours, contourldx, color[, thickness[,lineType[,hierarchy[,maxLevel[, offset]]]]]) -> image

  • Image 要绘制的轮廓图像

  • Contours 轮廓点

  • contourldx 要绘制的轮廓编号,-1表示绘制所有轮廓,0是最外层,1是内层

    :Color: 轮廓的颜色

  • Thickness:线宽,-1表示填充

代码示例:绘制左图中的所有边框轮廓

import cv2im = cv2.imread("p1.png")
im_orgin = im.copy()
im1 = cv2.cvtColor(im, cv2.COLOR_BGR2GRAY)# 查找轮廓
contours, _ = cv2.findContours(im1, cv2.RETR_TREE, cv2.CHAIN_APPROX_SIMPLE)# 绘制轮廓cv2.drawContours(im, contours, -1, (0, 0, 255), 2, cv2.LINE_AA)
cv2.imshow("im_orgin", im_orgin)
cv2.imshow("im", im)
cv2.waitKey(0)
cv2.destroyAllWindows()

这篇关于OpenCv形态学(一)的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/1085891

相关文章

vcpkg安装opencv中的特殊问题记录(无法找到opencv_corexd.dll)

我是按照网上的vcpkg安装opencv方法进行的(比如这篇:从0开始在visual studio上安装opencv(超详细,针对小白)),但是中间出现了一些别人没有遇到的问题,虽然原因没有找到,但是本人给出一些暂时的解决办法: 问题1: 我在安装库命令行使用的是 .\vcpkg.exe install opencv 我的电脑是x64,vcpkg在这条命令后默认下载的也是opencv2:x6

brew install opencv@2 时报错 Error: Can't create update lock in /usr/local/var/homebrew/locks!

解决方案,报错里已经说明了: 我的解决方案: sudo chown -R "$USER":admin /usr/local   stackoverflow上的答案 I was able to solve the problem by using chown on the folder: sudo chown -R "$USER":admin /usr/local Also you'

《学习OpenCV》课后习题解答7

题目:(P105) 创建一个结构,结构中包含一个整数,一个CvPoint和一个 CvRect;称结构体为“my_struct”。 a. 写两个函数:void Write_my_strct(CvFileStorage* fs, const char * name, my_struct* ms) 和 void read_my_struct(CvFileStorage* fs, CvFileNode

OpenCV中的按钮问题

在HighGUI中,没有显示提供任何形式的按钮。一般有两种方法替代: 1.用只有两个状态的滑动条来替代按钮。开关(switch)事实上就是只有两个状态的滑动条,这两个状态是on和off。然后通过回调函数来实现相关的功能。 实例源码(使用滑动条实现一个开关功能) #include<cv.h>#include<highgui.h>int g_switch_value = 0;void swit

《学习OpenCV》课后习题解答6

题目:(P104) 使用cvCmp()创建一个掩码。加载一个真实的图像。使用cvsplit()将图像分割成红,绿,蓝三个单通道图像。 a.找到并显示绿图。 b.克隆这个绿图两次(分别命名为clone1和clone2)。 c.求出这个绿色平面的最大值和最小值。 d.将clone1的所有元素赋值为theash=(unsigned char)((最大值-最小值)/2.0)。 e.将clone

《学习OpenCV》课后习题解答5

题目:(P104) 为一个图像创建多个图像头。读取一个大小至少为100*100的图像。另创建两个图像头并设置它们的origion,depth,nChannels和widthStep属性同之前读取的图像一样。在新的图像头中,设置宽度为20,高度为30.最后,将imageData指针分别指向像素(5,10)和(50,60)像素位置。传递这两个新的图像头给cvNot()。最后显示最初读取的图像,在那个

《学习OpenCV》课后习题解答3

题目:(P104) 创建一个大小为100*100的三通道RGB图像。将它的元素全部置0.使用指针算法以(20,5)与(40,20)为项点绘制一个绿色平面。 解答: #include "cv.h" #include "highgui.h" int main(int argc, char** argv) {IplImage* img = cvCreateImage(cvSize(100,

《学习OpenCV》课后习题解答2

题目:(P104) 创建一个拥有三个通道的二维字节类型矩阵,大小为100*100,并将所有值赋为0。通过函数cvPtr2D将指针指向中间的通道(“绿色”)。以(20,5)与(40,20)为顶点间画一个绿色的长方形。 解答: (此题的关键在于懂得函数cvPtr2D的用法) #include "cv.h" #include "highgui.h" int main(int argc, c

关于命令行参数argv(《学习OpenCV》)

在《学习OpenCV》这本书中,很多示例代码都用到了命令行参数。作为新手,之前总是很困扰,不知道怎么用。偶然的机会终于略知一二了。 在Visual Studio中,我们可以自行设置命令行参数。 如在这个示例程序中,我们想把图像存入argv[1]。 方法如下: 依次点击,项目、属性、配置属性、调试、命令参数。出现下面的界面: 然后进行编辑,即输入图像路径。如:E:\Lena.jpg

基于ZYNQ7000的交叉编译工具链Qt+OpenCV+ffmpeg等库支持总结

最近刚刚接触XILINX的ZYNQ板,刚接触没有十天。XILINX定位它为SOC,我也很认同,起码比TI定位MPU为SOC强很多。据说今年TI的最新产品也加入了ZYNQ板。 之前的MIPS处理器设计与实现的项目就算做告一段落,搞了将近7个月,成果显著,收获颇多,最近打算搞搞ZYNQ。 之前MIPS也有一套交叉编译工具,不过是老师提供的,自己也尝试搞了搞,太辛苦了,而且也没什么成果,因为我