霍夫圆检测和霍夫直线检测的原理类似。建议先理解霍夫直线检测的原理,再来看霍夫圆检测。
圆在极坐标下的数学表达式如下:
{ 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+r⋅cosθy=b+r⋅sinθ
其中 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=x−r⋅cosθy−r⋅sinθr
上面是标准霍夫圆变换的原理,和霍夫直线变换相比,最大的区别是霍夫空间变成了三维空间,这就给统计效率带来了挑战。2-1霍夫变换(21HT)是对标准霍夫变换的改进,把霍夫变换分为两个阶段,从而减小了霍夫空间的维数。第一阶段用于检测圆心,第二阶段从圆心推导出圆半径。该算法有一个不足之处就是由于圆半径的检测完全取决于圆心的检测,因此如果圆心检测出现偏差,那么圆半径的检测肯定也是错误的。OpenCV 中的霍夫变换圆是基于 21HT 实现的。更多关于霍夫圆变换的原理介绍可以参考 霍夫圆变换。
void HoughCircles
(InputArray image, OutputArray circles, int method, double dp, double minDist, double param1=100, double param2=100, int minRadius=0, int maxRadius=0 )Para | Disc. |
---|---|
image | 输入图像 ,必须是8位的单通道灰度图像 |
circles | 输出结果,发现的圆信息,也是向量数组vector |
method | 目前只有 HOUGH_GRADIENT,通过梯度来寻找 |
dp | dp = 1:在原图上寻找;dp = 2, 原图宽高减半 |
mindist | 如果两个圆的圆心距离小于 mindist 则认为是同一个圆 |
param1 | Canny 检测时的 高阈值,低阈值是 param1 的一半 |
param2 | 中心点累加器阈值,小于该阈值的会被忽略 |
minradius,maxradius | 搜寻半径范围 |
由于 对噪声比较敏感,所以一般需要先进行去噪操作,比如 GaussianBlur(), 或者 medianBlur 等。
#include
#include
#include
#include
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 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霍夫变换系列(中篇)-霍夫圆变换