标准霍夫变换本质上是把图像映射到它的参数空间上,它需要计算所有的M个边缘点,这样它的运算量和所需内存空间都会很大。如果在输入图像中只是处理M (m<米)个边缘点,则这M个边缘点的选取是具有一定概率性的,因此该方法被称为概率霍夫变换(概率霍夫变换)。该方法还有一个重要的特点就是能够检测出线端,即能够检测出图像中直线的两个端点,确切地定位图像中的直线。
HoughLinesP函数就是利用概率霍夫变换来检测直线的。它的一般步骤为:
1,随机抽取图像中的一个特征点,即边缘点,如果该点已经被标定为是某一条直线上的点,则继续在剩下的边缘点中随机抽取一个边缘点,直到所有边缘点都抽取完了为止;
2,对该点进行霍夫变换,并进行累加和计算,
3,选取在霍夫空间内值最大的点,如果该点大于阈值的,则进行步骤,否则回到步骤1;
4,根据霍夫变换得到的最大值,从该点出发,沿着直线的方向位移,从而找到直线的两个端点;
5,计算直线的长度,如果大于某个阈值,则被认为是好的直线输出,回到步骤1 .
HoughLinesP函数的原型为:
空白HoughLinesP (InputArray形象,OutputArray线、双ρ,双θ,int阈值,双minLineLength=0,双maxLineGap=0)
图像为输入图像,要求是8位单通道图像
线为输出的直线向量,每条线用4个元素表示,即直线的两个端点的4个坐标值
ρ和θ分别为距离和角度的分辨率
阈值为阈值,即步骤3中的阈值
minLineLength为最小直线长度,在步骤5中要用的到,即如果小于该值,则不被认为是一条直线
maxLineGap为最大直线间隙,在步骤4中要用的到,即如果有两条线段是在一条直线上,但它们之间因为有间隙,所以被认为是两个线段,如果这个间隙大于该值,则被认为是两条线段,否则是一条。
HoughLinesP函数是在来源/模块/imgproc/src/hough.cpp文件中被定义的:
空白的简历::HoughLinesP (InputArray _image, OutputArray _lines, 双ρ,双θ,int阈值, 双minLineLength,双maxGap) { Ptr存储=cvCreateMemStorage (STORAGE_SIZE); 垫图像=_image.getMat (); CvMat c_image=图像; CvSeq * seq=cvHoughLines2 (CV_HOUGH_PROBABILISTIC及c_image、存储, ρ,θ,阈值、minLineLength maxGap); seqToMat (seq, _lines); }
从HoughLinesP函数可以看的出,该函数会调用cvHoughLines2函数。它通过参数CV_HOUGH_PROBABILISTIC,最终调用了icvHoughLinesProbabilistic函数:
静态的空白 icvHoughLinesProbabilistic (CvMat *形象, ρ浮动,浮动θ,int阈值, int lineLength, int lineGap CvSeq *线,int linesMax) {//accum为累加器矩阵,面具为掩码矩阵 简历:垫accum面具; 简历:vectortrigtab;//用于存储事先计算好的正弦和余弦值//开辟一段内存空间 简历:MemStorage存储(cvCreateMemStorage (0));//用于存储特征点坐标,即边缘像素的位置 CvSeq * seq; CvSeqWriter作家; int宽度、高度;//图像的宽和高 int numangle numrho;//角度和距离的离散数量 和浮动; int r, n,计数; CvPoint pt; 浮动irhoρ=1/;//距离分辨率的倒数 CvRNG rng=CvRNG (1);//随机数 const浮* ttab;//向量trigtab的地址指针 uchar * mdata0;//矩阵面具的地址指针//确保输入图像的正确性 CV_Assert (CV_IS_MAT(图片),,CV_MAT_TYPE(图片→类型)==CV_8UC1); 图像宽度=乜?//提取出输入图像的宽 身高=形象→行;//提取出输入图像的高//由角度和距离分辨率,得到角度和距离的离散数量 numangle=cvRound (CV_PI/θ); numrho=cvRound(((宽+高)* 2 + 1)/ρ);//创建累加器矩阵,即霍夫空间 accum.create (numangle numrho CV_32SC1);//创建掩码矩阵,大小与输入图像相同 面具。创建(高度、宽度、CV_8UC1);//定义trigtab的大小,因为要存储正弦和余弦值,所以长度为角度离散数的2倍 trigtab.resize (numangle * 2);//累加器矩阵清零 accum=简历::标量(0);//避免重复计算,事先计算好所需的所有正弦和余弦值 (ang=0, n=0;n & lt;numangle;和+=θ,n + +) { trigtab [n * 2]=(浮动)(cos (ang) * irho); trigtab [n * 2 + 1]=(浮动)(sin (ang) * irho); }//赋值首地址 ttab=, trigtab [0]; mdata0=mask.data;//开始写入序列 cvStartWriteSeq (CV_32SC2 sizeof (CvSeq), sizeof (CvPoint)、存储、及作家);//第1阶段。收集非零像点//收集图像中的所有非零的点,因为输入图像是边缘图像,所以非零点就是边缘点 (pt.y=0,数=0;pt.y & lt;高度;pt.y + +) {//提取出输入图像和掩码矩阵的每行地址指针 const uchar *数据=https://www.yisu.com/zixun/image-> data.ptr + pt.y *图像->步骤; uchar * mdata=mdata0 + pt.y *宽度; (pt.x=0;pt.x Opencv2.4.9函数HoughLinesP分析