在之前的文章中,我介绍了傅里叶变换,这次我将介绍另一种图像处理方法,边缘检测。在openCV中,有很多函数可以让我们找到图像的边缘,在这篇文章中,我将挑选出比较有代表性的Sobal算子和Laplacian算子进行介绍。边缘检测
以上图为例,我们可以看到黑白的分界线就是我们要找的边缘,也就是像素之间的急剧变化。拉普拉斯算子
原则
拉普拉斯算子使用对图像进行微分的方法来提取边缘。具体推导方法如下。以与正面相似的图片为例,取其中一条横线,加以区分。可以看出,在边缘的交界处,经过微分后,会出现一个明显的峰值。我们可以设置一个阈值,这样如果微分后的图像超过这个阈值,就会判断为边缘,进行后续处理。但是这种方法不够严谨,所以也可以对图像进行两次微分。而二阶导数结果中的Z点,也就是“过零”,就是我们要找的边。在了解了基本原理之后,我们需要从数学上推导出 Laplacian 所需的掩码应该是什么样子。从上面的介绍可以看出,最重要的部分就是对图像进行区分,但其实这在图像中并不难,只要从下一个网格的像素中减去上一个网格的像素,即可以得到斜率,它是一阶导数。在知道如何推导一阶微分之后,同样可以推导出二阶微分。在这里,我们将跳过推导过程,直接查看结果。实施
我们可以使用 openCV 中提供的拉普拉斯运算函数:dst = cv2.Laplacian(src, ddepth, ksize)
ddepth :图像的深度。有许多标志可以使用。最常用的是cv2.CV_8U和cv2.CV_16S。示例程序
具体代码可以在 github 上查看:https://github.com/jeffrey0524/AAA/tree/main/article05import cv2
def main():
# read image
gray_img = cv2.imread('./lenna.jpg', 0)
cv2.imshow('img',gray_img)
# Try masks of different sizes
for n in range(1, 4):
# 使用拉普拉斯算子
kernel_size = 1+(n*2)
gray_lap = cv2.Laplacian(gray_img, cv2.CV_16S, ksize=kernel_size)
# Convert image format to uint8
abs_lap = cv2.convertScaleAbs(gray_lap)
# display image
cv2.imshow(f'{1+n*2}_lap_img',abs_lap)
cv2.waitKey(0)
cv2.destroyAllWindows()
# save image
cv2.imwrite(f'./result/Laplacian/Laplacian_{1+n*2}.png',abs_lap)
if __name__ == '__main__':
main()
Sobal 算子
原则
下图是 Sobal 算子使用的掩码。左边是水平方向的边缘检测,右边是垂直方向的边缘检测。实施
就像拉普拉斯算子一样,openCV 也提供了书面的 Sobal 函数。dst = cv2.Sobel(src, ddepth, dx, dy, ksize)
ddepth :图像的深度。有许多标志可以使用。最常用的是cv2.CV_8U和cv2.CV_16S。dx, dy :选择要在水平或垂直方向进行的操作,选择1, 0/0, 1。在Sobal操作之后,convertScaleAbs
通常会执行一个操作,将图像转换回可以正常显示的格式。dst = cv2.convertScaleAbs(src)
示例程序
具体代码可以在我的 github 上查看:https://github.com/jeffrey0524/AAA/tree/main/article05import cv2
def main():
# read image
gray_img = cv2.imread('./lenna.jpg', 0)
cv2.imshow('img',gray_img)
# Try masks of different sizes
for n in range(1, 4):
# 使用 sobel 算子
kernel_size = 1+(n*2)
x = cv2.Sobel(gray_img, cv2.CV_16S, 1, 0, ksize=kernel_size)
y = cv2.Sobel(gray_img, cv2.CV_16S, 0, 1, ksize=kernel_size)
# Convert image format to uint8
absX = cv2.convertScaleAbs(x)
absY = cv2.convertScaleAbs(y)
# Add the results from both directions to form a complete contour
dst = cv2.addWeighted(absX, 0.5, absY,0.5,0)
# display image
cv2.imshow(f'{1+n*2}_x',absX)
cv2.imshow(f'{1+n*2}_y',absY)
cv2.imshow(f'{1+n*2}_x+y',dst)
cv2.waitKey(0)
cv2.destroyAllWindows()
# save image
cv2.imwrite(f'./result/Sobal/Sobal_{1+n*2}_x.png',absX)
cv2.imwrite(f'./result/Sobal/Sobal_{1+n*2}_y.png',absY)
cv2.imwrite(f'./result/Sobal/Sobal_{1+n*2}_x+y.png',dst)
if __name__ == '__main__':
main()
参考
https://en.wikipedia.org/wiki/Sobel_operatorhttps://www.youtube.com/watch?v=usBg5zbD2wUhttps://www.youtube.com/watch?v=RSDcvDFXei4)https://www.youtube.com/watch?v=yHah3EbKwOIhttps://medium.com/%E9%9B%BB%E8%85%A6%E8%A6%96%E8%A6%BA/%E9%82%8A%E7%B7%A3%E5%81%B5%E6%B8%AC-%E7%B4%A2%E4%BC%AF%E7%AE%97%E5%AD%90-sobel-operator-95ca51c8d78ahttps://medium.com/%E9%9B%BB%E8%85%A6%E8%A6%96%E8%A6%BA/%E9%82%8A%E7%B7%A3%E5%81%B5%E6%B8%AC-%E6%8B%89%E6%99%AE%E6%8B%89%E6%96%AF%E7%AE%97%E5%AD%90-laplacian-operator-ea877f1945a0
本站仅提供存储服务,所有内容均由用户发布,如发现有害或侵权内容,请
点击举报。