生活随笔
收集整理的這篇文章主要介紹了
Opencv2.4.9源码分析——HoughLinesP
小編覺得挺不錯的,現在分享給大家,幫大家做個參考.
http://blog.csdn.net/zhaocj/article/details/400473
標準霍夫變換本質上是把圖像映射到它的參數空間上,它需要計算所有的M個邊緣點,這樣它的運算量和所需內存空間都會很大。如果在輸入圖像中只是處理m(m<M)個邊緣點,則這m個邊緣點的選取是具有一定概率性的,因此該方法被稱為概率霍夫變換(Probabilistic Hough Transform)。該方法還有一個重要的特點就是能夠檢測出線端,即能夠檢測出圖像中直線的兩個端點,確切地定位圖像中的直線。 HoughLinesP函數就是利用概率霍夫變換來檢測直線的。它的一般步驟為:
1、隨機抽取圖像中的一個特征點,即邊緣點,如果該點已經被標定為是某一條直線上的點,則繼續在剩下的邊緣點中隨機抽取一個邊緣點,直到所有邊緣點都抽取完了為止;
2、對該點進行霍夫變換,并進行累加和計算;
3、選取在霍夫空間內值最大的點,如果該點大于閾值的,則進行步驟4,否則回到步驟1;
4、根據霍夫變換得到的最大值,從該點出發,沿著直線的方向位移,從而找到直線的兩個端點;
5、計算直線的長度,如果大于某個閾值,則被認為是好的直線輸出,回到步驟1。
HoughLinesP函數的原型為:
void HoughLinesP(InputArray image,OutputArray lines, double rho, double theta, int threshold, double minLineLength=0,double maxLineGap=0 )
image為輸入圖像,要求是8位單通道圖像
lines為輸出的直線向量,每條線用4個元素表示,即直線的兩個端點的4個坐標值
rho和theta分別為距離和角度的分辨率
threshold為閾值,即步驟3中的閾值
minLineLength為最小直線長度,在步驟5中要用到,即如果小于該值,則不被認為是一條直線
maxLineGap為最大直線間隙,在步驟4中要用到,即如果有兩條線段是在一條直線上,但它們之間因為有間隙,所以被認為是兩個線段,如果這個間隙大于該值,則被認為是兩條線段,否則是一條。
?
HoughLinesP函數是在sources/modules/imgproc/src/hough.cpp文件中被定義的:
[cpp]?view plaincopy
void?cv::HoughLinesP(?InputArray?_image,?OutputArray?_lines,?? ??????????????????????double?rho,?double?theta,?int?threshold,?? ??????????????????????double?minLineLength,?double?maxGap?)?? {?? ????Ptr<CvMemStorage>?storage?=?cvCreateMemStorage(STORAGE_SIZE);?? ????Mat?image?=?_image.getMat();?? ????CvMat?c_image?=?image;?? ????CvSeq*?seq?=?cvHoughLines2(?&c_image,?storage,?CV_HOUGH_PROBABILISTIC,?? ????????????????????rho,?theta,?threshold,?minLineLength,?maxGap?);?? ????seqToMat(seq,?_lines);?? }?? 從HoughLinesP函數可以看出,該函數會調用cvHoughLines2函數。它通過參數CV_HOUGH_PROBABILISTIC,最終調用了icvHoughLinesProbabilistic函數:
[cpp]?view plaincopy
static?void?? icvHoughLinesProbabilistic(?CvMat*?image,?? ????????????????????????????float?rho,?float?theta,?int?threshold,?? ????????????????????????????int?lineLength,?int?lineGap,?? ????????????????????????????CvSeq?*lines,?int?linesMax?)?? {?? ?????? ????cv::Mat?accum,?mask;?? ????cv::vector<float>?trigtab;?????? ?????? ????cv::MemStorage?storage(cvCreateMemStorage(0));?? ?????? ????CvSeq*?seq;??? ????CvSeqWriter?writer;?? ????int?width,?height;?????? ????int?numangle,?numrho;?????? ????float?ang;?? ????int?r,?n,?count;?? ????CvPoint?pt;?? ????float?irho?=?1?/?rho;?????? ????CvRNG?rng?=?cvRNG(-1);?????? ????const?float*?ttab;?????? ????uchar*?mdata0;?????? ?????? ????CV_Assert(?CV_IS_MAT(image)?&&?CV_MAT_TYPE(image->type)?==?CV_8UC1?);?? ?? ????width?=?image->cols;?????? ????height?=?image->rows;?????? ?????? ????numangle?=?cvRound(CV_PI?/?theta);?? ????numrho?=?cvRound(((width?+?height)?*?2?+?1)?/?rho);?? ?????? ????accum.create(?numangle,?numrho,?CV_32SC1?);?? ?????? ????mask.create(?height,?width,?CV_8UC1?);?? ?????? ????trigtab.resize(numangle*2);?? ?????? ????accum?=?cv::Scalar(0);?? ?????? ????for(?ang?=?0,?n?=?0;?n?<?numangle;?ang?+=?theta,?n++?)?? ????{?? ????????trigtab[n*2]?=?(float)(cos(ang)?*?irho);?? ????????trigtab[n*2+1]?=?(float)(sin(ang)?*?irho);?? ????}?? ?????? ????ttab?=?&trigtab[0];?? ????mdata0?=?mask.data;?? ?????? ????cvStartWriteSeq(?CV_32SC2,?sizeof(CvSeq),?sizeof(CvPoint),?storage,?&writer?);?? ?? ?????? ?????? ????for(?pt.y?=?0,?count?=?0;?pt.y?<?height;?pt.y++?)?? ????{?? ?????????? ????????const?uchar*?data?=?image->data.ptr?+?pt.y*image->step;?? ????????uchar*?mdata?=?mdata0?+?pt.y*width;?? ????????for(?pt.x?=?0;?pt.x?<?width;?pt.x++?)?? ????????{?? ????????????if(?data[pt.x]?)?????? ????????????{?? ????????????????mdata[pt.x]?=?(uchar)1;?????? ????????????????CV_WRITE_SEQ_ELEM(?pt,?writer?);????把該坐標位置寫入序列?? ????????????}?? ????????????else?????? ????????????????mdata[pt.x]?=?0;?????? ????????}?? ????}?? ?????? ????seq?=?cvEndWriteSeq(?&writer?);?? ????count?=?seq->total;?????? ?? ?????? ?????? ????for(?;?count?>?0;?count--?)?? ????{?? ?????????? ?????????? ????????int?idx?=?cvRandInt(&rng)?%?count;?? ?????????? ????????int?max_val?=?threshold-1,?max_n?=?0;?? ?????????? ????????CvPoint*?point?=?(CvPoint*)cvGetSeqElem(?seq,?idx?);?? ?????????? ????????CvPoint?line_end[2]?=?{{0,0},?{0,0}};?? ????????float?a,?b;?? ?????????? ????????int*?adata?=?(int*)accum.data;?? ????????int?i,?j,?k,?x0,?y0,?dx0,?dy0,?xflag;?? ????????int?good_line;?? ????????const?int?shift?=?16;?? ?????????? ????????i?=?point->y;?? ????????j?=?point->x;?? ?? ?????????? ?????????? ????????*point?=?*(CvPoint*)cvGetSeqElem(?seq,?count-1?);?? ?? ?????????? ?????????? ?????????? ????????if(?!mdata0[i*width?+?j]?)?????? ????????????continue;?????? ?? ?????????? ?????????? ????????for(?n?=?0;?n?<?numangle;?n++,?adata?+=?numrho?)?? ????????{?? ?????????????? ????????????r?=?cvRound(?j?*?ttab[n*2]?+?i?*?ttab[n*2+1]?);?? ????????????r?+=?(numrho?-?1)?/?2;?? ?????????????? ????????????int?val?=?++adata[r];?? ?????????????? ????????????if(?max_val?<?val?)?? ????????????{?? ????????????????max_val?=?val;?? ????????????????max_n?=?n;?? ????????????}?? ????????}?? ?? ?????????? ?????????? ????????if(?max_val?<?threshold?)?? ????????????continue;?? ?? ?????????? ?????????? ?????????? ????????a?=?-ttab[max_n*2+1];?????? ????????b?=?ttab[max_n*2];?????? ?????????? ????????x0?=?j;?? ????????y0?=?i;?? ?????????? ????????if(?fabs(a)?>?fabs(b)?)?????? ????????{?? ????????????xflag?=?1;?????? ?????????????? ????????????dx0?=?a?>?0???1?:?-1;?????? ????????????dy0?=?cvRound(?b*(1?<<?shift)/fabs(a)?);?? ?????????????? ????????????y0?=?(y0?<<?shift)?+?(1?<<?(shift-1));?? ????????}?? ????????else?????? ????????{?? ????????????xflag?=?0;????? ?????????????? ????????????dy0?=?b?>?0???1?:?-1;?? ????????????dx0?=?cvRound(?a*(1?<<?shift)/fabs(b)?);?? ?????????????? ????????????x0?=?(x0?<<?shift)?+?(1?<<?(shift-1));?? ????????}?? ?????????? ????????for(?k?=?0;?k?<?2;?k++?)?? ????????{?? ?????????????? ????????????int?gap?=?0,?x?=?x0,?y?=?y0,?dx?=?dx0,?dy?=?dy0;?? ?????????????? ????????????if(?k?>?0?)?? ????????????????dx?=?-dx,?dy?=?-dy;?? ?? ?????????????? ?????????????? ?????????????? ????????????for(?;;?x?+=?dx,?y?+=?dy?)?? ????????????{?? ????????????????uchar*?mdata;?? ????????????????int?i1,?j1;?? ?????????????????? ????????????????if(?xflag?)?? ????????????????{?? ????????????????????j1?=?x;?? ????????????????????i1?=?y?>>?shift;?? ????????????????}?? ????????????????else?? ????????????????{?? ????????????????????j1?=?x?>>?shift;?? ????????????????????i1?=?y;?? ????????????????}?? ?????????????????? ????????????????if(?j1?<?0?||?j1?>=?width?||?i1?<?0?||?i1?>=?height?)?? ????????????????????break;?? ?????????????????? ????????????????mdata?=?mdata0?+?i1*width?+?j1;?? ?? ?????????????????? ?????????????????? ?????????????????? ?????????????????? ?????????????????? ????????????????if(?*mdata?)??? ????????????????{?? ????????????????????gap?=?0;?????? ?????????????????????? ????????????????????line_end[k].y?=?i1;?? ????????????????????line_end[k].x?=?j1;?? ????????????????}?? ?????????????????? ????????????????else?if(?++gap?>?lineGap?)?????? ????????????????????break;?? ????????????}?? ????????}?? ?????????? ?????????? ????????good_line?=?abs(line_end[1].x?-?line_end[0].x)?>=?lineLength?||?? ????????????????????abs(line_end[1].y?-?line_end[0].y)?>=?lineLength;?? ?????????? ????????for(?k?=?0;?k?<?2;?k++?)?? ????????{?? ????????????int?x?=?x0,?y?=?y0,?dx?=?dx0,?dy?=?dy0;?? ?? ????????????if(?k?>?0?)?? ????????????????dx?=?-dx,?dy?=?-dy;?? ?? ?????????????? ?????????????? ????????????for(?;;?x?+=?dx,?y?+=?dy?)?? ????????????{?? ????????????????uchar*?mdata;?? ????????????????int?i1,?j1;?? ?? ????????????????if(?xflag?)?? ????????????????{?? ????????????????????j1?=?x;?? ????????????????????i1?=?y?>>?shift;?? ????????????????}?? ????????????????else?? ????????????????{?? ????????????????????j1?=?x?>>?shift;?? ????????????????????i1?=?y;?? ????????????????}?? ?? ????????????????mdata?=?mdata0?+?i1*width?+?j1;?? ?? ?????????????????? ?????????????????? ?????????????????? ?????????????????? ????????????????if(?*mdata?)?? ????????????????{?? ?????????????????????? ????????????????????if(?good_line?)?????? ????????????????????{?? ?????????????????????????? ????????????????????????adata?=?(int*)accum.data;?? ????????????????????????for(?n?=?0;?n?<?numangle;?n++,?adata?+=?numrho?)?? ????????????????????????{?? ????????????????????????????r?=?cvRound(?j1?*?ttab[n*2]?+?i1?*?ttab[n*2+1]?);?? ????????????????????????????r?+=?(numrho?-?1)?/?2;?? ????????????????????????????adata[r]--;?????? ????????????????????????}?? ????????????????????}?? ?????????????????????? ????????????????????*mdata?=?0;?? ????????????????}?? ?????????????????? ????????????????if(?i1?==?line_end[k].y?&&?j1?==?line_end[k].x?)?? ????????????????????break;?? ????????????}?? ????????}?? ?????????? ????????if(?good_line?)?? ????????{?? ????????????CvRect?lr?=?{?line_end[0].x,?line_end[0].y,?line_end[1].x,?line_end[1].y?};?? ?????????????? ????????????cvSeqPush(?lines,?&lr?);?? ?????????????? ????????????if(?lines->total?>=?linesMax?)?? ????????????????return;?? ????????}?? ????}?? }?? 下面就給出應用HoughLinesP函數檢測直線段的應用程序:
[cpp]?view plaincopy
#include?"opencv2/core/core.hpp"?? #include?"opencv2/highgui/highgui.hpp"?? #include?"opencv2/imgproc/imgproc.hpp"?? ?? #include?<iostream>?? using?namespace?cv;?? using?namespace?std;?? ?? int?main(?int?argc,?char**?argv?)?? {?? ????Mat?src,?edge,color_edge;?? ????src=imread("building.jpg");?? ????if(?!src.data?)???? ????????return?-1;???? ?? ????Canny(src,edge,50,200,3);?? ????cvtColor(?edge,?color_edge,?CV_GRAY2BGR?);?? ????vector<Vec4i>?lines;?? ????HoughLinesP(edge,?lines,?1,?CV_PI/180,?80,?30,?10?);?? ????for(?size_t?i?=?0;?i?<?lines.size();?i++?)?? ????{?? ????????Vec4i?l?=?lines[i];?? ????????line(?color_edge,?Point(l[0],?l[1]),?Point(l[2],?l[3]),?Scalar(0,0,255),?2);?? ????}?? ?? ????namedWindow(?"lines",?CV_WINDOW_AUTOSIZE?);?? ????imshow(?"lines",?color_edge?);?? ????waitKey(0);?? ?? ????return?0;?? }?? 下圖為輸出的圖像:
轉載于:https://www.cnblogs.com/fag888/p/5789167.html
總結
以上是生活随笔為你收集整理的Opencv2.4.9源码分析——HoughLinesP的全部內容,希望文章能夠幫你解決所遇到的問題。
如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。