当前位置: 首页 > news >正文

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);
在这里插入图片描述

http://www.lryc.cn/news/36090.html

相关文章:

  • MySQL的同步数据Replication功能
  • 2023年全国最新高校辅导员精选真题及答案17
  • 中文代码92
  • Python SEO采集海量文本标题,用倒排索引找出“类似的标题“代码实现
  • 模型杂谈:快速上手元宇宙大厂 Meta “开源泄露”的大模型(LLaMA)
  • RedisCluster集群模式下master宕机主从切换期间Lettuce连接Redis无法使用报错Redis command timed out的问题
  • Xuetr杀毒工具使用实验(28)
  • fastapi(https)+openssl+测试(双向校验)
  • TiDB Server
  • S3C2440移植Linux4.19.275内核以及过程中遇到的问题
  • 解忧杂货铺(二):UML时序图
  • 微信小程序的代码由哪些结构组成?
  • Cloud Kernel SIG月度动态:发布 ANCK 新版本及 Plugsched v1.2.0
  • Jedis 使用详解(官方原版)
  • 关于Pytorch中的张量学习
  • 基于Transformer的目标检测算法学习记录
  • 嵌入式学习笔记——使用寄存器编程实现按键输入功能
  • 打卡小达人之路:Spring Boot与Redis GEO实现商户附近查询
  • Apache HTTP Server <2.4.56 mod_proxy_uwsgi 模块存在请求走私漏洞(CVE-2023-27522)
  • JUC并发编程设计模式
  • HTTPS加密解析
  • Python每日一练(20230309)
  • 哈希表题目:数组的度
  • 初识rollup 打包、配置vue脚手架
  • 软考网络工程师证书有用吗?
  • postgresql 自动备份 bat实现
  • gdb:在命令行中会莫名暂停;detach-on-fork
  • 【3.9】RedisAOF日志、字符串、操作系统进程管理
  • 安装mayavi的成功步骤
  • vue+echarts.js 实现中国地图——根据数值表示省份的深浅——技能提升