赞
踩
参数解释:
image:输入图像,类型为8字节,即CV_8UC1(灰度图),或者CV_8UC3(彩色图片)也可以。
edges:输出边缘图像,和输入图像大小一致,类型为CV_8UC1,单通道图像。
threshold1:低阈值
threshold2:高阈值
apertureSize:Sobel导数算子的大小。
L2gradient:计算方向梯度的方法。
#include <iostream> #include <opencv2/opencv.hpp> #include <opencv2/highgui.hpp> #include <opencv2/imgproc.hpp> #include <opencv2/videoio.hpp> #include<sstream> using std::cout; using std::endl; int main(int argc, char* argv[]) { std::string image_path = "C:\\Users\\hp\\Desktop\\demo\\8.jpg"; //图片的路径 cv::Mat img = cv::imread(image_path, 1); cv::Mat edge; cv::namedWindow("example", 1); //创建一个窗口用于显示源图像,1代表窗口适应图像的分辨率进行拉伸。 cv::namedWindow("dst", 1); //显示Canny结果 int first_th = 50; //初始化第一个阈值 int second_th = 150; //初始化第二个阈值 while (true) { cv::Canny(img, edge, first_th, second_th, 3, false); //边缘检测 //std::cout << "The channels of edges is: " << edge.channels() << " Type is: " << edge.type() << // " Depth: " << edge.depth() << std::endl; //int elem = edge.at<unsigned char>(20, 20); //cout << "elem: " << elem << endl; if (img.empty() == false) //图像不为空则显示图像 { cv::imshow("example", img); } if (edge.empty() == false) { cv::imshow("dst", edge); } int key = cv::waitKey(30); //等待任意键盘事件30ms if (key == int('q')) break; if (key == int('a')) --first_th; //按a减小第一个阈值 if (key == int('s')) ++first_th; //按s增加第一个阈值 if (key == int('d')) --second_th; //按d减小第二个阈值 if (key == int('f')) ++second_th; //按f增加第二个阈值 cout << "FIRST: " << first_th << " " << "SECOND: " << second_th << endl; //打印两个阈值 } cv::destroyAllWindows(); //关闭所有窗口 return 0; }
需要输入你自己的图片路径才能运行。
在英文输入法下,按q退出。按a减小第一个阈值,按s增加第一个阈值。
按d减小第二个阈值,按f增加第二个阈值。可以动态调整阈值观察边缘检测的效果。
threshold1:50, threshold2:150
threshold1:30, threshold2:90
Canny算法先在x、y方向上求一阶导数,然后将它们组合成四个方向的导数,具有方向导数局部最大值的点组成边缘的候选项。然后使用两个滞后阈值threshold1与threshold2来形成最后的边缘,如果某像素点所在处的方向导数大于threshold2,则认为是边缘点,若小于threshold1,则认为不是边缘点,若介于两者之间,那么需要该像素点连接到一个“边缘点”才认为它是边缘。
在上面的图片中,减小两个阈值可以看出会带来更多“细小的”边缘。
建议threshold1:threshold2 = 1:3。
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。