写点什么

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

发布于: 3 小时前

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

基础知识铺垫

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

Sobel 算子

使用该函数时,卷积核在 X 方向为: ,在 Y 方向为


上述卷积核时一个 3x3 的矩阵,当其与一个图像进行卷积计算的时候,如果覆盖的矩阵是


计算之后会得到如下结果 ,结果越大,差异越明显,还有为什么在 点,卷积核的值大,简单理解就是这个点距离中心点近。


先写一段测试代码如下:


import cv2 as cvimport 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 cvimport 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 cvimport 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 更好的精确度,主要因为它的卷积核是下面的数据




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


import cv2 as cvimport 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 算子

概算子的卷积核如下:



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

橡皮擦的小节

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


发布于: 3 小时前阅读数: 3
用户头像

爬虫 100 例作者,蓝桥签约作者,博客专家 2021.02.06 加入

6 年产品经理+教学经验,3 年互联网项目管理经验; 互联网资深爱好者; 沉迷各种技术无法自拔,导致年龄被困在 25 岁; CSDN 爬虫 100 例作者。 个人公众号“梦想橡皮擦”。

评论

发布
暂无评论
Python OpenCV Sobel 算子、Scharr 算子、laplacian 算子 复盘学习