尧图建网站 尧图建网站 YAOTU WEB BUILD 免费咨询
ARTICLE DETAIL

资讯详情

深耕网站建设与建站编程的一线实战洞察。

初学opencv3

初学opencv3 一.边缘检测边缘检测的作用是寻找图像中像素灰度发生“剧烈跳变”的像素点集合将这些点连成线即构成边缘。1.sobel算子通过一个 3x3 或者其它的卷积核分别计算图像在水平方向和垂直方向上的灰度变化率梯度从而锁定亮度骤变的位置。Sobel 算子拥有两个专属的 3x3 卷积核一个负责检测水平边缘Gx一个负责检测垂直边缘Gy。a.水平梯度核Gx检测垂直边缘对水平方向的变化敏感图像中的垂直竖线会在此核下产生极值。Gx [ -1 0 1 ] [ -2 0 2 ] [ -1 0 1 ]b.垂直梯度核Gy检测水平边缘对垂直方向的变化敏感图像中的水平横线会在此核下产生极值。Gy [ -1 -2 -1 ] [ 0 0 0 ] [ 1 2 1 ]在实际计算中分别用 Gx 和 Gy 与图像进行卷积得到水平方向梯度图 Gx 和垂直方向梯度图 Gy。最终的边缘强度和方向可以通过以下公式计算梯度幅值G √(Gx² Gy²) 或近似为 G |Gx| |Gy|梯度方向θ arctan(Gy / Gx)优缺点优点计算简单、效率极高对灰度渐变和噪声较多的图像处理效果较好因为带有平滑作用。缺点由于只使用了有限的3×3 窗口且只用了水平和垂直两个方向它对斜向边缘的检测精度不高定位精度不如Laplacian拉普拉斯或Canny坎尼算法。检测出的边缘通常较粗。c.代码示例cv2.Sobel(src, ddepth, dx, dy, ksize, scale, delta, borderType)参数说明src输入图像。ddepth输出图像的深度可以理解为数据类型-1 表示与原图像相同的深度。dx, dy当组合为 dx1, dy0 时求 x 方向的一阶导数当组合为 dx0, dy1 时求 y 方向的一阶导数如果同时为 1通常效果不佳。ksize可选参数Sobel 算子的大小必须是 1、3、5 或者 7默认为 3。导入cv2包读入原始图像import cv2 yuan cv2.imread(yuan.png) cv2.imshow(yuan,yuan) cv2.waitKey(0)使用sobel算子检测x方向上的边缘。yuan_x cv2.Sobel(yuan,-1,dx1,dy0) # 数据类型为uint8所以右侧负数信息保存不了 cv2.imshow(yuan_x,yuan_x) cv2.waitKey(0)通过结果图看到只有左侧有边缘右侧纯黑这是因为在cv2.sobel函数里默认数据类型为uint8只能存正数不能存负数。根据梯度核的特点和原图像卷积后右侧边缘为负值。这时把数据类型转为float64再取绝对值就行。因为负值也显示不出来。yuan_x_64 cv2.Sobel(yuan,cv2.CV_64F,dx1,dy0) # 默认uint8改为float64可保存负数 cv2.imshow(yuan_x_64,yuan_x_64) cv2.waitKey(0) # #x方向上的边缘,包括负数信息,进行取绝对值的操作右端的负值信息就可以显示出来了 yuan_x_full cv2.convertScaleAbs(yuan_x_64) # 转换为绝对值负数转换为正数 cv2.imshow(yuan_x_full,yuan_x_full) cv2.waitKey(0)同理使用sobel算子检测y方向上的边缘,使用cv2.CV_64F保存信息再使用cv2.convertScaleAbs对信息进行取绝对值。yuan_y_64 cv2.Sobel(yuan,cv2.CV_64F,dx0,dy1) # 默认uint8改为float64可保存负数 cv2.imshow(yuan_y_64,yuan_y_64) cv2.waitKey(0) yuan_y_full cv2.convertScaleAbs(yuan_y_64) # 转换为绝对值负数转换为正数 cv2.imshow(yuan_y_full,yuan_y_full) cv2.waitKey(0)y方向的边缘使用图像加权运算组合x和y方向的2个边缘。cv2.addweighted函数yuan_xy_full cv2.addWeighted(yuan_x_full,1,yuan_y_full,1,0) cv2.imshow(yuan_xy_full,yuan_xy_full) cv2.waitKey(0) cv2.destroyAllWindows()最终效果图二.Scharr算子Scharr 算子是 Sobel 算子的改进版本它使用更大的权重系数来增强对边缘的敏感度能够更准确地检测图像中的边缘尤其适用于对边缘定位精度要求较高的场景。Scharr 算子同样拥有两个 3x3 卷积核一个负责检测水平边缘Gx一个负责检测垂直边缘Gy。Gx [ -3 0 3 ] [ -10 0 10] [ -3 0 3 ] Gy [ -3 -10 -3 ] [ 0 0 0 ] [ 3 10 3 ]cv2.Scharr(src, ddepth, dx, dy, scale, delta, borderType)参数说明src输入图像。ddepth输出图像的深度可以理解为数据类型-1 表示与原图像相同的深度。dx, dy当组合为 dx1, dy0 时求 x 方向的一阶导数当组合为 dx0, dy1 时求 y 方向的一阶导数如果同时为 1通常效果不佳。scale可选参数计算导数值时可选的缩放因子默认值为 1。delta可选参数结果可选的增量值默认值为 0。borderType可选参数边界填充方式默认值为 cv2.BORDER_DEFAULT。使用 Scharr 算子检测 x 方向上的边缘。yuan_x_scharr cv2.Scharr(yuan, cv2.CV_64F, dx1, dy0) # 默认uint8改为float64可保存负数 yuan_x_scharr_full cv2.convertScaleAbs(yuan_x_scharr) # 转换为绝对值负数转换为正数 cv2.imshow(yuan_x_scharr_full, yuan_x_scharr_full) cv2.waitKey(0)同理使用 Scharr 算子检测 y 方向上的边缘。yuan_y_scharr cv2.Scharr(yuan, cv2.CV_64F, dx0, dy1) # 默认uint8改为float64可保存负数 yuan_y_scharr_full cv2.convertScaleAbs(yuan_y_scharr) # 转换为绝对值负数转换为正数 cv2.imshow(yuan_y_scharr_full, yuan_y_scharr_full) cv2.waitKey(0)使用图像加权运算组合 x 和 y 方向的 2 个边缘。yuan_xy_scharr_full cv2.addWeighted(yuan_x_scharr_full, 1, yuan_y_scharr_full, 1, 0) cv2.imshow(yuan_xy_scharr_full, yuan_xy_scharr_full) cv2.waitKey(0) cv2.destroyAllWindows()加权后的结果图优缺点Scharr算子是专为3x3卷积核优化的、精度更高的边缘检测算子。当你需要使用小尺寸算子时可以优先考虑它。但局限在于核大小固定为3x3。这使得它无法像Sobel算子那样通过调整ksize参数如5x5、7x7来获得更大范围的平滑效果。三.Laplacian算子Laplacian 算子是一种基于二阶导数的边缘检测算子它不依赖方向直接计算图像灰度值的二阶空间导数从而在灰度发生剧烈变化的位置产生响应。与 Sobel、Scharr 这类一阶导数算子不同Laplacian 对边缘方向不敏感能够同时检测各个方向的边缘。Laplacian 算子常用的 3x3 卷积核如下L [ 0 -1 0 ] [ -1 4 -1 ] [ 0 -1 0 ]也可以使用包含对角方向的变体L [ -1 -1 -1 ] [ -1 8 -1 ] [ -1 -1 -1 ]cv2.Laplacian(src, ddepth, ksize, scale, delta, borderType)参数说明src输入图像。ddepth输出图像的深度可以理解为数据类型-1 表示与原图像相同的深度。ksize可选参数用于计算二阶导数的滤波器大小必须是正奇数默认为 1。scale可选参数计算 Laplacian 值时可选的比例因子默认值为 1。delta可选参数结果可选的增量值默认值为 0。borderType可选参数边界填充方式默认值为 cv2.BORDER_DEFAULT。使用 Laplacian 算子检测边缘。yuan_lap cv2.Laplacian(yuan, cv2.CV_64F) # 默认uint8改为float64可保存负数 yuan_lap_full cv2.convertScaleAbs(yuan_lap) # 转换为绝对值负数转换为正数 cv2.imshow(yuan_lap_full, yuan_lap_full) cv2.waitKey(0) cv2.destroyAllWindows()优缺点优点对边缘方向不敏感能够同时检测各个方向的边缘定位精度较高。缺点对噪声非常敏感因为二阶导数会放大噪声的影响所以通常需要先对图像进行平滑如高斯滤波处理后再使用。结果图四.canny算子Canny 算子是一种多阶段的边缘检测算法由 John F. Canny 于 1986 年提出。它被认为是目前最优秀的边缘检测算法之一能够在抑制噪声的同时精确定位边缘并尽量保证每个边缘只被检测一次。Canny 边缘检测主要包含以下五个步骤高斯滤波使用高斯核与图像进行卷积对图像进行平滑处理以抑制噪声的影响。计算梯度幅值和方向使用 Sobel 等算子计算图像在水平方向和垂直方向上的梯度进而得到梯度幅值和梯度方向。非极大值抑制沿梯度方向比较当前像素与其相邻像素的梯度幅值只保留局部最大值从而细化边缘使边缘更细更准确。双阈值检测设置高阈值和低阈值将梯度幅值高于高阈值的像素视为强边缘低于低阈值的像素直接舍弃介于两者之间的像素视为弱边缘。滞后连接对于弱边缘像素如果它与强边缘像素相连则将其保留为边缘否则将其舍弃。这样可以有效减少断裂的边缘。cv2.Canny(image, threshold1, threshold2, apertureSize, L2gradient)参数说明image输入图像通常为灰度图。threshold1低阈值用于双阈值检测中的弱边缘判断。threshold2高阈值用于双阈值检测中的强边缘判断。apertureSize可选参数Sobel 算子的大小默认为 3。L2gradient可选参数是否使用更精确的 L2 范数计算梯度幅值默认为 False使用 L1 范数。使用 Canny 算子检测边缘。yuan_canny cv2.Canny(yuan, 50, 150) # 低阈值50高阈值150 cv2.imshow(yuan_canny, yuan_canny) cv2.waitKey(0) cv2.destroyAllWindows()优缺点优点检测精度高边缘定位准确抗噪能力强能够检测出连续且细的边缘是目前应用最广泛的边缘检测算法。缺点计算量相对较大对参数尤其是高低阈值比较敏感需要根据具体图像调整阈值才能获得理想的检测效果。结果图
返回列表