Python OpenCV Sobel 算子、Scharr 算子、laplacian 算子 复盘学习

举报
梦想橡皮擦 发表于 2021/09/23 13:32:52 2021/09/23
【摘要】 Python OpenCV 365 天学习计划,与橡皮擦一起进入图像领域吧。本篇博客是这个系列的第 46 篇。 基础知识铺垫关于 Sobel 算子、Scharr 算子、laplacian 算子在 这篇博客 中已经学习过了,第二次学习,可以针对算子卷积核进行一下稍微深入一点的理解。 Sobel 算子使用该函数时,卷积核在 X 方向为: [−10+1−20+2−10+1]\begin{bmatr...

Python OpenCV 365 天学习计划,与橡皮擦一起进入图像领域吧。本篇博客是这个系列的第 46 篇。

基础知识铺垫

关于 Sobel 算子、Scharr 算子、laplacian 算子在 这篇博客 中已经学习过了,第二次学习,可以针对算子卷积核进行一下稍微深入一点的理解。

Sobel 算子

使用该函数时,卷积核在 X 方向为: [ 1 0 + 1 2 0 + 2 1 0 + 1 ] \begin{bmatrix} -1&0&+1\\ -2&0&+2\\-1&0&+1 \end{bmatrix} ,在 Y 方向为 [ 1 2 1 0 0 0 + 1 + 2 + 1 ] \begin{bmatrix} -1&-2&-1\\ 0&0&0\\+1&+2&+1 \end{bmatrix}

上述卷积核时一个 3x3 的矩阵,当其与一个图像进行卷积计算的时候,如果覆盖的矩阵是 [ p 1 p 2 p 3 p 4 p 5 p 6 p 7 p 8 p 9 ] \begin{bmatrix} p_1&p_2&p_3\\ p_4&p_5&p_6\\p_7&p_8&p_9 \end{bmatrix}

计算之后会得到如下结果 p 3 p 1 + p 6 p 4 + p 9 p 7 p_3-p_1+p_6-p_4+p_9-p_7 ,结果越大,差异越明显,还有为什么在 p 4 p_4 p 6 p_6 点,卷积核的值大,简单理解就是这个点距离中心点近。

先写一段测试代码如下:

import cv2 as cv
import numpy as np


src = cv.imread('./star.png')

gray = cv.cvtColor(src, cv.COLOR_BGR2GRAY)

ret, thresh = cv.threshold(gray, 127, 255, cv.THRESH_BINARY_INV)

# Sobel 算子计算边缘
sobel_x = cv.Sobel(thresh, -1, 1, 0, ksize=3)

image = np.hstack((gray, thresh, sobel_x))
cv.imshow("image", image)
cv.waitKey()

运行结果如下:

最后一幅图片获取到的是图形的左侧,原因是这样导致的。
Sobel 在计算的是时候是右侧减左侧下面减上面,查看二值化图形会发现,右侧减左侧会得到左侧边缘的原因是,图形左侧的边缘两边,右侧是白色 255,左侧是黑色 0,所以可以得到边缘,相同的方式,在图形右侧边缘部分,两边分别是右侧黑色、左侧白色,所以边缘缺失。

如果希望右侧边缘也同时出现,需要用到下述函数,将得到的负值获取绝对值。

另一处代码修改的地方在代码注释部分:

# Sobel 算子计算边缘
# 注意计算 sobel_x 的函数传递参数的时候,第二个参数从 -1 修改为 cv.CV_64F,目的是为了获取到负值,方便后面的获取绝对值操作。
sobel_x = cv.Sobel(thresh, cv.CV_64F, 1, 0, ksize=3)
sobel_x = cv.convertScaleAbs(sobel_x)
image = np.hstack((gray, thresh, sobel_x))

上述代码计算的是 X 方向的边缘,同理计算一下 Y 方向的边缘,在合并 X 与 Y 方向的边缘,即可得到最后的图像边缘。

import cv2 as cv
import numpy as np


src = cv.imread('./star.png')

gray = cv.cvtColor(src, cv.COLOR_BGR2GRAY)

ret, thresh = cv.threshold(gray, 127, 255, cv.THRESH_BINARY_INV)

# Sobel 算子计算边缘
sobel_x = cv.Sobel(thresh, cv.CV_64F, 1, 0, ksize=3)
sobel_y = cv.Sobel(thresh, cv.CV_64F, 0, 1, ksize=3)
sobel_x = cv.convertScaleAbs(sobel_x)
sobel_y = cv.convertScaleAbs(sobel_y)
sobel_xy = cv.addWeighted(sobel_x, 0.5, sobel_y, 0.5, 0)
image = np.hstack((gray, sobel_xy, sobel_x, sobel_y))
cv.imshow("image", image)
cv.waitKey()

合并之后运行结果如下,一般不建议直接计算 X 和 Y 方向的 Sobel,而应该分别计算之后再进行合并。

可以对比一下分开计算再合并与直接计算的效果差异。

上述图片是由下面的代码运行得到的结果

import cv2 as cv
import numpy as np


src = cv.imread('./t3.jpg')

gray = cv.cvtColor(src, cv.COLOR_BGR2GRAY)

ret, thresh = cv.threshold(gray, 127, 255, cv.THRESH_BINARY_INV)

# Sobel 算子分开计算
sobel_x = cv.Sobel(thresh, cv.CV_64F, 1, 0, ksize=3)
sobel_y = cv.Sobel(thresh, cv.CV_64F, 0, 1, ksize=3)
sobel_x = cv.convertScaleAbs(sobel_x)
sobel_y = cv.convertScaleAbs(sobel_y)
sobel_xy = cv.addWeighted(sobel_x, 0.5, sobel_y, 0.5, 0)

# 直接计算
sobel_xy1 = cv.Sobel(thresh, cv.CV_64F, 1, 1, ksize=3)
sobel_xy1 = cv.convertScaleAbs(sobel_xy1)
image = np.hstack((gray, sobel_xy, sobel_xy1))
cv.imshow("image", image)
cv.waitKey(0)

Scharr 算子

该算子有着比 Sobel 更好的精确度,主要因为它的卷积核是下面的数据

G x = [ 3 0 + 3 10 0 + 10 3 0 + 3 ] G_x =\begin{bmatrix}-3&0&+3\\ -10&0&+10\\-3&0&+3 \end{bmatrix}

G y = [ 3 10 3 0 0 0 3 10 3 ] G_y =\begin{bmatrix}-3&-10&-3\\ 0&0&0\\-3&-10&-3 \end{bmatrix}

使用的时候依旧是分开计算

import cv2 as cv
import numpy as np


src = cv.imread('./t3.jpg')

gray = cv.cvtColor(src, cv.COLOR_BGR2GRAY)

ret, thresh = cv.threshold(gray, 127, 255, cv.THRESH_BINARY_INV)

# Scharr 算子分开计算
scharr_x = cv.Scharr(thresh, cv.CV_64F, 1, 0)
scharr_y = cv.Scharr(thresh, cv.CV_64F, 0, 1)
scharr_x = cv.convertScaleAbs(scharr_x)
scharr_y = cv.convertScaleAbs(scharr_y)
scharr_xy = cv.addWeighted(scharr_x, 0.5, scharr_y, 0.5, 0)


image = np.hstack((gray, scharr_xy))
cv.imshow("image", image)
cv.waitKey(0)

laplacian 算子

概算子的卷积核如下:

G = [ 0 1 0 1 4 1 0 1 0 ] G =\begin{bmatrix}0&1&0\\ 1&-4&1\\0&1&0 \end{bmatrix}

laplacian 算子噪点敏感,在使用的时候需要提前去噪。

橡皮擦的小节

希望今天的 1 个小时你有所收获,我们下篇博客见~

相关阅读


技术专栏

  1. Python 爬虫 100 例教程,超棒的爬虫教程,立即订阅吧
  2. Python 爬虫小课,精彩 9 讲

今天是持续写作的第 88 / 100 天。
如果你想跟博主建立亲密关系,可以关注同名公众号 梦想橡皮擦,近距离接触一个逗趣的互联网高级网虫。
博主 ID:梦想橡皮擦,希望大家点赞评论收藏

【版权声明】本文为华为云社区用户原创内容,未经允许不得转载,如需转载请自行联系原作者进行授权。如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@huaweicloud.com
  • 点赞
  • 收藏
  • 关注作者

评论(0

0/1000
抱歉,系统识别当前为高风险访问,暂不支持该操作

全部回复

上滑加载中

设置昵称

在此一键设置昵称,即可参与社区互动!

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。