Canny边缘检测

1、Canny算法内容;
2、API : cv::canny();
3、代码演示;

Canny算法

1、Canny算法是一种边缘检测算法,1986年提出,是一个很好的边缘检测器,很常用也很实用的图像处理方法(提取边缘);

Canny算法步骤

Canny算法的主要步骤如下:
1. 高斯模糊(用于降噪,尽量去除噪声对最终图像的干扰);
2. 灰度转换(将图像转换为灰度图像);
3. 计算图像梯度(Sobel、Scharr);
4. 非最大信号抑制;
5. 高低阈值输出二值图像;(高低阈值连接)

注:非最大信号抑制是指:边缘的信号很强,梯度很大,但边缘只能有一个,对于非边缘的像素点进行抑制,即非最大信号抑制,如果在它的梯度方向上其不是最大值,就将其去掉。
高低阈值连接:经过非最大信号抑制操作后,边缘已经很明显了,但部分边缘由于干扰没有连接起来,使用高低阈值可以将边缘连接起来(大于最高阈值保留,小于最低阈值丢弃,在两者之间,进行高低阈值连接),高低阈值连接后,即可输出对应的二值图像

非最大信号抑制实现

1、根据前几步的计算,可以得到X方向上的梯度Gx,Y方向上的梯度GY,以及合成后的梯度G;以及梯度的夹角θ;如下图所示;
2、θ代表梯度的方向,取值(0°~180°),如果X方向梯度大,θ就会很小,如果Y方向梯度大,θ就趋近90°;
3、理论…

高低阈值输出二值图像

如下:

API说明

1、Canny()算法API:Canny();
注: Canny(): 不支持彩色图像输入,只能输入8位灰度图像
L1/L2的选择是决定使用完整归一化(true)还是使用简化归一化(有误差)(false)求取X,Y混合后的梯度;
一般不使用L2,L1精度足够了;

Code

代码说明:
1、可以先转换为灰度图像,再进行滤波操作;
2、src.copyto(dst,edge_image): 将Canny计算得到的二值图像作为函数的掩膜(遮盖层),这样做,可以从原图像中提取出轮廓的彩色图像(只有非0的元素才能被Copy);
3、二值图像对象前加~可以对像素值取反,改变图像背景***r> 4、Canny计算速度比较慢,同时,高低阈值的选取会影响最终的输出结果,使用时最好先找到合适的高低阈值;Canny()算法最终输出的是二值图像;阈值设置越低,保留的细节越多;

#include <opencv2/opencv.hpp>
#include <iostream>

using namespace std;
using namespace cv;

Mat src, dst, graysrc;
int t1_value = 50;
int max_value = 255;
const char * OUTPUT_WIN = "Canny Result";
void Canny_Demo(int, void*);
int main(int argc, char** argv)
{
   
	
	src = imread("C:\\Users\\hello\\Desktop\\lena512color.tiff");
	if (!src.data)
	{
   
		cout << "could not load the image..." << endl;
		return -1;
	}
	namedWindow("input image",CV_WINDOW_AUTOSIZE);
	imshow("input image", src);
	namedWindow(OUTPUT_WIN, CV_WINDOW_AUTOSIZE);

	cvtColor(src, graysrc, CV_BGR2GRAY); //转换为灰度图像
	//创建滑动条
	createTrackbar("Threshold Value:", OUTPUT_WIN, &t1_value, max_value, Canny_Demo);
	Canny_Demo(0, 0);

	waitKey(0);
	return 0;
}
void Canny_Demo(int, void*)
{
   
	Mat edge_output;
	//blur(graysrc, graysrc, Size(3, 3), Point(-1, -1), BORDER_DEFAULT);//均值滤波
	GaussianBlur(graysrc, graysrc, Size(3, 3), 0, 0);
	Canny(graysrc, edge_output, t1_value, t1_value * 2, 3, false);

	imshow(OUTPUT_WIN, ~edge_output);

	//低阈值高阈值会影响Canny运算的结果,应该首先找到一个合适的值

	dst.create(src.size(), src.type());//调用create方法对mat初始化
	//mask非0,则将图像拷贝到dst,是0,则不拷贝,Canny运算后会将边缘保留,为1,作为掩膜计算即可得到边缘图像
	src.copyTo(dst, edge_output);//将二值图像中1的像素提取到新的图像中,形成彩色图片
	//imshow(OUTPUT_WIN, dst);

}

效果

Canny计算原始图:(二值图像)

反转颜色图:

彩色图片提取图:(保留彩色图像中轮廓的像素点)