OpenCV-Python图像处理学习笔记(四)——形态学操作、图像梯度

本篇学习笔记主要内容在图像的形态学操作,图像梯度内容。

获取更多可以查看本栏目其他文章。

  往期内容:

OpenCV-Python图像处理学习笔记(一)——认识、安装、环境测试

OpenCV-Python图像处理学习笔记(二)——图像/视频读取保存、分割及边界填充

OpenCV-Python图像处理学习笔记(三)——数值运算、图像阈值、图像平滑(滤波)

OpenCV-Python图像处理学习笔记(四)——形态学操作、图像梯度
OpenCV-Python图像处理学习笔记(五)——Canny 边缘检测、图像金字塔、轮廓检测(一)

OpenCV-Python图像处理学习笔记(六)——轮廓检测(二)、模板匹配
OpenCV-Python图像处理学习笔记(七)——直方图、图像变换

目录

1  形态学操作

1.1  腐蚀

 1.2  膨胀

 1.3  开运算

 1.4  闭运算

1.5  梯度计算

 1.6  礼帽与黑帽

 1.7  形态学操作之间的关系

 2  图像梯度

2.1  Sobel算子

2.2  Scharr算子

2.3  Laplacian算子

2.4  梯度计算方法

3  小结


导入必要Python包

import cv2
import numpy as np
import matplotlib.pyplot as plt

1  形态学操作

形态学操作是根据图像形状进行的简单操作。一般情况下对二值化图像进行的操作。两个基本的形态学操作是腐蚀和膨胀。他们的变体构成了开运算,闭运算,梯度等。

1.1  腐蚀

就像土壤侵蚀一样,这个操作会把图像边界腐蚀掉。具体操作是卷积核沿着图像滑动,如果与卷积核对应的原图像的所有像素值都是 1,那么中心元素就保持原来的像素值,否则就变为零。

img = cv2.imread('j.png', 0)
kernel = np.ones((5,5))
erosion = cv2.erode(img, kernel, iterations=1)  # 参数iterations表示腐蚀效果,数值越大腐蚀逐渐增强

 经过上述代码执行后,下列左侧图将会变为右侧图:

 1.2  膨胀

膨胀和腐蚀像是反方向的操作,与卷积核对应的原图像的像素值中只要有一个是1,中心元素的像素值就是 1。所以这个操作会增加图像中的白色区域(前景)。一般在去噪声时先用腐蚀再用膨胀。因为腐蚀在去掉白噪声的同时,也会使前景对象变小。所以我们再对他进行膨胀。这时噪声已经被去除了,不会再回来了,但是前景还在并会增加。膨胀也可以用来连接两个分开的物体。

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

 上述代码执行完后,原图像将变成下图效果:

 1.3  开运算

先进性腐蚀再进行膨胀就叫做开运算。就像我们上面介绍的那样,它被用 来去除噪声。

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

cv2.MORPH_OPEN表示进行开运算。

 1.4  闭运算

先膨胀再腐蚀。它经常被用来填充前景物体中的小洞,或者前景物体上的 小黑点。

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

cv2.MORPH_CLOSE表示进行开运算。

1.5  梯度计算

梯度 = 膨胀 - 腐蚀

即得到结果类似图像的轮廓。

gradient = cv2.morphologyEx(img, cv2.MORPH_GRADIENT, kernel)

cv2.MORPH_GRADIENT表示进行开运算。

 1.6  礼帽与黑帽

  • 礼帽 = 原始图像 - 开运算输出图像
  • 黑帽 = 闭运算输出图像 - 原始图像
# 礼帽
tophat = cv2.morphologyEx(img, cv2.MORPH_TOPHAT, kernel)

# 黑帽
blackhat = cv2.morphologyEx(img, cv2.MORPH_BLACKHAT, kernel)
  • cv2.MORPH_TOPHAT表示进行礼帽。
  • cv2.MORPH_BLACKHAT表示进行黑帽。
礼帽
黑帽

 1.7  形态学操作之间的关系

  • 开运算:dst = open(src, element) = dilate(erode(src, element), element)
  • 闭运算:dst = close(src, element) = erode(dilate(src, element), element)
  • 梯度计算:dst = morph_grad(src, element) = dilate(src, element) - erode(src, element)
  • 礼帽:dst = tophat(src, element)=src - open(src, element)
  • 黑帽:dst = blackhat(src, element) =close(src, element) - src

 2  图像梯度

梯度简单来说就是求导。

OpenCV 提供了三种不同的梯度滤波器,或者说高通滤波器:Sobel, Scharr 和 Laplacian。

  • Sobel,Scharr 其实就是求一阶或二阶导数
  • Scharr 是对Sobel(使用小的卷积核求解求解梯度角度时)的优化
  • Laplacian 是求二阶导数

2.1  Sobel算子

Sobel算子是高斯平滑与微分操作的结合体,所以它的抗噪声能力很好。

3x3 的Sobel滤波器卷积核如下:

G_{x} = \left [ \begin{matrix} -1 & 0&1 \\ -2&0 &2 \\ -1&0 & 1 \end{matrix} \right ] \Leftrightarrow G_{y} = \left [ \begin{matrix} -1 & -2&-1 \\ 0&0 &0 \\ 1&2 & 1 \end{matrix} \right ]

右 - 左 或 上 - 下

img=cv2.imread('dave.jpg')

laplacian = cv2.Laplacian(img, cv2.CV_64F)

sobelx = cv2.Sobel(img, cv2.CV_64F, 1, 0, ksize=5)

sobely = cv2.Sobel(img, cv2.CV_64F, 0, 1, ksize=5)
  • cv2.CV_64F 输出图像的深度(数据类型),可以使用-1, 与原图像保持一致。一个从黑到白的边界 的导数是整数,而一个从白到黑的边界点导数却是负数。如果原图像的深度是 np.int8 时,所有的负值都会被截断变成 0,换句话说就是把把边界丢失掉。
  • 参数 1,0 为只在水平方向求一阶导数,最大可以求 2 阶导数。
  • 参数 0,1 为只在竖直方向求一阶导数,最大可以求 2 阶导数。
  • ksize是sobel算子大小。

根据上述方式计算的结果往往不尽人意,或者说图像不是完整的,那么可以通过下来方式,得到完整的梯度图像。

首先有一个原始图像如下:

 先在水平方向进行梯度计算,再在竖直方向进行计算,然后分别对它们结果进行abs求绝对值,此时再将两组结果进行加权求和。

img = cv2.imread('lena.jpg', cv2.IMREAD_GRAYSCALE)

sobelx = cv2.Sobel(img, cv2.CV_64F, 1, 0, ksize=3) 
sobelx = cv2.convertScaleAbs(sobelx)

sobely = cv2.Sobel(img, cv2.CV_64F, 0, 1, ksize=3) 
sobely=cv2.convertScaleAbs(sobely)

sobelxy = cv2.addWeighted(sobelx, 0.5, sobely, 0.5, 0) 

cv_show(sobelxy,' sobelky')

最终结果如下图:

2.2  Scharr算子

如果 ksize=-1,会使用 3x3 的 Scharr 滤波器,它的的效果要比3x3的Sobel滤波器好,而且速度相同,3x3 的Scharr滤波器卷积核如下:

G_{x} = \left [ \begin{matrix} -3 & 0&3 \\ -10&0 &10 \\ -3&0 & 3 \end{matrix} \right ] \Leftrightarrow G_{y} = \left [ \begin{matrix} -3 & -10&-3 \\ 0&0 &0 \\ 3&10 & 3 \end{matrix} \right ]

计算类似Sobel算子。

2.3  Laplacian算子

拉普拉斯算子可以使用二阶导数的形式定义,可假设其离散实现类似于二 阶Sobel导数,公式为:

\Delta src = \frac{\partial ^{2}src}{\partial x^{2}} + \frac{\partial ^{2}src}{\partial y^{2}}

拉普拉斯滤波器使用的卷积核:

G_{x} = \left [ \begin{matrix} 0 & 1&0 \\ 1&-4 &1 \\ 0&1 & 0 \end{matrix} \right ]

拉普拉斯算子一般情况对噪音点较为敏感,效果不是很好,通常会结合其他方法进行使用,不单独使用。

2.4  梯度计算方法

不同算子计算方法差异:

img = cv2.imread('lena.jpg', cv2.IMREAD_GRAYSCALE) 

sobelx = cv2.Sobel(img, cv2.CV_64F,1,0,ksize=3) 
sobely = cv2.Sobel(img, cv2.CV_64F,0,1,ksize=3) 
sobelx = cv2.convertScaleAbs(sobelx)
sobely = cv2.convertScaleAbs(sobely)
sobelxy = cv2.addWeighted(sobelx, 0.5, sobely, 0.5, 0) 

scharrx = cv2.Scharr(img, cv2.CV_64F, 1, 0)
scharry = cv2.Scharr(img, cv2.CV_64F, 0, 1) 
scharrx = cv2.convertScaleAbs(scharrx) 
scharry = cv2.convertScaleAbs(scharry)
scharrxy = cv2.addWeighted(scharrx, 0.5, scharry, 0.5, 0) 

laplacian =cv2.Laplacian(img, cv2.CV_64F)
laplacian = cv2.convertScaleAbs(laplacian) 

res = np.hstack((sobelxy, scharrxy, laplacian)) 
cv_show(res, 'res')

下图为上述三种算子的输出结果:

 不难看出,Scharr算子相对敏感,能够捕捉较为丰富的信息。

3  小结

下期将继续同步OpenCV边缘检测等内容。

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

熊仔阿大

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值