【C++ OpenCV】 Canny算子边缘检测

1.Canny算子算法介绍

a.高斯模糊——GaussianBlur
b. 灰度转换——cvtColor
c. 计算梯度——Sobel/Scharr
d. 非最大信号抑制
e. 高低阈值输出二值图像

2.非最大信号抑制

首先经过梯度的计算,得到X,Y方向上的两个梯度,然后计算总梯度(对GX,GY的平方和开平方或者绝对值相加)
X方向

-1 0 +1
-2 0 +2
-1 0 +1

Y方向

-1 -2 -1
0 0 0
+1 +2 +1

梯度计算公式:
G=√Gx2+Gy2
梯度方向(0-180)
α = a r c t a n ( G   y   / G   x   ) \alpha=arctan(G~y~/G~x~) α=arctan(G y /G x )
根据方向做切线,在切线方向上看左右两个相邻的两个像素,如果大于左右两个像素,则记为边缘,若小于左右两个像素,则该像素值像素值应该用0填充。

3.高低阈值输出二值图像

T1,T2为阈值,凡是和高于T2的都保留,凡是小于T1的都丢弃,从高于T2的像素出发,凡是大于T1而且相互连接的,都保留,最终得到一个输出二值图像。
推荐的高低阈值比值为T2:T1=3:1/2:1,其中T2为高阈值,T1为低阈值。

4.Canny算子API

Canny(
InputArray src,		//8-bit的输入图像
OutputArray edges,   //输出边缘图像,一般都是二值图像,背景是黑色
double threshold1,    //低阈值,常取高阈值的1/2或者1/3
double threshold2,    //高阈值
int aptertureSize,     //Sobel算子的size,通常是3*3,取值3
bool L2gradient      //选择true表示是L2来归一化,否则用L1归一化
)

代码演示:

#include 
#include
#include

using namespace cv;

Mat src, dstGaussian,dst;
Mat gray;
int t1_value = 40;     //滑块的初始值
int max_value = 255;   //滑块的最大值
const char* OUTPUT_TITLE = "Canny Result";

void Canny_Demo(int,void*) {
	Mat edge_output;
	//GaussianBlur(gray, dstGaussian, Size(3, 3), 0, 0);
	blur(gray, dstGaussian, Size(3, 3), Point(-1,-1), BORDER_DEFAULT);
	Canny(dstGaussian, edge_output, t1_value, t1_value * 2, 3, false);

	dst.create(src.size(), src.type());
	src.copyTo(dst, edge_output);  //把边缘中非零的复制过去,显示出来彩色图像
		//函数的说明:把edge_output作为一个mask,mask上为0的图像不复制,复制值为1的图像。
			//dege_output本身就是一个二值图像


	imshow(OUTPUT_TITLE, edge_output);

	imshow(OUTPUT_TITLE, ~edge_output);  
	  //在dege_output前面加上~,表示把原来黑色变成白色,白色变成黑色
}




int main(int argc, int argv) {
	src = imread("D:/image/img1.jpg");
	if (src.empty()) {
		printf("could not load image...\n");
		return -1;
	}

	imshow("src", src);

	cvtColor(src, gray, COLOR_BGR2GRAY);
	createTrackbar("Threshold Value:",OUTPUT_TITLE,&t1_value,max_value,Canny_Demo);
	Canny_Demo(0,0);
	waitKey(0);
	return 0; 
}

你可能感兴趣的:(Opencv,c++版)