7.1.2opencv中调用Canny函数边缘检测:
#include <opencv2\opencv.hpp>
#include<opencv2/highgui/highgui.hpp>
#include<opencv2/imgproc/imgproc.hpp>
using namespace cv;
int main()
{
Mat img = imread("sg.jpg");//名为sg.jpg的图片一定要与.cpp文件同路径。
Mat src1 = img.clone();
imshow("原始图Canny边缘检测", img);
Mat dst, edge, gray;
dst.create(src1.size(), src1.type());
cvtColor(src1, gray, COLOR_BGR2GRAY);
blur(gray, edge, Size(3, 3));
Canny(edge, edge, 3, 9, 3);
dst = Scalar::all(0);//将g_dstImage内所有元素置0
src1.copyTo(dst, edge);//将原图g_srcImage拷贝到目标图g_dstImage中
imshow("效果图Canny边缘检测", dst);
imwrite("轮廓图.jpg", dst);
waitKey(0);
return 0;
}
原图如下:
程序执行结果如图:
7.1.3Sobel算子的使用
#include <opencv2\opencv.hpp>
#include<opencv2/highgui/highgui.hpp>
#include<opencv2/imgproc/imgproc.hpp>
using namespace cv;
int main()
{
Mat grad_x, grad_y;
Mat abs_grad_x, abs_grad_y, dst;
Mat img = imread("sg.jpg");//名为sg.jpg的图片一定要与.cpp文件同路径。
imshow("原始图Sobel边缘检测", img);
//求x方向梯度
Sobel(img, grad_x, CV_16S, 1, 0, 3, 1, 1, BORDER_DEFAULT);
//CV_16S是输出的图像深度
convertScaleAbs(grad_x, abs_grad_x);
imshow("效果图X方向Sobel", abs_grad_x);
//求y方向梯度
Sobel(img, grad_y, CV_16S, 0, 1, 3, 1, 1, BORDER_DEFAULT);
convertScaleAbs(grad_y, abs_grad_y);/*该函数对整个图像数组中的每一个元素,进行操作,可实现图像增强等相关先行操作的快速运算,也常用于将CV_16S、CV_32F等
其他类型的输出图像转变成CV_8U型的图像。*/
imshow("效果图Y方向Sobel", abs_grad_y);
//合并梯度
addWeighted(abs_grad_x, 0.5, abs_grad_y, 0.5, 0, dst);
imshow("效果图整体方向Spbel", dst);
imwrite("轮廓图01.jpg", abs_grad_x);
imwrite("轮廓图02.jpg", abs_grad_y);
imwrite("轮廓图03.jpg", dst);
waitKey(0);
return 0;
}
程序执行效果如图;Sobel整体方向图:
7.1.6边缘检测综合实例:
#include<opencv2/highgui/highgui.hpp>
#include<opencv2/imgproc/imgproc.hpp>
using namespace cv;
//原图,灰度图和目标图
Mat g_srcImage, g_srcGrayImage, g_dstImage;
//Canny边缘检测相关变量
Mat g_cannyDetectedEdges;
int g_cannyLowThreshold = 1;//Trackbar位置参数
//Sobel边缘检测相关变量
Mat g_sobelGradient_X, g_sobelGradient_Y;
Mat g_sobelAbsgradient_X, g_sobelAbsgradient_Y;
int g_sobelKernelSize = 1;
//Scharr滤波器相关变量
Mat g_scharrGradient_X, g_scharrGradient_Y;
Mat g_scharrAbsGradient_X, g_scharrAbsGradient_Y;
static void on_Canny(int, void*);
static void on_Sobel(int, void*);
void Scharr();
int main(int argc, char** argv)
{
system("color 2F");
g_srcImage = imread("sg.jpg");
if (!g_srcImage.data) {
printf("读取错误\n");return false;
}
namedWindow("原始图");
imshow("原始图", g_srcImage);
g_dstImage.create(g_srcImage.size(), g_srcImage.type());
cvtColor(g_srcImage, g_srcGrayImage, COLOR_BGR2GRAY);
namedWindow("效果图Canny边缘检测", WINDOW_AUTOSIZE);
namedWindow("效果图Sobel边缘检测", WINDOW_AUTOSIZE);
createTrackbar("参数值", "效果图Canny边缘检测", &g_cannyLowThreshold,
120, on_Canny);
createTrackbar("参数值", "效果图Sobel边缘检测", &g_sobelKernelSize,
3, on_Sobel);
on_Canny(0, 0);//调用回调函数
on_Sobel(0, 0);
Scharr();
while ((char(waitKey(1)) != 'q')) {}
return 0;
}
//Canny边缘检测窗口滚动条的回调函数
void on_Canny(int, void*)
{
blur(g_srcGrayImage, g_cannyDetectedEdges, Size(3, 3));
Canny(g_cannyDetectedEdges, g_cannyDetectedEdges, g_cannyLowThreshold,
g_cannyLowThreshold * 3, 3);
g_dstImage = Scalar::all(0);
g_srcImage.copyTo(g_dstImage, g_cannyDetectedEdges);
imshow("效果图Canny边缘检测", g_dstImage);
}
//Sobel边缘检测窗口滚动条的回调函数
void on_Sobel(int, void*)
{
Sobel(g_srcImage, g_sobelGradient_X, CV_16S, 1, 0, (2 * g_sobelKernelSize + 1),
1, 1, BORDER_DEFAULT);//CV_16S是输出的图像深度
convertScaleAbs(g_sobelGradient_X, g_sobelAbsgradient_X);
Sobel(g_srcImage, g_sobelGradient_Y, CV_16S, 0, 1, (2 * g_sobelKernelSize + 1),
1, 1, BORDER_DEFAULT);
convertScaleAbs(g_sobelGradient_Y, g_sobelAbsgradient_Y);
addWeighted(g_sobelAbsgradient_X, 0.5, g_sobelAbsgradient_Y, 0.5, 0, g_dstImage);
imshow("效果图Sobel边缘检测", g_dstImage);
}
//Scharr边缘检测,
void Scharr()
{
Scharr(g_srcImage, g_scharrGradient_X, CV_16S, 1, 0, 1,
0, BORDER_DEFAULT);//CV_16S是输出的图像深度
convertScaleAbs(g_scharrGradient_X, g_scharrAbsGradient_X);
Scharr(g_srcImage, g_scharrGradient_Y, CV_16S, 0, 1,
1, 0, BORDER_DEFAULT);
convertScaleAbs(g_scharrGradient_Y, g_scharrAbsGradient_Y);
addWeighted(g_scharrAbsGradient_X, 0.5, g_scharrAbsGradient_Y, 0.5, 0, g_dstImage);
imshow("效果图Scharr滤波器", g_dstImage);
}
程序执行效果如图;
1.Canny边缘检测:
2.Sobel边缘检测:
3.Scharr滤波器:
7.2.4标准霍夫变换:HoughLines()函数
#include<opencv2/highgui/highgui.hpp>
#include<opencv2/imgproc/imgproc.hpp>
using namespace cv;
using namespace std;
int main()
{
Mat srcImage = imread("tsg.jpg");
Mat midImage, dstImage;
Canny(srcImage, midImage, 50, 200, 3);
cvtColor(midImage, dstImage, COLOR_GRAY2BGR);//为什么是转化边缘检测后的图为灰度图?
vector<Vec2f>lines;
HoughLines(midImage, lines, 1, CV_PI / 180, 150, 0, 0);
for (size_t i = 0;i < lines.size();i++)
{
float rho = lines[i][0], theta = lines[i][1];
Point pt1, pt2;
double a = cos(theta), b = sin(theta);
double x0 = a*rho, y0 = b*rho;
pt1.x = cvRound(x0 + 1000 * (-b));
pt1.y = cvRound(y0 + 1000 * (a));
pt2.x = cvRound(x0 + 1000 * (-b));
pt2.y = cvRound(y0 + 1000 * (a));
line(dstImage, pt1, pt2, Scalar(55, 100, 195), 1, LINE_AA);
//以上参数含义:输入图像,线段起点、终点、线条颜色、线宽、线段类型。
}
imshow("原始图", srcImage);
imshow("Canny边缘检测图", midImage);
imshow("效果图", dstImage);
waitKey(0);
return 0;
}
程序执行结果如图:
7.2.5累计概率霍夫变换:HoughLinesP()
#include<opencv2/highgui/highgui.hpp>
#include<opencv2/imgproc/imgproc.hpp>
using namespace cv;
using namespace std;
int main()
{
Mat srcImage = imread("tsg.jpg");
Mat midImage, dstImage;
Canny(srcImage, midImage, 50, 200, 3);
cvtColor(midImage, dstImage, COLOR_GRAY2BGR);//为什么是转化边缘检测后的图为灰度图?
vector<Vec4i>lines;
HoughLinesP(midImage, lines, 1, CV_PI / 180, 80,50, 10);
/*以上参数含义:第三个是单位的距离精度,依次是:单位的角度精度、累加平面的阈值参数、
50表示最低线段的长度、10允许同一行点与点之间连起来的最大距离*/
for (size_t i = 0;i < lines.size();i++)
{
Vec4i l = lines[i];
line(dstImage,Point(l[0],l[1]),Point(l[2],l[3]), Scalar(186, 88, 255), 1, LINE_AA);
//以上参数含义:输入图像,线段起点、终点、线条颜色、线宽、线段类型。
}
imshow("原始图", srcImage);
imshow("Canny边缘检测图", midImage);
imshow("效果图", dstImage);
waitKey(0);
return 0;
}
程序执行结果如图:
7.2.9霍夫圆变换:HoughCircles():
#include<opencv2/highgui/highgui.hpp>
#include<opencv2/imgproc/imgproc.hpp>
using namespace cv;
using namespace std;
int main()
{
Mat srcImage = imread("qiu.jpg");
Mat midImage, dstImage;
imshow("原始图", srcImage);
cvtColor(srcImage,midImage, COLOR_BGR2GRAY);//彩色图转化为灰度图
GaussianBlur(midImage, midImage, Size(9, 9), 2, 2);
vector<Vec3f>circles;
HoughCircles(midImage,circles, HOUGH_GRADIENT, 1.5,10,200,100,0,0);
/*以上参数含义:第三个是检测算法,依次是:检测圆心的累加器图像的分辨率与输入图像之比的倒数、
10表示圆心与圆心之间的最小距离、200、100分别是累加器阈值的上下限,0、0分别是圆半径的最小和最大值*/
for (size_t i = 0;i < circles.size();i++)
{
Point center(cvRound(circles[i][0]), cvRound(circles[i][1]));
int radius = cvRound(circles[i][2]);
circle(srcImage, center,3, Scalar(0,255, 0), -1, 8, 0);//绘制圆心
//-1表示一个实心的圆心
circle(srcImage, center, radius, Scalar(155,50, 255), 3, 8, 0);//绘制圆的轮廓
//3表示元的线条粗细,若是负数表示填充圆。8表示线条类型
}
imwrite("2.jpg",srcImage);
imshow("效果图", srcImage);
waitKey(0);
return 0;
}
7.2.10综合示例:
#include<opencv2/highgui/highgui.hpp>
#include<opencv2/imgproc/imgproc.hpp>
using namespace cv;
using namespace std;
Mat g_srcImage, g_dstImage, g_midImage;
vector <Vec4i> g_lines;
int g_nthreshold = 100;
static void on_HoughLines(int, void*);
int main()
{
system("color 3F");
Mat g_srcImage = imread("tsg.jpg");
imshow("原始图", g_srcImage);
namedWindow("效果图", 1);
createTrackbar("值", "效果图", &g_nthreshold, 200, on_HoughLines);
Canny(g_srcImage, g_midImage, 50, 200, 3);
cvtColor(g_midImage, g_dstImage, COLOR_GRAY2BGR);//为什么是转化边缘检测后的图为灰度图?
on_HoughLines(g_nthreshold, 0);
HoughLinesP(g_midImage, g_lines, 1, CV_PI / 180, 80, 50, 10);
imshow("效果图", g_dstImage);
waitKey(0);
return 0;
}
static void on_HoughLines(int, void*)
{
Mat dstImage = g_dstImage.clone();
Mat midImage = g_midImage.clone();
vector <Vec4i>mylines;
HoughLinesP(midImage, mylines,1, CV_PI / 180, g_nthreshold + 1, 50, 10);
for (size_t i = 0;i < mylines.size();i++)
{
Vec4i l = mylines[i];
line(dstImage, Point(l[0], l[1]), Point(l[2], l[3]), Scalar(23, 180, 55), 1, LINE_AA);
}
imshow("效果图", dstImage);
}
程序执行结果如图: