Hough 检测直线
1、Hough變換
Hough變換是一種快速的形狀匹配技術。經典的H ough變換適用于曲線形狀可以用參數來描述、而曲線位置未知情況下的曲線檢測。如下:
在笛卡兒坐標系中, 直線可以用斜截方程y = kx + b 表示。考慮同一直線上的兩點( x i, yi ) 和( xj, yj ), 滿足yi = kx i+ b 和yj = kxj + b, 映射到參數空間后的兩條正弦曲線Q=x i cos H+ yi sin H和Q= xj cos H+ yj s in H將相交于一點。如下圖所示:
從而在圖像空間中同一條直線上的所有點在變換到參數空間后的正弦曲線都將交匯于一點( Q, H)。因此可以設計二維計數器H ( Q, H) 來累加極坐標系中的參考點數。最后通過統計計數器矩陣的局部極大值, 即可檢測出圖像中的直線。
推廣后的Hough變換可以檢測任意形狀。
2、OpenCV中利用Hough變換檢測直線
/* Finds lines on binary image using one of several methods.line_storage is either memory storage or 1 x <max number of lines> CvMat, itsnumber of columns is changed by the function.method is one of CV_HOUGH_*;rho, theta and threshold are used for each of those methods;param1 ~ line length, param2 ~ line gap - for probabilistic,param1 ~ srn, param2 ~ stn - for multi-scale */ CVAPI(CvSeq*) cvHoughLines2( CvArr* image, void* line_storage, int method,double rho, double theta, int threshold,double param1 CV_DEFAULT(0), double param2 CV_DEFAULT(0));參數說明:
image
輸入8-比特、單通道(二值)圖像,當用CV_HOUGH_PROBABILISTIC方法檢測的時候其內容會被函數改變。
line_storage
檢測到的線段存儲倉.可以是內存存儲倉(此種情況下,一個線段序列在存儲倉中被創建,并且由函數返回),或者是包含線段參數的特殊類型(見下面)的具有單行/單列的矩陣(CvMat*)。矩陣頭為函數所修改,使得它的?cols/rows?將包含一組檢測到的線段。如果?line_storage?是矩陣,而實際線段的數目超過矩陣尺寸,那么最大可能數目的線段被返回(線段沒有按照長度、可信度或其它指標排序).
method
Hough?變換變量,是下面變量的其中之一:
CV_HOUGH_STANDARD?-?傳統或標準?Hough?變換.?每一個線段由兩個浮點數?(ρ,?θ)?表示,其中?ρ?是直線與原點(0,0)?之間的距離,θ?線段與?x-軸之間的夾角。因此,矩陣類型必須是?CV_32FC2?type.
CV_HOUGH_PROBABILISTIC-?概率?Hough?變換(如果圖像包含一些長的線性分割,則效率更高).?它返回線段分割而不是整個線段。每個分割用起點和終點來表示,所以矩陣(或創建的序列)類型是?CV_32SC4.
CV_HOUGH_MULTI_SCALE?-?傳統?Hough?變換的多尺度變種。線段的編碼方式與?CV_HOUGH_STANDARD?的一致。
rho
以象素為單位的距離精度,一般取1
theta
以弧度為單位角度精度,一般取CV_PI/180
threshold
閾值參數。當在一條直線上的像素點數大于threshold時,才將該直線作為檢測結果顯示出來。該值越大,得到直線越少。
param1
對傳統?Hough?變換,不使用(0).
對概率Hough變換,它是最小線段長度.即當線段長度大于param1時,才將該線段作為檢測結果顯示。與上一參數類似,不過上一參數為像素數,而該參數為線段長度。
對多尺度?Hough?變換,它是距離精度?rho?的分母?(大致的距離精度是?rho?而精確的應該是?rho?/?param1?).
param2
對傳統?Hough?變換,不使用?(0).
對概率?Hough?變換,這個參數表示在同一條直線上進行碎線段連接的最大間隔值(gap),?即當同一條直線上的兩條碎線段之間的間隔小于param2時,將其合二為一條長直線。
對多尺度?Hough?變換,它是角度精度?theta?的分母?(大致的角度精度是?theta?而精確的角度應該是?theta?/?param2).
?
注意:
(1)傾斜角的理解
標準hough變換中返回的line[1],我們知道其表示直線的傾斜角,但是為極坐標下的傾斜角,注意當theta?=?PI?/2時,直線是水平的。
(2)選擇不同形式的hough變換直線檢測類型,line[0]和line[1]表示的意思是不同的。
這里兩種形式的hough檢測方法是通過函數cvHoughLines2的的參數method來區分的。method可以是CV_HOUGH_STANDRD?(?標hough)??和?CV_HOUGH_PROBABILISTIC(概率累積hough)
?對于返回的每條直線?: float*?line?=?(?float*?)?cvGetSeqElem(?lines,i)??
在標準hough中:
?line[?0?]?表示矢量長度(rho_x來表示),?line[1]表示直線的傾斜角(theta_x來表示)
在概率hough變換中,line[0]??和line[1]表示返回直線的兩個端點
?
示例代碼如下:
#include<cv.h> #include <highgui.h> #include <math.h>int main(void) {IplImage *src = cvLoadImage("1.jpg",1);if (src){IplImage *dst = cvCreateImage(cvGetSize(src),8,1);IplImage *color_dst = cvCreateImage(cvGetSize(src),8,3);CvMemStorage *storage = cvCreateMemStorage();CvSeq *lines = 0;int i ;cvCanny(src,dst,50,200,3);cvCvtColor(dst,color_dst,CV_GRAY2BGR); #if 1lines = cvHoughLines2(dst,storage,CV_HOUGH_STANDARD,1,CV_PI/180,40);for (i=0;i<lines->total;i++){float *line = (float *)cvGetSeqElem(lines,i);float rho = line[0];float theta = line[1];CvPoint pt1,pt2;double a = cos(theta);double b = sin(theta);if (fabs(a)<0.001){pt1.x = pt2.x = cvRound(rho);pt1.y = 0;pt2.y = color_dst->height;}else if (fabs(b)<0.001){pt1.y = pt2.y = cvRound(rho);pt1.x = 0;pt2.x = color_dst->width;}else{pt1.x = 0;pt1.y = cvRound(rho/b);pt2.x = cvRound(rho/a);pt2.y = 0;}cvLine(color_dst,pt1,pt2,CV_RGB(255,0,0),1,8);} #elselines = cvHoughLines2(dst,storage,CV_HOUGH_PROBABILISTIC,1,CV_PI/180,40);for (i=0;i<lines->total;i++){CvPoint *line = (CvPoint *)cvGetSeqElem(lines,i);cvLine(color_dst,line[0],line[1],CV_RGB(255,0,0),1,CV_AA);} #endifcvNamedWindow("Source");cvShowImage("Source",src);cvNamedWindow("Hough");cvShowImage("Hough",color_dst);cvWaitKey(0);cvReleaseImage(&src);cvReleaseImage(&dst);cvReleaseImage(&color_dst);cvReleaseMemStorage(&storage);cvDestroyAllWindows();return 1;} }
?
?
總結
以上是生活随笔為你收集整理的Hough 检测直线的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: python爬取csdn排名积分等信息
- 下一篇: OpenCV-图像几何变换:旋转,缩放,