pyhton—opencv直线检测(HoughLines)找到最长的一条线(一)

提示:实际情况实际处理


前言

霍夫变换是图像处理必然接触到的一个算法,它通过一种投票算法检测具有特定形状的物体,该过程在一个参数空间中通过计算累计结果的局部最大值得到一个符合该特定形状的集合作为霍夫变换结果,该方法可以进行圆,直线,椭圆等形状的检测。在车道线检测中,当初考虑的一个方案便是采用霍夫变换检测直线进行车道线提取。


一、图像处理

示例:针对图像特征检测,对图像的清晰度比较高,对于比较模糊的图像,需要对器经行处理:

  • 高斯滤波
  • 均值滤波
  • 中值滤波
  • 双边滤波
  • 直方滤波
    等都是对模糊图像处理的较为常用的方法;
    # 高斯滤波
    img = cv2.GaussianBlur(img, (5,5),1)
    # cv2.imshow('gaosi', img)
    # # 均值滤波
    img = cv2.blur(img, (3,3))# 5,5
    # cv2.imshow('junzhi', img)
    # 中值滤波
    img = cv2.medianBlur(img, 5)
    # 双边滤波
    """
    src:输入图像
    d:过滤时周围每个像素领域的直径
    sigmaColor:Sigma_color较大,则在邻域中的像素值相差较大的像素点也会用来平均。
    sigmaSpace:Sigma_space较大,则虽然离得较远,但是,只要值相近,就会互相影响。
    将sigma_space设置较大,sigma_color设置较小,可获得较好的效果(椒盐噪声)。
    """
    # img = cv2.bilateralFilter(img, 10, 75,75)#10,75,75
    #直方滤波
    (b, g, r) = cv2.split(img)
    bH = cv2.equalizeHist(b)
    gH = cv2.equalizeHist(g)
    rH = cv2.equalizeHist(r)

在这里插入图片描述
经过图像增强之后的图像,它的轮廓信息更加明显,对特征更好提取;

二、直线检测

代码分析

片段分析1

edges = cv2.Canny(img, 10, 200, apertureSize=3)  # 边缘检测 #10
lines = cv2.HoughLines(edges, 1, np.pi / 180, 20) # 直线检测

HoughLines经过霍夫变换,返回rho(与原点(0,0)的距离)和theta(直线的角度),最后在根据三角形定理,进行计算,就可以得到最长线段的端坐标。

[[0.        3.0019662]] 0.0 3.0019662 0.7853981633974483 2.356194490192345 ----------------------------------
[[-2.         3.0194197]] -2.0 3.0194197 0.7853981633974483 2.356194490192345 ----------------------------------
[[0.        3.0019662]] 0.0 3.0019662 0.7853981633974483 2.356194490192345 ----------------------------------
[[0.        3.0019662]] 0.0 3.0019662 0.7853981633974483 2.356194490192345 ----------------------------------
[[0.        3.0019662]] 0.0 3.0019662 0.7853981633974483 2.356194490192345 ----------------------------------

在这里插入图片描述

片段分析2

        if (theta < (np.pi / 4.)) or (theta > (3. * np.pi / 4.0)):  # 垂直直线
            pt1 = (int(rho / np.cos(theta)), 0)  # 该直线与第一行的交点
            # 该直线与最后一行的焦点
            pt2 = (int((rho - img.shape[0] * np.sin(theta)) / np.cos(theta)), img.shape[0])
        else:  # 水平直线
            pt1 = (0, int(rho / np.sin(theta)))  # 该直线与第一列的交点
            # 该直线与最后一列的交点
            pt2 = (img.shape[1], int((rho - img.shape[1] * np.cos(theta)) / np.sin(theta)))

这里我计算也没有理解过来,它是怎么转化过来的,有大佬知道,希望能指点一下

完整代码

import time
import cv2
import numpy as np
def opencv_img(img):# img 必须为灰度图
    img2 = cv2.cvtColor(img, cv2.COLOR_BGR2HSV)
    cv2.imshow('ded',img2)
    img = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY) # 转灰度图
    cv2.imshow('huidutu',img)
    # 高斯滤波
    img = cv2.GaussianBlur(img, (5,5),1)
    # cv2.imshow('gaosi', img)
    # # 均值滤波
    img = cv2.blur(img, (3,3))# 5,5
    # cv2.imshow('junzhi', img)
    # 中值滤波
    img = cv2.medianBlur(img, 5)
    # 双边滤波
    """
    src:输入图像
    d:过滤时周围每个像素领域的直径
    sigmaColor:Sigma_color较大,则在邻域中的像素值相差较大的像素点也会用来平均。
    sigmaSpace:Sigma_space较大,则虽然离得较远,但是,只要值相近,就会互相影响。
    将sigma_space设置较大,sigma_color设置较小,可获得较好的效果(椒盐噪声)。
    """
    # img = cv2.bilateralFilter(img, 10, 75,75)#10,75,75

    edges = cv2.Canny(img, 10, 200, apertureSize=3)  # 边缘检测 #10
    cv2.imshow('Canny',edges)
    lines = cv2.HoughLines(edges, 1, np.pi / 180, 20) # 直线检测
    print(lines,'\n')
    if lines is None:
        return ((0,1),(1,0))
    for line in lines:
        rho = line[0][0]  # 第一个元素是距离rho
        theta = line[0][1]  # 第二个元素是角度theta
        # print(line,rho,theta,np.pi / 4.,3. * np.pi / 4.0,'----------------------------------')
        if (theta < (np.pi / 4.)) or (theta > (3. * np.pi / 4.0)):  # 垂直直线
            """
            1
            """
            pt1 = (int(rho / np.cos(theta))+490, 0+372)  # 该直线与第一行的交点
            # 该直线与最后一行的焦点
            pt2 = (int((rho - img.shape[0] * np.sin(theta)) / np.cos(theta))+490, img.shape[0]+372)
            """
            2
            """
            # pt1 = (int(rho / np.cos(theta)) + 66, 0 + 487)  # 该直线与第一行的交点
            # # 该直线与最后一行的焦点
            # pt2 = (int((rho - img.shape[0] * np.sin(theta)) / np.cos(theta)) + 66, img.shape[0] + 487)
            # print(pt1,pt2)
        else:  # 水平直线
            """
            1
            """
            pt1 = (0, int(rho / np.sin(theta)))  # 该直线与第一列的交点
            # 该直线与最后一列的交点
            pt2 = (img.shape[1], int((rho - img.shape[1] * np.cos(theta)) / np.sin(theta)))
            """
            2
            """
            # pt1 = (int(rho / np.cos(theta)) + 66, 0 + 487)  # 该直线与第一行的交点
            # # 该直线与最后一行的焦点
            # pt2 = (int((rho - img.shape[0] * np.sin(theta)) / np.cos(theta)) + 66, img.shape[0] + 487)
            # print(pt1, pt2)
        # print(pt1,pt2)
        return (pt1,pt2)
    pass


cap = cv2.VideoCapture(r'E:\1\pidai\pinayi_1.mp4')  # 检测数据地址
while(True):
    ret, frame = cap.read()
    gray = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY)
    t0 = time.time()
    # print(a)
    img = frame[372:560,490:518] # 切片后图像  这是为了能够更好的检测,选取图像中的某一位置的图像经行检测
    #直方滤波
    (b, g, r) = cv2.split(img)
    bH = cv2.equalizeHist(b)
    gH = cv2.equalizeHist(g)
    rH = cv2.equalizeHist(r)
    # 合并每一个通道
    img = cv2.merge((bH, gH, rH))
    cv2.imshow('a',img)
    # Display the resulting frame
    pt1, pt2 = opencv_img(img)
    cv2.line(frame, pt1, pt2,(0,0,255) , 2)  # 绘制一条蓝线
    t1 = time.time()
    print("Total time running seconds:" , str(t1 - t0))
    cv2.imshow('frame',frame)
    if cv2.waitKey(1) & 0xFF == ord('q'):
        break
cap.release()
cv2.destroyAllWindows()

在这里插入图片描述
希望这对您有用!
谢谢点赞评论~~~

猜你喜欢

转载自blog.csdn.net/qq_44936246/article/details/124947903