HoughLinesP函数(概率检测直线)

  1. 统计概率霍夫线变换
  • 这是执行起来效率更高的霍夫线变换. 它输出检测到的直线的端点 (x_{0}, y_{0}, x_{1}, y_{1})
  • 在OpenCV 中它通过函数 HoughLinesP 来实现

代码

  1. 这个程序是用来做什么的?
    • 加载一幅图片
    • 对图片进行 标准霍夫线变换 或是 统计概率霍夫线变换.
    • 分别在两个窗口显示原图像和绘出检测到直线的图像.
  2. 我们将要说明的例程能从 这里 下载。 一个更高级的版本 (能同时演示标准霍夫线变换和统计概率霍夫线变换并带有活动条来改变变换的阈值) 能从 这里 下载。
#include "opencv2/highgui/highgui.hpp"
#include "opencv2/imgproc/imgproc.hpp"

#include <iostream>

using namespace cv;
using namespace std;

void help()
{
 cout << "\nThis program demonstrates line finding with the Hough transform.\n"
         "Usage:\n"
         "./houghlines <image_name>, Default is pic1.jpg\n" << endl;
}

int main(int argc, char** argv)
{
 const char* filename = argc >= 2 ? argv[1] : "pic1.jpg";

 Mat src = imread(filename, 0);
 if(src.empty())
 {
     help();
     cout << "can not open " << filename << endl;
     return -1;
 }

 Mat dst, cdst;
 Canny(src, dst, 50, 200, 3);
 cvtColor(dst, cdst, CV_GRAY2BGR);

 #if 0
  vector<Vec2f> lines;
  HoughLines(dst, lines, 1, CV_PI/180, 100, 0, 0 );

  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( cdst, pt1, pt2, Scalar(0,0,255), 3, CV_AA);
  }
 #else
  vector<Vec4i> lines;
  HoughLinesP(dst, lines, 1, CV_PI/180, 50, 50, 10 );
  for( size_t i = 0; i < lines.size(); i++ )
  {
    Vec4i l = lines[i];
    line( cdst, Point(l[0], l[1]), Point(l[2], l[3]), Scalar(0,0,255), 3, CV_AA);
  }
 #endif
 imshow("source", src);
 imshow("detected lines", cdst);

 waitKey();

 return 0;
}

代码说明

  1. 加载图片

    Mat src = imread(filename, 0);
    if(src.empty())
    {
      help();
      cout << "can not open " << filename << endl;
      return -1;
    }
    
  2. 用Canny算子对图像进行边缘检测

    Canny(src, dst, 50, 200, 3);
    

    现在我们将要执行霍夫线变换. 我们将会说明怎样使用OpenCV的函数做到这一点:

  3. 标准霍夫线变换

    1. 首先, 你要执行变换:

      vector<Vec2f> lines;
      HoughLines(dst, lines, 1, CV_PI/180, 100, 0, 0 );
      

      带有以下自变量:

      • dst: 边缘检测的输出图像. 它应该是个灰度图 (但事实上是个二值化图)
      • lines: 储存着检测到的直线的参数对  的容器 * rho : 参数极径 r 以像素值为单位的分辨率. 我们使用 1 像素.
      • theta: 参数极角  以弧度为单位的分辨率. 我们使用 1度 (即CV_PI/180)
      • threshold: 要”检测” 一条直线所需最少的的曲线交点
      • srn and stn: 参数默认为0. 查缺OpenCV参考文献来获取更多信息.
    2. 通过画出检测到的直线来显示结果.

      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( cdst, pt1, pt2, Scalar(0,0,255), 3, CV_AA);
      }
      
  4. 统计概率霍夫线变换

    1. 首先, 你要执行变换:

      vector<Vec4i> lines;
      HoughLinesP(dst, lines, 1, CV_PI/180, 50, 50, 10 );
      

      带有以下自变量:

      • dst: 边缘检测的输出图像. 它应该是个灰度图 (但事实上是个二值化图) * lines: 储存着检测到的直线的参数对 (x_{start}, y_{start}, x_{end}, y_{end}) 的容器
      • rho : 参数极径 r 以像素值为单位的分辨率. 我们使用 1 像素.
      • theta: 参数极角  以弧度为单位的分辨率. 我们使用 1度 (即CV_PI/180)
      • threshold: 要”检测” 一条直线所需最少的的曲线交点 * minLinLength: 能组成一条直线的最少点的数量. 点数量不足的直线将被抛弃.
      • maxLineGap: 能被认为在一条直线上的亮点的最大距离.
    2. 通过画出检测到的直线来显示结果.

      for( size_t i = 0; i < lines.size(); i++ )
      {
        Vec4i l = lines[i];
        line( cdst, Point(l[0], l[1]), Point(l[2], l[3]), Scalar(0,0,255), 3, CV_AA);
      }
      
  5. 显示原始图像和检测到的直线:

    imshow("source", src);
    imshow("detected lines", cdst);
    
  6. 等待用户按键推出程序

    waitKey();
    

结果

Note

 

得到的结果使用的是在上面 代码 部分提到的更高级版代码. 霍夫线变换的代码没有改变, 唯一不同的是在GUI的部分加入了活动条可动态改变阈值.输入图像为:

HoughLinesP函数(概率检测直线)_第1张图片

通过执行统计概率霍夫线变换我们能得到下面的结果:

当你使用滑动条来改变 阈值 的时候会观察到检测到线的数目的改变. 这是因为: 如果你设置了一个更大的阈值, 能检测到的线的数目将更少 (你需要更多的点来表示一条能检测到的直线).

你可能感兴趣的:(HoughLinesP函数(概率检测直线))