opencv基础 42- Scharr算子-cv2.Scharr()(边缘检测基础)

Scharr算子是用于计算图像梯度的一种常用算子,特别是在边缘检测任务中。它是Sobel算子的改进版本,旨在提供更加准确和敏感的边缘检测。

在离散的空间上,有很多方法可以用来计算近似导数,在使用 3×3 的 Sobel 算子时,可能计算结果并不太精准。OpenCV 提供了 Scharr 算子,该算子具有和 Sobel 算子同样的速度,且精度更高。可以将 Scharr 算子看作对 Sobel 算子的改进,其核通常为:

opencv基础 42- Scharr算子-cv2.Scharr()(边缘检测基础)_第1张图片
OpenCV 提供了函数 cv2.Scharr()来计算 Scharr 算子,其语法格式如下:

dst = cv2.Scharr( src, ddepth, dx, dy[, scale[, delta[, borderType]]] )

式中:

  • dst 代表输出图像。
  • src 代表原始图像。
  • ddepth 代表输出图像深度。该值与函数 cv2.Sobel()中的参数 ddepth 的含义相同,具体可
    以参考上节表 9-1。
  • dx 代表 x 方向上的导数阶数。
  • dy 代表 y 方向上的导数阶数。
  • scale 代表计算导数值时的缩放因子,该项是可选项,默认值是 1,表示没有缩放。
  • delta 代表加到目标图像上的亮度值,该项是可选项,默认值为 0。
  • borderType 代表边界样式。具体可以参考上节表 9-2。

在函数 cv2.Sobel()中介绍过,如果 ksize=-1,则会使用 Scharr 滤波器。

因此,如下语句:

dst=cv2.Scharr(src, ddepth, dx, dy)

dst=cv2.Sobel(src, ddepth, dx, dy, -1)

是等价的。

函数 cv2.Scharr()和函数 cv2.Sobel()的使用方式基本一致。
首先,需要注意的是,参数 ddepth 的值应该设置为“cv2.CV_64F”,并对函数 cv2.Scharr()的计算结果取绝对值,才能保证得到正确的处理结果

具体语句为:

dst=Scharr(src, cv2.CV_64F, dx, dy)
dst= cv2.convertScaleAbs(dst)

另外,需要注意的是,在函数 cv2.Scharr()中,要求参数 dx 和 dy 满足条件:

dx >= 0 && dy >= 0 && dx+dy == 1

因此,参数 dx 和参数 dy 的组合形式有:

  • 计算 x 方向边缘(梯度):dx=1, dy=0。
  • 计算 y 方向边缘(梯度): dx=0, dy=1。
  • 计算 x 方向与 y 方向的边缘叠加:通过组合方式实现。

下面分别对上述情况进行简要说明。

  1. 计算x方向边缘(梯度):dx=1, dy=0
    此时,使用的语句是:
dst=Scharr(src, ddpeth, dx=1, dy=0)
  1. 计算y方向边缘(梯度):dx=0,dy=1
    此时,使用的语句是:
dst=Scharr(src, ddpeth, dx=0, dy=1)
  1. 计算x方向与y方向的边缘叠加

将两个方向的边缘相加,使用的语句是:

dx=Scharr(src, ddpeth, dx=1, dy=0)
dy=Scharr(src, ddpeth, dx=0, dy=1)
Scharrxy=cv2.addWeighted(dx,0.5,dy,0.5,0)

需要注意的是,参数 dx 和 dy 的值不能都为 1。

例如,如下语句是错误的:

dst=Scharr(src, ddpeth, dx=1, dy=1)

示例:使用函数 cv2.Scharr()获取图像水平方向的边缘信息。

import cv2
o = cv2.imread('scharr.bmp',cv2.IMREAD_GRAYSCALE)
Scharrx = cv2.Scharr(o,cv2.CV_64F,1,0)
Scharrx = cv2.convertScaleAbs(Scharrx)
cv2.imshow("original",o)
cv2.imshow("x",Scharrx)
cv2.waitKey()
cv2.destroyAllWindows()

opencv基础 42- Scharr算子-cv2.Scharr()(边缘检测基础)_第2张图片

使用函数 cv2.Scharr()获取图像垂直方向的边缘信息。

import cv2
o = cv2.imread('Scharr.bmp',cv2.IMREAD_GRAYSCALE)
Scharry = cv2.Scharr(o,cv2.CV_64F,0,1)
Scharry = cv2.convertScaleAbs(Scharry)
cv2.imshow("original",o)
cv2.imshow("y",Scharry)
cv2.waitKey()
cv2.destroyAllWindows()

运行结果:
opencv基础 42- Scharr算子-cv2.Scharr()(边缘检测基础)_第3张图片

使用函数 cv2.Scharr()实现水平方向和垂直方向边缘叠加的效果。

代码如下:

import cv2
o = cv2.imread('scharr.bmp',cv2.IMREAD_GRAYSCALE)
scharrx = cv2.Scharr(o,cv2.CV_64F,1,0)
scharry = cv2.Scharr(o,cv2.CV_64F,0,1)
scharrx = cv2.convertScaleAbs(scharrx)
scharry = cv2.convertScaleAbs(scharry)
scharrxy = cv2.addWeighted(scharrx,0.5,scharry,0.5,0)
cv2.imshow("original",o)
cv2.imshow("xy",scharrxy)
cv2.waitKey()
cv2.destroyAllWindows()

运行结果:
opencv基础 42- Scharr算子-cv2.Scharr()(边缘检测基础)_第4张图片

Sobel 算子和 Scharr 算子的比较

Sobel 算子的缺点是,当其核结构较小时,精确度不高,而 Scharr 算子具有更高的精度。
Sobel 算子和 Scharr 算子的核结构如图 9-22 所示。

opencv基础 42- Scharr算子-cv2.Scharr()(边缘检测基础)_第5张图片

代码示例:

分别使用 Sobel 算子和 Scharr 算子计算一幅图像的水平边缘和垂直边缘的叠加信息。

import cv2
o = cv2.imread('lena.png',cv2.IMREAD_GRAYSCALE)
Sobelx = cv2.Sobel(o,cv2.CV_64F,1,0,ksize=3)
Sobely = cv2.Sobel(o,cv2.CV_64F,0,1,ksize=3)
Sobelx = cv2.convertScaleAbs(Sobelx)
Sobely = cv2.convertScaleAbs(Sobely)
Sobelxy = cv2.addWeighted(Sobelx,0.5,Sobely,0.5,0)
Scharrx = cv2.Scharr(o,cv2.CV_64F,1,0)
Scharry = cv2.Scharr(o,cv2.CV_64F,0,1)
Scharrx = cv2.convertScaleAbs(Scharrx)
Scharry = cv2.convertScaleAbs(Scharry)
Scharrxy = cv2.addWeighted(Scharrx,0.5,Scharry,0.5,0)
cv2.imshow("original",o)
cv2.imshow("Sobelxy",Sobelxy)
cv2.imshow("Scharrxy",Scharrxy)
cv2.waitKey()
cv2.destroyAllWindows()

运行结果:

你可能感兴趣的:(opencv,人工智能,计算机视觉,opencv,计算机视觉,人工智能,python,目标检测)