直线道路线通过霍夫变换进行识别并画出

news2025/1/21 15:40:07

最近在研究高速直线识别,搜了一圈看了很多文章,确定了以下的主要流程。
主要流程

霍夫变换

lines = cv2.HoughLinesP(image,rho,theta,threshold,lines,minLineLength,maxLineGap)#概率霍夫变换
image:必须是二值图像,推荐使用canny边缘检测的结果图像。
rho:线段以像素为单位的距离紧固带,double类型,推荐使用2.0 距离分辨率,表示以像素为单位的距离精度,参数越高线段越多。
theta:线段以弧度为单位的角度精度,推荐使用numpy.pi/180。
threshod:累加平面的阈值参数,int类型,超过设定的阈值才会被检测出线段,值越大,基本上意味着检出的线段越长,检出的线段个数越少。根据情况推荐先试用100在逐步调整。
lines:可选参数,用于存储检测到的直线的输出数组。返回即为存储图中所有直线的数组。
minLineLength:线段以像素为单位的最小长度,低于这个长度的线段将不会显示,根据应用场景设置。
maxLineGap:同一方向上两条线段判定为一条线段的最大允许间隔,小于这个最大值,都认为是一条线段。

def hough_lines(img, rho, theta, threshold,
                min_line_len, max_line_gap):  #进行霍夫变换


    lines = cv2.HoughLinesP(img, rho, theta, threshold, np.array([]),
                            minLineLength=min_line_len,
                            maxLineGap=max_line_gap)  #概率霍夫变换
    line_img = np.zeros((img.shape[0], img.shape[1], 3), dtype=np.uint8) #整一个黑底图片,展示画的线
    #print(lines)
    draw_lines(line_img, lines) #将底图和直线数组传入draw_lines进行画线
    return line_img #返回画好的图片

整体代码

# coding:utf-8

import cv2
import numpy as np
import os
import numpy

def gauss_blur(img):  #高斯滤波
    blur_ksize = 5  # Gaussian blur kernel size
    blur_gray = cv2.GaussianBlur(gray, (blur_ksize, blur_ksize), 0, 0)
    return blur_gray

def canny_edgedet(blur_gray): #canny 边缘检测
    # Define our parameters for Canny and apply
    low_threshold = 250
    high_threshold = 320
    edges = cv2.Canny(blur_gray, low_threshold, high_threshold)
    return edges

def ROI_filtering(edges):  #选择需要的区域
    # Next we'll create a masked edges image using cv2.fillPoly()
    mask = np.zeros_like(edges)
    ignore_mask_color = 255

    # This time we are defining a four sided polygon to mask
    #imshape = image.shape
    vertices = np.array([[(30, 300), (220, 200), (400, 80), (860, 300)]], dtype=np.int32)
    cv2.fillPoly(mask, vertices, ignore_mask_color)
    masked_edges = cv2.bitwise_and(edges, mask)
    return masked_edges

def draw_lines(img, lines, color=[255, 0, 0], thickness=2):  #画线
    x1_list = []
    lines_list = lines.tolist()
    
    #按照线段start x1坐标进行删除重复坐标
    #print(lines_list)
    # for line in lines_list:
    #     x1_list.append(line[0][0])
    # #print(x1_list)
    # for lin in lines_list:
    #     for i in x1_list:
    #         if abs(int(line[0][0]) - i) <= 30 and abs(int(line[0][0]) - i) != 0:
    #             #print(lin)
    #             lines_list.remove(lin)
    # #print(lines_list)
    # print(len(lines_list))

    #延长直线

    for line in lines_list:
        x1 = int(line[0][0])  # 以(x0, y0)为起点,将线段延长
        y1 = int(line[0][1])
        x2 = int(line[0][2])
        y2 = int(line[0][3])

        # 延长直线
        #定义起点和终点
        start_point = (x2,y2)
        end_point = (x1,y1)

        #计算线条的方向和长度
        direction = np.subtract(end_point, start_point)
        length = np.linalg.norm(direction)

        #设置延长线的长度因子
        extension_factor = 200

        #计算延长线的起点
        extended_start_point = tuple(np.subtract(start_point, extension_factor * direction / length).astype(int))
        # 计算延长线的终点
        extended_end_point = tuple(np.add(end_point, extension_factor * direction / length).astype(int))

        #画线
        cv2.line(img, extended_start_point, extended_end_point, color, thickness)
        #cv2.line(img, (x1, y1), (x2, y2), color, thickness)

    #print('type(lines_list)',type(lines_list))
    # for line in lines_list:
    #     for x3, y3, x4, y4 in line:
    #         x1_list.append(x3)
    # for line in lines_list:
    #     for x1, y1, x2, y2 in line:
    #         print(type(line))
    #         print(x1_list)
    #         for i in x1_list:
    #             #print(abs(int(x1) - i))
    #             if abs(int(x1) - i) <= 120:
    #                 pass
    #                 #numpy.delete(lines, line, axis=None)
    # print(lines)
    #                 #cv2.line(img, (x1, y1), (x2, y2), color, thickness)

def hough_lines(img, rho, theta, threshold,
                min_line_len, max_line_gap):  #进行霍夫变换

    # cv2.HoughLinesP(image,rho,theta,threshold,lines,minLineLength,maxLineGap)
    # image:必须是二值图像,推荐使用canny边缘检测的结果图像
    # rho:线段以像素为单位的距离紧固带,double类型,推荐使用1.0 距离分辨率,表示以像素为单位的距离精度
    # theta:线段以弧度为单位的角度精度,推荐使用numpy.pi/180
    # threshod:累加平面的阈值参数,int类型,超过设定的阈值才会被检测出线段,值越大,基本上意味着检出的线段越长,检出的线段个数越少。根据情况推荐先试用100
    # lines:可选参数,用于存储检测到的直线的输出数组。
    # minLineLength:线段以像素为单位的最小长度,根据应用场景设置
    # maxLineGap:同一方向上两条线段判定为一条线段的最大允许间隔,小于这个最大值,都认为是一条线段

    lines = cv2.HoughLinesP(img, rho, theta, threshold, np.array([]),
                            minLineLength=min_line_len,
                            maxLineGap=max_line_gap)  #概率霍夫变换
    line_img = np.zeros((img.shape[0], img.shape[1], 3), dtype=np.uint8)
    #print(lines)
    draw_lines(line_img, lines)
    return line_img

def weighted_img(img, initial_img, α=0.7, β=1., λ=0.):

    return cv2.addWeighted(img, α, initial_img, β, λ)   #将画线图和原图重合

if __name__=='__main__':
    img_path = './img/1c.png' #图片位置
    img = cv2.imread(img_path) #读取原图
    gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY) #将原图转换成灰度图
    blur_gray = gauss_blur(gray) #高斯滤波
    canny_img = canny_edgedet(blur_gray)

    # cv2.imshow('img',masked_edges)  #canny边缘检测和非极大值抑制
    # cv2.waitKey(0)
    # cv2.destroyAllWindows()

    # 霍夫变换的参数,这个是我测试最符合我的参数,详细作用看第97行
    rho = 3
    theta = np.pi / 180
    threshold = 180
    min_line_length = 80
    max_line_gap = 2000

    line_img = hough_lines(canny_img, rho, theta, threshold,
                           min_line_length, max_line_gap)

    mix = weighted_img(line_img, img, α=0.7, β=1., λ=0.)


    cv2.imshow('img', mix)
    cv2.waitKey(0)
    cv2.destroyAllWindows()




这是原图
在这里插入图片描述

这是画线图
在这里插入图片描述

这是最终效果
在这里插入图片描述

有待改进
1、目前没有直线拟合函数,用过很多都有问题,还需突破。
2、与YOLOv5识别进行结合,检测车辆越线别车或非法变道、占用应急车道等违法违规行为。

参考文章:
视觉无人机高速公路违章检测之——车道线检测
OpenCV-Python 霍夫直线检测-HoughLinesP函数参数

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1673842.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

C语言笔记14

指针1 在C语言中给内存单元的编号起了个名字叫做指针&#xff0c;通俗来说就是地址。&#xff08;内存单元编号地址指针&#xff09; 1.指针变量与地址 int a10&#xff1b; int* p&a&#xff1b; * 说明了这里p的是指针变量&#xff1b;int*说明p是一个整形指针&…

【class2】人工智能初步(自然语言处理)

要实现从评价中提取高频关键词&#xff0c;并判别其正负面性&#xff0c;其实是通过人工智能领域中的一个分支&#xff1a;自然语言处理。 在了解自然语言处理之前&#xff0c;我们先来说说&#xff0c;什么是自然语言&#xff08;Natural Language&#xff09;&#xff1f;自…

正点原子[第二期]Linux之ARM(MX6U)裸机篇学习笔记-15.1,2,3-GPIO中断控制实验

前言&#xff1a; 本文是根据哔哩哔哩网站上“正点原子[第二期]Linux之ARM&#xff08;MX6U&#xff09;裸机篇”视频的学习笔记&#xff0c;在这里会记录下正点原子 I.MX6ULL 开发板的配套视频教程所作的实验和学习笔记内容。本文大量引用了正点原子教学视频和链接中的内容。…

全自动发布小红薯思维导图笔记(附爆款AI提示词)

全自动电脑接管&#xff0c;帮你生成图片、文案&#xff0c;然后还帮你自动发布。 大家好&#xff0c;我是大胡子&#xff0c;专注于研究RPA实战与解决方案&#xff0c;今天来介绍一款全自动生产内容并发布小红薯的神器&#xff0c;最后附有AI提示词&#xff0c;记得收藏点赞…

【C#】学习获取程序执行路径,Gemini 帮助分析

一、前言&#xff1a; 在Delphi中&#xff0c;如果想要获取当前执行程序的目录&#xff0c;程序代码如下&#xff1a; ExtractFilePath(ParamStr(0)); 今天在分析一个别人做的C#程序时看到了一段C#代码&#xff0c;意思是获取执行程序所在的文件目录&#xff1a; public stat…

[图解]实现领域驱动设计译文暴露的问题04

0 00:00:00,960 --> 00:00:03,020 今天我们继续说一下 1 00:00:03,460 --> 00:00:05,350 实现领域驱动设计 2 00:00:05,630 --> 00:00:08,120 译文里面暴露的问题 3 00:00:10,630 --> 00:00:14,740 前面三个视频&#xff0c;我们提到了第①句 4 00:00:15,550 -…

国家网络与信息系统安全产品质量检验检测中心是什么机构?成立于一年?有什么用?

在当今信息化快速发展的时代&#xff0c;网络安全问题日益凸显其重要性&#xff0c;而检测中心则扮演着守护网络安全、保障信息系统稳定运行的关键角色。今天我们就来聊聊国家网络与信息系统安全产品质量检验检测中心是什么机构&#xff1f;成立于一年&#xff1f;有什么用&…

RedisTemplate操作Redis详解之连接Redis及自定义序列化

连接到Redis 使用Redis和Spring时的首要任务之一是通过IoC容器连接到Redis。为此&#xff0c;需要java连接器&#xff08;或绑定&#xff09;。无论选择哪种库&#xff0c;你都只需要使用一组Spring Data Redis API&#xff08;在所有连接器中行为一致&#xff09;&#xff1a;…

基础模型的推理:综述

24年1月论文“A Survey of Reasoning with Foundation Models”&#xff0c;来自香港中文大学、华为、香港大学、上海AI实验室、香港科技大学、大连理工、北京大学、清华大学、合肥工大、中国人民大学、复旦大学和香港科技大学广州分校。 推理是解决复杂问题的关键能力&#x…

Windows/Mailing

Mailing Enumeration nmap 使用 nmap 扫描系统&#xff0c;发现对外开放了如下端口 ┌──(kali㉿kali)-[~/vegetable/HTB] └─$ nmap -sC -sV -oA nmap 10.10.11.14 Starting Nmap 7.93 ( https://nmap.org ) at 2024-05-08 01:46 EDT Nmap scan report for 10.10.11.14 H…

软件各阶段资料(需求设计,系统架构,开发文档,测试文档,运维阶段的部署维护文档,概要设计,详细设计)

一、 引言 &#xff08;一&#xff09; 编写目的 &#xff08;二&#xff09; 范围 &#xff08;三&#xff09; 文档约定 &#xff08;四&#xff09; 术语 二、 项目概要 &#xff08;一&#xff09; 建设背景 &#xff08;二&#xff09; 建设目标 &#xff08;三&#xff0…

linux上用Jmter进行压测

在上一篇中安装好了Jmeter环境&#xff0c;在这一篇中将主要分享如何使用jmeter在linux中进行单机压测。 1.项目部署 在这里我们先简单部署一下测试环境&#xff0c;所用到的项目环境是个jar包&#xff0c;先在linux上home目录下新建app目录&#xff0c;然后通过rz命令将项目ja…

一些近来对内网攻防的思考

我知道我最近托更托了很久了&#xff0c;其实也不是小编懒啊 这小编也是一直在写&#xff0c;但是遇到的问题比较多&#xff08;我太菜了&#xff09;&#xff0c;所以一直拖着。 但是总不能不更吧 那就讲一下进来的一些内网攻防的思考吧 1.CrossC2上线Linux到CS(成功) …

程序设计文档—软件分析报告(Word)

第3章 技术要求 3.1 软件开发要求 第4章 项目建设内容 第5章 系统安全需求 5.1 物理设计安全 5.2 系统安全设计 5.3 网络安全设计 5.4 应用安全设计 5.5 对用户安全管理 5.6 其他信息安全措施 第6章 其他非功能需求 6.1 性能设计 6.2 稳定性设计 6.3 安全性设计 6.4 兼容性设计…

DriveWorld:通过自动驾驶世界模型进行 4D 预训练场景理解

24年5月北大论文“DriveWorld: 4D Pre-trained Scene Understanding via World Models for Autonomous Driving”。 近年来&#xff0c;以视觉为中心的自动驾驶因其较低的成本而受到广泛关注。预训练对于提取通用表示至关重要。然而&#xff0c;当前以视觉为中心的预训练通常依…

【Linux】进程信号(2万字)

目录 前言 一、生活角度的信号 1.1、我们来见一见信号&#xff1a; 1.2、模拟一下 kill 指令 二、信号的处理 三、产生信号的5种方法 3.1、kill命令 3.2、键盘可以产生信号 3.3、3种系统调用 3.4、软件条件 3.5、异常 四、比较 core 和 Term 五、键盘信号产生 六…

Docker安装、使用及常用命令

一、Docker是什么&#xff1f; Docker是一种开源的容器化技术&#xff0c;允许开发者将应用及其运行环境打包在一个轻量级、可移植的容器中。这样&#xff0c;不论在开发、测试还是生产环境中&#xff0c;应用都能在任何Docker支持的平台上无缝运行。Docker使用Dockerfile来自…

人形机器人场景应用全解析,2024睿抗 AI ROBOT创新挑战赛火热报名中!

人工智能&#xff08;AI&#xff09;已成为推动科技革命和产业变革的关键力量。随着大模型等AIGC技术的迅猛发展&#xff0c;AI正深刻改变我们的生活并重新定义生产方式。越来越多人期望将AI技术从纯粹的思维和计算扩展到与物理世界的互动中&#xff0c;即发展具身智能。 为了推…

网络库-libcurl介绍

1.简介 libcurl 是一个功能强大的库&#xff0c;支持多种协议&#xff0c;用于数据传输。它广泛应用于实现网络操作&#xff0c;如HTTP、HTTPS、FTP、FTPS、SCP、SFTP等。libcurl 提供了丰富的 API&#xff0c;可以在多种编程语言中使用。 libcurl 主要特点 支持多种协议&am…

812寸硅片为什么没有平边(flat)?

知识星球&#xff08;星球名&#xff1a;芯片制造与封测社区&#xff0c;星球号&#xff1a;63559049&#xff09;里的学员问&#xff1a;上期种说2&#xff0c;4&#xff0c;6寸硅片都有平边&#xff0c;那为什么8&12寸硅片只有一个notch&#xff1f;为什么不能像小尺寸晶…