目标
在本教程中,您将学习如何:
- 使用 OpenCV 函数 HoughLines() 和 HoughLinesP() 检测图像中的线条。
理论
Hough 线变换
- 霍夫线变换是用于检测直线的变换。
- 要应用变换,首先需要进行边缘检测预处理。
它是如何工作的?
如您所知,图像空间中的一条线可以用两个变量表示。例如:
- 在笛卡尔坐标系中:参数 (x, y)
- 在极坐标系中:参数 (r, θ)
对于 Hough 变换,我们将在极坐标系中表达线条。因此,直线方程可以写成:
r = x cosθ + y sinθ
通常,对于每个点 (x0, y0),我们可以将穿过该点的线族定义为:
这意味着每对 (r, θ) 代表经过 (x0, y0) 的每条线。
如果对于给定的 (x0, y0),我们绘制穿过它的线族,我们得到一个正弦曲线。例如,对于 x0 = 8 和 y0 = 6,我们得到以下图(在平面 θ - r 中)。
我们可以对图像中的所有点执行相同的操作。如果两个不同点的曲线在平面 θ - r 中相交,则表示两个点都属于同一条直线。
这三个图在一个点 (0.925, 9.6) 相交,这些坐标是参数 (θ, r)。这意味着通常,可以通过查找曲线之间的交点数来检测一条线。相交的曲线越多,意味着该相交所表示的线具有更多的点。通常,我们可以定义检测一条线所需的最小交叉点数的阈值。
这就是 Hough Line Transform 的作用。它跟踪图像中每个点的曲线之间的交点。如果交叉点的数量高于某个阈值,则将其声明为带有交叉点参数 (θ, r) 的线。
标准和概率霍夫线变换
OpenCV 实现了两种 Hough Line Transforms:
a. 标准 Hough 变换
- 它几乎包含我们在上一节中解释的内容。结果,它为您提供了一对向量 (θ, r)。
- 在 OpenCV 中,它是使用函数
cv::HoughLines。
b. 概率霍夫线变换
- 更高效地实现 Hough Line Transform。它给出检测到的线的极端值 (x0, y0, x1, y1)。
- 在 OpenCV 中,它是使用函数
cv::HoughLinesP。
代码实现
我们将使用 C++ 编写示例代码。
#include <opencv2/opencv.hpp>
#include <iostream>
using namespace cv;
using namespace std;
int main(int argc, char** argv)
{
// 声明输出变量
Mat src, dst, cdst, cdstP;
const char* default_file = ;
* filename = argc >= ? argv[] : default_file;
src = (filename, IMREAD_COLOR);
(src.()) {
();
(, default_file);
;
}
(src, dst, , , );
dst.(cdst);
cdstP = cdst.();
vector<Vec2f> lines;
(dst, lines, , CV_PI / , , , );
( i = ; i < lines.(); i++) {
rho = lines[i][], theta = lines[i][];
Point2f pt1, pt2;
a = (theta), b = (theta);
x0 = a * rho, y0 = b * rho;
ptx = (x0 + * (-b));
pty = (y0 + * (a));
ptx = (x0 - * (-b));
pty = (y0 - * (a));
(cdst, pt1, pt2, (, , ), , LINE_AA);
}
vector<Vec4i> linesP;
(dst, linesP, , CV_PI / , , , );
( i = ; i < linesP.(); i++) {
Vec4i l = linesP[i];
(cdstP, (l[], l[]), (l[], l[]), (, , ), , LINE_AA);
}
(, src);
(, cdst);
(, cdstP);
();
;
}


