Sobel算子
什么是方向导数和梯度
Ps:实战中多用近似计算,用加减计算代替乘除计算以满足对速度的要求。
API:
Sobel代码:
#include<opencv2/opencv.hpp>
#include<iostream>
using namespace cv;
using namespace std;
int main(int argc, char** argv)
{
Mat src, dst;
src = imread("C:/Users/Administrator/Pictures/20160711084909.jpg");
if (!src.data)
cout << "无法识别" << endl;
namedWindow("input image", CV_WINDOW_AUTOSIZE);
imshow("input image", src);
GaussianBlur(src, dst, Size(3, 3), 0, 0);
Mat gray_src;
cvtColor(dst, gray_src, CV_BGR2GRAY);
Mat xgrad, ygrad;
Sobel(gray_src, xgrad, CV_16S, 1, 0, 3);
Sobel(gray_src, ygrad, CV_16S, 0, 1, 3);
//convertScaleAbs(xgrad, xgrad);
//convertScaleAbs(ygrad, ygrad);
imshow("xgrad", xgrad);
imshow("ygrad", ygrad);
waitKey(0);
return 0;
}
图1-1 Sobel算子生产x和y方向的梯度
如果改成-1,能明显看出图形不理想
图1-2 Sobel算子生产x和y方向的梯度(改成-1)
addWeighted(xgrad, 0.5, ygrad, 0.5, 0, xygrad);
imshow("final image", xygrad);
图1-3 Sobel算子生产x和y方向的梯度加起来
#include<opencv2/opencv.hpp>
#include<iostream>
using namespace cv;
using namespace std;
int main(int argc, char** argv)
{
Mat src, dst;
src = imread("C:/Users/Administrator/Pictures/20160711084909.jpg");
if (!src.data)
cout << "无法识别" << endl;
namedWindow("input image", CV_WINDOW_AUTOSIZE);
imshow("input image", src);
GaussianBlur(src, dst, Size(3, 3), 0, 0);
Mat gray_src;
cvtColor(dst, gray_src, CV_BGR2GRAY);
Mat xgrad, ygrad;
Sobel(gray_src, xgrad, CV_16S, 1, 0, 3);
Sobel(gray_src, ygrad, CV_16S, 0, 1, 3);
convertScaleAbs(xgrad, xgrad);
convertScaleAbs(ygrad, ygrad);
Mat xygrad = Mat(xgrad.size(), xgrad.type());
int width = xgrad.cols;
int height = xgrad.rows;
for(int row = 0; row<height;row++)
for (int col = 0; col < width; col++) {
int xg = xgrad.at<uchar>(row, col);
int yg = ygrad.at<uchar>(row, col);
int xy = xg + yg;
xygrad.at<uchar>(row, col) = saturate_cast<uchar>(xy);
}
//addWeighted(xgrad, 0.5, ygrad, 0.5, 0, xygrad);
imshow("final image", xygrad);
//imshow("xgrad", xgrad);
//imshow("ygrad", ygrad);
waitKey(0);
return 0;
}
图1-4 Sobel算子生产x和y方向的梯度绝对值相加
图1-5 Sobel算子生产x和y方向的梯度绝对值相加(左)对比addWeighted直接相加
opencv的Sobel:
//Sobel(gray_src, xgrad, CV_16S, 1, 0, 3);
//Sobel(gray_src, ygrad, CV_16S, 0, 1, 3);//普通sobel
Scharr(gray_src, xgrad, CV_16S, 1, 0);//opencv的sobel
Scharr(gray_src, ygrad, CV_16S, 1, 0);
图1-6 opencv的Sobel算子生产x和y方向的梯度.
Laplance算子
#include<opencv2/opencv.hpp>
#include<iostream>
using namespace cv;
using namespace std;
int main(int argc, char** argv)
{
Mat src, dst;
src = imread("C:/Users/Administrator/Pictures/20160711084909.jpg");
if (!src.data)
{
cout << "无法加载图像" << endl;
return -1;
}
namedWindow("input image", CV_WINDOW_AUTOSIZE);
namedWindow("Laplance image", CV_WINDOW_AUTOSIZE);
Mat gray_src, edge_image;
GaussianBlur(src, dst, Size(3, 3), 0, 0);
cvtColor(dst, gray_src, CV_BGR2GRAY);
Laplacian(gray_src, edge_image, CV_16S, 3);
convertScaleAbs(edge_image, edge_image);
imshow("input image", src);
imshow("Laplance image", edge_image);
waitKey(0);
return 0;
}
图1-7 Laplace算子
二值化后输出:
threshold(edge_image, edge_image, 0, 255, THRESH_OTSU | THRESH_BINARY);
图1-8 Laplace算子(二值化后的)