最近在matlab平台和opencv上都尝试了以下霍夫变换直线识别。

发现matlab中可以通过设置相近直线距离和最小长度,去除一些角度相近、距离相近的直线;

而opencv的houghline函数没有类似的功能,houghlinesP又不能直接返回rho、theta,总之无法自动剔除相近的直线(当然也很可能是我没用对),于是自己写了下面的函数:

功能大概是检测houghlines返回的参数列表,将theta和rho差值均小于一定范围的直线合并。但目前也有不足,即由于houghlines不返回检测到的直线模量,因此实际上保留的是几条相似直线中第一个被遍历到的直线。

具体代码如下:

import cv2 as cv
import numpy as np


def rho_theta_draw(src: np.ndarray, rho, theta):
    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(src, (x1, y1), (x2, y2), (0, 0, 255), 2)  # 画直线,对象、起点、终点、颜色、线宽


def hough_draw(lines: np.ndarray, src: np.ndarray, min_rho=10, min_theta=np.pi/90):
    '''
        函数根据HoughLine函数返回参数进行作图,且自动剔除相近直线
        函数将把theta差值小于一定范围,并且在此基础上,rho差值小于一定范围的直线剔除
    '''
    drew_list = []  # 创建空列表用于存储已经作图的theta
    i = 0
    j = 0
    draw_flag = 1
    # 检查lines是否为空,否则作出第一条线
    if len(lines) != 0:
        rho, theta = lines[0, 0]  # 读取第一条直线数据
        rho_theta_draw(src, rho, theta)
        i += 1
        drew_list.append({'theta': theta, 'rho': rho})  # 在drew_list中存入第一个直线数据

    for rho, theta in lines[1:, 0]:  # lines是一个三维深度的数组,此处遍历每个[rho, theta]元素
        for past_line in drew_list:
            theta_error = abs(past_line['theta'] - theta)
            rho_error = abs(past_line['rho'] - rho)
            if theta_error <= min_theta:  # 若两条直线的theta差值小于阈值
                if rho_error <= min_rho:  # 若两条直线距离rho小于阈值,则视作一条直线
                    j += 1
                    draw_flag = 0
                    break  # 跳出遍历
        else:  # 若函数正常完成遍历,说明是一条新直线
            drew_list.append({'theta': theta, 'rho': rho})  # 存入drew_list

        # 画图
        if draw_flag == 1:
            rho_theta_draw(src, rho, theta)
            i += 1
        else:
            draw_flag = 1  # 不作图,但恢复标志位

        pre_rho = rho  # 保存参数
        pre_theta = theta
    print(f'输入{i+j}条直线,共作{i}条直线,{j}条被合并')
    print(drew_list)
    return src

起到剔除作用的主要是hough_draw这个函数,rho_theta_draw只是一个用于简化代码用的小函数。

hough_draw要求输入houghlines返回的lines,走图对象src,最小距离rho(默认为10)和最小theta(单位为rad,默认为pi/90,即2°)。

运行效果如下:

不做剔除时,总共画了五条直线

opencv 线条检测 opencv直线检测去除多余直线_opencv 线条检测

opencv 线条检测 opencv直线检测去除多余直线_python_02

 设置min_rho=40,min_theta=pi/180,即1°时:

opencv 线条检测 opencv直线检测去除多余直线_opencv 线条检测_03

opencv 线条检测 opencv直线检测去除多余直线_opencv_04

 最底下的时进行作图的直线参数。

修改min_theta=pi/90,即2°时:

opencv 线条检测 opencv直线检测去除多余直线_霍夫变换_05

opencv 线条检测 opencv直线检测去除多余直线_opencv_06

 最后还是得承认,目前作为opencv新手,各种函数用的还是很垃圾,如果库内自带函数有上述函数的功能,那只能说是很尴尬了。

函数还有提升空间,如果换成基于houghlinesP去编程,应该能将直线模量进一步考虑进去,不过直线检测只是当前毕设里面一个弄着玩的功能,估计是不会继续深入了。