开启成长之旅!这是我参与「日新方案 12 月更文挑战」的第28天
1 霍夫线改换的原理
(1)众所周知,一条直线在图画二维空间可由两个变量表明,有以下两种状况。如图所示。
①在笛卡尔坐标系:可由参数斜率和截距(m,b)表明。
②在极坐标系:可由参数极径和极角(r,)表明。
关于霍夫改换,咱们将采用第二种方法极坐标系来表明直线.因此,直线的表达式可为:
化简便可得到:
(2)一般来说关于点(xoyo),能够将经过这个点的一族直线一致界说为:
这就意味着每一对(ro,)代表一条经过点(xoyo)的直线。
(3)假如关于一个给定点(xoyo),咱们在极坐标对极径极角平面绘出所有经过它的直线,将得到一条正弦曲线.例如,关于给定点x0=8和yo=6能够绘出如图所示平面图。
只绘出满足下列条件的点r>0和.0<<2。
(4)咱们能够对图画中所有的点进行上述操作,假如两个不同点进行上述操作后得到的曲线在平面—r相交,这就意味着它们经过同一条直线。例如,接上面的比如持续对点x1=9,y1=4和点x2=12,y2=3绘图,得到图7.18。
这三条曲线在平面相交于点(0.925,9.6),坐标表明的是参数对—r或者是说点(xoyo),点(x1y1)和点(x2y2)组成的平面内的的直线。
(5)以上的阐明表明,一般来说,一条直线能够经过在平面—r寻觅交于一点的曲线数量来检测。而越多曲线交于一点也就意味着这个交点表明的直线由更多的点组成。一般来说咱们能够经过设置直线上点的阈值来界说多少条曲线交于一点,这样才以为检测到了一条直线。
(6)这便是霍夫线改换要做的。它追寻图画中每个点对应曲线间的交点.假如交于一点的曲线的数量超过了阈值,那么能够以为这个交点所代表的参数对(,ro)在原图画中为一条直线。
2 标准霍夫改换:HoughLines()函数
此函数能够找出采用标准霍夫改换的二值图画线条。在OpenCV中,咱们能够用其来调用标准霍夫改换SHT和多标准霍夫改换MSHT的OpenCV内建算法。
C++:
void HoughLines(InputArray image, OutputArray lines, double rho, double theta,
int threshold, double srn=0, double stn=0);
- 第一个参数,InputArray类型的image,输入图画,即源图画。需为8位的单通道二进制图画,能够将任意的源图载入进来,并由函数修改成此格式后,再填在这儿。
- 第二个参数,InputArray类型的lines,经过调用 HoughLines 函数后储存了霍 夫线改换检测到线条的输出矢量。每一条线由具有两个元素的矢量(p,)表明,其间,p是离坐标原点(0,0)(也便是图画的左上角)的间隔,是弧度线条旋转视点(0度表明垂直线,/2度表明水平线)。
- 第三个参数,double类型的rho,以像素为单位的间隔精度。另一种表述方法是直线查找时的前进标准的单位半径。(Latex 中/rho即表明p)
- 第四个参数,double类型的theta,以弧度为单位的视点精度。另一种表述方法是直线查找时的前进标准的单位视点。
- 第五个参数,int类型的threshold,累加平面的阈值参数,即辨认某部分为图中的一条直线时它在累加平面中有必要达到的值。大于阈值threshold的线段才能够被检测经过并返回到成果中。
- 第六个参数,double类型的srn,有默认值0。关于多标准的霍夫改换,这是第三个参数前进标准 rho的除数间隔。大略的累加器前进标准直接是第三个参数rho,而精确的累加器前进标准为rho/srn。
- 第七个参数,double 类型的 stn,有默认值0,关于多标准霍夫改换,smn表明第四个参数前进标准的单位视点 theta的除数间隔。且假如 srn和stn一起为0,就表明运用经典的霍夫改换。否则,这两个参数应该都为正数。
学完函数解析后,看一个以HoughLines为核心的示例程序,就能够全方位了解HoughLines函数的运用方法。
3 示例
代码:
//---------------------------------【头文件、命名空间包括部分】----------------------------
// 描绘:包括程序所运用的头文件和命名空间
//---------------------------------------------------------------------------------------
#include <opencv2/opencv.hpp>
#include <opencv2/imgproc/imgproc.hpp>
using namespace cv;
//-----------------------------------【main( )函数】--------------------------------------------
// 描绘:控制台应用程序的进口函数,咱们的程序从这儿开端
//---------------------------------------------------------------------------------------------
int main( )
{
//【1】载入原始图和Mat变量界说
Mat srcImage = imread("1.jpg"); //工程目录下应该有一张名为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
效果图2