前言
在这里我们不硬啃原理(原理可参考Opencv[人民邮电出版社出版])。
一.霍夫变换原理
霍夫变换是图像处理中检测是否存在直线的重要算法,其基本原理为:通过将图像中的像素在一个空间坐标系中变换到另一个空间坐标系中,使得在原空间中具有相同特性的曲线或者直线映射到另一个空间中形成峰值,从而把检测任意形状的问题转化为统计峰值的问题。
二. 霍夫变换检测直线的步骤
2.1 将参数空间的坐标轴离散化
2.2 将图像中每个非零像素通过映射关系求取在参数空间通过的方格
2.3 统计参数空间内每个方格出现的次数,选取次数大于某一阈值的方格作为表示直线的方格
2.4 将参数空间中表示直线的方格的参数作为图像中直线的参数
三.标准霍夫变换和渐近概率式霍夫变换
3.1 标准霍夫变换
HoughLines( InputArray image, OutputArray lines, double rho, double theta, int threshold, double srn = 0, double stn = 0, double min_theta = 0, double max_theta = CV_PI );
其中各参数解释如下:
image: 输入图像,必须是CV-8U的单通道图像。
lines: 检测到的直线坐标描述的系数,每条直线都由两个参数表示,分别表示直线距离坐标原点的距离和坐标原点到直线的垂线与X轴的夹角。
rho: 以像素为单位的距离分辨率。
theta: 以弧度为单位的角度分辨率。
threshold: 累加计数值的阈值参数,当参数空间某个交点的累加计数的值超过该阈值,则认为该交点对应了图像空间的一条直线。
srn: 默认值为0,用于在多尺度霍夫变换中作为参数rho的除数,rho=rho/srn。
stn: 默认值为0,用于在多尺度霍夫变换中作为参数theta的除数,theta=theta/stn。
如果srn和stn同时为0,就表示HoughLines函数执行标准霍夫变换,否则就是执行多尺度霍夫变换。\
3.2. 渐近概率式霍夫变换
HoughLinesP( InputArray image, OutputArray lines, double rho, double theta, int threshold, double minLineLength = 0, double maxLineGap = 0 )
其中各参数解释如下:
image: 输入图像,必须是CV-8U的单通道图像。
lines: 霍夫检测到的直线或者线段的两个端点的坐标,每一条直线都由4个参数进行描述,分别是直线两个端点的坐标(x1,y1,x2,y2)。
rho: 以像素为单位的距离分辨率。
theta: 以弧度为单位的角度分辨率。
threshold: 累加计数值的阈值参数,当参数空间某个交点的累加计数的值超过该阈值,则认为该交点对应了图像空间的一条直线。
minLineLength: 直线的最小长度,当检测直线时长度小于该数值时将被剔除。
maxLineGap: 同一直线上相邻的两个点之间的最大距离
动手开撸:
开撸之前的准备工作:我们拿倒图像后,先检查是三通道还是单通道,三通道则转单通道,接下来就需要传统的滤波降噪等操作的处理,这样是为了剔除不必要的干扰.
示例图像:
进行边缘检测处理
img = cv2.imread('2.jpg') # 将图像转换为灰度图像 gray_img = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY) # 应用直方图均衡化 dst_img = cv2.equalizeHist(gray_img) # 高斯滤波降噪 gaussian_img = cv2.GaussianBlur(dst_img, (11, 11), 0) # 利用Canny进行边缘检测 edges_img = cv2.Canny(gaussian_img, 50, 150, apertureSize=3) cv2.imshow("edges_img", edges_img) cv2.waitKey(0) cv2.destroyAllWindows()
截止到边缘检测后可以发现咱们的图像噪点处理的还不错,但是图像中还是存在些许断点,那么在进行霍夫变换的时候就需要将minLineLength设置的较小(木桶原理)
我们选择HoughLinesP作为处理边缘检测后的图像,具体参数如下(大家可自行更改尝试):
plot_lines = cv2.HoughLinesP(edges_img, 1, np.pi/180, 1, minLineLength=1, maxLineGap=22) for line in plot_lines: x1, y1, x2, y2 = line[0] cv2.line(img, (x1, y1), (x2, y2), (0, 0, 255), 2) cv2.imshow("plot_lines ", img) cv2.waitKey(0) cv2.destroyAllWindows()
完整demo:(HoughLinesPointSet具备同样效果)
import cv2 import numpy as np img = cv2.imread('2.jpg') # 将图像转换为灰度图像 gray_img = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY) # 应用直方图均衡化 dst_img = cv2.equalizeHist(gray_img) # 高斯滤波降噪 gaussian_img = cv2.GaussianBlur(dst_img, (11, 11), 0) # 利用Canny进行边缘检测 edges_img = cv2.Canny(gaussian_img, 50, 150, apertureSize=3) plot_lines = cv2.HoughLinesP(edges_img, 1, np.pi/180, 1, minLineLength=1, maxLineGap=22) for line in plot_lines: x1, y1, x2, y2 = line[0] cv2.line(img, (x1, y1), (x2, y2), (0, 0, 255), 2) cv2.imshow("plot_lines ", img) cv2.waitKey(0) cv2.destroyAllWindows()