原理:
参考链接:https://blog.csdn.net/poem_qianmo/article/details/25560901
OpenCV调用:
C++: 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 );
第一个参数,InputArray 类型的src,为输入图像,填Mat类型即可。
第二个参数,OutputArray类型的dst,即目标图像,函数的输出参数,需要和源图片有一样的尺寸和类型。
第三个参数,int类型的ddepth,输出图像的深度,支持如下src.depth()和ddepth的组合:
我们可以在文档中查阅getDerivKernels的相关介绍,来得到这个参数的更多信息。
第八个参数,double类型的delta,表示在结果存入目标图(第二个参数dst)之前可选的delta值,有默认值0。
第九个参数, int类型的borderType,我们的老朋友了(万年是最后一个参数),边界模式,默认值为BORDER_DEFAULT。这个参数可以在官方文档中borderInterpolate处得到更详细的信息。
//把图像的各个像素点的值存到一个二维数组,增加代码的可读性
int img_garry[imgHeight][imgWidth];
for(int i = 0; i<imgHeight; i++)
{
for(int j = 0; j<imgWidth;j++)
{
img_garry[i][j] = grayData[i*imgWidth+j];
}
}
//sobel算法
IplImage* sobel_img = NULL; //创建用于灰度图像的结构体指针
sobel_img = cvCreateImage(cvSize(imgWidth,imgHeight), imgDepth, 1 ); //创建单通道的色彩空间用于灰度变换
uchar *sobel_Data = (uchar*) sobel_img->imageData;//声明无符号char型指针指向结构体的变量imageData
double Gmax = 150; //设定阈值Gmax
double Gx=0;
double Gy=0;
double G =0;
for(int i = 1;i<imgHeight-2; i++)
for(int j = 1;j<imgWidth-2; j++)
{
Gx = -1 * img_garry[i-1][j-1] + 0 * img_garry[i-1][ j ] + 1 * img_garry[i-1][j+1]
+ -2 * img_garry[ i ][j-1] + 0 * img_garry[ i ][ j ] + 2 * img_garry[ i ][j+1]
+ -1 * img_garry[i+1][j-1] + 0 * img_garry[i+1][ j ] + 1 * img_garry[i+1][j+1];
Gy = -1 * img_garry[i-1][j-1] + -2 * img_garry[i-1][ j ] + -1 * img_garry[i-1][j+1]
+ 0 * img_garry[ i ][j-1] + 0 * img_garry[ i ][ j ] + 0 * img_garry[ i ][j+1]
+ 1 * img_garry[i+1][j-1] + 2 * img_garry[i+1][ j ] + 1 * img_garry[i+1][j+1];
G = sqrt(Gx*Gx+Gy*Gy);
if(G>Gmax)
sobel_Data[i*imgWidth+j]=255;
else
sobel_Data[i*imgWidth+j] = 0;
}
cvShowImage("sobel_img", sobel_img); //显示彩色图像灰度处理的图像
OpenCV调用:
C++: void Laplacian(InputArray src,OutputArray dst, int ddepth, int ksize=1, double scale=1, double delta=0, int borderType=BORDER_DEFAULT );
InputArray
类型的image
,输入图像,即源图像,填Mat
类的对象即可,且需为单通道8位图像。OutputArray
类型的edges
,输出的边缘图,需要和源图片有一样的尺寸和通道数。int
类型的ddepth
,目标图像的深度。int
类型的ksize
,用于计算二阶导数的滤波器的孔径尺寸,大小必须为正奇数,且有默认值1。double
类型的scale
,计算拉普拉斯值的时候可选的比例因子,有默认值1
。double
类型的delta
,表示在结果存入目标图(第二个参数dst
)之前可选的delta
值,有默认值0
。int
类型的borderType
,边界模式,默认值为BORDER_DEFAULT
。这个参数可以在官方文档中borderInterpolate()
处得到更详细的信息。Laplacian()
函数其实主要是利用sobel
算子的运算。它通过加上sobel算子运算出的图像x方向和y方向上的导数,来得到我们载入图像的拉普拉斯变换结果。
//laplace算法
IplImage* laplace_img = NULL; //创建用于灰度图像的结构体指针
laplace_img = cvCreateImage(cvSize(imgWidth,imgHeight), imgDepth, 1 ); //创建单通道的色彩空间用于灰度变换
uchar *laplace_Data = (uchar*) laplace_img->imageData;//声明无符号char型指针指向结构体的变量imageData
double L =0;
for(int i = 1;i<imgHeight-2; i++)
{
for(int j = 1;j<imgWidth-2; j++)
{
L = 0 * img_garry[i-1][j-1] + 1 * img_garry[i-1][ j ] + 0 * img_garry[i-1][j+1]
+ 1 * img_garry[ i ][j-1] + -4 * img_garry[ i ][ j ] + 1 * img_garry[ i ][j+1]
+ 0 * img_garry[i+1][j-1] + 1 * img_garry[i+1][ j ] + 0 * img_garry[i+1][j+1];
if(L>255)
laplace_Data[i*imgWidth+j] = 255;
else if( 0<L & L<255)
laplace_Data[i*imgWidth+j] = L ;
else if(L<0)
laplace_Data[i*imgWidth+j] = 0 ;
}
}
cvShowImage("laplace_img", laplace_img);
OpenCV调用:
C++: void Canny(InputArray image,OutputArray edges, double threshold1, double threshold2, int apertureSize=3,bool L2gradient=false )
第一个参数,InputArray
类型的image
,输入图像,即源图像,填Mat
类的对象即可,且需为单通道8位图像。
第二个参数,OutputArray
类型的edges
,输出的边缘图,需要和源图片有一样的尺寸和类型。
第三个参数,double
类型的threshold1
,第一个滞后性阈值。
第四个参数,double
类型的threshold2
,第二个滞后性阈值。
第五个参数,int
类型的apertureSize
,表示应用Sobel
算子的孔径大小,其有默认值3
。
第六个参数,bool
类型的L2gradient
,一个计算图像梯度幅值的标识,有默认值false
。
需要注意的是,这个函数阈值1和阈值2两者的小者用于边缘连接,而大者用来控制强边缘的初始段,推荐的高低阈值比在2:1到3:1之间。
openCV调用示例:
//Canny算法
Mat Canny_Image = imread("/Users/inbc/Desktop/OpenCV学习/opencv_test_3/666.jpg");//注意修改路径
if (!Canny_Image.data){
cout << "falied to read" << endl;
system("pause");
//return;
}
Mat srcGray;
cvtColor(Canny_Image, srcGray, CV_BGR2GRAY);
//高斯滤波
GaussianBlur(srcGray, srcGray, Size(3, 3),
0, 0, BORDER_DEFAULT);
//Canny检测
int edgeThresh =100;
Mat Canny_result;
Canny(Canny_Image, Canny_result, edgeThresh, edgeThresh * 3, 3); //调用Canny算子
imshow("Canny_Image", Canny_Image);
imshow("Canny_Image", Canny_result);
OpenCV调用:
C++:void HoughLinesP(InputArray image, OutputArray lines, double rho, double theta, int threshold, double minLineLength=0, double maxLineGap=0 )
InputArray
类型的image
,输入图像,即源图像,需为8位的单通道二进制图像,可以将任意的源图载入进来后由函数修改成此格式后,再填在这里。InputArray
类型的lines
,经过调用HoughLinesP
函数后后存储了检测到的线条的输出矢量,每一条线由具有四个元素的矢量(x_1,y_1,x_2, y_2)
表示,其中,(x_1, y_1)
和(x_2, y_2)
是是每个检测到的线段的结束点。double
类型的rho
, 以像素为单位的距离精度。 另一种形容方式是直线搜索时的进步尺寸的单位半径。double
类型的theta
,以弧度为单位的角度精度。另一种形容方式是直线搜索时的进步尺寸的单位角度。int
类型的threshold
,累加平面的阈值参数,即识别某部分为图中的一条直线时它在累加平面中必须达到的值。 大于阈值threshold
的线段才可以被检测通过并返回到结果中。double
类型的minLineLength
,有默认值0
,表示最低线段的长度,比这个设定参数短的线段就不能被显现出来。double
类型的maxLineGap
,有默认值0
,允许将同一行点与点之间连接起来的最大的距离。OpenCV调用示例:
//Hough变换检测直线
Mat Hough_Image = imread("/Users/inbc/Desktop/OpenCV学习/opencv_test_3/666.jpg", 0);//注意修改路径
Mat CannyImg;
Canny(Hough_Image, CannyImg, 70, 200, 3);
imshow("CannyImg_2", CannyImg);
Mat DstImg;
cvtColor(Hough_Image, DstImg, CV_GRAY2BGR);
vector<Vec4i> Lines;
HoughLinesP(CannyImg, Lines, 1, CV_PI / 360, 170,30,15);
for (size_t i = 0; i < Lines.size(); i++)
{
line(DstImg, Point(Lines[i][0], Lines[i][1]), Point(Lines[i][2], Lines[i][3]), Scalar(0, 0, 255), 2, 8);
}
imshow("Hough_Image", DstImg);