OpenCV 梯度运算

14 min read

梯度是指图像上像素值变化最快的地方,通常指图像的边缘或角落等。

在OpenCV中,可以通过Sobel、Scharr、Laplacian等来计算图像的梯度。

  1. Sobel算子

Sobel算子是一种边缘检测算子,它可以计算图像的一阶导数,通过求取图像在水平和垂直方向的梯度来确定边缘的位置和方向。具体实现方式如下:

cv::Mat src;
cv::Mat src_gray;
cv::Mat grad_x, grad_y;
cv::Mat abs_grad_x, abs_grad_y;
cv::Mat grad;

int scale = 1;
int delta = 0;
int ddepth = CV_16S;

// 加载图片
src = cv::imread("image.jpg");

// 灰度化
cv::cvtColor(src, src_gray, cv::COLOR_BGR2GRAY);

// 改变图像深度为16位有符号,以便计算Sobel算子
cv::GaussianBlur(src_gray, src_gray, cv::Size(3, 3), 0, 0, cv::BORDER_DEFAULT);

cv::Sobel(src_gray, grad_x, ddepth, 1, 0, 3, scale, delta, cv::BORDER_DEFAULT);
cv::Sobel(src_gray, grad_y, ddepth, 0, 1, 3, scale, delta, cv::BORDER_DEFAULT);

// 转换为8位无符号
cv::convertScaleAbs(grad_x, abs_grad_x);
cv::convertScaleAbs(grad_y, abs_grad_y);

// 梯度叠加
cv::addWeighted(abs_grad_x, 0.5, abs_grad_y, 0.5, 0, grad);

  1. Scharr算子

Scharr算子与Sobel算子类似,也可以用来计算图像的一阶导数。但相比较而言,Scharr算子具有更好的抗噪声能力。具体实现方式如下:

cv::Mat src;
cv::Mat src_gray;
cv::Mat grad_x, grad_y;
cv::Mat abs_grad_x, abs_grad_y;
cv::Mat grad;

int scale = 1;
int delta = 0;
int ddepth = CV_16S;

// 加载图片
src = cv::imread("image.jpg");

// 灰度化
cv::cvtColor(src, src_gray, cv::COLOR_BGR2GRAY);

// 改变图像深度为16位有符号,以便计算Sobel算子
cv::GaussianBlur(src_gray, src_gray, cv::Size(3, 3), 0, 0, cv::BORDER_DEFAULT);

cv::Scharr(src_gray, grad_x, ddepth, 1, 0, scale, delta, cv::BORDER_DEFAULT);
cv::Scharr(src_gray, grad_y, ddepth, 0, 1, scale, delta, cv::BORDER_DEFAULT);

// 转换为8位无符号
cv::convertScaleAbs(grad_x, abs_grad_x);
cv::convertScaleAbs(grad_y, abs_grad_y);

// 梯度叠加
cv::addWeighted(abs_grad_x, 0.5, abs_grad_y, 0.5, 0, grad);

  1. Laplacian算子

Laplacian算子可以用来计算图像上像素值的二阶导数,可以通过计算图像的边缘来检测图像中的物体。具体实现方式如下:

cv::Mat src;
cv::Mat src_gray;
cv::Mat lap;

// 加载图片
src = cv::imread("image.jpg");

// 灰度化
cv::cvtColor(src, src_gray, cv::COLOR_BGR2GRAY);

// 改变图像深度为16位有符号,以便计算Laplacian算子
cv::GaussianBlur(src_gray, src_gray, cv::Size(3, 3), 0, 0, cv::BORDER_DEFAULT);

cv::Laplacian(src_gray, lap, CV_16S, 3, 1, 0, cv::BORDER_DEFAULT);

// 转换为8位无符号
cv::convertScaleAbs(lap, lap);

参考文献:
1.https://www.cnblogs.com/hejiaqi/p/14044738.html
2.https://docs.opencv.org/4.5.4/d5/d0f/tutorial_py_gradients.html