Opencv图像处理---Hough线变换

理论

  • 霍夫线变换是用于检测直线的变换。
  • 为了应用变换,首先需要边缘检测预处理。

它是如何工作的?

  • 图像空间中的一条线可以用两个变量表示。 例如:
  1. 在笛卡尔坐标系中:参数:(m,b)
  2. 在极坐标系中:参数:(r,θ)
  • 对于霍夫变换,我们将在极坐标系统中表达线条。 因此,线方程可以写成:
  • 通常对于每个点(x0,y0),我们可以定义经过该点的行:
  • 如果对于给定的(x0,y0)我们绘制经过它的线,我们得到一个正弦曲线。 例如,对于x0 = 8和y0 = 6,我们得到以下图(在平面θ-r中):
  • 我们可以对图像中的所有点执行相同的操作。 如果两个不同点的曲线在平面θ-r中相交,则意味着两个点都属于同一条线。 例如,按照上面的例子,绘制两个点的图:x1 = 4,y1 = 9,x2 = 12,y2 = 3,我们得到:
  • 上面的所有东西意味着什么? 这意味着通常可以通过查找曲线之间的交叉点数来检测线。交叉的曲线越多意味着该交点所代表的线具有更多的点。 通常,我们可以定义检测线所需的最小交叉点数量的阈值。
  • 这就是霍夫线变换所做的。 它跟踪图像中每个点的曲线之间的交点。 如果交点的数量高于某个阈值,则将其声明为具有交点的参数(θ,rθ)的线。

标准和概率Hough线变换

OpenCV实现了两种Hough Line变换:

  • 标准霍夫变换:
  1. ​​​​​​​它给你一个对的矢量(θ,rθ)。
  2. 在OpenCV中,它使用函数cv :: HoughLines实现
  • ​​​​​​​概率Hough线变换
  1. ​​​​​​​Hough Line变换的更有效实现。 它给出了检测线(x0,y0,x1,y1)的极值作为输出
  2. 在OpenCV中,它使用函数cv :: HoughLinesP实现​​​​​​​

代码

#include "opencv2/imgcodecs.hpp"
#include "opencv2/highgui/highgui.hpp"
#include "opencv2/imgproc/imgproc.hpp"
#include <iostream>
using namespace cv;
using namespace std;
static void help()
{
    cout << "\nThis program demonstrates line finding with the Hough transform.\n"
            "Usage:\n"
            "./houghlines <image_name>, Default is ../data/pic1.png\n" << endl;
}
int main(int argc, char** argv)
{
    cv::CommandLineParser parser(argc, argv,
        "{help h||}{@image|../data/pic1.png|}"
    );
    if (parser.has("help"))
    {
        help();
        return 0;
    }
    string filename = parser.get<string>("@image");
    if (filename.empty())
    {
        help();
        cout << "no image_name provided" << endl;
        return -1;
    }
    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, COLOR_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, LINE_AA);
    }
#endif
    imshow("source", src);
    imshow("detected lines", cdst);
    waitKey();
    return 0;
}

解释

  • 加载图像

  • 使用Canny检测器检测图像的边缘

  • 标准霍夫线变换

        (1)dst:边缘检测器的输出。 它应该是灰度图像(虽然实际上它是二进制图像)

        (2)lines:一个向量,用于存储检测到的行的参数(r,θ)

        (3)rho:参数r的分辨率,以像素为单位。 我们使用1个像素。

        (4)theta:以弧度表示的参数θ的分辨率。 我们使用1度(CV_PI / 180)

        (5)threshold:“*检测*”一条线的最小交叉点数

        (6)srn和stn:默认参数为零。

  1. 首先,应用Transform:

  2. 然后通过绘制线条显示结果。

  • 概率Hough线变换
  1. 首先应用转换:
  2. 然后通过绘制线条显示结果。
  • 显示原始图像和检测到的线条:
  • 等到用户退出程序

效果

使用输入图像,例如:

我们使用概率Hough线变换得到以下结果:

猜你喜欢

转载自blog.csdn.net/LYKymy/article/details/83186697