目录
- 前言
- 正文
- 原理
- 函数
- Canny
- HoughLines
- cv.line
- cv.houghLineP
- 结果
- 参考文献
前言
霍夫变换(Hough Transform)是图像处理中的一种特征提取技术,可以识别图像中的几何形状。它将图像空间中的特征点映射到参数空间进行投票,通过检测累计结果的局部极值点得到一个符合某特定形状的点的集合。经典霍夫变换用来检测图像中的直线,后来霍夫变换扩展到任意形状物体的识别,多为圆和椭圆。它的抗噪声、抗形变能力较强。另一种直线提取的方法是对图像边缘点进行链码追踪,在得到的链码串中提取直线。
霍夫变换将在一个空间中具有相同形状的曲线或直线映射到另一个坐标空间的一个点上形成峰值,从而把检测任意形状的问题转化为统计峰值问题。
正文
原理
- 关于原理,请看这篇文章Hough直线检测的理解,或者是这篇文章:霍夫变换。这篇关于hough的原理写的很透彻,值得好好看一下。
函数
Canny
HoughLines
void HoughLines(
InputArray image, // 输入图像,即源图像(需为8位的单通道二进制图像)
OutputArray lines, // 经过调用HoughLines函数后储存了霍夫线变换检测到线条的输出矢量(每一条线由具有两个元素的矢量(rho,theta)表示)
double rho, // 以像素为单位的距离精度 rho,另一种形容方式是直线搜索时的进步尺寸的单位半径。
double theta, // 以弧度为单位的角度精度 theta,另一种形容方式是直线搜索时的进步尺寸的单位角度。
int threshold, // 累加平面的阈值参数,即识别某部分为图中的一条直线时它在累加平面中必须达到的值
double srn=0, // 对于多尺度的霍夫变换,这是第三个参数进步尺寸rho的除数距离
double stn=0 // 对于多尺度的霍夫变换,srn表示第四个参数进步尺寸的单位角度theta的除数距离
)
cv.line
void cvLine( CvArr* img,CvPoint pt1, CvPoint pt2, CvScalar color,int thickness=1, int line_type=8, int shift=0 );
第一个参数img:要划的线所在的图像;
第二个参数pt1:直线起点
第二个参数pt2:直线终点
第三个参数color:直线的颜色 e.g:Scalor(0,0,255)
第四个参数thickness=1:线条粗细
第五个参数line_type=8,
8 (or 0) - 8-connected line(8邻接)连接 线。
4 - 4-connected line(4邻接)连接线。
CV_AA - antialiased 线条。
第六个参数:坐标点的小数点位数。
cv.houghLineP
void HoughLinesP(InputArray image, OutputArray lines, double rho, double theta, int threshold, double minLineLength=0, double maxLineGap=0 )
cv::HoughLinesP(
InputArray src, // 输入图像,必须8-bit的灰度图像
OutputArray lines, // 输出的极坐标来表示直线,经过调用HoughLinesP函数后后存储了检测到的线条的输出矢量,每一条线由具有四个元素的矢量(x_1,y_1, x_2, y_2) 表示,其中,(x_1, y_1)和(x_2, y_2) 是是每个检测到的线段的结束点。
double rho, // 生成极坐标时候的像素扫描步长,一般取值为 1
double theta, //生成极坐标时候的角度步长,一般取值CV_PI/180,即表示一度
int threshold, // 阈值,只有获得足够交点的极坐标点才被看成是直线
double minLineLength=0;// 最小直线长度,有默认值0,表示最低线段的长度,比这个设定参数短的线段就不能被显现出来。
double maxLineGap=0;// 最大间隔,有默认值0,允许将同一行点与点之间连接起来的最大的距离。
)
这里输出的是图像的两个点。
结果
第一种方法cv.HoughLines效果图
第二种方法效果图
第二种这里的效果不是很好,应该是我的图片或是参数没调好的问题。
代码:
import cv2 as cv
import numpy as np
def line_detection(image):
gray = cv.cvtColor(image,cv.COLOR_BGR2GRAY)
edges = cv.Canny(gray,50,150,apertureSize=3)
# cv2.HoughLines()返回值就是(ρ,θ)。ρ 的单位是像素,θ 的单位是弧度。
# 这个函数的第一个参数是一个二值化图像,所以在进行霍夫变换之前要首先进行二值化,或者进行 Canny 边缘检测。
# 第二和第三个值分别代表 ρ 和 θ 的精确度。第四个参数是阈值,只有累加其中的值高于阈值时才被认为是一条直线,
# 也可以把它看成能 检测到的直线的最短长度(以像素点为单位)。
lines = cv.HoughLines(edges,1,np.pi/180,200)
# 若输入的图采用上面的函数去检测直线没有检测到,则lines的数量为0,则会报错
for line in lines:
rho, theta = line[0]
a = np.cos(theta)
b = np.sin(theta)
x0 = a * rho
y0 = b * rho
x1 = int(x0 + 1000 * (-b))
y1 = int(y0 + 1000 * (a))
x2 = int(x0 - 1000 * (-b))
y2 = int(y0 - 1000 * (a))
cv.line(image, (x1, y1), (x2, y2), (43, 43, 43), 2)
cv.imshow("line_detection", image)
def line_detection_possible_demo(image):
gray = cv.cvtColor(image, cv.COLOR_BGR2GRAY)
edges = cv.Canny(gray, 50, 150, apertureSize=3)
# lines = cv.HoughLines(edges,1,np.pi/180,200)
minLineLength = 50
maxLineGap = 10
lines = cv.HoughLinesP(edges,1,np.pi/180,100,minLineLength,maxLineGap)
for x1,y1,x2,y2 in lines[0]:
cv.line(image,(x1,y1),(x2,y2),(0,255,0),2)
cv.imshow('hough_lines',image)
src = cv.imread("../images/shufa3.jpg")
cv.namedWindow("input image",cv.WINDOW_AUTOSIZE)
cv.imshow('input image', src)
#line_detection(src)
line_detection_possible_demo(src)
cv.waitKey(0) # 等有键输入或者1000ms后自动将窗口消除,0表示只用键输入结束窗口
cv.destroyAllWindows()
参考文献
- 霍夫直线变换介绍
- opencv学习笔记——cv::line函数详解