1.代码实现功能
这个程序是做什么的?
1.要求用户输入数值以设置我们的Canny Edge Detector的下限(通过Trackbar)。
2.应用Canny Detector并生成一个蒙版(亮线表示黑色背景上的边缘)。
3.应用在原始图像上获得的蒙版,并将其显示在窗口中。
2.代码
#include "opencv2/imgproc.hpp"
#include "opencv2/imgcodecs.hpp"
#include "opencv2/highgui.hpp"
using namespace cv;
Mat src, src_gray;
Mat dst, detected_edges;
int edgeThresh = 1;
int lowThreshold;
int const max_lowThreshold = 100;
int ratio = 3;
int kernel_size = 3;
const char* window_name = "Edge Map";
static void CannyThreshold(int, void*)
{
blur( src_gray, detected_edges, Size(3,3) );
Canny( detected_edges, detected_edges, lowThreshold, lowThreshold*ratio, kernel_size );
dst = Scalar::all(0);
src.copyTo( dst, detected_edges);
imshow( window_name, dst );
}
int main( int, char** argv )
{
src = imread( argv[1], IMREAD_COLOR ); // Load an image
if( src.empty() )
{ return -1; }
dst.create( src.size(), src.type() );
cvtColor( src, src_gray, COLOR_BGR2GRAY );
namedWindow( window_name, WINDOW_AUTOSIZE );
createTrackbar( "Min Threshold:", window_name, &lowThreshold, max_lowThreshold, CannyThreshold );
CannyThreshold(0, 0);
waitKey(0);
return 0;
}
3.代码分析
分析代码一般从主函数开始,请先忽略上面的那些定义的变量。我们直接到主函数开始。
int main( int, char** argv )
{
src = imread( argv[1], IMREAD_COLOR ); // Load an image
if( src.empty() )
{ return -1; }
dst.create( src.size(), src.type() );
cvtColor( src, src_gray, COLOR_BGR2GRAY );
namedWindow( window_name, WINDOW_AUTOSIZE );
createTrackbar( "Min Threshold:", window_name, &lowThreshold, max_lowThreshold, CannyThreshold );
CannyThreshold(0, 0);
waitKey(0);
return 0;
}
第一行读取图像来自命令行的第一个参数。
imread我的笔记中有对该函数的注解
第二行对图像的判断是否为空。
empty是用来检测函数是否为空
第三行如果为空返回错误值
第四行如果创建我们需要进行检测的照片存储地址
create函数我的笔记中也有记载。
第五行将RGB转换成灰度图
cvtcolor函数
void cv::cvtColor(
cv::InputArray src;
cv::OutputArray dst;
int code;
int dstCn = 0 ;)
)
. InputArray src: 原图像
. OutputArray dst: 颜色空间变换后存储图像
. int code: 转换的代码或标识
. int dstCn = 0: 目标图像通道数,如果取值为0,则由src和code决定
第六行预设窗口
之前笔记中有
第七行
函数代码意义可参考
https://www.cnblogs.com/geek-hao/p/11668248.html
主要重点函数
CannyThreshold
Trackbar要控制的变量是lowThreshold,最大值为max_lowThreshold(我们先前设置为100)
每次Trackbar注册一个动作时,将调用回调函数CannyThreshold。
让我们检查CannyThreshold函数,一步一步:
首先,我们用内核大小为3的过滤器模糊图像:
blur(src_gray,detected_edges,Size(3,3));
然后,我们应用OpenCV函数cv :: Canny:
Canny(detected_edges,detected_edges,lowThreshold,lowThreshold * ratio,kernel_size);
其中的解释:
detected_edges:源图像,灰度
detected_edges:检测器的输出(可以与输入相同)
lowThreshold:用户移动轨迹栏输入的值
highThreshold:在程序中设置为下限阈值的三倍(在Canny的建议之后)
kernel_size:我们将它定义为3(要在内部使用的Sobel内核的大小)
我们用零填充dst图像(意味着图像是完全黑色的)。
dst = Scalar :: all(0);
最后,我们将使用函数cv :: Mat :: copyTo仅映射被识别为边缘的图像的区域(在黑色背景上)。cv :: Mat :: copy将src映像复制到dst上。但是,它只会复制它们具有非零值的位置中的像素。由于Canny检测器的输出是黑色背景上的边缘轮廓,因此所得到的dst在所有区域都将为黑色,但检测到的边缘为黑色。
src.copyTo(dst,detected_edges);
我们显示结果:
imshow(window_name,dst);