霍夫變換圓檢測原理及 OpenCV API 應用

kuweicai發表於2020-11-30

霍夫變換圓檢測原理及 OpenCV API 應用

1. 霍夫圓變換

霍夫圓檢測和霍夫直線檢測的原理類似。建議先理解霍夫直線檢測的原理,再來看霍夫圓檢測。

圓在極座標下的數學表示式如下:
{ x = a + r ⋅ c o s θ y = b + r ⋅ s i n θ \left\{ \begin{aligned} x = a + r\cdot cos\theta \\ y = b + r\cdot sin\theta \\ \end{aligned} \right. {x=a+rcosθy=b+rsinθ
其中 a , b a, b a,b 是圓心的座標, r r r 是半徑。上面的表示式如果轉換到霍夫空間( a b r abr abr三維座標)上,一個點就可以表示一個圓。所以在abr組成的三維座標系中,一個點可以唯一確定一個圓。
{ a = x − r ⋅ c o s θ b = y − r ⋅ s i n θ r = r \left\{ \begin{aligned} a = &x - r\cdot cos\theta \\ b = &y - r\cdot sin\theta \\ r = &r \end{aligned} \right. a=b=r=xrcosθyrsinθr
上面是標準霍夫圓變換的原理,和霍夫直線變換相比,最大的區別是霍夫空間變成了三維空間,這就給統計效率帶來了挑戰。2-1霍夫變換(21HT)是對標準霍夫變換的改進,把霍夫變換分為兩個階段,從而減小了霍夫空間的維數。第一階段用於檢測圓心,第二階段從圓心推匯出圓半徑。該演算法有一個不足之處就是由於圓半徑的檢測完全取決於圓心的檢測,因此如果圓心檢測出現偏差,那麼圓半徑的檢測肯定也是錯誤的。OpenCV 中的霍夫變換圓是基於 21HT 實現的。更多關於霍夫圓變換的原理介紹可以參考 霍夫圓變換

2. OpenCV API

  • C++:void HoughCircles(InputArray image, OutputArray circles, int method, double dp, double minDist, double param1=100, double param2=100, int minRadius=0, int maxRadius=0 )
ParaDisc.
image輸入影像 ,必須是8位的單通道灰度影像
circles輸出結果,發現的圓資訊,也是向量陣列vector
method目前只有 HOUGH_GRADIENT,通過梯度來尋找
dpdp = 1:在原圖上尋找;dp = 2, 原圖寬高減半
mindist如果兩個圓的圓心距離小於 mindist 則認為是同一個圓
param1Canny 檢測時的 高閾值,低閾值是 param1 的一半
param2中心點累加器閾值,小於該閾值的會被忽略
minradius,maxradius搜尋半徑範圍

3. OpenCV API 應用

由於 對噪聲比較敏感,所以一般需要先進行去噪操作,比如 GaussianBlur(), 或者 medianBlur 等。

#include <opencv2/imgproc.hpp>
#include <opencv2/highgui.hpp>
#include <math.h>
#include <vector>

using namespace cv;
using namespace std;

int main(int argc, char** argv)
{
	Mat img, gray;
	img = imread("D:\\Code\\test\\image\\c.jpg", 1); // color image
	cvtColor(img, gray, COLOR_BGR2GRAY);
	// smooth it, otherwise a lot of false circles may be detected
	GaussianBlur(gray, gray, Size(9, 9), 2, 2);
	vector<Vec3f> circles;
	HoughCircles(gray, circles, HOUGH_GRADIENT, 2, gray.rows / 4, 200, 100);
	for (size_t i = 0; i < circles.size(); i++)
	{
		Point center(cvRound(circles[i][0]), cvRound(circles[i][1]));
		int radius = cvRound(circles[i][2]);
		// draw the circle center
		circle(img, center, 3, Scalar(0, 255, 0), -1, 8, 0);
		// draw the circle outline
		circle(img, center, radius, Scalar(0, 0, 255), 3, 8, 0);
	}
	namedWindow("circles", 1);
	imshow("circles", img);
	waitKey(0);
	return 0;
}

在這裡插入圖片描述

參考

-霍夫圓檢測

-霍夫圓檢測

-OpenCV霍夫變換系列(中篇)-霍夫圓變換

相關文章