OpenCvSharp 学习笔记20-- 霍夫变换 - 直线检测 (Hough Line transform)
一,霍夫变换介绍:霍夫(Hough) 变换是一种用于检测线,圆或者图像中其他简单形状的方法。使用霍夫直线检测,首先要对图像进项边缘检测预处理。平面空间到极坐标空间的转换图像空间中的直线可以用两个变量表示。例如:在笛卡尔坐标系中:参数:(m,b)在极坐标系统:参数:(r,θ)霍夫变换基本原理是:二进制图像中的任何点都可能属于某可能的线。如果为我们将每一条线参数化,比如斜率为a...
一,霍夫变换介绍:
- 霍夫(Hough) 变换是一种用于检测线,圆或者图像中其他简单形状的方法。
- 使用霍夫直线检测,首先要对图像进项边缘检测预处理。
- 平面空间到极坐标空间的转换
图像空间中的直线可以用两个变量表示。例如:
- 在笛卡尔坐标系中:参数:(m,b)
- 在极坐标系统:参数:(r,θ)
x
=
ρ
cos
θ
,
y
=
ρ
cos
θ
x=\rho\cos\theta , y=\rho\cos\theta
x=ρcosθ,y=ρcosθ
ρ
2
=
x
2
+
y
2
,
tan
θ
=
y
/
x
(
x
不
等
于
0
)
\rho^2=x^2+y^2 , \tan\theta=y/x (x不等于0)
ρ2=x2+y2,tanθ=y/x(x不等于0)
霍夫变换基本原理是:二进制图像中的任何点都可能属于某些可能的线。如果为我们将每一条线参数化,比如斜率为
a
a
a ,截距为
b
b
b ,原始图像中的点就可以转换为对应于通过该点的所有线在该平面
(
a
,
b
)
(a,b)
(a,b) 中的点的轨迹,也可能只是一部分根轨迹。如果我们将原图中的每个非0 像素 都转换成输出图像中这样的一系列点,并将所有这些贡献相加,那么原图
(
(
x
,
y
)
平
面
)
((x,y)平面)
((x,y)平面) 中的线将显示为输出图像
(
(
a
,
b
)
平
面
)
((a,b)平面)
((a,b)平面) 中的局部最大值。由于我们对每个点的贡献进行求和 ,所以
(
(
a
,
b
)
平
面
)
((a,b)平面)
((a,b)平面) 通常称为" 累加器平面"。
但是可能会发现,斜截式方程并不是代表所有穿过某个点的线的最佳方式( 因为图像中线的密度和斜率有很大的不同,还有一个相关的事实是,斜率的区间可能从
−
∞
-\infty
−∞ 到
+
∞
+\infty
+∞ ,正是因为如此,图像变换时数值计算实际用到的参数有所不同,最好的参数形式是用极坐标中的点(
ρ
\rho
ρ,
θ
\theta
θ)表示线,每条直线经过这个点并且垂直于它与原点相连的线) 如图:
图像平面 (A) 中有一个点可以表示很多直线,每条直线都可以有 (B) 中的
ρ
\rho
ρ 和
θ
\theta
θ 参数化,在 (
ρ
\rho
ρ,
θ
\theta
θ) 平面中,这些线组合在一起形成特殊的形状 (C) 的曲线
对于霍夫变换,我们将在极坐标系统中表示直线。因此,直线方程可以写成:
y
=
(
−
cos
θ
sin
θ
)
x
+
(
r
sin
θ
)
y=(-\frac{\cos\theta}{\sin\theta})x +(\frac{r}{\sin\theta})
y=(−sinθcosθ)x+(sinθr)
1:Arranging the terms(极经):
r
=
x
c
o
s
θ
+
y
s
i
n
θ
r=xcosθ+ysinθ
r=xcosθ+ysinθ
一般对于每个点(x0,y0),我们可以定义通过该点的直线族为:
r
θ
=
x
0
∗
cos
θ
+
y
0
∗
sin
θ
r\theta=x_0 * \cos\theta +y_0 * \sin\theta
rθ=x0∗cosθ+y0∗sinθ
θ
\theta
θ 的取值范围在 0° ~ 180° 或 0° ~ 360° 之间, 每次取 1°,(x,y)坐标不变 获取一次 r (极坐标的极经)值,获取一定范围内的点绘制成曲线。即:
每一对(
r
θ
rθ
rθ,
θ
θ
θ)代表,经过每一行(
x
0
x_0
x0,
y
0
y_0
y0)。
2:便利所有像素点,绘制曲线,绘制无数条曲线,这些曲线相交与一点,这表明,这些像素点都属于同一条直线。
对于任意一条直线上的点来说,变换到极坐标中, 从 [0 ~ 360] 空间 可以得到 r 的大小,属于同一条直线上的点在极坐标空间 (r,θ) 必然在一个点上有最强的信号出现,据此反算到平面坐标中就可以得到直线上各个点的坐标。从而得到直线。
二,API:
标准的霍夫变换
Cv2.HoughLines():使用标准霍夫变换查找二进制图像中的行。从平面坐标转换到极坐标空间,最终返回输出 (r,θ)表示极坐标空间。
返回值: LineSegmentPolar[]
结果需要自己反变换到平面空间,使用难度较大!
参数 | 描述 |
---|---|
InputArray image | 输入图像,8位、单通道、二进制源图像。 |
double rho | 累加器的距离分辨率(以像素为单位),(生成极坐标时的像素扫描的步长) |
double theta | 累加器的角度分辨率(以弧度为单位) (生成极坐标的角度步长,一般为 1°) |
int threshold | 累加器阈值参数,只有获取足够交点的极坐标才能看作直线 |
double srn = 0 | 对于多尺度霍夫变换,它是距离分辨率的因子。[默认值为0] 如果不是设置0 表示经典霍夫变换 |
double stn = 0 | 对于多尺度霍夫变换,它是距离分辨率的因子。[默认值为0] 如果不是设置0 表示经典霍夫变换 |
霍夫变换直线概率
**Cv2.HoughLinesP:**使用概率霍夫变换查找二进制图像中的线段。最终输出的是直线的两个点坐标
返回值类型:LineSegmentPoint[]
参数 | 描述 |
---|---|
InputArray image | 输入图像,8位、单通道、二进制源图像。 |
double rho | 累加器的距离分辨率(以像素为单位),(生成极坐标时的像素扫描的步长) |
double theta | 累加器的角度分辨率(以弧度为单位) (生成极坐标的角度步长,一般为 1°) |
int threshold | 阈值参数,只有获取足够交点的极坐标才能看作直线 |
double minLineLength = 0 | 最小线长度。比这短的线段将被拒绝。[默认值为0] |
double maxLineGap = 0 | 同一条线上的点之间连接它们的最大允许间隙。[默认值为0] |
三,代码:
/// <summary>
/// 霍夫变换-直线
/// </summary>
/// <param name="imagePath"></param>
private static void HoughtLine(string imagePath)
{
using (Mat srcLine = new Mat(imagePath, ImreadModes.AnyColor | ImreadModes.AnyDepth))
using (Mat dst = new Mat(srcLine.Size(), MatType.CV_8UC3, Scalar.Blue))
{
// 1:边缘检测
Mat canyy = new Mat(srcLine.Size(), srcLine.Type());
Cv2.Canny(srcLine, canyy, 60, 200, 3, false);
/*
* HoughLinesP:使用概率霍夫变换查找二进制图像中的线段。
* 参数:
* 1; image: 输入图像 (只能输入单通道图像)
* 2; rho: 累加器的距离分辨率(以像素为单位) 生成极坐标时候的像素扫描步长
* 3; theta: 累加器的角度分辨率(以弧度为单位)生成极坐标时候的角度步长,一般取值CV_PI/180 ==1度
* 4; threshold: 累加器阈值参数。只有那些足够的行才会返回 投票(>阈值);设置认为几个像素连载一起 才能被看做是直线。
* 5; minLineLength: 最小线长度,设置最小线段是有几个像素组成。
* 6;maxLineGap: 同一条线上的点之间连接它们的最大允许间隙。(默认情况下是0):设置你认为像素之间 间隔多少个间隙也能认为是直线
* 返回结果:
* 输出线。每条线由一个4元向量(x1, y1, x2,y2)
*/
LineSegmentPoint[] linePiont = Cv2.HoughLinesP(canyy, 1, 1, 1, 1, 10);//只能输入单通道图像
Scalar color = new Scalar(0, 255, 255);
for (int i = 0; i < linePiont.Count(); i++)
{
Point p1 = linePiont[i].P1;
Point p2 = linePiont[i].P2;
Cv2.Line(dst, p1, p2, color, 4, LineTypes.Link8);
}
using (new Window("DST", WindowMode.AutoSize, dst))
using (new Window("CANYY", WindowMode.AutoSize, canyy))
using (new Window("SRC", WindowMode.AutoSize, srcLine))
{
Cv2.WaitKey(0);
}
}
}
右边黄色线段为霍夫直线检测值输出。
更多推荐
所有评论(0)