霍夫變換的基本理解(第八天)


千萬注意:使用opencv自帶的霍夫API

HoughLinesP():此函數輸入的是一個二進制且八位的圖像,例如:你不能用cvtcolor()變換之后直接輸入。

HoughCircles():此函數輸入的是一個灰度且八位的圖像,例如:你不能經過threshold()、findcontours()等之后的圖像進行輸入。

我現在還不知道經過二值化的圖像怎么轉化為灰度圖。。。。會了再補充。

 ---霍夫直線變換---

源程序沒有分析,只是分析了基本的原理。。。等以后用到之后再進行分析

首先回顧一下坐標系的概念--->>>

1.直角坐標系(直線)<--->極坐標系(點),極坐標系(直線)<--->直角坐標系(點)。相互對應的關系

2.推導的公式很簡單,看一下就懂了。

3.對於第三個公式,我們給定一個(x0,y0),就是圖像的一個像素點(這個圖是經過濾波、灰度、梯度等處理的),那么這個點在極坐標就可以畫出一條直線。因為在極坐標看的不明顯,把這個函數畫在直角坐標系顯示(圖一),就類似三角函數的圖像。現在我們再給定點(x1,y1)、(x2,y2)。。。進行同樣的方法畫圖(圖二),這個點在直角坐標系就是一條直線,那么多重合的點,就說明很多的像素點在這個直線上,我們設定一個閾值L,當點的重合率大於這個閾值就認定是直線。

4.有點饒人,直角和極坐標相互的轉化實現。

 

圖一

圖二

 

上面的原理是可以運行的:

1.效率太低了,試想一下圖像邊緣非常的多,如果每一個像素點都進行計算的話,那太費時費事了。

2.線段的端點沒辦法檢測。

3.對於相近的線段沒辦法區分。

HoughLinesP函數就是利用概率霍夫變換來檢測直線的。它的一般步驟為:

1、隨機抽取圖像中的一個特征點,即邊緣點,如果該點已經被標定為是某一條直線上的點,則繼續在剩下的邊緣點中隨機抽取一個邊緣點,直到所有邊緣點都抽取完了為止;

2、對該點進行霍夫變換,並進行累加和計算;

3、選取在霍夫空間內值最大的點,如果該點大於閾值的,則進行步驟4,否則回到步驟1;

4、根據霍夫變換得到的最大值,從該點出發,沿着直線的方向位移,從而找到直線的兩個端點;

5、計算直線的長度,如果大於某個閾值,則被認為是好的直線輸出,回到步驟1。

 

opencv霍夫直線變換:

houghlines()--->>>

其返回的是(ρ,Θ),ρ代表距離(0,0)點到直線的歐幾里得距離,也就是直線距離。Θ代表的是(0,0)點垂直直線然后與Y軸的夾角。

 

houghlinesP()--->>>

返回的是直線兩個點:(x0,y0)(x1,y1)

 

剛開始我看不起houghlines函數,感覺效率低,后來基本上都是用houghlinesP的,但是這次實現文本的轉正就用到了,這兩個用途不一樣吧!

 

---霍夫圓變換---

圓變換的想法和直線變化是一樣的,就是把直角坐標系中的圓畫在極坐標系中,然后求交點

 

第一階段:檢測圓心

1.1、對輸入圖像邊緣檢測;

1.2、計算圖形的梯度,並確定圓周線,其中圓周的梯度就是它的法線;

1.3、在二維霍夫空間內,繪出所有圖形的梯度直線,某坐標點上累加和的值越大,說明在該點上直線相交的次數越多,也就是越有可能是圓心;

1.4、在霍夫空間的4鄰域內進行非最大值抑制;

1.5、設定一個閾值,霍夫空間內累加和大於該閾值的點就對應於圓心。

第二階段:檢測圓半徑

2.1、計算某一個圓心到所有圓周線的距離,這些距離中就有該圓心所對應的圓的半徑的值,這些半徑值當然是相等的,並且這些圓半徑的數量要遠遠大於其他距離值相等的數量;

2.2、設定兩個閾值,定義為最大半徑和最小半徑,保留距離在這兩個半徑之間的值,這意味着我們檢測的圓不能太大,也不能太小;

2.3、對保留下來的距離進行排序;

2.4、找到距離相同的那些值,並計算相同值的數量;

2.5、設定一個閾值,只有相同值的數量大於該閾值,才認為該值是該圓心對應的圓半徑;

2.6、對每一個圓心,完成上面的2.1~2.5步驟,得到所有的圓半徑。

 opencv實例:

 1 #include<iostream>
 2 #include <opencv2/opencv.hpp>
 3 #include <math.h>
 4 using namespace cv;
 5 using namespace std;
 6 
 7 int main(int argc,char**argv)
 8 {
 9     Mat input_image = imread("1.jpg");
10     if (input_image.data==NULL) {
11         return -1; cout << "can't open image.../";
12     }
13     imshow("Sourse image", input_image);
14     Mat mid_image,output_image, mid_image1;
15     mid_image.create(input_image.size(),input_image.type());
16     mid_image1.create(input_image.size(), input_image.type());
17     cvtColor(input_image,output_image,COLOR_BGR2GRAY);
18     GaussianBlur(output_image,output_image,Size(3,3),2,2);
19     Canny(output_image, output_image,50,200);
20     vector<Vec4i> lines;
21     vector<Vec3f> circles;
22     HoughLinesP(output_image,lines,1,CV_PI/180,80,50,10);
23     HoughCircles(output_image,circles,HOUGH_GRADIENT,1.5,10,200,100,0,0);
24     for (size_t i = 0; i < lines.size(); i++)
25     {
26         Vec4i l;
27         l = lines[i];
28         line(mid_image,Point(l[0],l[1]),Point(l[2],l[3]),Scalar(100,255,200),1,LINE_AA);
29     }
30     imshow("Destinate1 image", output_image);
31     imshow("Destinate2 image", mid_image);
32     for (size_t j = 0; j < circles.size(); j++)
33     {
34         Vec3f c;
35         c = circles[j];
36         circle(mid_image1, Point(cvRound(c[0]), cvRound(c[1])), 3, Scalar(0, 255, 50));
37         circle(mid_image1, Point(cvRound(c[0]), cvRound(c[1])), cvRound(c[2]), Scalar(0, 255, 50),3,8,0);
38     }
39     imshow("Destinate3 image", mid_image1);
40     waitKey(0);
41     return 0;
42 }

 opencv自帶的API主要就是參數的設置,設置不好的參數要么檢測的不好,要么根本檢測不到直線和圓!

 1.圓的檢測是找不到同心圓的

 2.很容易受噪聲干擾

 3.必須非常的圓度,橢圓不行

主要參考:http://blog.csdn.net/zhaocj/article/details/50454847


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM