当前位置:网站首页 > 创业 > 正文

OpenCV:霍夫变换HoughLines vs HoughCircles

0 张子豪 张子豪 2025-10-12 03:21 1

绪:

若何检测和识别图像中的直线和圆?

一个很是有用的方式就是霍夫变换;

是图像中识别各类几何外形的根基算法之一;

本文介绍一下opencv中的霍夫线变换和霍夫圆变换的应用。

东西/原料

  • OpenCV 2410

方式/步调

  1. 1

    霍夫线变换:

    霍夫线变换是一种在图像中寻找直线的方式;

    OpenCV中撑持三种霍夫线变换,别离为尺度霍夫线变换、多标准霍夫线变换、累计概率霍夫线变换。

    在OpenCV中可以挪用HoughLines来进行尺度霍夫线变换和多标准霍夫线变换;

    挪用HoughLinesP函数进行累积概率霍夫线变换。

  2. 2

    霍夫直线思惟:

    我们都知道,

    二维坐标轴上暗示一条直线的方程式y = a*x + b,

    我们想求出一条直线就得想方设法求出此中的a和b的值。

    若是用极坐标来暗示就是:rho=xcos(theta)+ysin(theta);

    此中,

    theta就是直线与程度线所当作的角度,

    而rho就是圆的半径;

    同样地,这两个参数也是表征一条直线的主要参数,

    确定他们俩了,也就确定一条直线了。

    【注】:

    OpenCV里,只需挪用HoughLines就可获得表征一条直线的这两个参数值!

  3. 3

    霍夫直线检测示例一:HoughLines

    #include <opencv2\opencv.hpp>

    #include <opencv2\highgui\highgui.hpp>

    #include <opencv2\features2d\features2d.hpp>

    #include <opencv2\core\core.hpp>

    #include <opencv2\imgproc\imgproc.hpp>

     

    using namespace std; 

    using namespace cv; 

     

    int main()

    {

           Mat srcImage = imread("0.jpg");

           imshow("srcImg", srcImage);

           //边缘检测

           Mat midImage, dstImage;

           Canny(srcImage, midImage, 50, 200, 3);

           cvtColor(midImage, dstImage, CV_GRAY2BGR);

           //界说矢量布局存放检测出来的直线

           vector<Vec2f> lines;

           HoughLines(midImage, lines, 1, CV_PI / 180, 150, 0, 0);

           //第五个参数表阈值,阈值越年夜检测越精准速度越快直线越少

           //lines是包含rho和theta的,而不包罗直线上的点,

           //所以下面需要按照获得的rho和theta来成立一条直线

     

           //依次画出每条线段

           for (size_t i = 0; i < lines.size(); i++)

           {

                  float rho = lines[i][0]; //就是圆的半径r

                  float 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(dstImage, pt1, pt2, Scalar(55, 100, 195), 1, CV_AA);

                  imshow("边缘检测后的图", midImage);

                  imshow("最终结果图", dstImage);

           }

           waitKey();

           return 0;

    }

    【问题】:

    你会发现,怎么图中一些很较着的的直线都没检测出来啊?

    原因是,我们阈值写的有点高了,只有那些有足够的把握认为是直线的直线才可能检测出来。

    若是把阈值改为150,直线检测结果就酿成如许子了。

    显然多了良多直线,把那些“可能是直线”的直线都当做是直线了。

    所以,阈值的选择很主要,就看你是要切确查找仍是恍惚查找了。

    【注】:角度theta用的单元不是我们所说的度数(70度、80度),而是数学上的π/2,π/3。

  4. 4

    霍夫直线检测示例二:HoughLinesP

           //与HoughLines分歧的是,

           //HoughLinesP获得lines的是含有直线上点的坐标的,

           //所以下面进行划线时就不再需要本身求出两个点来确定独一的直线了

    #include <opencv2\opencv.hpp>

    #include <opencv2\highgui\highgui.hpp>

    #include <opencv2\features2d\features2d.hpp>

    #include <opencv2\core\core.hpp>

    #include <opencv2\imgproc\imgproc.hpp>

     

    using namespace std; 

    using namespace cv; 

     

    int main()

    {

           Mat srcImage = imread("2.jpg");

           imshow("Src Pic", srcImage);

           Mat midImage, dstImage;

           Canny(srcImage, midImage, 50, 200, 3);

           cvtColor(midImage, dstImage, CV_GRAY2BGR);

     

           vector<Vec4i> lines;

           HoughLinesP(midImage, lines, 1, CV_PI / 180, 80, 50, 10);//注重第五个参数,为阈值

     

           //依次画出每条线段

           for (size_t i = 0; i < lines.size(); i++)

           {

                  Vec4i l = lines[i];

                  line(dstImage, Point(l[0], l[1]), Point(l[2], l[3]), Scalar(186, 88, 255), 1, CV_AA);

                  imshow("边缘检测后的图", midImage);

                  imshow("最终结果图", dstImage);

           }

           waitKey();

           return 0;

    }

  5. 5

    霍夫圆变换:

    对直线来说,一条直线由参数极径极角(rho,theta)暗示;

    对圆来说,需要三个参数来暗示一个圆;(center_x,center_y,r);其对应一条三维空间的曲线;

    那么与二维的霍夫线变换同样的事理,

    对于多个边缘点越多这些点对应的三维空间曲线交于一点,那么他们颠末的配合圆上的点就越多,

    近似的我们也就可以用同样的阈值的方式来判定一个圆是否被检测到, 这就是尺度霍夫圆变换的道理,

    但也恰是在三维空间的计较量年夜年夜增添的原因, 尺度霍夫圆转变很难被应用到现实中;

     

    出于对运算效率的考虑, OpenCV实现的是一个比尺度霍夫圆变换更为矫捷的检测方式: 霍夫梯度法, 也叫2-1霍夫变换(21HT),

    道理:依据是圆心必然是在圆上的每个点的模标的目的量上, 这些圆上点模标的目的量的交点就是圆心, 霍夫梯度法的第一步就是找到这些圆心, 如许三维的累加平面就又转化为二维累加平面.;

    第二步按照所有候选中间的边缘非0像素对其的撑持水平来确定半径.;

  6. 6

    霍夫圆变换示例:

    #include <opencv2\opencv.hpp>

    #include <opencv2\highgui\highgui.hpp>

    #include <opencv2\features2d\features2d.hpp>

    #include <opencv2\core\core.hpp>

    #include <opencv2\imgproc\imgproc.hpp>

     

    using namespace std; 

    using namespace cv; 

     

    int main()

    {

           Mat srcImage = imread("test5.jpg"); 

           Mat midImage, dstImage;

           imshow("srcImg", srcImage);

     

           cvtColor(srcImage, midImage, CV_BGR2GRAY);

           GaussianBlur(midImage, midImage, Size(9, 9), 2, 2);

     

           //霍夫圆变换 

           vector<Vec3f> circles;

           HoughCircles(midImage, circles, CV_HOUGH_GRADIENT, 1.5, 10, 200, 150, 0, 0);

           //注重第七的参数为阈值,可以自行调整,值越年夜,检测的圆更精准

     

           //依次在图中绘制出圆 

           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(srcImage, center, 3, Scalar(0, 255, 0), -1, 8, 0);

                  //绘制圆轮廓 

                  circle(srcImage, center, radius, Scalar(155, 50, 255), 3, 8, 0);

           }

     

           imshow("【结果图】", srcImage);

           waitKey(0);

           return 0;

    }

注重事项

  • 挪用HoughLines就可获得表征一条直线的这两个参数值!

来源:百闻(微信/QQ号:9397569),转载请保留出处和链接!


本文链接:https://www.ibaiwen.com/web/235542.html

张子豪

张子豪

TA很懒,啥都没写...

@百闻娱乐 本站部分内容转自互联网,若有侵权等问题请及时与本站联系,我们将在第一时间删除处理。 | 粤ICP备2024343649号 | (地图