1.目的
(1)如何使用opencv的houghcircles在影象中檢測圓區域
2.原理
[1]標準霍夫變換
霍夫圓變換可以根據霍夫線變換來實現 ,通過極座標來表示圓(a,b)表示圓心,r表示半徑,則圓表示為:
x = a + rcosθ
y = b + rsinθ
θ的值為0-360
一開始我們假設r是已知的,那麼我們就可以把x,y空間的公式變換為關於a、b空間的公式:
a = x1 – rcosθ
b = y1 – rsinθ
x1、y1為x、y空間中的每乙個非零畫素點,如此一來,後面的變換就可以跟霍夫線變換一樣操作了。
具體操作步驟為:
①、讀取一副影象
②、檢測邊緣,產生一副二值影象
③、對於每個非零畫素轉換到ab空間中
④、對於每個ab空間中的點,進行累加
⑤、提取數量最多的點作為圓點
ps:在上面提到r是假設已知的,那麼當r是未知的情況怎麼辦?其實很簡單,就是將r設定為1、2、3……這樣子已知下去,慢慢試,再對r和圓心數量進行閾值就可以了。
[2]霍夫梯度法
霍夫梯度法的原理是這樣的。
首先對影象應用邊緣檢測,比如用canny邊緣檢測。
然後,對邊緣影象中的每乙個非零點,考慮其區域性梯度,即用sobel()函式計算x和y方向的sobel一階導數得到梯度。
利用得到的梯度,由斜率指定的直線上的每乙個點都在累加器中被累加,這裡的斜率是從乙個指定的最小值到指定的最大值的距離。
同時,標記邊緣影象中每乙個非0畫素的位置。
然後從二維累加器中這些點中選擇候選的中心,這些中心都大於給定閾值並且大於其所有近鄰。這些候選的中心按照累加值降序排列,以便於最支援畫素的中心首先出現。
接下來對每乙個中心,考慮所有的非0畫素。
這些畫素按照其與中心的距離排序。從到最大半徑的最小距離算起,選擇非0畫素最支援的一條半徑。
如果乙個中心收到邊緣影象非0畫素最充分的支援,並且到前期被選擇的中心有足夠的距離,那麼它就會被保留下來。
這個實現可以使演算法執行起來更高效,或許更加重要的是,能夠幫助解決三維累加器中 會產生許多雜訊並且使得結果不穩定的 稀疏分布問題。
霍夫梯度法的缺點:
<1> 在霍夫梯度法中,我們使用sobel導數來計算區域性梯度,那麼隨之而來的假設是,其可以視作等同於一條區域性切線,並這個不是乙個數值穩定的做法。在大多數情況下,這樣做會得到正確的結果,但或許會在輸出中產生一些雜訊。
<2> 在邊緣影象中的整個非0畫素集被看做每個中心的候選部分。因此,如果把累加器的閾值設定偏低,演算法將要消耗比較長的時間。
<3> 因為中心是按照其關聯的累加器值的公升序排列的,並且如果新的中心過於接近之前 已經接受的中心的話,就不會被保留下來。且當有許多同心圓或者是近似的同心圓時,霍夫梯度法的傾向是保留最大的乙個圓。可以說這是一種比較極端的做法,因 為在這裡預設sobel導數會產生雜訊,若是對於無窮解析度的平滑影象而言的話,這才是必須的。 (實際上可以設定min_dist來解決該問題)
ps:opencv中實現的是霍夫梯度法
3.部分**解釋
(1)houghcircles
/*
houghcircles引數解釋
edge:通過邊緣檢測獲得的二值影象,一般可以使用canny邊緣檢測運算元
circles:檢測到的圓的引數(圓心point([0],[1]),半徑radius([2]))
cv_hough_gradient:霍夫梯度法
dp = 1:累加器影象的反比解析度
min_dist = src_gray.rows/8: 檢測到圓心之間的最小距離
param_1 = 200: canny邊緣函式的高閾值
param_2 = thresh:圓心檢測閾值
min_radius:最小能夠檢測的圓大小
max_radius:最大能夠檢測的圓大小
ps:min_radius, max_radius預設值為0,當max_radius設定為0時候,可以檢測任意大小的圓
*/houghcircles(edge, circles, cv_hough_gradient, 1, edge.rows/8, 200, thresh, 0, edge.rows/2);
4.完整**
(1)commoninclude.h
#ifndef common_include
#define common_include
#include
#include
using
namespace
std;
#include
#include
#include
using
namespace cv;
#endif
(2)houghcircles.cpp
#include"commoninclude.h"
int thresh = 50;
int max_thresh = 200;
mat src, gray, edge, dst;
char windowname = "houghcircles";
void houghcirclestrans(int, void*)
imshow(windowname, dst);
}int main(int argc, char** argv)
src = imread(argv[1]);
if(!src.data)
namedwindow(windowname, cv_window_autosize);
//高斯平滑,去除雜訊
gaussianblur(src, src, size(5,5), 0, 0);
//轉換成灰度影象
cvtcolor(src, gray, cv_bgr2gray);
imshow("gray", gray);
//canny邊緣檢測
canny(gray, edge, 50, 200, 3);
createtrackbar("thresh", windowname,
&thresh, max_thresh,
houghcirclestrans);
houghcirclestrans(0,0);
waitkey(0);
return(0);
}
參考文獻
1.
缺點 霍夫圓 霍夫圓變換
對於直線來說,一條直線能有引數極徑級角表示,而對圓來說我們需要三個引數來表示乙個圓 在opencv中,我們常常通過乙個叫 霍夫梯度法 的方法來解決圓變換的問題。霍夫梯度法的原理 1 首先對影象應用邊緣檢測,比如canny邊緣檢測 2 然後對邊緣影象中的每乙個非零點,考慮其區域性梯度,即用sobel函...
霍夫圓變換
對於直線來說,一條直線能有引數極徑級角表示,而對圓來說我們需要三個引數來表示乙個圓 在opencv中,我們常常通過乙個叫 霍夫梯度法 的方法來解決圓變換的問題。霍夫梯度法的原理 1 首先對影象應用邊緣檢測,比如canny邊緣檢測 2 然後對邊緣影象中的每乙個非零點,考慮其區域性梯度,即用sobel函...
缺點 霍夫圓 霍夫變換
霍夫變換是一種特徵提取,被廣泛應用在影象分析 電腦視覺以及數字影像處理。霍夫變換是用來辨別找出物件中的特徵,例如 線條。他的演算法流程大致如下,給定乙個物件 要辨別的形狀的種類,演算法會在引數空間中執行投票來決定物體的形狀,而這是由累加空間 accumulator space 裡的區域性最大值來決定...