霍夫圓變換的基本思路是認為圖像上每一個非零像素點都有可能是一個潛在的圓上的一點,跟霍夫線變換一樣,也是通過投票,生成累積坐标平面,設定一個累積權重來定位圓。
在笛卡爾坐标系中圓的方程為:
![](https://img.laitimes.com/img/9ZDMuAjOiMmIsIjOiQnIsIiN4YzMyEzMxITMxkDM2EDMy8CX0Vmbu4GZzNmLn9Gbi1yZtl2Lc9CX6MHc0RHaiojIsJye.jpg)
其中(a,b)是圓心,r是半徑,也可以表述為:
即
是以在abr組成的三維坐标系中,一個點可以唯一确定一個圓。
而在笛卡爾的xy坐标系中經過某一點的所有圓映射到abr坐标系中就是一條三維的曲線:
經過xy坐标系中所有的非零像素點的所有圓就構成了abr坐标系中很多條三維的曲線。
在xy坐标系中同一個圓上的所有點的圓方程是一樣的,它們映射到abr坐标系中的是同一個點,是以在abr坐标系中該點就應該有圓的總像素N0個曲線相交。通過判斷abr中每一點的相交(累積)數量,大于一定門檻值的點就認為是圓。
以上是标準霍夫圓變換實作算法,問題是它的累加面試一個三維的空間,意味着比霍夫線變換需要更多的計算消耗。Opencv霍夫圓變換對标準霍夫圓變換做了運算上的優化。它采用的是“霍夫梯度法”。它的檢測思路是去周遊累加所有非零點對應的圓心,對圓心進行考量。如何定位圓心呢?圓心一定是在圓上的每個點的模向量上,即在垂直于該點并且經過該點的切線的垂直線上,這些圓上的模向量的交點就是圓心。
霍夫梯度法就是要去查找這些圓心,根據該“圓心”上模向量相交數量的多少,根據門檻值進行最終的判斷。
以下是Opencv中霍夫圓變換的實作:
#include "opencv2/imgproc/imgproc.hpp"
#include "opencv2/highgui/highgui.hpp"
using namespace cv;
using namespace std;
int main( int argc, char* argv[] )
{
Mat image=imread(argv[1]);
Mat imageGray;
cvtColor(image,imageGray,CV_RGB2GRAY);
GaussianBlur(imageGray,imageGray,Size(3,3),1,2);
imshow("Gaussian Image",imageGray);
vector<Vec3f>circles;
HoughCircles(imageGray,circles,CV_HOUGH_GRADIENT,1,1,200,160,0);
for(int i=0;i<circles.size();i++)
{
Point circleCenter(circles[i][0],circles[i][1]);
int radius=circles[i][2];
circle(image,circleCenter,radius,Scalar(0,0,255),3); //做圓
circle(image,circleCenter,3,Scalar(255,0,0),3); //圓心
}
imshow("Circle Image",image);
waitKey();
}
在目前參數下隻有一個圓被檢測出來,檢測效果:
HoughCircles方法對參數比較敏感,很小的改動就可能導緻差别很大的檢測效果,需要針對不同圖像的不同檢測用途進行調試。
函數原型:
void HoughCircles( InputArray image, OutputArray circles,
int method, double dp, double minDist,
double param1=100, double param2=100,
int minRadius=0, int maxRadius=0 );
第一個參數image是輸入圖像矩陣,要求是灰階圖像;
第二個參數 circles是一個包含檢測到的圓的資訊的向量,向量内第一個元素是圓的橫坐标,第二個是縱坐标,第三個是半徑大小;
第三個參數 methodmethod是所使用的圓檢測算法,目前隻有CV_HOUGH_GRADIENT一個可選;
第四個參數 dp是累加面與原始圖像相比的分辨率的反比參數,dp=2時累計面分辨率是元素圖像的一半,寬高都縮減為原來的一半,dp=1時,兩者相同。(關于這個分辨率的概念沒有了解透,按道理低分辨率應該意味着更快的檢測速度,然而實測恰恰相反)
第五個參數 minDist定義了兩個圓心之間的最小距離;
第六個參數param1是Canny邊緣檢測的高門檻值,低門檻值被自動置為高門檻值的一半;
第七個參數param2是累加平面對是否是圓的判定門檻值;
第八和第九個參數定義了檢測到的圓的半徑的最大值和最小值;