六、Hough变换
1.Hough线变换
Hough线变换是一种用来寻找直线的方法。首先要对图像进行边缘检测处理,Hough线变换的直接输入只能是边缘的二值图像。
- 标准霍夫变换(HoughLines函数)
- 多尺度霍夫变换(HoughLines函数)
- 累计概率霍夫变换(HoughLinesP函数)
1.首先对于一个点
,通过这个点的直线定义为:
2.而对于一个定点
,则可以
画出所有通过此点的线,例如点(8,6)则有:
3.继续对其他点进行画图,则有:
4.而三条线相交的一点
,则是三条线的共同参数,表明三点在同一条直线上。
5.于是,可以通过寻找在平面
交于一点的曲线数量来检测同一条直线上的点。之后通过设置阈值来定义相交点是否满足条件。
6.若交于一点的曲线数量超过阈值,那么可以认为这个交点所代表的参数对
在原图中为一条直线。
1.1HoughLines()函数
void HoughLines(InputArray image,
OutputArray lines,
double rho,
double theta,
int threshold,
double srn=0,
double stn=0 )
参数1:输入图像。参数2:存储了检测的线条的输出矢量。每条直线由具有两个元素的矢量
参数3:以像素为单位的距离精度。
参数4:以弧度为单位的角度精度。
参数5:阈值。
参数6:对于多尺度的霍夫变换,这是第三个参数进步尺寸rho的除数距离。粗略的累加器进步尺寸直接是第三个参数rho,而精确的累加器进步尺寸为rho/srn。
参数7:对于多尺度霍夫变换,srn表示第四个参数进步尺寸的单位角度theta的除数距离。且如果srn和stn同时为0,就表示使用经典的霍夫变换。否则,这两个参数应该都为正数。
int main( )
{
//【1】载入原始图和Mat变量定义
Mat srcImage = imread("1.jpg");
Mat midImage,dstImage;//临时变量和目标图的定义
//【2】进行边缘检测和转化为灰度图
Canny(srcImage, midImage, 50, 200, 3);//进行一此canny边缘检测
cvtColor(midImage,dstImage, CV_GRAY2BGR);//转化边缘检测后的图为灰度图
//【3】进行霍夫线变换
vector<Vec2f> lines;//定义一个矢量结构lines用于存放得到的线段矢量集合
HoughLines(midImage, lines, 1, CV_PI/180, 150, 0, 0 );
//【4】依次在图中绘制出每条线段
for( size_t i = 0; i < lines.size(); i++ )
{
float rho = lines[i][0], theta = lines[i][1];
Point pt1, pt2;
double a = cos(theta), b = sin(theta);
double x0 = a*rho, y0 = b*rho;
pt1.x = cvRound(x0 + 1000*(-b));
pt1.y = cvRound(y0 + 1000*(a));
pt2.x = cvRound(x0 - 1000*(-b));
pt2.y = cvRound(y0 - 1000*(a));
line( dstImage, pt1, pt2, Scalar(55,100,195), 1, CV_AA);
}
//【5】显示原始图
imshow("【原始图】", srcImage);
//【6】边缘检测后的图
imshow("【边缘检测后的图】", midImage);
//【7】显示效果图
imshow("【效果图】", dstImage);
waitKey(0);
return 0;
}
1.2HoughLinesP()函数
void HoughLinesP(InputArray image,
OutputArray lines,
double rho,
double theta,
int threshold,
double minLineLength=0,
double maxLineGap=0 )
参数1:输入图像。
参数2:存储线条的输出矢量。
参数3:以像素为单位的距离精度。
参数4:以弧度为单位的角度精度。
参数5:阈值。
参数5:阈值。
参数6:最低线段的长度,默认值为0。
参数7:同一行点与点之间连接起来的最大距离,默认值为0。
int main( )
{
//【1】载入原始图和Mat变量定义
Mat srcImage = imread("1.jpg");
Mat midImage,dstImage;//临时变量和目标图的定义
//【2】进行边缘检测和转化为灰度图
Canny(srcImage, midImage, 50, 200, 3);//进行一此canny边缘检测
cvtColor(midImage,dstImage, CV_GRAY2BGR);//转化边缘检测后的图为灰度图
//【3】进行霍夫线变换
vector<Vec4i> lines;//定义一个矢量结构lines用于存放得到的线段矢量集合
HoughLinesP(midImage, lines, 1, CV_PI/180, 80, 50, 10 );
//【4】依次在图中绘制出每条线段
for( size_t i = 0; i < lines.size(); i++ )
{
Vec4i l = lines[i];
line( dstImage, Point(l[0], l[1]), Point(l[2], l[3]), Scalar(186,88,255), 1, CV_AA);
}
//【5】显示原始图
imshow("【原始图】", srcImage);
//【6】边缘检测后的图
imshow("【边缘检测后的图】", midImage);
//【7】显示效果图
imshow("【效果图】", dstImage);
waitKey(0);
return 0;
}
2.Hough圆变换
霍夫梯度法原理:
1.对图像进行边缘检测。
2.对边缘图像中的每一个非零点,考虑其局部梯度,即用Sobel()函数计算X和Y方向的一阶导数得到梯度。
3.利用得到的梯度,由斜率指定的直线上的每一个点都在累加器中被累加。斜率指的是从一个指定的最小值到指定的最大值的距离。
4.标记图像中每一个非0像素的位置。
5.从二维累加器中这些点钟选择候选的中心,这些中心都大于给定阈值并且大于其所有近邻。这些候选中心按照累加值降序排列,以便于最支持像素的中心首先出现。
6.对每个中心,考虑所有的非0像素。
7.这些像素按照其与中心的距离排序。从最大半径的最小距离算起,选择非0像素最支持的一条半径。
8.如果一个中心收到边缘图像非0像素的最充分支持,并且前期被选择的中心有足够的距离,那么它就会被保留下来。
void HoughCircles(InputArray image,
OutputArray circles,
int method,
double dp,
double minDist,
double param1=100,
double param2=100,
int minRadius=0,
int maxRadius=0 )
参数1:输入像素。
参数2:存储检测圆的矢量,每个矢量由包含了3个元素的浮点矢量(x,y,radius)表示。
参数3:检测方法,目前使用CV_HOUGH_GRADIENT。
参数4:若dp=1,累加器和输入图像具有相同的分辨率;若dp=2,累加器只有输入图像的一半那么大的宽度和高度。即输入图像与累加器大小的比值。
参数4:若dp=1,累加器和输入图像具有相同的分辨率;若dp=2,累加器只有输入图像的一半那么大的宽度和高度。即输入图像与累加器大小的比值。
参数5:区分两个不同检测到的圆之间的最小距离。
参数6:检测方法的参数,即canny检测算子的高阈值,而低阈值为高阈值的一半。
参数7:检测方法的参数,为检测阶段圆心的累加器阈值。越小就可以检测到更多的圆甚至不存在的圆,越大则通过的圆就越接近完美的圆形。
参数8:圆半径最小值,默认值为0。
参数9:圆半径最大值,默认值为0。
int main( )
{
//【1】载入原始图和Mat变量定义
Mat srcImage = imread("1.jpg");
Mat midImage,dstImage;//临时变量和目标图的定义
//【2】显示原始图
imshow("【原始图】", srcImage);
//【3】转为灰度图,进行图像平滑
cvtColor(srcImage,midImage, CV_BGR2GRAY);//转化边缘检测后的图为灰度图
GaussianBlur( midImage, midImage, Size(9, 9), 2, 2 );
//【4】进行霍夫圆变换
vector<Vec3f> circles;
HoughCircles( midImage, circles, CV_HOUGH_GRADIENT,1.5, 10, 200, 100, 0, 0 );
//【5】依次在图中绘制出圆
for( size_t i = 0; i < circles.size(); i++ )
{
Point center(cvRound(circles[i][0]), cvRound(circles[i][1]));
int radius = cvRound(circles[i][2]);
//绘制圆心
circle( srcImage, center, 3, Scalar(0,255,0), -1, 8, 0 );
//绘制圆轮廓
circle( srcImage, center, radius, Scalar(155,50,255), 3, 8, 0 );
}
//【6】显示效果图
imshow("【效果图】", srcImage);
waitKey(0);
return 0;
}
特别说明:本文为本人学习opencv所做笔记。具体参照:http://blog.csdn.net/column/details/opencv-tutorial.html