天天看点

OpenCV中霍夫圆检测OpenCV中霍夫圆检测

OpenCV中霍夫圆检测

在直线检测中,变换后在 r − θ r-\theta r−θ空间内曲线交点,然后根据阈值来得到直线。在圆中需要有三个变量圆心坐标和半径,因此变换后的空间在三维空间,根据三维空间中的曲线的交点得到圆。这就是标准的霍夫圆变换。但这个变换涉及到计算量过于巨大,所以很难实际应用。

在实际应用中常用的是: 霍 夫 梯 度 法 \color{#f00}霍夫梯度法 霍夫梯度法。算法的原理:圆心一定在圆上每个点的模向量上,这些圆上的点的模向量的交点就是圆心,霍夫梯度法的第一步便是找到这些圆心,第二部根据所有候选中心的的边缘非零像素对其的支持程度来确定半径。

感觉太墨迹了,说说个人理解,不一定正确,希望看到的大佬多多指正。霍夫梯度算法:先做边缘检测,然后利用边缘像素的点模向量相交,发现可能的圆心,然后再根据有多少个边缘像素的模向量交于圆心,从而得到最佳的半径。

API:

HoughCircles(
	输入图像,8位单通道
	vector<Vec3f>变量,发现圆的信息(x,y,r)
	int method(CV_HOUGH_GRADIENT)
	dp,用来检测圆心的累加器图像的分辨率与输入图像之比的导数,如dp=2,累加器有输入图像一半的宽度和高度。
	mindist 最短距离-可以分辨是两个圆的,否则认为时同心圆。太小相邻的检测成一个重合的圆,太大,有些就检测不出来了。
	param1 传递给Canny的高阈值,低的为高阈值的一半。
	param2 中心累加器阈值-候选圆心,越小检测到更多根本不存在的圆,越大能通过检测的圆更加接近完美的圆形。
	int 最小半径
	inti 最大半径	
);
           

下面是一个小的demo

#include "opencv2/opencv.hpp"

using namespace cv;
using namespace std;


int main(int argc, char *argv[])
{
    Mat src,dst,temp;
    RNG rng((unsigned int)time(NULL));
    src = Mat::zeros(500,500,CV_8UC3);
    for(int i = 0;i < 5;i++)
        circle(src,Point(rng.uniform(100,400),rng.uniform(100,400)),rng.uniform(1,100),Scalar(255,255,255),-1);
    imshow("src",src);
    cvtColor(src,temp,CV_RGB2GRAY);
    GaussianBlur(temp,dst,Size(9,9),2,2);
    vector<Vec3f> circles;
    HoughCircles(dst,circles,CV_HOUGH_GRADIENT,1,30,200,50,0,0);
    cout << circles.size() << endl;
    for(size_t i = 0;i < circles.size();i++)
    {
        cout << cvRound(circles[i][0]) << "," << cvRound(circles[i][1]) << endl;
        Point center(cvRound(circles[i][0]),cvRound(circles[i][1]));
        int radius = cvRound(circles[i][2]);
        circle(src,center,3,Scalar(0,255,0),-1);
        circle(src,center,radius,Scalar(rng.uniform(0,255),rng.uniform(0,255),rng.uniform(0,255)),3,8,0);
    }
    imshow("back",src);
    waitKey(0);
    return 0;
}