当前位置: 首页 » 资讯 » 行业资讯 » 正文

数字图像处理:边缘检测

分享到:
放大字体  缩小字体    发布日期:2022-11-17  来源:WKW |  浏览次数:738
核心提示:
序言

在之前的文章中,我介绍了傅里叶变换,这次我将介绍另一种图像处理方法,边缘检测。在openCV中,有很多函数可以让我们找到图像的边缘,在这篇文章中,我将挑选出比较有代表性的Sobal算子Laplacian算子进行介绍。

边缘检测

既然我们要检测边缘,首先我们需要了解边缘是什么。

最简单的边缘

以上图为例,我们可以看到黑白的分界线就是我们要找的边缘,也就是像素之间的急剧变化。

拉普拉斯算子

原则拉普拉斯算子使用对图像进行微分的方法来提取边缘。具体推导方法如下。

以与正面相似的图片为例,取其中一条横线,加以区分。

可以看出,在边缘的交界处,经过微分后,会出现一个明显的峰值。我们可以设置一个阈值,这样如果微分后的图像超过这个阈值,就会判断为边缘,进行后续处理。

但是这种方法不够严谨,所以也可以对图像进行两次微分。而二阶导数结果中的Z点,也就是“过零”,就是我们要找的边。

在了解了基本原理之后,我们需要从数学上推导出 Laplacian 所需的掩码应该是什么样子。从上面的介绍可以看出,最重要的部分就是对图像进行区分,但其实这在图像中并不难,只要从下一个网格的像素中减去上一个网格的像素,即可以得到斜率,它是一阶导数。

数学表达式

在知道如何推导一阶微分之后,同样可以推导出二阶微分。在这里,我们将跳过推导过程,直接查看结果。

二阶微分的数学公式

至此,我们得到了我们需要的拉普拉斯掩码。

拉普拉斯算子掩码

实施

我们可以使用 openCV 中提供的拉普拉斯运算函数:

dst = cv2.Laplacian(src, ddepth, ksize)

src :要处理的图像。

dst :输出图像。

ddepth :图像的深度。有许多标志可以使用。最常用的是cv2.CV_8U和cv2.CV_16S。

ksize :掩码的大小。

import 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, ksizekernel_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)

src :要处理的图像。

dst :输出图像。

ddepth :图像的深度。有许多标志可以使用。最常用的是cv2.CV_8U和cv2.CV_16S。

dx, dy :选择要在水平或垂直方向进行的操作,选择1, 0/0, 1。

ksize :掩码的大小。

在Sobal操作之后,convertScaleAbs通常会执行一个操作,将图像转换回可以正常显示的格式。

dst = cv2.convertScaleAbs(src)

示例程序

import 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()

输入

结果(内核大小 = 3)

结果(内核大小 = 5)

结果(内核大小 = 7)

参考

image.png


       原文标题 : 数字图像处理:边缘检测

 
 
打赏
[ 资讯搜索 ]  [ 加入收藏 ]  [ 告诉好友 ]  [ 打印本文 ]  [ 违规举报 ]  [ 关闭窗口 ]

免责声明:
本网站部分内容来源于合作媒体、企业机构、网友提供和互联网的公开资料等,仅供参考。本网站对站内所有资讯的内容、观点保持中立,不对内容的准确性、可靠性或完整性提供任何保证,亦不承担任何法律责任。如果有侵权等问题,请及时联系网站客服,我们将在收到通知后第一时间删除相关内容。
 

数字图像处理:边缘检测二维码

扫扫二维码用手机关注本条新闻报道也可关注本站官方微信账号:"xxxxx",每日获得互联网最前沿资讯,热点产品深度分析!
 

 
0相关评论