方法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; }