用于对图像的边缘检测
void cvCanny( const CvArr* image,CvArr*edges,double threshold1,double threshold2, int aperture_size=3 );
image 输入单通道图像(可以是彩色图像)对于多通道的图像可以用cvCvtColor(将图像从一个颜色空间转换到另一个颜色空间的转换)修改。
edges 输出的边缘图像,也是单通道的,但是是黑白的
threshold1 第一个阈值(低阈值)
threshold2 第二个阈值(高阈值)
aperture_size Sobel 算子内核大小(滤波计算矩阵的大小默认为3)可以是1、3、5、7
函数 cvCanny 采用 Canny 算法发现输入图像的边缘而且在输出图像中标识这些边缘。
注释:threshold1和threshold2 当中的小阈值用来控制边缘连接,大的阈值用来控制强边缘的初始分割。
高阈值比较严格,求的边缘很少,认为高阈值的边缘都是有效。低阈值宽松,求的边缘很多(一般包括了高阈值求到的边缘),其中不少是无效的边缘(反正不想要的)。
先用高阈值求边缘。canny求得的边缘希望是连在一起的(通常是封闭的),但高阈值求的边缘一般断断续续。断开的地方如果低阈值求的边缘存在,就用低阈值的边缘接上去,目的让边缘尽量都连在一起。其它情况下低阈值的边缘是不用的。
两个阈值是有区别的,高的那个阈值是将要提取轮廓的物体与背景区分开来,就像阈值分割的那个参数一样,是决定目标与背景对比度的,低的那个阈值是用来平滑边缘的轮廓,有时高的阈值设置太大了,可能边缘轮廓不连续或者不够平滑,通过低阈值来平滑轮廓线,或者使不连续的部分连接起来
第一步:灰度化
第二步:高斯滤波
第三步:计算梯度值和方向
第四步:非极大值抑制
第五步:双阈值的选取
第六步:边缘检测
// 应用Canny算法
cv::Mat contours;
cv::Canny(image, // 灰度图像
contours, // 输出轮廓
125, // 低阈值
350); // 高阈值
//canny算子
#include
#include
#include
#include
#include
using namespace std;
using namespace cv;
Mat srcImage, grayImage, dstImage;
int edgeThresh = 1;
int lowThreshold;
int const max_lowThreshold = 100;
int ratio = 3; //阈值倍数
int kernel_size = 3; //Sobel算子孔径尺寸
const String windowName = "Canny算子边缘检测";
double fscale=0.5;
Size outSize;
Mat ResizeImage;
//声明回调函数
void CannyThreshold(int,void*);
int main()
{
srcImage = imread("zjl.bmp"); //读取图像
outSize.width=srcImage.cols*fscale; //读取图像行
outSize.height=srcImage.rows*fscale; //读取图像列
resize(srcImage,ResizeImage,outSize,0,0,INTER_AREA); //缩小图像0.15倍
srcImage=ResizeImage; //复制图像
if (srcImage.empty())
{
cout << "图像加载失败!" << endl;
return -1;
}
else
cout << "图像加载成功!" << endl;
//高斯滤波转灰度图
GaussianBlur(srcImage, srcImage, Size(3, 3), 0, 0, BORDER_DEFAULT);
cvtColor(srcImage, grayImage, COLOR_BGR2GRAY);
namedWindow("原始图像", WINDOW_AUTOSIZE);
imshow("原始图像", grayImage);
//定义轨迹属性
namedWindow(windowName, WINDOW_AUTOSIZE);
char trackbarName[20];
sprintf(trackbarName, "阈D值¦Ì", max_lowThreshold);
lowThreshold = 20;
//创建迹条
createTrackbar(trackbarName, windowName, &lowThreshold, max_lowThreshold, CannyThreshold);
CannyThreshold(lowThreshold, 0);
waitKey(0);
return 0;
}
void CannyThreshold(int,void*)
{
Canny(grayImage, dstImage, lowThreshold, lowThreshold*ratio, kernel_size);
imshow(windowName, dstImage);
waitKey(0);
}