OpenCV——霍夫圆实现简单的圆检测
程序员文章站
2022-03-22 16:55:39
...
1.原理
圆周上任意三点所确定的圆,经Hough变换后在三维参数空间应对应一点。遍历圆周上所有点,任意三个点所确定的候选圆进行
投票。遍历结束后,得票数最高点(理论上圆周上任意三点确定的圆在Hough变换后均对应三维参数空间中的同一点)所确定的圆
即为该圆周上,绝大多数点所确定的圆(以下称为当选圆),即绝大多数点均在该当选圆的圆周上,以此确定该圆。
2.API介绍
cv::HoughCircles
- 因为霍夫圆检测对噪声比较敏感,所以首先要对图像做中值滤波。
- 基于效率考虑,Opencv中实现的霍夫变换圆检测是基于图像梯度的实现,分为两步:
- 检测边缘,发现可能的圆心
- 基于第一步的基础上从候选圆心开始计算最佳半径大小
3.代码(VS2017+OpenCV3.4)
#include <iostream>
#include <opencv2/opencv.hpp>
#include <math.h>
using namespace std;
using namespace cv;
Mat src;
Mat medianImg;
Mat grayImg;
Mat houghCirclesImg;
int main()
{
src = imread("002.png");
if (src.empty())
{
cout << "fail to load Img" << endl;
return -1;
}
namedWindow("input_Img", 0);
imshow("input_Img", src);
//中值滤波
medianBlur(src, medianImg, 3);
//灰度化处理
cvtColor(medianImg, grayImg, CV_BGR2GRAY);
//霍夫圆检测
vector<Vec3f> pcircles;
//输入,输出,方法(类型)-HOUGH_GRADIENT,dp(dp=1时表示霍夫空间与输入图像空间的大小一致,dp=2时霍夫空间是输入图像空间的一半,以此类推),最短距离-可以分辨是两个圆否 则认为是同心圆 ,边缘检测时使用Canny算子的高阈值,中心点累加器阈值—候选圆心(霍夫空间内累加和大于该阈值的点就对应于圆心),检测到圆的最小半径,检测到圆的的最大半径
HoughCircles(grayImg,pcircles,CV_HOUGH_GRADIENT,1,10,100,30,5,50);
//在原图画出圆心和圆
for (size_t i = 0; i < pcircles.size(); i++)//size_t 无符号整数 unsigned int
{
//提取圆心坐标
Point center(cvRound(pcircles[i][0]), cvRound(pcircles[i][1]));//cvRound 返回和参数最接近的整数值
//提取半径
int radius = cvRound(pcircles[i][2]);
//圆心
circle(src, center, 3, Scalar(0, 255, 0), -1, 8, 0);
//圆
circle(src, center, radius, Scalar(0, 255, 0), 3, 8, 0);
}
namedWindow("circles", 0);
imshow("circles", src);
waitKey();
return 0;
}
4.结果
检测结果和参数设置有很大的关系,不同图像的圆检测最好根据具体情况分析
原图
效果图