霍夫圓變換的基本原理與霍夫線變換大體類似
對(duì)直線來(lái)說(shuō),一條直線能由極徑極角(r,θ)表示,而對(duì)于圓來(lái)說(shuō),我們需要三個(gè)參數(shù):圓心(a,b),半徑 r

笛卡爾坐標(biāo)系中圓的方程為:
(x-a)2 + (y-b)2 = r2
化簡(jiǎn)便可得到:
a = x - r·cosθ
b = y - r·sinθ
對(duì)于(x0,y0),我們可以將通過(guò)這一點(diǎn)的所有圓統(tǒng)一定義為:
a = x0 - r·cosθ
b = y0 - r·sinθ
這就意味著每一組(a,b,r)代表一個(gè)通過(guò)點(diǎn)(x0,y0)的圓。
對(duì)于一個(gè)給定點(diǎn)(x0,y0),我們可以在三維直角坐標(biāo)系中,繪出所有通過(guò)它的圓。最終我們將得到一條三維的曲線。
我們可以對(duì)圖像中所有的點(diǎn)進(jìn)行上述操作.。如果兩個(gè)不同點(diǎn)進(jìn)行上述操作后得到的曲線在空間 a - b - r 相交, 即它們有一組公共的(a,b,r),這就意味著它們?cè)谕粋€(gè)圓上。
越多曲線交于一點(diǎn),也就意味著這個(gè)交點(diǎn)表示的圓由更多的點(diǎn)組成。我們可以設(shè)置一個(gè)閾值,來(lái)決定多少條曲線交于一點(diǎn)我們才認(rèn)為檢測(cè)到了一個(gè)圓。
這就是霍夫圓變換要做的.。它追蹤圖像中每個(gè)點(diǎn)對(duì)應(yīng)曲線間的交點(diǎn).。如果交于一點(diǎn)的曲線的數(shù)量超過(guò)了閾值, 那么可以認(rèn)為這個(gè)交點(diǎn)所代表的參數(shù)(a,b,r)在原圖像中為一個(gè)圓。
以上是標(biāo)準(zhǔn)霍夫圓變換實(shí)現(xiàn)算法。問(wèn)題是它的累加面(繪制三維曲線的空間)是一個(gè)三維的空間,意味著比霍夫線變換需要更多的計(jì)算消耗。OpenCV 霍夫圓變換對(duì)標(biāo)準(zhǔn)霍夫圓變換做了運(yùn)算上的優(yōu)化。它采用的是 “霍夫梯度法”。
霍夫梯度法的原理
估計(jì)圓心
1.把原圖做一次 Canny 邊緣檢測(cè),得到邊緣檢測(cè)的二值圖。
2.對(duì)原始圖像執(zhí)行一次 Sobel 算子,計(jì)算出所有像素的鄰域梯度值。
3.初始化圓心空間 N(a,b),令所有的 N(a,b)=0。
4.遍歷 Canny 邊緣二值圖中的所有非零像素點(diǎn),沿著梯度方向 ( 切線的垂直方向 )畫(huà)線,將線段經(jīng)過(guò)的所有累加器中的點(diǎn) (a,b) 的 N(a,b)+=1。

5.統(tǒng)計(jì)排序 N(a,b),得到可能的圓心(N(a,b) 越大,越有可能是圓心)
估計(jì)半徑(針對(duì)某一個(gè)圓心 (a,b))
1.計(jì)算 Canny 圖中所有非 0 點(diǎn)距離圓心的距離。
2.距離從小到大排序,根據(jù)閾值,選取合適的可能半徑(比如 3 和 3.5 都被劃為半徑值 3 中)。
3.初始化半徑空間 r, N(r)=0。
4.遍歷 Canny 圖中的非 0 點(diǎn),N( 距離 )+=1。
5.統(tǒng)計(jì)得到可能的半徑值(N(r) 越大,說(shuō)明這個(gè)距離值出現(xiàn)次數(shù)越多,越有可能是半徑值)。
霍夫梯度法缺點(diǎn)
1.在霍夫梯度法中,我們使用 Sobel 導(dǎo)數(shù)來(lái)計(jì)算局部梯度,那么隨之而來(lái)的假設(shè)是,其可以視作等同于一條局部切線,并這個(gè)不是一個(gè)數(shù)值穩(wěn)定的做法。在大多數(shù)情況下,這樣做會(huì)得到正確的結(jié)果,但或許會(huì)在輸出中產(chǎn)生一些噪聲。
2.在邊緣圖像中的整個(gè)非0像素集被看做每個(gè)中心的候選部分。因此,如果把累加器的閾值設(shè)置偏低,算法將要消耗比較長(zhǎng)的時(shí)間。
3.因?yàn)槊恳粋€(gè)中心只選擇一個(gè)圓,如果有同心圓,就只能選擇其中的一個(gè)。
4.因?yàn)橹行氖前凑掌潢P(guān)聯(lián)的累加器值的升序排列的,并且如果新的中心過(guò)于接近之前已經(jīng)接受的中心的話,就不會(huì)被保留下來(lái)。且當(dāng)有許多同心圓或者是近似的同心圓時(shí),霍夫梯度法的傾向是保留最大的一個(gè)圓??梢哉f(shuō)這是一種比較極端的做法,因?yàn)樵谶@里默認(rèn)Sobel導(dǎo)數(shù)會(huì)產(chǎn)生噪聲,若是對(duì)于無(wú)窮分辨率的平滑圖像而言的話,這才是必須的。
霍夫圓變換:HoughCircles 函數(shù)
HoughCircles 函數(shù)可以利用霍夫變換算法檢測(cè)出灰度圖中的圓。它相比之前的 HoughLines 和HoughLinesP,比較明顯的一個(gè)區(qū)別是不需要源圖像是二值的,而 HoughLines 和HoughLinesP 都需要源圖像是二值圖像。
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,輸入圖像,即源圖像,需要為 8 位的灰度單通道圖像。
circles,調(diào)用 HoughCircles 函數(shù)后此參數(shù)存儲(chǔ)了檢測(cè)到的圓的輸出矢量,每個(gè)矢量由包含了 3 個(gè)元素的浮點(diǎn)矢量(x,y,radius)表示。
method,使用的檢測(cè)方法,目前 OpenCV 中就霍夫梯度法一種可以使用,標(biāo)識(shí)符為 HOUGH_GRADIENT。
dp,累加面分辨率(大?。?= 原始圖像分辨率(大小) × 1/dp。默認(rèn) dp = 1 時(shí),兩者分辨率相同。
minDist,兩個(gè)圓心之間的最小距離。若兩圓心距離 < minDist,則認(rèn)為是同一個(gè)圓。
param1,Canny 邊緣檢測(cè)的高閾值,低閾值被自動(dòng)置為高閾值的一半,默認(rèn)為 100。
param2,累加平面某點(diǎn)是否是圓心的判定閾值。它越大,能通過(guò)檢測(cè)的圓就更接近完美的圓形,默認(rèn)為 100。
minRadius,圓半徑的最小值。默認(rèn)為 0。
maxRadius,圓半徑的最大值,默認(rèn)為 0。文章來(lái)源:http://www.zghlxwxcb.cn/news/detail-772920.html
此函數(shù)可以很容易地檢測(cè)出圓心,但是可能找不到合適地圓半徑。我們可以通過(guò) minRadius 和 maxRadius 兩個(gè)參數(shù)指定最大和最小圓半徑,來(lái)輔助圓檢測(cè)的結(jié)果?;蛘呖梢灾苯雍雎苑祷匕霃?,讓二者均為默認(rèn)值,只用 HoughCircles 函數(shù)檢測(cè)出圓心,用額外步驟進(jìn)一步確定半徑。文章來(lái)源地址http://www.zghlxwxcb.cn/news/detail-772920.html





/*OpenCV26霍夫圓檢測(cè)
*/
#include <opencv2\opencv.hpp>
#include <iostream>
using namespace std;
using namespace cv;
Mat src;
Mat src2;
Mat dst;
char *output_name = "霍夫圓結(jié)果";
int main(int argc, char *argv[])
{
//src = imread("e:\\pictures\\梁平柚.jpg");
// src = imread("e:\\pictures\\多個(gè)圓.jpg");
src = imread("e:\\pictures\\blk_bg_sample.jpg");
//src = imread("e:\\pictures\\圓形.jpg");
//src = imread("e:\\pictures\\球形圖.jpg");
if (!src.data)
{
printf("failed to load image");
return -1;
}
namedWindow("原圖",CV_WINDOW_AUTOSIZE);
namedWindow(output_name,CV_WINDOW_AUTOSIZE);
imshow("原圖",src);
Mat m_output;
//中值濾波,去噪聲
medianBlur(src,m_output,3);
//轉(zhuǎn)灰度圖像
cvtColor(m_output,m_output,CV_BGR2GRAY);
//霍夫圓檢測(cè)
vector<Vec3f> maybe_circles;//檢測(cè)出有幾個(gè)圓
//30表示,達(dá)到30,可能是圓
//HoughCircles(m_output,maybe_circles,CV_HOUGH_GRADIENT,1,10,100,30,5,50);//多個(gè)圓
// xx xx method dp,minDist,p1 ,param2, min,max(半徑最大值,0是默認(rèn)值)
//minDist 和 param2 數(shù)值的設(shè)定是關(guān)鍵,第5,7個(gè)參數(shù)
//HoughCircles(m_output, maybe_circles, CV_HOUGH_GRADIENT, 1, 100, 100, 80 ,0, 0 );//圓形,球形圖
HoughCircles(m_output, maybe_circles, CV_HOUGH_GRADIENT, 1, 100, 100, 28, 0, 0);//blk_bg_sample
src.copyTo(dst);
for (size_t i = 0; i < maybe_circles.size(); i++)
{
Vec3f cc = maybe_circles[i];
circle(dst,Point(cc[0],cc[1]),cc[2],Scalar(0,0,255),2,LINE_AA);
circle(dst, Point(cc[0], cc[1]), 2, Scalar(99, 23, 255), 2, LINE_AA);
}
imshow(output_name,dst);
waitKey(0);
return 0;
}
到了這里,關(guān)于OpenCV26HoughCircles 霍夫圓變換原理及圓檢測(cè)的文章就介紹完了。如果您還想了解更多內(nèi)容,請(qǐng)?jiān)谟疑辖撬阉鱐OY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!