Opencv学习笔记四 霍夫变换

最简单的霍夫变换是在图像中识别直线。在平面直角坐标系(x-y)中,一条直线可以用下式表示。

y=kx+b

对于直线上一个确定的点(x_0,y_0),有:y_0=kx_0+b

这表示参数平面(k-b)中的一条直线。因此,图像中的一个点对应参数平面中的一条直线,图像中的一条直线对应参数平面中的一个点。对图像上所有的点作霍夫变换,最终所要检测的直线对应的一定是参数平面中直线相交最多的那个点。这样就在图像中检测出了直线。在实际应用中,直线通常采用参数方程

Opencv里有以下函数检测直线(最基本的霍夫变换):

void HoughLines(InputArray image,OutputArray lines, double rho, double theta, int threshold, doublesrn=0, double stn=0 )

具体用法看代码就知道了:

[cpp] viewplaincopyprint?
  1. #include"opencv2/opencv.hpp"
  2. #definePI3.1415926
  3. intmain(intargc,char*argv[])
  4. {
  5. cv::Matimage=cv::imread("road.jpg");
  6. cv::Matresult;
  7. cv::cvtColor(image,result,CV_BGRA2GRAY);
  8. cv::Matcontours;
  9. //边缘检测
  10. cv::Canny(result,contours,125,350);
  11. std::vector<cv::Vec2f>lines;
  12. //霍夫变换,获得一组极坐标参数(rho,theta),每一对对应一条直线,保存到lines
  13. //第3,4个参数表示在(rho,theta)坐标系里横纵坐标的最小单位,即步长
  14. cv::HoughLines(contours,lines,1,PI/180,80);
  15. std::vector<cv::Vec2f>::const_iteratorit=lines.begin();
  16. std::cout<<lines.size()<<std::endl;
  17. while(it!=lines.end()){
  18. floatrho=(*it)[0];
  19. floattheta=(*it)[1];
  20. if(theta<PI/4.||theta>3.*PI/4){
  21. //画交点在上下两边的直线
  22. cv::Pointpt1(rho/cos(theta),0);
  23. cv::Pointpt2((rho-result.rows*sin(theta))/cos(theta),result.rows);
  24. cv::line(image,pt1,pt2,cv::Scalar(255),1);
  25. }
  26. else{
  27. //画交点在左右两边的直线
  28. cv::Pointpt1(0,rho/sin(theta));
  29. cv::Pointpt2(result.cols,(rho-result.cols*cos(theta)/sin(theta)));
  30. cv::line(image,pt1,pt2,cv::Scalar(255),1);
  31. }
  32. ++it;
  33. }
  34. cv::namedWindow("hough");
  35. cv::imshow("hough",image);
  36. cv::waitKey(0);
  37. }
#include "opencv2/opencv.hpp"#define PI 3.1415926int main(int argc, char *argv[]){    cv::Mat image = cv::imread ("road.jpg");    cv::Mat result;    cv::cvtColor (image,result,CV_BGRA2GRAY);    cv::Mat contours;    //边缘检测    cv::Canny (result,contours,125,350);    std::vector<cv::Vec2f> lines;    //霍夫变换,获得一组极坐标参数(rho,theta),每一对对应一条直线,保存到lines    //第3,4个参数表示在(rho,theta)坐标系里横纵坐标的最小单位,即步长    cv::HoughLines (contours,lines,1,PI/180,80);    std::vector<cv::Vec2f>::const_iterator it = lines.begin ();    std::cout<<lines.size ()<<std::endl;    while(it != lines.end()){        float rho = (*it)[0];        float theta = (*it)[1];        if(theta<PI/4.||theta>3.*PI/4){            //画交点在上下两边的直线            cv::Point pt1(rho/cos(theta),0);            cv::Point pt2((rho-result.rows*sin(theta))/cos(theta),result.rows);            cv::line(image,pt1,pt2,cv::Scalar(255),1);        }       else {            //画交点在左右两边的直线            cv::Point pt1(0,rho/sin(theta));            cv::Point pt2(result.cols,(rho-result.cols*cos(theta)/sin(theta)));            cv::line(image,pt1,pt2,cv::Scalar(255),1);        }        ++it;    }    cv::namedWindow ("hough");    cv::imshow("hough",image);    cv::waitKey (0);}

检测结果示例:

另外,可以看出,上面的直线检测存在以下问题:

1)只能检测出线段所在的直线,而不知道具体线段位置,也不知道线段长度;

2)同一直线可能检测出多条直线;

3)偶然地也可能误判段直线。

针对这些问题,opencv有那么一个函数:

void HoughLinesP(InputArray image,OutputArray lines, double rho, double theta, int threshold,dou-
ble minLineLength=0, double maxLineGap=0 )
这个方法是通过概率霍夫变换实现的:

1)随机获取边缘图片上的前景点,映射到级坐标系画曲线;

2)当极坐标系里面有交点达到最小投票数,将该点对应x-y坐标系的直线L找出来;

3)搜索边缘图片上前景点,在直线L上的点(且点与点之间距离小于maxLineGap的)连成线段,然后这些点全部删除,并且记录该线段的参数,就是起始点和终止点啦~~~~~~~~~~~~~~~~~~~(当然这里线段长度要满足最小长度的,否则就不用记录了)

4)重复1),2),3)

其使用方法见代码:

[cpp] viewplaincopyprint?
  1. #include"opencv2/opencv.hpp"
  2. #definePI3.1415926
  3. classLineFinder{
  4. private:
  5. //直线对应的点参数向量
  6. std::vector<cv::Vec4i>lines;
  7. //步长
  8. doubledeltaRho;
  9. doubledeltaTheta;
  10. //判断是直线的最小投票数
  11. intminVote;
  12. //判断是直线的最小长度
  13. doubleminLength;
  14. //同一条直线上点之间的距离容忍度
  15. doublemaxGap;
  16. public:
  17. //初始化
  18. LineFinder():deltaRho(1),deltaTheta(PI/180),
  19. minVote(10),minLength(0.),maxGap(0.){}
  20. //设置步长
  21. voidsetAccResolution(doubledRho,doubledTheta){
  22. deltaRho=dRho;
  23. deltaTheta=dTheta;
  24. }
  25. //设置最小投票数
  26. voidsetMinVote(intminv){
  27. minVote=minv;
  28. }
  29. //设置最小线段长度和线段间距容忍度
  30. voidsetLineLengthAndGap(doublelength,doublegap){
  31. minLength=length;
  32. maxGap=gap;
  33. }
  34. //寻找线段
  35. std::vector<cv::Vec4i>findLines(cv::Mat&binary){
  36. lines.clear();
  37. cv::HoughLinesP(binary,lines,deltaRho,deltaTheta,minVote,minLength,maxGap);
  38. //returnlines;
  39. }
  40. //画线段
  41. voiddrawDetectedLines(cv::Mat&image,cv::Scalarcolor=cv::Scalar(255,255,255)){
  42. std::vector<cv::Vec4i>::const_iteratorit2=lines.begin();
  43. while(it2!=lines.end()){
  44. cv::Pointpt1((*it2)[0],(*it2)[1]);
  45. cv::Pointpt2((*it2)[2],(*it2)[3]);
  46. cv::line(image,pt1,pt2,color);
  47. ++it2;
  48. }
  49. }
  50. };
  51. intmain(intargc,char*argv[])
  52. {
  53. cv::Matimage=cv::imread("road.jpg");
  54. cv::Matresult;
  55. cv::cvtColor(image,result,CV_BGRA2GRAY);
  56. cv::Matcontours;
  57. //边缘检测
  58. cv::Canny(result,contours,125,350);
  59. LineFinderfinder;
  60. finder.setMinVote(80);
  61. finder.setLineLengthAndGap(100,20);
  62. finder.findLines(contours);
  63. finder.drawDetectedLines(image);
  64. cv::namedWindow("hough");
  65. cv::imshow("hough",image);
  66. cv::waitKey(0);
  67. }
#include "opencv2/opencv.hpp"#define PI 3.1415926class LineFinder{private:        // 直线对应的点参数向量        std::vector<cv::Vec4i> lines;        //步长        double deltaRho;        double deltaTheta;        // 判断是直线的最小投票数        int minVote;        // 判断是直线的最小长度        double minLength;        // 同一条直线上点之间的距离容忍度        double maxGap;public:        //初始化        LineFinder() : deltaRho(1), deltaTheta(PI/180),        minVote(10), minLength(0.), maxGap(0.) {}        // 设置步长        void setAccResolution(double dRho, double dTheta) {                deltaRho= dRho;                deltaTheta= dTheta;        }        // 设置最小投票数        void setMinVote(int minv) {                minVote= minv;        }        // 设置最小线段长度和线段间距容忍度        void setLineLengthAndGap(double length, double gap) {                minLength= length;                maxGap= gap;        }        //寻找线段        std::vector<cv::Vec4i> findLines(cv::Mat& binary) {                lines.clear();                cv::HoughLinesP(binary,lines, deltaRho, deltaTheta, minVote,minLength, maxGap);//                return lines;        }        // 画线段        void drawDetectedLines(cv::Mat &image, cv::Scalar color=cv::Scalar(255,255,255)) {        std::vector<cv::Vec4i>::const_iterator
  

爱华网本文地址 » http://www.413yy.cn/a/25101018/367759.html

更多阅读

Matlab实现霍夫变换 霍夫变换matlab代码

本代码提供了matlab下求取经过霍夫变换的直线斜率,并将其联合,代码见下方,实验结果见文末。%入口图像为BW,出口图像为f%optimizefrommain_optimize,merelyselect2lines,onehaspositive%slope,theotherhasnegativeslopeclearall,clo

小李飞刀--比埃尔霍夫我们曾经拥有 重生在小李飞刀

在昔年一个充满了暴力邪恶动乱的时代里,江湖中突然有一种飞刀出现了。没有人知道它的形状和式样,也没有人能够形容它的力量和速度。这就是“小李飞刀”。在今日动荡不安的欧洲足坛,也突然出现了这样一位前锋。他的传奇故事就像童话中的

中小学教师职业道德规范学习笔记

中小学教师职业道德规范学习笔记一、依法执教。学习和宣传马列主义、毛泽东思想和邓--同志建设有中国特色社会主义理论,拥护党的基本路线,全面贯彻国家教育方针,自觉遵守《教师法》等法律法规,在教育教学中同党和国家的方针政策保持一

伤寒学习笔记(下

伤寒学习笔记---14,桂枝用量问题?学习仲景药法,涉及用量问题。深入考证,固然不必,简单了解,实属必要。仅以桂枝为例,整理如下:基本资料:《现代中医药应用与研究大系》1985年版,简称《大系》。药法:凡例里说:“将其折合今之用量---,并结合笔者临床

关于闪光灯TTL的学习笔记

关于闪光灯TTL的学习笔记(转)俺注:一直对加闪光灯的拍摄比较疑惑,要知道并不是加开个闪光就一了百了的。特别是现在的专业闪灯,有好几种模式,都需要配合相机的测光使用。今天无意之间看到一篇解疑的文章,赶紧收集下来仔细学习。想学习下闪

声明:《Opencv学习笔记四 霍夫变换》为网友小郎君分享!如侵犯到您的合法权益请联系我们删除