Hough 变换

Hough 变换是图像处理中,检测直线最基本,也是应用最广泛的一种传统方法。虽然现在是深度学习大行其道的时代,但是很多传统的算法,依然有其参考的价值所在,至少从数学表达上来看,是更加的简洁,有理有据。

在介绍 Hough 变换之前,我们先回顾一下中学时代学的一些知识,我们学过直角坐标系,也就是常说的 X-Y 坐标系,我们知道在直角坐标系里,一条直线可以简单的用两个参数来表示 y = k x + b y = kx + b y=kx+b,同时我们学过极坐标系,一条直线可以由法向半径 ρ \rho ρ θ \theta θ 表示, ρ = x c o s θ + y s i n θ \rho = x cos \theta + y sin \theta ρ=xcosθ+ysinθ,所以一条直线可以有两种参数形式来表示:

y = k x + b ρ = x c o s θ + y s i n θ y = kx + b \\ \rho = x cos \theta + y sin \theta y=kx+bρ=xcosθ+ysinθ

Hough 变换_第1张图片
所以一条直线可以由直角坐标系下的 k , b k, b k,b 来决定,也可以由极坐标系下的 KaTeX parse error: Expected 'EOF', got '\thea' at position 7: \rho, \̲t̲h̲e̲a̲ 来表示,给定一条直线,其对应的参数就是确定的,那么,我们知道过一个点的直线有无数条,那么过这个点就会生成很多的 KaTeX parse error: Expected 'EOF', got '\thea' at position 7: \rho, \̲t̲h̲e̲a̲

ρ = x c o s θ + y s i n θ \rho = x cos \theta + y sin \theta ρ=xcosθ+ysinθ

一组 ρ , θ \rho, \theta ρ,θ 在直角坐标系下可以决定一条直线,反过来,直角坐标系下的一个点 x , y x, y x,y 在极坐标系下可以决定一条曲线,这个时候的变量就是 ρ , θ \rho, \theta ρ,θ,如下图所示,选择直线上的三个点,每个点在极坐标系下都形成了不同的曲线

Hough 变换_第2张图片
在图像中,一条直线有很多离散的点,每个点都会产生很多的 ρ , θ \rho, \theta ρ,θ,而有一组 ρ , θ \rho, \theta ρ,θ 是这条直线上的所有点都会产生的,如果看投票的话,就会看到这组 ρ , θ \rho, \theta ρ,θ 被命中的次数最多,如上图所示,所有极坐标系的下的曲线都会相交于某一个 ρ , θ \rho, \theta ρ,θ 而这个 ρ , θ \rho, \theta ρ,θ 其实就对应直角坐标下的一条直线。
hough 变换就是利用这样的关系,来找直线。

简单来说,就是先构造一个离散的 ρ , θ \rho ,\theta ρ,θ 空间,比如在图像域的话,一般可以假设 ρ \rho ρ 的范围是 -R ~ R,R 表示图像的长或者宽的一半, θ \theta θ 可以取 0   2 π 0 ~ 2\pi 0 2π,然后把这些参数离散化成 n n n 个区间,比如 20 或者 30 等,对应图像上的每一个像素坐标,都可以在这个 ρ , θ \rho, \theta ρ,θ 表上生成一系列的点,每个图像的像素点都能生成一系列的点,然后统计哪个 ρ , θ \rho, \theta ρ,θ 上命中的点多,那就有可能是一条直线,实际判断的时候,也会考虑设置一个阈值。

当然,如果对图像每个像素坐标都做这样的统计,显然计算量太大了,所以一般在做 hough 变换之前,会先做一个边缘检测,将明显不符合要求的点去掉,一般都做 canny 边缘检测。

OpenCV 有封装好的边缘检测与 hough 变换的函数:


# Read image 
	img = cv2.imread('lanes.jpg', cv2.IMREAD_COLOR)   # road.png is the filename
# Convert the image to gray-scale
	gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
# Find the edges in the image using canny detector
	edges = cv2.Canny(gray, 50, 200)
# Detect points that form a line
	lines = cv2.HoughLinesP(edges, 1, np.pi/180, max_slider, minLineLength=10, maxLineGap=250)
# Draw lines on the image
for line in lines:
    x1, y1, x2, y2 = line[0]
    cv2.line(img, (x1, y1), (x2, y2), (255, 0, 0), 3)
# Show result
cv2.imshow("Result Image", img)

参考来源:
https://www.learnopencv.com/hough-transform-with-opencv-c-python/

你可能感兴趣的:(图像处理,计算摄影与图像处理)