写在前面
边缘:像素值发生跃迁的地方。可通过一阶导数求得
delta=f(x)-f(x-1)
delta越大,说明像素在x方向变化越大,边缘信号越强
Sobel算子,称为一阶微分算子或者求导算子 (拉普拉斯为二阶)
水平梯度Gx,垂直梯度Gy
最终梯度: G=abs(Gx)+abs(Gy);
G=pow(GxGx+GyGy,0.5);
代码
#include<iostream>
#include<opencv2/opencv.hpp>
#include<cmath>
using namespace std;
using namespace cv;
int main() {
Mat src = imread("A:\\专用\\TestForTheCV\\class18沙滩女.jpg");
Mat dst;
//pyrDown(src, src, Size(src.cols / 2, src.rows / 2));
imshow("图片", src);
Mat gray_src, xgrad, ygrad;
GaussianBlur(src, dst, Size(3, 3), 0, 0);
cvtColor(dst, gray_src, CV_BGR2GRAY);
imshow("灰度图", gray_src);
Sobel(gray_src, xgrad, CV_16S, 1, 0, 3); //CV_16S,比原图位数必须高才行
Sobel(gray_src, ygrad, CV_16S, 0, 1, 3);
//Sobel算法在CV里有一个进化版Scharr,两者参数完全一致
Scharr(gray_src, xgrad, CV_16S, 1, 0, 3);
Scharr(gray_src, ygrad, CV_16S, 0, 1, 3);
convertScaleAbs(xgrad, xgrad);
convertScaleAbs(ygrad, ygrad);
imshow("xgrad", xgrad);
imshow("ygrad", ygrad);
Mat xygrad;
//直接调用API融合
addWeighted(xgrad, 0.5, ygrad, 0.5, 0, xygrad);
imshow("xygrad自动", xygrad);
//手动融合
xygrad = Mat(xgrad.size(), xgrad.type());
for (int row = 0; row < xgrad.rows; row++) {
for (int col = 0; col < xgrad.cols; col++) {
int xpx = xgrad.at<uchar>(row, col);
int ypx = ygrad.at<uchar>(row, col);
int xypx = xpx + ypx;
xygrad.at<uchar>(row, col) = saturate_cast<uchar>(xypx);
}
}
imshow("xygrad手动", xygrad);
waitKey(0);
return 0;
}
/*
边缘:像素值发生跃迁的地方。可通过一阶导数求得
delta=f(x)-f(x-1)
delta越大,说明像素在x方向变化越大,边缘信号越强
Sobel算子,称为一阶微分算子或者求导算子 (拉普拉斯为二阶)
水平梯度Gx,垂直梯度Gy
最终梯度: G=abs(Gx)+abs(Gy);
G=pow(Gx*Gx+Gy*Gy,0.5);
*/
运行结果