opencv识别车道线(霍夫线变换)
目录
- 1、前言
- 2、霍夫线变换
- 2.1、霍夫线变换是什么?
- 2.2、在opencv中的基本用法
- 2.2.1、HoughLinesP函数定义
- 2.2.2、用法
- 3、识别车道
- 3.1、优化
- 3.1.1、降噪
- 3.1.2、过滤方向
- 3.1.3、截选区域
- 3.1.4、测试其它图片
- 图片1
- 图片2
- 图片3
1、前言
最近学习opencv学到了霍夫线变换,霍夫线变换是一个查找图像中直线的算法,它的其中一种应用场景就是识别车道,本文以识别车道为例,介绍霍夫线的简单用法。
2、霍夫线变换
2.1、霍夫线变换是什么?
下面是chatGPT给出的说明:
霍夫线变换(Hough Line Transform)是一种图像处理技术,可以用于检测图像中的直线。它的基本思想是,将直线转换为参数空间,并在参数空间中寻找与图像中的边缘相对应的点,从而找到这些直线。霍夫线变换常用于计算机视觉领域,例如在车道线检测、图像拼接、人脸识别等方面应用广泛。
原理性的东西这里不讲,因为有点复杂,我看得也有点懵。
2.2、在opencv中的基本用法
2.2.1、HoughLinesP函数定义
opencv实现霍夫线变换的函数是HoughLinesP,它的定义如下。
void HoughLinesP( InputArray image, OutputArray lines,double rho, double theta, int threshold,double minLineLength = 0, double maxLineGap = 0 );
它的参数的含义如下:
image:8位、单通道二进制源图像。
lines:输出线的矢量。每条线由一个4元素矢量表示,可以传入vector< cv::Vec4i>类型。
控制精度:
rho:累加器的距离分辨率(以像素为单位)。
theta:累加器的角度分辨率(弧度)。
过滤:
threshold:累加器阈值参数。
minLineLength:最小行长度。小于该长度的线段将被拒绝。
maxLineGap:同一条线上链接点的最大允许间隙。
2.2.2、用法
因为HoughLinesP传入的图像必须是8位、单通道二进制源图像,所以在传入图像之前,需要做转灰度图-》转二进制图的操作。
opencv提供了一些转二进制图的方法,因为HoughLinesP的目的是找到直线,而直线其实也是轮廓的一部分,所以一般我们采用Canny算法来把灰度图转为二进制图。
例程:
#include <opencv2/core.hpp>
#include <opencv2/imgcodecs.hpp>
#include <opencv2/highgui.hpp>
#include <opencv2/imgproc.hpp>using namespace cv;int main() {Mat src = imread("road.png");imshow("src", src);Mat gray;cvtColor(src, gray, COLOR_BGR2GRAY);imshow("gray", gray);// Apply Canny edge detectionMat edges;Canny(gray, edges, 50, 150);imshow("canny", edges);// Perform Hough transform to find linesstd::vector<Vec4i> lines;HoughLinesP(gray, lines, 1, CV_PI / 180, 50, 50, 10);// Draw lines on output imageMat dst = src.clone();for (size_t i = 0; i < lines.size(); i++) {Vec4i vline = lines[i];line(dst, Point(vline[0], vline[1]), Point(vline[2], vline[3]), Scalar(0, 0, 255), 2);}imshow("dst", dst);waitKey(0);}
3、识别车道
首先准备一张图片,如下图所示,要识别出它的白色车道线。

我们直接使用上一节的例程,效果如下。

发现虽然车道是识别出来了,但是环境中的纹理也被误认为车道,所以要做进一步优化。
3.1、优化
3.1.1、降噪
从上面的Canny图可以看到,环境中的树木形成了密密麻麻的纹理,这些就是影响效果的因素之一。
经过测试,我选用了“二值化 - 》腐蚀 - 》膨胀”的方式来完成降噪,经过优化后的代码如下:
#include <opencv2/core.hpp>
#include <opencv2/imgcodecs.hpp>
#include <opencv2/highgui.hpp>
#include <opencv2/imgproc.hpp>using namespace cv;int main() {Mat src = imread("/road.png");imshow("src", src);Mat gray;cvtColor(src, gray, COLOR_BGR2GRAY);imshow("gray", gray);//二值化Mat thr;threshold(gray, thr, 100, 255, THRESH_BINARY);imshow("threshold", thr);// 腐蚀Mat eroded;Mat element = getStructuringElement(MORPH_RECT, Size(5, 5));erode(thr, eroded, element);// 膨胀Mat dilated;dilate(eroded, dilated, element);imshow("dilated", dilated);// Apply Canny edge detectionMat edges;Canny(dilated, edges, 50, 150);imshow("canny", edges);// Perform Hough transform to find linesstd::vector<Vec4i> lines;HoughLinesP(edges, lines, 1, CV_PI / 180, 50, 50, 10);// Draw lines on output imageMat dst = src.clone();for (size_t i = 0; i < lines.size(); i++) {Vec4i vline = lines[i];line(dst, Point(vline[0], vline[1]), Point(vline[2], vline[3]), Scalar(0, 0, 255), 2);}imshow("dst", dst);waitKey(0);
}
优化后的效果如下:

从Canny中明显可以看到环境纹理少了很多。
3.1.2、过滤方向
在上图中,可以看到还有一些横向的纹理影响了效果,我们可以通过直线的方向来做进一步过滤。
在车的视角下,车道是朝中间斜的,两边车道成八字型,如图所示。

也就是说,车道的线在图像上倾斜角度不会小,所以我们可以在得出最终结果时,添加一个过滤条件:倾斜角度小于20度的直线不满足条件。
修改代码如下:
.....// Perform Hough transform to find linesstd::vector<Vec4i> lines;HoughLinesP(edges, lines, 1, CV_PI / 180, 50, 50, 10);// Draw lines on output imageMat dst = src.clone();for (size_t i = 0; i < lines.size(); i++) {Vec4i vline = lines[i];/* 过滤倾斜45度及以下的斜线 */float tanVal = (float)(vline[3] - vline[1]) / (vline[2] - vline[0]);if (abs(tanVal) < tan(CV_PI / 18)) continue;line(dst, Point(vline[0], vline[1]), Point(vline[2], vline[3]), Scalar(0, 0, 255), 2);}
.......
效果:

3.1.3、截选区域
在识别车道时,因为车道是在车的脚下,需要识别的图像只有相机拍下的下半截,所以这里还可以加多一层优化:把上半截图像砍掉,只处理下半截图像。
修改代码:
int main() {Mat src = imread("road.png");Rect vaildRect(0, src.rows / 2, src.cols, src.rows / 2);Mat src = src(vaildRect);imshow("src", src);
......
效果:

3.1.4、测试其它图片
图片1
因为拍照时的亮度不一,所以需要根据亮度来调整二值化时的阀值,此例用的是
threshold(gray, thr, 170, 255, THRESH_BINARY);

图片2

图片3
threshold(gray, gray, 150, 255, THRESH_BINARY);

相关文章:
opencv识别车道线(霍夫线变换)
目录1、前言2、霍夫线变换2.1、霍夫线变换是什么?2.2、在opencv中的基本用法2.2.1、HoughLinesP函数定义2.2.2、用法3、识别车道3.1、优化3.1.1、降噪3.1.2、过滤方向3.1.3、截选区域3.1.4、测试其它图片图片1图片2图片31、前言 最近学习opencv学到了霍夫线变换&am…...
MySQL的同步数据Replication功能
MySQL提供了Replication功能,可以实现将一个数据库的数据同步到多台其他数据库。前者通常称之为主库(master),后者则被称从库(slave)。MySQL复制过程采用异步方式,但延时非常小,秒级…...
2023年全国最新高校辅导员精选真题及答案17
百分百题库提供高校辅导员考试试题、辅导员考试预测题、高校辅导员考试真题、辅导员证考试题库等,提供在线做题刷题,在线模拟考试,助你考试轻松过关。 21.完善大学生的自我意识,我们可以采取的措施是()。 …...
中文代码92
PK 嘚釦 docProps/PK 嘚釦諿hl | docProps/app.xml漅Mo?糤?皘幅H??Q州濾mじ沜咅K宩Z5~q矹阶浇?灭貄}鰜>hk?i灐Q墩娲蝊毲b檊!J邮?\鏶 鵉苻牢[?j Y?a漺1簕B傟p悺L睮恃鶤?龎劂Q|瓣} A??苷0???5m?髤咄佶?\/#姧1N_??熹 冟.琽僠糧固Pw襅…...
Python SEO采集海量文本标题,用倒排索引找出“类似的标题“代码实现
Python SEO采集海量文本标题,用倒排索引找出“类似的标题“代码实现 作者:虚坏叔叔 博客:https://xuhss.com 早餐店不会开到晚上,想吃的人早就来了!😄 一、说明 假设这个是采集到的海量文本标题: 现在要判断找到的这个标题 title = "拜登称特朗普拒绝承认选举…...
模型杂谈:快速上手元宇宙大厂 Meta “开源泄露”的大模型(LLaMA)
本篇文章聊聊如何低成本快速上手使用 Meta(Facebook)的开源模型 LLaMA。 写在前面 在积累点赞,兑现朋友提供的显卡算力之前,我们先来玩玩“小号的”大模型吧。我相信 2023 年了,应该不需要再赘述如何使用 Docker 干净…...
RedisCluster集群模式下master宕机主从切换期间Lettuce连接Redis无法使用报错Redis command timed out的问题
背景springboot使用redisTemplate访问redis cluster(三主三从),底层是Lettuce,当其中一个master挂掉后,slave正常升为master,程序报错 Redis commond timed out after 6 seconds。解决手动连接集群…...
Xuetr杀毒工具使用实验(28)
实验目的 (1)学习Xuetr的基本功能; (2)掌握Xuetr的基本使用方法。预备知识 windows操作系统的基本知识如:进程、网络、服务和文件等的了解。 XueTr是近年推出的一款广受好评的ARK工具。ARK工具全称为Anti R…...
fastapi(https)+openssl+测试(双向校验)
第一步生成根证书 # Generate CA private key openssl genrsa -out ca.key 2048 # Generate CSR openssl req -new -key ca.key -out ca.csr # Generate Self Signed certificate(CA 根证书) openssl x509 -req -days 365 -in ca.csr -signkey ca.key -o…...
TiDB Server
文章目录TiDB Server架构TiDB Server作用TiDB Server的进程SQL语句的解析和编译SQL读写相关模块在线DDL相关模块GC机制与相关模块TiDB Server的缓存热点小表缓存TiDB Server架构 Protocol Layer、Parse、Compile负责sql语句的解析编译和优化,然后生成sql语句执行计划…...
S3C2440移植Linux4.19.275内核以及过程中遇到的问题
目录 1 问题一:内核移植时MTD分区问题 2 问题二:uboot的MTDPARTS_DEFAULT定义的MTD分区,bootargs中的文件系统分区,内核的mtd_partition smdk_default_nand_part定义的分区,三者要对应起来 3 问题三:ubo…...
解忧杂货铺(二):UML时序图
目录 1、概述 2、UML时序图 2.1、什么是时序图 2.2、时序图的元素 2.2.1 角色(Actor) 2.2.2 对象(Object) 2.2.3 生命线(LifeLine) 2.2.4 控制焦点(Activation) 2.2.5 消息(Message) 2.2.6 自关联消息 2.2.7 组合片段 1、概述 在看AUTOSAR规范的时候发现时序图里面的…...
微信小程序的代码由哪些结构组成?
小程序官方建议把所有小程序的页面,都存放在pages 目录中,以单独的文件夹存在,如图所示: 其中,每个页面由4 个基本文件组成,它们分别是:js文件(页面的脚本文件,存放页面的数据、事件…...
Cloud Kernel SIG月度动态:发布 ANCK 新版本及 Plugsched v1.2.0
Cloud Kernel SIG(Special Interest Group):支撑龙蜥内核版本的研发、发布和服务,提供生产可用的高性价比内核产品。 01 2 月 SIG 整体进展 发布 ANCK 4.19.91-27.1 版本。 发布 ANCK 5.10.134-13.1 版本。 调度器热升级相关事…...
Jedis 使用详解(官方原版)
一、配置 Maven 依赖项Jedis也通过Sonatype作为Maven Dependency 分发。要配置它,只需将以下 XML 代码段添加到您的 pom.xml 文件中。<dependency><groupId>redis.clients</groupId><artifactId>jedis</artifactId><version>2.…...
关于Pytorch中的张量学习
关于Pytorch中的张量学习 张量的概念和创建 张量的概念 Tensor是pytorch中非常重要且常见的数据结构,相较于numpy数组,Tensor能加载到GPU中,从而有效地利用GPU进行加速计算。但是普通的Tensor对于构建神经网络还远远不够,我们需…...
基于Transformer的目标检测算法学习记录
前言 本文主要通过阅读相关论文了解当前Transformer在目标检测领域的应用与发展。 谷歌在 ICLR2020 上提出的 ViT(Vision Transformer)是将 Transformer 应用在视觉领域的先驱。从此,打开了Transformer进入CV领域的桥梁,NLP与CV几…...
嵌入式学习笔记——使用寄存器编程实现按键输入功能
文章目录前言模块介绍原理图编程思路前言 昨天,通过配置通用输出模式,实现了LED灯的点亮、熄灭以及流水等操作,解决了通用输出的问题,今天我们再借用最常见的输入模块,按键来实现一个按键控制LED的功能,重…...
打卡小达人之路:Spring Boot与Redis GEO实现商户附近查询
在当今社会,定位服务已经成为了各种应用的重要组成部分,比如地图、打车、美食等应用。如何在应用中实现高效的附近商户搜索功能呢?传统的做法是将商户的经纬度信息存储在关系型数据库中,然后使用SQL查询语句实现附近商户搜索功能。…...
Apache HTTP Server <2.4.56 mod_proxy_uwsgi 模块存在请求走私漏洞(CVE-2023-27522)
漏洞描述 Apache HTTP Server 是一个Web服务器软件。 该项目受影响版本存在请求走私漏洞。由于mod_proxy_uwsgi.c 中uwsgi_response方法对于源响应头缺少检查,当apache启用mod_proxy_uwsgi后,攻击者可利用过长的源响应头等迫使应转发到客户端的响应被截…...
在HarmonyOS ArkTS ArkUI-X 5.0及以上版本中,手势开发全攻略:
在 HarmonyOS 应用开发中,手势交互是连接用户与设备的核心纽带。ArkTS 框架提供了丰富的手势处理能力,既支持点击、长按、拖拽等基础单一手势的精细控制,也能通过多种绑定策略解决父子组件的手势竞争问题。本文将结合官方开发文档,…...
苍穹外卖--缓存菜品
1.问题说明 用户端小程序展示的菜品数据都是通过查询数据库获得,如果用户端访问量比较大,数据库访问压力随之增大 2.实现思路 通过Redis来缓存菜品数据,减少数据库查询操作。 缓存逻辑分析: ①每个分类下的菜品保持一份缓存数据…...
Linux云原生安全:零信任架构与机密计算
Linux云原生安全:零信任架构与机密计算 构建坚不可摧的云原生防御体系 引言:云原生安全的范式革命 随着云原生技术的普及,安全边界正在从传统的网络边界向工作负载内部转移。Gartner预测,到2025年,零信任架构将成为超…...
新能源汽车智慧充电桩管理方案:新能源充电桩散热问题及消防安全监管方案
随着新能源汽车的快速普及,充电桩作为核心配套设施,其安全性与可靠性备受关注。然而,在高温、高负荷运行环境下,充电桩的散热问题与消防安全隐患日益凸显,成为制约行业发展的关键瓶颈。 如何通过智慧化管理手段优化散…...
微软PowerBI考试 PL300-在 Power BI 中清理、转换和加载数据
微软PowerBI考试 PL300-在 Power BI 中清理、转换和加载数据 Power Query 具有大量专门帮助您清理和准备数据以供分析的功能。 您将了解如何简化复杂模型、更改数据类型、重命名对象和透视数据。 您还将了解如何分析列,以便知晓哪些列包含有价值的数据,…...
day36-多路IO复用
一、基本概念 (服务器多客户端模型) 定义:单线程或单进程同时监测若干个文件描述符是否可以执行IO操作的能力 作用:应用程序通常需要处理来自多条事件流中的事件,比如我现在用的电脑,需要同时处理键盘鼠标…...
怎么让Comfyui导出的图像不包含工作流信息,
为了数据安全,让Comfyui导出的图像不包含工作流信息,导出的图像就不会拖到comfyui中加载出来工作流。 ComfyUI的目录下node.py 直接移除 pnginfo(推荐) 在 save_images 方法中,删除或注释掉所有与 metadata …...
根目录0xa0属性对应的Ntfs!_SCB中的FileObject是什么时候被建立的----NTFS源代码分析--重要
根目录0xa0属性对应的Ntfs!_SCB中的FileObject是什么时候被建立的 第一部分: 0: kd> g Breakpoint 9 hit Ntfs!ReadIndexBuffer: f7173886 55 push ebp 0: kd> kc # 00 Ntfs!ReadIndexBuffer 01 Ntfs!FindFirstIndexEntry 02 Ntfs!NtfsUpda…...
HubSpot推出与ChatGPT的深度集成引发兴奋与担忧
上周三,HubSpot宣布已构建与ChatGPT的深度集成,这一消息在HubSpot用户和营销技术观察者中引发了极大的兴奋,但同时也存在一些关于数据安全的担忧。 许多网络声音声称,这对SaaS应用程序和人工智能而言是一场范式转变。 但向任何技…...
rknn toolkit2搭建和推理
安装Miniconda Miniconda - Anaconda Miniconda 选择一个 新的 版本 ,不用和RKNN的python版本保持一致 使用 ./xxx.sh进行安装 下面配置一下载源 # 清华大学源(最常用) conda config --add channels https://mirrors.tuna.tsinghua.edu.cn…...
