笛卡爾坐標系中,圓的方程為(x-a)^2+(y-b)^2=r^2
其中(a,b)是圓心,r是半徑
也可以表示為
x=a+rcosθ
y=b+rsinθ
再進行一次轉換
a=x-rcosθ
b=y-rsinθ
此時由於xy是給定的,將abr看成變量,映射到abr的三維坐標系中如圖

所有經過(x,y)點的圓都可以用這條曲線表示
同樣,在xy坐標系中的所有圓都可以在這個三維坐標系中用曲線表示出來
假設空間中有三個點ABC,經過ABC三點的圓都是無數多的,在abr坐標系中可以可以表示為三條曲線,但是如果有一個圓同時過ABC三點,那么在abr坐標系中,它對應三條曲線的交點
因此,在xy坐標系中的一個圓上的所有點的圓方程,他們在abr坐標系中會交於同一點,通過判斷abr坐標系中該點有多少條直線相交,大於一定閾值的點就認定為圓
代碼演示
#include"pch.h" #include<iostream> #include<opencv2/opencv.hpp> using namespace std; using namespace cv; int main(int argc, char **argv) { Mat src, dst; src = imread("2.jpg"); if (!src.data) { printf("Error\n"); return -1; } char INPUT_TITLE[] = "input_image"; char OUTPUT_TITLE[] = "hough_circle_demo"; namedWindow(INPUT_TITLE, CV_WINDOW_AUTOSIZE); namedWindow(OUTPUT_TITLE, CV_WINDOW_AUTOSIZE); imshow(INPUT_TITLE, src); //中值濾波 Mat mlf_opt; medianBlur(src, mlf_opt, 3);//ksize取3 cvtColor(mlf_opt, mlf_opt, CV_BGR2GRAY); //霍夫圓檢測 vector<Vec3f> pcircles;//可能的圓心 HoughCircles(mlf_opt, pcircles, CV_HOUGH_GRADIENT, 1, 10, 100, 35, 5, 50); cout << pcircles[1] << endl; src.copyTo(dst); for (size_t i = 0; i < pcircles.size(); ++i) { Vec3f cc = pcircles[i]; circle(dst, Point(cc[0], cc[1]), cc[2], Scalar(0, 0, 255), 2, LINE_AA); circle(dst, Point(cc[0], cc[1]), 1, Scalar(198, 20, 255), 2, LINE_AA); } imshow(OUTPUT_TITLE, dst); waitKey(0); return 0; }


函數帶有以下自變量:
- src_gray: 輸入圖像 (灰度圖)
- circles: 存儲下面三個參數:
集合的容器來表示每個檢測到的圓. - CV_HOUGH_GRADIENT: 指定檢測方法. 現在OpenCV中只有霍夫梯度法
- dp = 1: 累加器圖像的反比分辨率
- min_dist = src_gray.rows/10: 檢測到圓心之間的最小距離
- param_1 = 100: Canny邊緣函數的高閾值
- param_2 = 35: 圓心檢測閾值.
- min_radius = 5: 能檢測到的最小圓半徑, 默認為0.
- max_radius = 50: 能檢測到的最大圓半徑, 默認為0
circle打印圓,第一個打印邊界,第二個打印圓心(半徑調小)
