【opencv】圆检测(非hough)

来源:互联网 发布:餐厅门店经营数据 编辑:程序博客网 时间:2024/04/30 13:20

hough圆检测不是很稳定,需要调节的参数也比较多,即便半径都调节到合适的范围内,但是结果有时候仍然存在较大偏差,但是hough受噪声影响小,不受轮廓不连续影响。但是如果存在比较完整的轮廓,也可以直接对轮廓进行一个圆的检测。依据为圆的定义,“平面上到定点的距离等于定长的所有点组成的图形叫做圆.”


//************************************// Description: 两点距离// Method:    GetDistance// FullName:  GetDistance// Access:    public // Parameter: Point2f p1// Parameter: Point2f p2// Returns:   float// Author:    小白// Date:      2017/09/27// History://************************************float GetDistance(Point2f p1, Point2f p2){    float dis = sqrt((p1.x - p2.x) * (p1.x - p2.x) + (p1.y - p2.y) * (p1.y - p2.y));    return dis;}//************************************// Description: 根据轮廓点和圆心计算方差// Method:    ComputeVariance// FullName:  ComputeVariance// Access:    public // Parameter: std::vector<cv::Point> theContour 某个轮廓点向量// Parameter: Point2f theCenter 最小外接圆圆心// Returns:   float// Author:    小白// Date:      2017/09/27// History://************************************float ComputeVariance(std::vector<cv::Point> theContour, Point2f theCenter){    int n = theContour.size();    vector<int> a(n);    float aver,s;    float sum = 0, e = 0;    for(int i = 0; i < n; i++)    {        a[i] = GetDistance(theContour[i],theCenter);        sum += a[i];    }    aver = sum / n;    for(int i = 0; i < n; i++)        e += (a[i] - aver) * (a[i] - aver);    e /= n - 1;    s = sqrt(e);    return e;}//************************************// Description: 判断某个轮廓是否为圆// Method:    FindCircles// FullName:  FindCircles// Access:    public // Parameter: Mat img 二值化图(不是边缘检测结果)// Parameter: int minPoints 轮廓最小点数(过滤噪点)// Parameter: int maxOffset 圆检测最大偏差// Parameter: int minr 最小半径// Parameter: int maxr 最大半径// Returns:   vector<Point3f>// Author:    小白// Date:      2017/09/27// History://************************************vector<Point3f> FindCircles(Mat img, int minPoints, int maxOffset, int minr, int maxr){    vector<Point3f> result;    vector<vector<Point> > contours;    vector<Vec4i> hierarchy;    findContours( img.clone(), contours, hierarchy, CV_RETR_CCOMP, CV_CHAIN_APPROX_SIMPLE );    for (int i = 0; i < contours.size(); i++)    {        Point2f center; float radius;          if (contours[i].size() > minPoints)        {            minEnclosingCircle(contours[i], center, radius);//得到最小外接圆圆心和半径              int offset = ComputeVariance(contours[i], center);            if (offset < maxOffset && radius > minr && radius <= maxr)            {                Point3f p(center.x, center.y, radius);                result.push_back(p);            }        }    }    return result;}void main(){    Mat a = imread("t.jpg", 1);//原图    Mat b;//灰度图    cvtColor(a, b, CV_BGR2GRAY);    Mat c;//二值图    threshold(b, c, 128, 255, CV_THRESH_BINARY);    int minr = 0;    int maxr = 100;    vector<Point3f> circles = FindCircles(c, 50, 80, 0, 100);//检测结果    for (int i = 0; i < circles.size(); i++)    {        circle(a, Point(circles[i].x, circles[i].y), circles[i].z, Scalar(0,0,255), 2, 8, 0);    }    imshow("检测结果", a);    waitKey(0);}


测试图


结果图













原创粉丝点击