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) 

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

相关推荐
顾道长生'17 分钟前
(Arxiv-2025)通过动态 token 剔除实现无需训练的高效视频生成
计算机视觉·音视频·视频生成
麻雀无能为力3 小时前
CAU数据挖掘实验 表分析数据插件
人工智能·数据挖掘·中国农业大学
时序之心3 小时前
时空数据挖掘五大革新方向详解篇!
人工智能·数据挖掘·论文·时间序列
.30-06Springfield3 小时前
人工智能概念之七:集成学习思想(Bagging、Boosting、Stacking)
人工智能·算法·机器学习·集成学习
说私域4 小时前
基于开源AI智能名片链动2+1模式S2B2C商城小程序的超级文化符号构建路径研究
人工智能·小程序·开源
永洪科技4 小时前
永洪科技荣获商业智能品牌影响力奖,全力打造”AI+决策”引擎
大数据·人工智能·科技·数据分析·数据可视化·bi
shangyingying_14 小时前
关于小波降噪、小波增强、小波去雾的原理区分
人工智能·深度学习·计算机视觉
书玮嘎6 小时前
【WIP】【VLA&VLM——InternVL系列】
人工智能·深度学习
猫头虎6 小时前
猫头虎 AI工具分享:一个网页抓取、结构化数据提取、网页爬取、浏览器自动化操作工具:Hyperbrowser MCP
运维·人工智能·gpt·开源·自动化·文心一言·ai编程
要努力啊啊啊6 小时前
YOLOv2 正负样本分配机制详解
人工智能·深度学习·yolo·计算机视觉·目标跟踪