霍夫变换(Hough Line Transform)-直线检测

灰太狼 2022-03-29 14:48 430阅读 0赞

OpenCV官网
参考1

原理

  • 直角坐标表示
  1. 用 y = m x + b y=mx+b y=mx+b 描述一条直线, m是斜率, b是截距,m和b是参数。
  2. 如果将上面 的式子改写: b = − m x + y b=-mx+y b=−mx+y ,x和y 是参数。

根据以上两个式子得出结论:给定一个点(x,y),对应到 2 上就是一条直线,x 相当于斜率,y相当于截距。如果给定一系列的点(x1,y1)、(x2,y2)、(x3,y3)…都在一条直线上,也就是满足 y = m x + b y=mx+b y=mx+b,那么对应到 2 中,每个点对应的线将交于一点。 但是由于 参数 m 和 b可能比较大,所以采用极坐标比较合适。

在这里插入图片描述

  • 极坐标系表示
  1. 极坐标系,一条直线的表示,知道 r r r 和 θ \theta θ ,确定一条直线(红色):

20190108164756872.png20190108165152872.png

  1. 整理后:

20190108164211159.png

Image Space中每一个点对应到 Parameter Space 中就是一条曲线(三角函数曲线)。在Image Space中的一条直线上,对应到Parameter Space 中 也是相交于一点(只看 r > 0 r>0 r>0 和 0 < θ < 2 π 0<\theta < 2\pi 0<θ<2π):

2019010816474562.png

  • 检测方法
  1. 对于图像的每个像素点(x,y),对应到参数空间中,找到交点,交于此点的曲线个数就是图像空间的直线上的像素点数。
  2. 设置一个阈值,交于一点曲线个数超过这个值,图像中才算一条直线;在图像空间中意味着参数为( r , θ r,\theta r,θ)的直线。

代码

  1. #include <opencv2/opencv.hpp>
  2. #include <iostream>
  3. using namespace cv;
  4. using namespace std;
  5. int main(void)
  6. {
  7. Mat dst,cdst,cdstP;
  8. const char* image = "../res/lines.png";
  9. Mat src = imread(image, cv::IMREAD_GRAYSCALE);
  10. if(src.empty())
  11. {
  12. cout << " Oops, failed load image" << endl;
  13. }
  14. Canny(src,dst,50,200,3);
  15. cvtColor(dst,cdst,cv::COLOR_GRAY2BGR);
  16. cdstP = cdst.clone();
  17. //第一种API
  18. vector<Vec2f> lines;
  19. HoughLines(dst,lines,1,CV_PI/180,120,0,0);
  20. for(int i=0; i< lines.size(); i++)
  21. {
  22. float rho= lines[i][0], theta = lines[i][1];
  23. Point pt1,pt2;
  24. double a = cos(theta), b = sin(theta);
  25. double x0 = a*rho, y0 = b*rho;
  26. pt1.x = cvRound(x0+1000*(-b)); //见底下图的解释
  27. pt1.y = cvRound(y0+1000*(a));
  28. pt2.x = cvRound(x0- 1000*(-b));
  29. pt2.y = cvRound(y0 - 1000*(a));
  30. line(cdst,pt1,pt2,Scalar(0,0,255),3,LINE_AA);
  31. }
  32. //第二种API
  33. vector<Vec4i> linesP;
  34. HoughLinesP(dst,linesP,1,CV_PI/180,50,50,10);
  35. for(int i=0;i<linesP.size();i++)
  36. {
  37. Vec4i l = linesP[i];
  38. line(cdstP,Point(l[0],l[1]),Point(l[2],l[3]),Scalar(0,0,255),3,LINE_AA);
  39. }
  40. //显示
  41. imshow("HoughLines Demo", cdst);
  42. imshow("HoughLinesP Demo" ,cdstP);
  43. waitKey(0);
  44. return 0;
  45. };

在这里插入图片描述

结果:

20190109143318117.png20190109143933713.png20190109143748438.png


OpenCV API

不建议使用
void cv::HoughLines
(
InputArray image,     // 8bits 单通道灰度 图像
OutputArray lines,    // vector (ρ,θ) ,ρ和θ是极坐标,θ弧度制,范围 0- π 2 \frac{\pi}{2} 2π​, 横轴为0,纵轴为 π 2 \frac{\pi}{2} 2π​
double rho,    // r 的步长(没明白),一般设1
double theta,    //θ部长(没明白),一般设置CV_PI/180
int threshold,    // votes 的阈值,只有大于这个的点数的线,才会被检测
double srn = 0,    // 处理多尺度图像,一般默认即可
double stn = 0,    //处理多尺度图像,一般默认即可
double min_theta = 0,    // 默认即可
double max_theta = CV_PI     //默认即可
)

建议使用

void cv::HoughLinesP
(
InputArray image,          // 8bits 单通道灰度图像
OutputArray lines,          // 4-element vector (x1,y1,x2,y2) (x1,y1)和(x2,y2)是直线的端点
double rho,          // r 的步长(没明白),一般设1
double theta,          // θ部长(没明白),一般设置CV_PI/180
int threshold,          //直线点数的阈值,>threshold才会被检测
double minLineLength = 0,     //小于此点数的直线将会被删除
double maxLineGap = 0     //同一条直线上两点的最小Gap
)

发表评论

表情:
评论列表 (有 0 条评论,430人围观)

还没有评论,来说两句吧...

相关阅读