• 理解霍夫变换的概念
• 学习如何在一张图片中检测直线
• 学习函数:cv2.HoughLines(),cv2.HoughLinesP()
霍夫变换在检测各种形状的的技术中非常流行,如果你要检测的形状可以用数学表达式写出,你就可以是使用霍夫变换检测它。即使要检测的形状存在一点破坏或者扭曲也可以使用。我们下面就看看如何使用霍夫变换检测直线。一条直线可以用数学表达式y = mx + c 或者ρ = x cosθ + y sinθ 表示。是从原点到直线的垂直距离,θ是直线的垂线与横轴顺时针方向的夹角(如果你使用的坐标系不同方向也可能不同,我是按OpenCV 使用的坐标系描述的)。如下图所示:
在霍夫变换中我们常用公式:
ρ = xcosθ + ysinθ
θ是直线与水平线所成的角度(0~180°),确定了它们,也就确定一条直线了
上图转自网址:https://www.cnblogs.com/hellcat/p/9896426.html#_label0
lines = cv2.HoughLines(edges,1,np.pi/180,200)
cv2.HoughLines(),它返回(ρ, θ)值的序列,ρ单位像素,θ单位弧度(lines: lines[i][0]为第i条直线的rho,lines[i][1]表示第i条直线的theta)。第一个参数,输入的图片是一个二进制图片,在使用hough变换之前,应用阈值或使用canny边缘检测。第二和第三个参数分别是ρ(rho:像素精度,一般设置为1;)和θ的精度(theta:角度精度,一般设置为CV_PI/180),第4个参数是阈值,指可以被认为是一个线条的最小计数值。由于计数值的多少取决于线上的点数(threshold:表示累计的像素达到多少才能形成直线),所以这代表了可以被识别为线的最小长度。
void HoughLinesP( InputArray image, OutputArray lines,
double rho, double theta, int threshold,
double minLineLength = 0, double maxLineGap = 0 );
lines:lines[i]为Vec4i类型,若令L=lines[i],则Point(L[0],L[1])为第一个点坐标,Point(L[2],L[3])为第二个点坐标
rho、theta及threshold解释同上
minLineLength:最小的线段长度,感觉与threshold意思差不多
maxLineGap:两条线的间隔如果小于这个值为一条线
实例( cv2.HoughLines):
import cv2
import numpy as np
def line_detecte(img):
gray = cv2.cvtColor(img,cv2.COLOR_BGR2GRAY)
edges = cv2.Canny(gray,100,150,apertureSize=3)
lines = cv2.HoughLines(edges,1,np.pi/180,178)
print(lines)
result_img = img.copy()
for line in lines:
rho,theta = line[0] # 第一个元素是距离rho
#theta = line[1] # 第二个元素是角度theta
if (theta < (np.pi / 4.)) or (theta > (3. * np.pi / 4.0)): # 垂直直线
# 该直线与第一行的交点
pt1 = (int(rho / np.cos(theta)), 0)
# 该直线与最后一行的焦点
pt2 = (int((rho - result_img.shape[0] * np.sin(theta)) / np.cos(theta)), result_img.shape[0])
# 绘制一条白线
cv2.line(result_img, pt1, pt2, (255),3)
else: # 水平直线
# 该直线与第一列的交点
pt1 = (0, int(rho / np.sin(theta)))
# 该直线与最后一列的交点
pt2 = (result_img.shape[1], int((rho - result_img.shape[1] * np.cos(theta)) / np.sin(theta)))
# 绘制一条直线
cv2.line(result_img, pt1, pt2, (255), 3)
cv2.namedWindow(“img”, 0)
cv2.namedWindow(“edges”, 0)
cv2.namedWindow(“result_img”, 0)
cv2.resizeWindow(“img”, 400, 480)
cv2.resizeWindow(“edges”, 400, 480)
cv2.resizeWindow(“result_img”, 400, 480)
cv2.imshow(“img”, img)
cv2.imshow(“edges”, edges)
cv2.imshow(“result_img”, result_img)
img=cv2.imread(‘6.jpg’,1)
line_detecte(img)
cv2.waitKey()
实例( cv2.HoughLinesP):
给出的结果是线段,可用来测距等应用
import cv2
import numpy as np
def line_detecte_poss(img):
gray = cv2.cvtColor(img,cv2.COLOR_BGR2GRAY)
edges = cv2.Canny(gray,100,150,apertureSize=3)
lines = cv2.HoughLinesP(edges,1,np.pi/180,250,5)
print(lines)
result_img = img.copy()
for line in lines:
x1,y1,x2,y2 = line[0] # 第一个元素是距离rho
#theta = line[1] # 第二个元素是角度theta
cv2.line(result_img, (x1,y1), (x2,y2), (255), 3)
cv2.namedWindow("img", 0)
cv2.namedWindow("edges", 0)
cv2.namedWindow("result_img", 0)
cv2.resizeWindow("img", 400, 480)
cv2.resizeWindow("edges", 400, 480)
cv2.resizeWindow("result_img", 400, 480)
cv2.imshow("img", img)
cv2.imshow("edges", edges)
cv2.imshow("result_img", result_img)
img=cv2.imread('6.jpg',1)
line_detecte_poss(img)
cv2.waitKey()
步骤:
gray = cv2.cvtColor(img,cv2.COLOR_BGR2GRAY)
edges = cv2.Canny(gray,100,150,apertureSize=3)
前两步之后进行检测直线。