• 理解霍夫变换的概念
• 学习如何在一张图片中检测直线
• 学习函数:cv2.HoughLines(),cv2.HoughLinesP()

霍夫变换在检测各种形状的的技术中非常流行,如果你要检测的形状可以用数学表达式写出,你就可以是使用霍夫变换检测它。即使要检测的形状存在一点破坏或者扭曲也可以使用。我们下面就看看如何使用霍夫变换检测直线。一条直线可以用数学表达式y = mx + c 或者ρ = x cosθ + y sinθ 表示。是从原点到直线的垂直距离,θ是直线的垂线与横轴顺时针方向的夹角(如果你使用的坐标系不同方向也可能不同,我是按OpenCV 使用的坐标系描述的)。如下图所示:

opencv计算照片上曲线长度 opencv计算直线角度_段长度


在霍夫变换中我们常用公式:

ρ = xcosθ + ysinθ

θ是直线与水平线所成的角度(0~180°),确定了它们,也就确定一条直线了

opencv计算照片上曲线长度 opencv计算直线角度_霍夫变换_02


opencv计算照片上曲线长度 opencv计算直线角度_opencv计算照片上曲线长度_03


opencv计算照片上曲线长度 opencv计算直线角度_Hough 直线变换_04


opencv计算照片上曲线长度 opencv计算直线角度_opencv计算照片上曲线长度_05


opencv计算照片上曲线长度 opencv计算直线角度_边缘检测_06

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()

opencv计算照片上曲线长度 opencv计算直线角度_霍夫变换_07

实例( 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()

opencv计算照片上曲线长度 opencv计算直线角度_opencv计算照片上曲线长度_08


步骤:

gray = cv2.cvtColor(img,cv2.COLOR_BGR2GRAY)
edges = cv2.Canny(gray,100,150,apertureSize=3)

前两步之后进行检测直线。