Sobel
算子主要用于边缘检测;
sobel
算子:
sobel
算子功能集合高斯平滑和微分求导;那么最终的图像梯度:
可以近似为:
改进的版本Scharr
算子:
当内核大小为3时,以上Sobel
可能产生比较明显的误差(毕竟,Sobel
算子只是求取了导数的近似值),为了解决这一问题,OpenCV提供了Scharr
函数,但该函数仅作用域大小为3的内核;计算速度与Sobel
函数一样快,但结果更加精确,不怕干扰,其内核为:
使用Sobel
算子提取图像边缘,包含以下四个步骤:
Sobel
算子或者Scharr
算子计算图像梯度;Sobel
算子API的使用方式:
void Sobel( InputArray src, OutputArray dst, int ddepth,
int dx, int dy, int ksize = 3,
double scale = 1, double delta = 0,
int borderType = BORDER_DEFAULT );
src
表示输入的灰度图像dst
表示输出的梯度;ddepth
表示输出梯度的数据类型,必须大于输入的图像数据类型,关系如下图所示:dx=1, dy=0
表示对x
方向计算梯度;dx=0, dy=1
表示对y
方向计算梯度;Scharr
算子的使用方式:
void Scharr( InputArray src, OutputArray dst, int ddepth,
int dx, int dy, double scale = 1, double delta = 0,
int borderType = BORDER_DEFAULT );
Sobel
算子基本一致;Scharr
默认就是3;完成代码如下:
#include <iostream>
#include <opencv2/opencv.hpp>
using namespace std;
using namespace cv;
/**
* 边缘处理
*/
int main(){
// 读取图像
Mat src = imread("/home/chen/dataset/lena.jpg");
if (src.empty()){
cout << "could not load image." << endl;
return -1;
}
namedWindow("src", WINDOW_AUTOSIZE);
imshow("src", src);
// 1. 高斯模糊
Mat srcBlur;
GaussianBlur(src, srcBlur, Size(3, 3), 0, 0);
// 2. 转灰度
Mat srcGray;
cvtColor(srcBlur, srcGray, COLOR_BGR2GRAY);
// 3. 求方向梯度
Mat gradX, gradY;
Sobel(srcGray, gradX, CV_16S, 1, 0, 3);
Sobel(srcGray, gradY, CV_16S, 0, 1, 3);
// Scharr(srcGray, gradX, CV_16S, 1, 0);
// Scharr(srcGray, gradY, CV_16S, 0, 1);
convertScaleAbs(gradX, gradX); // calculates absolute values, and converts the result to 8-bit.
convertScaleAbs(gradY, gradY);
namedWindow("gradY", WINDOW_AUTOSIZE);
imshow("gradX", gradX);
namedWindow("gradY", WINDOW_AUTOSIZE);
imshow("gradY", gradY);
printf("type: %d, %d", gradX.type(), gradY.type());
// 4. 图像混合
Mat dst;
addWeighted(gradX, 0.5, gradY, 0.5, 0, dst);
namedWindow("dst", WINDOW_AUTOSIZE);
imshow("dst", dst);
// 4.1
Mat gradXY = Mat(gradX.size(), gradX.type());
for (int row = 0; row < gradX.rows; row++){
for (int col = 0; col < gradX.cols; col++){
int gX = gradX.at<uchar>(row, col);
int gY = gradY.at<uchar>(row, col);
gradXY.at<uchar>(row, col) = saturate_cast<uchar>(gX + gY);
}
}
namedWindow("gradXY", WINDOW_AUTOSIZE);
imshow("gradXY", gradXY);
waitKey(0);
return 0;
}
使用Sobel
的结果
使用Scharr
算子的结果
原文:https://www.cnblogs.com/chenzhen0530/p/14660498.html