【opencv学习之二十七】Hough霍夫变换寻找直线和圆

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/abcvincent/article/details/79222978

霍夫变换是在图像中寻找直线、圆和其他一些简单形状的方法。霍夫变换有一个很重要的性质就是对图形在图像中残缺、噪声等不敏感,有较强抗干扰性;但其也有缺点,比如要检测的目标曲线要提前定义好,而如果曲线参数过多则计算量呈指数增长;理论上霍夫检测任意预定目标;opencv实现了其部分算法;Hough变换有很长的研究历史,同样也有很多的文献和资料;Hough基本思想是边缘信息A进行f(x)的拟合操作,通过计算拟合权重值来检测图形;衍生出的算法很多;

这里不做理论研究了,简单呈现opencv 霍夫变换的应用;直接上代码:

// 标准霍夫变换-HoughLines(),检测直线
    Mat src = imread("D:/ImageTest/sudoku.png");
    Mat dstImg = src.clone();
    imshow("src", src);
    //为了减少数据量,霍夫变换前一般进行边缘检测处理,将边缘二值图输入到变换算子中
    cvtColor(src, src, CV_BGR2GRAY);
    Mat cannyImg;
    Canny(src, cannyImg, 38, 100, 3);
    imshow("Canny", cannyImg);
    vector<Vec2f> lines;  //定义矢量结构lines用于存放得到的线段矢量(ρ,θ)集合
    HoughLines(
                cannyImg,//输入原图像
                lines,//输出矢量集合(ρ,θ)
                1, //以1像素点为单位的距离精度
                CV_PI / 180,//以1弧度为单位的角度精度
                150//阈值,大于阈值的线段才可以被检测通过并返回到结果中
                );
    //将线段画在目标图像上
    for (size_t i = 0; i < lines.size(); i++)
    {
        float rho = lines[i][0], theta = lines[i][1];
        Point pt1, pt2;
        double a = cos(theta), b = sin(theta);
        double x0 = a *rho, y0 = b* rho;
        pt1.x = cvRound(x0 + 1000 * (-b));
        pt1.y = cvRound(y0 + 1000 * (a));
        pt2.x = cvRound(x0 - 1000 * (-b));
        pt2.y = cvRound(y0 - 1000 * (a));
        line(dstImg, pt1, pt2, Scalar(0, 0, 255), 1, CV_AA);
    }
    imshow("dst", dstImg);
    waitKey(0);
效果:


累计霍夫变换:

//累计概率霍夫变换-HoughLinesP()
    Mat cannyImg;
    Mat src = imread("D:/ImageTest/sudoku.png");
    Mat dstImg = src.clone();
    imshow("src", src);
    cvtColor(src, src, CV_BGR2GRAY);
    Canny(src, cannyImg, 32, 100, 3);
    vector<Vec4i> lines;  //定义矢量结构lines用于存放得到的线段矢量(x_1,y_1,x_2,y_2)集合
    HoughLinesP(cannyImg, lines, 1, CV_PI/180, 150, 50, 10);
    //将线段画在目标图像上
    for(size_t i = 0; i<lines.size(); i++)
    {
        Vec4i l = lines[i];
        line(dstImg, Point(l[0], l[1]), Point(l[2], l[3]), Scalar(0, 255, 0), 2, CV_AA);
    }
    imshow("dst", dstImg);
    waitKey(0);
效果:


检测圆形:

  ///霍夫圆变换-HoughCircles()
        Mat src = imread("D:/ImageTest/cercle.png");
        Mat dst = src.clone();
        imshow("src", src);
        cvtColor(src, src, CV_BGR2GRAY);
        GaussianBlur(src, src, Size(9, 9), 2, 2);//不滤波会有非常非常多的误检圆
        vector<Vec3f> circles;//存放经霍夫变换后检测出的圆的输出矢量(x,y,radius)
        HoughCircles(src, circles, CV_HOUGH_GRADIENT, 2, 30, 200, 100, 10, 200);
        //将圆画在目标图像上
        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]);
            circle(dst, center, 3, Scalar(0, 0, 255), -1, 8, 0);
            circle(dst, center, radius, Scalar(0, 255, 0), 3, 8, 0);
        }
        imshow("dst", dst);
        waitKey(0);
效果:






猜你喜欢

转载自blog.csdn.net/abcvincent/article/details/79222978