opencv 形态学变换

形态学变换

  • [1. 核](#1. 核)
  • 2.腐蚀(cv2.erode)
  • [3. 膨胀(cv2.dilate)](#3. 膨胀(cv2.dilate))
  • [4. 开运算(cv.MORPH_OPEN)](#4. 开运算(cv.MORPH_OPEN))
  • [5. 闭运算(cv2.MORPH_CLOSE)](#5. 闭运算(cv2.MORPH_CLOSE))
  • [6. 礼帽运算(找出增多的白色区域)](#6. 礼帽运算(找出增多的白色区域))
  • [7. 黑帽运算](#7. 黑帽运算)
  • [8. 形态学梯度](#8. 形态学梯度)

形态学变换(Morphological Transformations)是一种 基于形状的简单变换,它的处理对象通常是二值化图像 。形态学变换有两个输入,一个输出:输入为 原图像、核 (结构化元素),输出为形态学**变换后的图像。**其基本操作有腐蚀和膨胀,这两种操作是相反的,即较亮的像素会被腐蚀和膨胀。下面我们来说一下核、腐蚀与膨胀的概念。

1. 核

其实在上一章节自适应二值化中,我们已经接触过核了,还记得吗?就是那个在原图中不断滑动计算的3*3的小区域,那其实就是一个3*3的核。

核(kernel)其实就是一个小区域,通常为3*3、5*5、7*7大小,有着其自己的结构,比如矩形结构、椭圆结构、十字形结构,如下图所示。通过不同的结构可以对不同特征的图像进行形态学操作的处理。

2.腐蚀(cv2.erode)

腐蚀操作 就是使用核在原图(二值化图)上进行从左到右、从上到下的滑动(也就是从图像的左上角开始,滑动到图像的右下角)。在滑动过程中,令核值为1的区域与被核覆盖的对应区域进行相乘,得到其最小值,该最小值就是卷积核覆盖区域的中心像素点的新像素值 ,接着继续滑动。由于操作图像为二值图,所以不是黑就是白,这就意味着,在被核值为1覆盖的区域内,只要有黑色(像素值为0),那么该区域的中心像素点必定为黑色(0)。这样做的结果就是会将二值化图像中的白色部分尽可能的压缩,如下图所示,该图经过腐蚀之后,"变瘦"了。

腐蚀操作的详细流程

腐蚀原理的代码:

python 复制代码
 '''腐蚀操作------原理'''
    img=np.zeros((10,10),dtype=np.uint8)
    img[3:7,3:7]=255
    img[2,2]=10
    print(img)
    print("="*20)
    kernel=np.ones((3,3),dtype=np.uint8)#填充了一个全1的核
    img2=cv2.erode(img,kernel=kernel)#第一个填入一个二值图,
    print(img2)
    '''
     [  0   0  10   0   0   0   0   0   0   0]
 [  0   0   0 255 255 255 255   0   0   0]
 [  0   0   0 255 255 255 255   0   0   0]
 [  0   0   0 255 255 255 255   0   0   0]
 [  0   0   0 255 255 255 255   0   0   0]
 [  0   0   0   0   0   0   0   0   0   0]
 [  0   0   0   0   0   0   0   0   0   0]
 [  0   0   0   0   0   0   0   0   0   0]]
====================
[[  0   0   0   0   0   0   0   0   0   0]
 [  0   0   0   0   0   0   0   0   0   0]
 [  0   0   0   0   0   0   0   0   0   0]
 [  0   0   0   0   0   0   0   0   0   0]
 [  0   0   0   0 255 255   0   0   0   0]
 [  0   0   0   0 255 255   0   0   0   0]
 [  0   0   0   0   0   0   0   0   0   0]
 [  0   0   0   0   0   0   0   0   0   0]
 [  0   0   0   0   0   0   0   0   0   0]
 [  0   0   0   0   0   0   0   0   0   0]]
    '''

由上面代码可以知道腐蚀是以每个元素为中心做一个3*3的全1的核找到最小值填充到核的中心

腐蚀操作代码部分:

python 复制代码
 '''腐蚀操作'''
    img=cv2.imread(r'../15day4.10\src\long.png',cv2.IMREAD_GRAYSCALE)
    kernel=np.ones((3,3),dtype=np.uint8)#填充了一个全1的核
    img_erode=cv2.erode(img,kernel=kernel,iterations=2)#表示进行腐蚀两次
    cv2.imshow('img',img)
    cv2.imshow("img_erode",img_erode)
    cv2.waitKey(0)

注意:

  • 腐蚀的本质是输出将一个以一个像素点为中心的核的最小值,若是上图则是白色被腐蚀了(白色变少了)
  • 腐蚀可以去除图像中的白色噪点

3. 膨胀(cv2.dilate)

膨胀与腐蚀刚好相反,膨胀操作就是使用核在原图(二值化图)上进行从左到右、从上到下的滑动(也就是从图像的左上角开始,滑动到图像的右下角),在滑动过程中,令核值为1的区域与被核覆盖的对应区域进行相乘,得到其最大值 ,该最大值就是核覆盖区域的中心像素点的新像素值,接着继续滑动。由于操作图像为二值图,所以不是黑就是白,这就意味着,在卷积核覆盖的区域内,只要有白色(像素值为255),那么该区域的中心像素点必定为白色(255)。这样做的结果就是会将二值化图像中的白色部分尽可能的扩张,如下图所示,该图经过膨胀之后,"变胖"了。

膨胀的详细操作

膨胀原理代码:

python 复制代码
 '''膨胀操作------原理'''
    img=np.zeros((10,10),dtype=np.uint8)
    img[3:7,3:7]=255
    img[2,2]=10
    img[2,4]=100
    print(img)
    print("="*20)
    kernel=np.ones((3,3),dtype=np.uint8)#填充了一个全1的核
    img2=cv2.dilate(img,kernel=kernel)#第一个填入一个二值图,
    print(img2)
    '''
    [[  0   0   0   0   0   0   0   0   0   0]
 [  0   0   0   0   0   0   0   0   0   0]
 [  0   0  10   0 100   0   0   0   0   0]
 [  0   0   0 255 255 255 255   0   0   0]
 [  0   0   0 255 255 255 255   0   0   0]
 [  0   0   0 255 255 255 255   0   0   0]
 [  0   0   0 255 255 255 255   0   0   0]
 [  0   0   0   0   0   0   0   0   0   0]
 [  0   0   0   0   0   0   0   0   0   0]
 [  0   0   0   0   0   0   0   0   0   0]]
====================
[[  0   0   0   0   0   0   0   0   0   0]
 [  0  10  10 100 100 100   0   0   0   0]
 [  0  10 255 255 255 255 255 255   0   0]
 [  0  10 255 255 255 255 255 255   0   0]
 [  0   0 255 255 255 255 255 255   0   0]
 [  0   0 255 255 255 255 255 255   0   0]
 [  0   0 255 255 255 255 255 255   0   0]
 [  0   0 255 255 255 255 255 255   0   0]
 [  0   0   0   0   0   0   0   0   0   0]
 [  0   0   0   0   0   0   0   0   0   0]]
    '''

由上面代码可以知道腐蚀是以每个元素为中心做一个3*3的全1的核找到最大值填充到核的中心

膨胀的操作的代码:

python 复制代码
'''膨胀操作'''
    img=cv2.imread(r'../15day4.10\src\long.png',cv2.IMREAD_GRAYSCALE)
    kernel=np.ones((3,3),dtype=np.uint8)
    img_dilate=cv2.dilate(img,kernel=kernel,iterations=3)
    cv2.imshow('img',img)
    cv2.imshow("img_dilate",img_dilate)
    cv2.waitKey(0)


注意:

  • 膨胀的本质是输出将一个以一个像素点为中心的核的最大值,若是上图则是白色扩大了
  • 膨胀可以去除图像中的黑色噪点

4. 开运算(cv.MORPH_OPEN)

开运算是先腐蚀后膨胀 ,其作用 是:分离物体,消除小区域。特点 :消除噪点,去除小的干扰块,而不影响原来的图像

代码如下:

python 复制代码
 '''开运算:先腐蚀后膨胀'''
    img=cv2.imread(r'../15day4.10\src\open.png',cv2.IMREAD_GRAYSCALE)
    kernel=np.ones((3,3),dtype=np.uint8)
    img_open=cv2.morphologyEx(img,cv2.MORPH_OPEN,kernel=kernel)
    cv2.imshow('img',img)
    cv2.imshow("img_open",img_open)
    cv2.waitKey(0)

5. 闭运算(cv2.MORPH_CLOSE)

闭运算与开运算相反,是先膨胀后腐蚀作用 是消除/"闭合"物体里面的孔洞,特点:可以填充闭合区域

代码如下:

python 复制代码
'''闭运算:先膨胀后腐蚀'''
    img=cv2.imread(r'../15day4.10\src\car.png',cv2.IMREAD_GRAYSCALE)
    kernel=np.ones((3,3),dtype=np.uint8)
    img_close=cv2.morphologyEx(img,cv2.MORPH_CLOSE,kernel=kernel)
    cv2.imshow('img',img)
    cv2.imshow("img_close",img_close)
    cv2.waitKey(0)    

6. 礼帽运算(找出增多的白色区域)

cv2.MORPH_TOPHAT

原图像与"开运算"的结果图之差,因为开运算带来的结果是放大了裂缝或者局部低亮度的区域,因此,从原图中减去开运算后的图,得到的效果图突出了比原图轮廓周围的区域更明亮的区域,且这一操作和选择的核的大小相关。

礼帽运算用来分离比邻近点亮一些的斑块。当一幅图像具有大幅的背景的时候,而微小物品比较有规律的情况下,可以使用礼帽运算进行背景提取(找到原图中的白色噪点

代码如下:

python 复制代码
'''礼帽运算'''   
    img=cv2.imread(r'../15day4.10\src\open.png',cv2.IMREAD_GRAYSCALE)
    kernel=np.ones((5,5),np.uint8)
    img2=cv2.morphologyEx(img,cv2.MORPH_TOPHAT,kernel=kernel)
    cv2.imshow('img',img)
    cv2.imshow('img2',img2)
    cv2.waitKey(0) 

7. 黑帽运算

cv2.MORPH_BLACKHAT

黑帽运算为"闭运算"的结果图与原图像之差,

黑帽运算后的效果图突出了比原图轮廓周围的区域更暗的区域,且这一操作和选择的核的大小相关。

黑帽运算用来分离比邻近点暗一些的斑块

代码如下:

python 复制代码
'''黑帽运算'''
    img=cv2.imread(r'../15day4.10\src\car.png',cv2.IMREAD_GRAYSCALE)
    kernel=np.ones((3,3),np.uint8)
    img2=cv2.morphologyEx(img,cv2.MORPH_BLACKHAT,kernel=kernel)
    cv2.imshow('img',img)
    cv2.imshow('img2',img2)
    cv2.waitKey(0) 

8. 形态学梯度

cv2.MORPH_GRADIENT

形态学梯度是一个基于结构元素的图像处理方法,它通过比较原图像与膨胀图和腐蚀图之间的差异来突出图像边缘特征。具体来说,对于图像中的每个像素点,其形态学梯度值是该像素点在膨胀后的图像值与其在腐蚀后的图像值之差 。这样得到的结果通常能够强化图像的边缘信息,并且对噪声有一定的抑制作用

代码如下:

python 复制代码
  '''形态学梯度'''   
    img=cv2.imread(r'../15day4.10\src\car.png',cv2.IMREAD_GRAYSCALE)
    kernel=np.ones((3,3),np.uint8)
    img2=cv2.morphologyEx(img,cv2.MORPH_GRADIENT,kernel=kernel) #gradient
    cv2.imshow('img',img)
    cv2.imshow('img2',img2)
    cv2.waitKey(0) 

形态学梯度是图像膨胀后与腐蚀后的差值,这样可以得到原图像的轮廓

相关推荐
文心快码BaiduComate18 小时前
百度云与光本位签署战略合作:用AI Agent 重构芯片研发流程
前端·人工智能·架构
风象南18 小时前
Claude Code这个隐藏技能,让我告别PPT焦虑
人工智能·后端
Mintopia19 小时前
OpenClaw 对软件行业产生的影响
人工智能
陈广亮20 小时前
构建具有长期记忆的 AI Agent:从设计模式到生产实践
人工智能
会写代码的柯基犬20 小时前
DeepSeek vs Kimi vs Qwen —— AI 生成俄罗斯方块代码效果横评
人工智能·llm
Mintopia20 小时前
OpenClaw 是什么?为什么节后热度如此之高?
人工智能
爱可生开源社区21 小时前
DBA 的未来?八位行业先锋的年度圆桌讨论
人工智能·dba
叁两1 天前
用opencode打造全自动公众号写作流水线,AI 代笔太香了!
前端·人工智能·agent
前端付豪1 天前
LangChain记忆:通过Memory记住上次的对话细节
人工智能·python·langchain