主要内容:
1. 通过Canny算子检测图像轮廓
2. Hough变换检测图像中的直线
3.通过一系列点拟合直线
4.检测组件的轮廓
5. 组件轮廓的描述
一、引言
为了能执行对图形基本内容的分析,从由一系列像素组成的图像中检测出有意义的特点来是有必要的,例如轮廓,直线,斑点等图像的基本组件。本节将教大家怎样检测这些图像中有用的组件。
二、通过Canny算子检测图像轮廓
在前面我们介绍了通过高通滤波器方法(Sobel和Laplace)方法很方便的检测出图像的轮廓。我们对梯度幅值的设置门限来显示一个二进制的图像轮廓。轮廓带有很重要的视觉信息,因此轮廓检测被广泛使用,例如目标识别。但是,简单的二进制边缘图像有两个缺点:一是边缘检测图形有些线条太粗,不适合精准的表达物体的形状。第二点,也是比较重要的一点是,门限值的选择,很难足够低,以致显示所有重要目标的边缘,也很难足够高,使得不包含太多没有用的边缘,这是一个需要权衡的问题,
Canny算法就尝试解决这个问题。
2.1 Canny算法实现目标和步奏
Canny算法实现的目标:
1.低误差率:只检测存在的边缘
2.良好的定位性:边缘比较细,与真实边缘的距离小
3.最小响应:每个边缘只响应一个检测器
Canny边缘检测是John F.Canny 提出的广为人知的边缘检测算法,其实现步奏是
1.高斯滤波
2.通过上下限,分别对图形进行类似Sobel算法的边缘检测,
3.滞后阈值化
1)超过最大阈值的点,是边缘点
2)比最小阈值点小的点,不作为边缘点
3)介于两者之间的的点,与上限相连的点是边缘点
4)上下限阈值推荐比例为3:2
2.2 Canny算子的opencv实现
opencv中提供Canny算子函数,
//! applies Canny edge detector and produces the edge map.
CV_EXPORTS_W void Canny( InputArray image, OutputArray edges,
double threshold1, double threshold2,
int apertureSize=3, bool L2gradient=false );
使用实例:
cv::Canny(image,contours,125,350);
程序实例:
// Read input image
cv::Mat image= cv::imread("road.jpg",0);
if (!image.data)
return 0;
// Display the image
cv::namedWindow("Original Image");
cv::imshow("Original Image",image);
cv:imwrite("Original Image.jpg",image);
// Compute Sobel
EdgeDetector ed;
ed.computeSobel(image);
// Display the Sobel orientation
cv::namedWindow("Sobel (orientation)");
cv::imshow("Sobel (orientation)",ed.getSobelOrientationImage());
cv::imwrite("ori.bmp",ed.getSobelOrientationImage());
// Display the Sobel low threshold
cv::namedWindow("Sobel (low threshold)");
cv::imshow("Sobel (low threshold)",ed.getBinaryMap(125));
cv::imwrite("Sobel (low threshold).jpg",ed.getBinaryMap(125));
// Displa