方法1:
- 如下圖所示,確定一個圓需要3個參數:半徑,圓心的橫坐標,圓心的縱坐標
2.所以我們可以以如下方式進行投票:
遍歷圖像上的所有像素點,選取不同的半徑進行投票,選擇投票數超過閾值的那個像素點作為圓心,如下圖所示:
缺點:計算量太大
方法二:霍夫梯度法
原理:
如下圖所示:
圓的邊緣點切線的垂直方向,也就是梯度方向過圓點,所以我們可以遍歷圖像的所有點,對每個像素點計算梯度,比如Sobel算子,對該直線上的所有像素點進行投票,最后選取超過閾值的某個像素點,為了避免選取過多的圓心,可以把一個像素點周圍相差不大的像素點看做成一個圓心,確定圓心后再計算以改點為圓心的最佳半徑,結果如下:
該方法優點:速度快
缺點:圓心可能會有偏差,這個方法對噪聲比較敏感,所以可以先做中值濾波,做完之后再用hough圓變換
原圖直接處理的代碼:
#include <opencv2/opencv.hpp> #include <iostream> #include <math.h> #include <vector> using namespace cv; using namespace std; Mat src, dst,dst2,gray_src; char* INPUT_WIN = "input image"; char* OUTPUT_WIN = "binary image"; int t1_value = 50; int max_value = 255; int main() { src = imread(".//pic//0.jpg"); namedWindow(INPUT_WIN, CV_WINDOW_AUTOSIZE); imshow(INPUT_WIN, src); Mat moutput; //轉成灰度圖 cvtColor(src, moutput, CV_BGR2GRAY); //霍夫圓檢測 vector<Vec3f> pcircles; HoughCircles(moutput, pcircles, CV_HOUGH_GRADIENT, 1, 30, 100, 30, 110, 200); 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, 2), 2, LINE_AA); circle(dst, Point(cc[0], cc[1]), cc[2], Scalar(0, 255, 0), 2, LINE_AA); } imshow("Hough檢測后", dst); waitKey(0); return 0; }
轉成灰度圖再處理的代碼:
#include <opencv2/opencv.hpp> #include <iostream> #include <math.h> #include <vector> using namespace cv; using namespace std; Mat src, dst,dst2,gray_src; char* INPUT_WIN = "input image"; char* OUTPUT_WIN = "binary image"; int t1_value = 50; int max_value = 255; int main() { src = imread(".//pic//0.jpg"); namedWindow(INPUT_WIN, CV_WINDOW_AUTOSIZE); imshow(INPUT_WIN, src); Mat moutput; //轉成灰度圖 cvtColor(src, moutput, CV_BGR2GRAY); //中值濾波 medianBlur(moutput, moutput, 3); imshow("中值濾波后", moutput); //邊緣檢測 Canny(moutput, dst2, 100, 100 * 2, 3, false); imshow("canny", dst2); //霍夫圓檢測 vector<Vec3f> pcircles; HoughCircles(dst2, pcircles, CV_HOUGH_GRADIENT, 1, 10, 100, 30, 110, 200); 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, 2), 2, LINE_AA); circle(dst, Point(cc[0], cc[1]), cc[2], Scalar(0, 255, 0), 2, LINE_AA); } imshow("Hough檢測后", dst); waitKey(0); return 0; }