# Sobel 梯度算子

在图像处理中，梯度反映了像素值的最大变化率的方向，能够突出和提取边缘，常用于工业检测中产品缺陷检测和自动检测的预处理。

OpenCV 提供了三种梯度算子：Sobel、Scharr 和 Laplacian。Sobel 梯度算子是高斯平滑和微分求导的联合运算，抗噪声能力强。

Sobel 梯度算子很容易通过卷积操作 cv.filter2D 实现，OpenCV 也提供了函数 **cv.Sobel** 实现 Sobel 梯度算子。

**函数说明：**

```
cv.Sobel(src, ddepth, dx, dy[, dst[, ksize[, scale[, delta[, borderType]]]]]) → dst
```

我们用 Sobel 算子从 Lena 图像提取边缘，看看会产生什么样的效果吧。

![](./gradientOutput.png)

下面对 Sobel 梯度算子实现代码正确的是？

##  答案

```
import cv2 as cv

if __name__ == '__main__':
    img = cv.imread("lena.png", flags=1)
    imgGray = cv.cvtColor(img, cv.COLOR_BGR2GRAY)

    SobelX = cv.Sobel(imgGray, cv.CV_16S, 1, 0)  # 计算 x 轴方向
    SobelY = cv.Sobel(imgGray, cv.CV_16S, 0, 1)  # 计算 y 轴方向
    absX = cv.convertScaleAbs(SobelX)  # 转回 uint8
    absY = cv.convertScaleAbs(SobelY)  # 转回 uint8
    SobelXY = cv.addWeighted(absX, 0.5, absY, 0.5, 0)  # 用绝对值近似平方根

    cv.imshow("Sobel gradient", SobelXY)
    cv.waitKey(0)
```

##  选项

###  函数 cv.Sobel() 缺少参数：数据深度 ddepth

```
import cv2 as cv

if __name__ == '__main__':
    img = cv.imread("lena.png", flags=1)
    imgGray = cv.cvtColor(img, cv.COLOR_BGR2GRAY)

    SobelX = cv.Sobel(imgGray, 1, 0)
    SobelY = cv.Sobel(imgGray, 0, 1)
    absX = cv.convertScaleAbs(SobelX)
    absY = cv.convertScaleAbs(SobelY)
    SobelXY = cv.addWeighted(absX, 0.5, absY, 0.5, 0)

    cv.imshow("Sobel gradient", SobelXY)
    cv.waitKey(0)
```

###  梯度运算结果有正负，绝对值或平方和处理后才能加权

```
import cv2 as cv

if __name__ == '__main__':
    img = cv.imread("lena.png", flags=1)
    imgGray = cv.cvtColor(img, cv.COLOR_BGR2GRAY)

    SobelX = cv.Sobel(imgGray, cv.CV_16S, 1, 0)  # 计算 x 轴方向
    SobelY = cv.Sobel(imgGray, cv.CV_16S, 0, 1)  # 计算 y 轴方向
    SobelXY = cv.addWeighted(SobelX, 0.5, SobelY, 0.5, 0)  # 用绝对值近似平方根

    cv.imshow("Sobel gradient", SobelXY)
    cv.waitKey(0)

```

###  只对 x 轴方向进行了梯度运算

```
import cv2 as cv

if __name__ == '__main__':
    img = cv.imread("lena.png", flags=1)
    imgGray = cv.cvtColor(img, cv.COLOR_BGR2GRAY)

    SobelX = cv.Sobel(imgGray, cv.CV_16S, 1, 0)  # 计算 x 轴方向
    absX = cv.convertScaleAbs(SobelX)  # 转回 uint8

    cv.imshow("Sobel gradient", absX)
    cv.waitKey(0)
```
