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

《MATLAB实战训练营:从入门到工业级应用》工程实用篇-自动驾驶初体验:车道线检测算法实战(MATLAB2016b版)

《MATLAB实战训练营:从入门到工业级应用》工程实用篇-🚗 自动驾驶初体验:车道线检测算法实战(MATLAB2016b版)

大家好!今天我要带大家一起探索自动驾驶中一个非常基础但又至关重要的技术——车道线检测。我们将从零开始,一步步用MATLAB2016b实现一个完整的车道线检测系统。准备好你的MATLAB,让我们开始这场有趣的自动驾驶之旅吧!✨

一、准备工作与环境搭建

1.1 为什么选择MATLAB2016b?

MATLAB在图像处理和计算机视觉领域有着强大的功能,而2016b版本稳定且兼容性好,适合教学和实验。当然,如果你有更新的版本也完全没问题!

1.2 需要安装的工具箱

确保你已经安装了以下工具箱(可以通过ver命令查看):

  • Image Processing Toolbox
  • Computer Vision System Toolbox
    在这里插入图片描述

如果没有安装,可以通过MATLAB的"附加功能"菜单进行安装。

1.3 测试数据准备

我们将使用一段高速公路行车视频作为测试数据。你可以使用自己的行车记录仪视频,或者自己从网上下载一个视频:

高速公路驾驶highway_lane

二、车道线检测基础理论

2.1 车道线检测的基本流程

一个典型的车道线检测流程包括以下几个步骤:

  1. 图像获取 📷
  2. 预处理(去噪、增强等) 🛠️
  3. 边缘检测 ✂️
  4. 感兴趣区域(ROI)提取 🔍
  5. 霍夫变换检测直线 📐
  6. 车道线拟合与可视化 🚦

2.2 为什么选择霍夫变换?

霍夫变换是检测图像中几何形状(如直线、圆等)的经典算法。它能够将图像空间中的像素点映射到参数空间,通过累加器找出最可能的几何形状参数。

三、实战开始!一步步实现车道线检测

3.1 读取并显示视频

首先,我们需要读取视频并显示第一帧,看看我们的"战场"是什么样子:

% 创建视频读取对象
videoReader = VideoReader('highway_lane.mp4');% 读取第一帧
frame = readFrame(videoReader);% 显示原始图像
figure('Name', '原始视频帧');
imshow(frame);
title('原始视频帧');

在这里插入图片描述

3.2 图像预处理

原始图像包含太多干扰信息,我们需要进行预处理:

% 转换为灰度图像
grayFrame = rgb2gray(frame);% 高斯滤波去噪
filteredFrame = imgaussfilt(grayFrame, 2);% 显示预处理结果
figure('Name', '预处理结果');
subplot(1,2,1); imshow(grayFrame); title('灰度图像');
subplot(1,2,2); imshow(filteredFrame); title('高斯滤波后');

在这里插入图片描述

3.3 边缘检测

边缘检测是车道线检测的关键步骤,我们使用Canny算法:

% Canny边缘检测
edgeThreshold = [0.1, 0.2]; % 阈值可以调整
sigma = 1; % 高斯滤波参数
edges = edge(filteredFrame, 'Canny', edgeThreshold, 'both', sigma);% 显示边缘检测结果
figure('Name', '边缘检测结果');
imshow(edges);
title('Canny边缘检测结果');

小技巧:阈值的选择很重要,太低会检测到太多噪声,太高可能会漏掉真实的车道线。可以尝试调整看看效果变化!
在这里插入图片描述

3.4 感兴趣区域(ROI)提取

我们不需要分析整个图像,只需要关注车辆前方的道路区域:

% 获取图像尺寸
[rows, cols] = size(edges);% 定义ROI多边形顶点(梯形区域)
roi = [1, rows; cols/2-50, rows/2+50; cols/2+50, rows/2+50; cols, rows];% 创建ROI掩模
roiMask = poly2mask(roi(:,1), roi(:,2), rows, cols);% 应用ROI掩模
roiEdges = edges & roiMask;% 显示ROI提取结果
figure('Name', 'ROI提取');
subplot(1,2,1); imshow(edges); hold on; 
plot(roi(:,1), roi(:,2), 'r-', 'LineWidth', 2); 
title('原始边缘+ROI区域');
subplot(1,2,2); imshow(roiEdges); 
title('ROI内边缘');

在这里插入图片描述

3.5 霍夫变换检测直线

现在是重头戏——使用霍夫变换检测直线:

% 霍夫变换参数设置
thetaResolution = 0.5; % 角度分辨率
rhoResolution = 1; % 距离分辨率
threshold = 50; % 累加器阈值
minLineLength = 30; % 最小线段长度
maxLineGap = 20; % 线段间最大间隔% 执行霍夫变换
[H, theta, rho] = hough(roiEdges, 'Theta', -90:thetaResolution:89, 'RhoResolution', rhoResolution);% 检测峰值
peaks = houghpeaks(H, 10, 'Threshold', threshold);% 检测线段
lines = houghlines(roiEdges, theta, rho, peaks, 'FillGap', maxLineGap, 'MinLength', minLineLength);% 显示霍夫变换结果
figure('Name', '霍夫变换检测结果');
imshow(frame); hold on;
for k = 1:length(lines)xy = [lines(k).point1; lines(k).point2];plot(xy(:,1), xy(:,2), 'LineWidth', 2, 'Color', 'green');
end
title('霍夫变换检测到的直线');

在这里插入图片描述

3.6 车道线筛选与拟合

不是所有检测到的直线都是车道线,我们需要筛选:

% 筛选左右车道线
leftLines = [];
rightLines = [];for k = 1:length(lines)% 计算线段斜率x1 = lines(k).point1(1);y1 = lines(k).point1(2);x2 = lines(k).point2(1);y2 = lines(k).point2(2);slope = (y2 - y1) / (x2 - x1);% 根据斜率筛选if slope < -0.3  % 左车道线通常有负斜率leftLines = [leftLines; [x1, y1; x2, y2]]; % 往后追加elseif slope > 0.3  % 右车道线通常有正斜率rightLines = [rightLines; [x1, y1; x2, y2]]; % 往后追加end
end% 拟合左右车道线(使用最小二乘法)
if ~isempty(leftLines)leftPoints = [leftLines(1:2,:); leftLines(3:4,:)];leftPoly = polyfit(leftPoints(:,2), leftPoints(:,1), 1);
endif ~isempty(rightLines)rightPoints = [rightLines(1:2,:); rightLines(3:4,:)];rightPoly = polyfit(rightPoints(:,2), rightPoints(:,1), 1);
end% 显示最终结果
figure('Name', '最终车道线检测结果');
imshow(frame); hold on;% 绘制左车道线
if exist('leftPoly', 'var')yLeft = [rows/2+50, rows];xLeft = polyval(leftPoly, yLeft);plot(xLeft, yLeft, 'LineWidth', 4, 'Color', 'red');
end% 绘制右车道线
if exist('rightPoly', 'var')yRight = [rows/2+50, rows];xRight = polyval(rightPoly, yRight);plot(xRight, yRight, 'LineWidth', 4, 'Color', 'blue');
endtitle('最终车道线检测结果');
legend('左车道线', '右车道线');

在这里插入图片描述

四、完整视频处理与优化

4.1 封装为函数

让我们把上面的代码封装成一个函数,方便处理视频的每一帧:

function [leftLine, rightLine] = detectLanes(frame)% 转换为灰度图像grayFrame = rgb2gray(frame);% 高斯滤波filteredFrame = imgaussfilt(grayFrame, 2);% 边缘检测edgeThreshold = [0.1, 0.2];sigma = 1;
%     edges = edge(filteredFrame, 'Canny', edgeThreshold, 'both', sigma);edges = edge(filteredFrame, 'Canny', edgeThreshold, 'both');% ROI提取[rows, cols] = size(edges);roi = [1, rows; cols/2-50, rows/2+50; cols/2+50, rows/2+50; cols, rows];roiMask = poly2mask(roi(:,1), roi(:,2), rows, cols);roiEdges = edges & roiMask;% 霍夫变换thetaResolution = 0.5;rhoResolution = 1;threshold = 50;minLineLength = 30;maxLineGap = 20;[H, theta, rho] = hough(roiEdges, 'Theta', -90:thetaResolution:89, 'RhoResolution', rhoResolution);peaks = houghpeaks(H, 10, 'Threshold', threshold);lines = houghlines(roiEdges, theta, rho, peaks, 'FillGap', maxLineGap, 'MinLength', minLineLength);% 筛选和拟合车道线leftLines = [];rightLines = [];for k = 1:length(lines)x1 = lines(k).point1(1);y1 = lines(k).point1(2);x2 = lines(k).point2(1);y2 = lines(k).point2(2);slope = (y2 - y1) / (x2 - x1);if slope < -0.3leftLines = [leftLines; [x1, y1; x2, y2]];elseif slope > 0.3rightLines = [rightLines; [x1, y1; x2, y2]];endend% 返回拟合结果leftLine = [];rightLine = [];if ~isempty(leftLines)  & length(leftLines)>4leftPoints = [leftLines(1:2,:); leftLines(3:4,:)];leftLine = polyfit(leftPoints(:,2), leftPoints(:,1), 1);endif ~isempty(rightLines)   & length(rightLines)>4rightPoints = [rightLines(1:2,:); rightLines(3:4,:)];rightLine = polyfit(rightPoints(:,2), rightPoints(:,1), 1);end
end

4.2 处理整个视频

现在我们可以处理整个视频了:

clc
close all
% 创建视频读取和写入对象
videoReader = VideoReader('highway_lane.mp4');
videoWriter = VideoWriter('lane_detection_result.avi');
open(videoWriter);% 创建显示窗口
figure('Name', '实时车道线检测', 'Position', [100, 100, 800, 600]);while hasFrame(videoReader)% 读取当前帧frame = readFrame(videoReader);% 检测车道线[leftLine, rightLine] = detectLanes(frame);% 显示结果imshow(frame); hold on;% 绘制左车道线if ~isempty(leftLine)yLeft = [size(frame,1)/2+50, size(frame,1)];xLeft = polyval(leftLine, yLeft);plot(xLeft, yLeft, 'LineWidth', 4, 'Color', 'red');end% 绘制右车道线if ~isempty(rightLine)yRight = [size(frame,1)/2+50, size(frame,1)];xRight = polyval(rightLine, yRight);plot(xRight, yRight, 'LineWidth', 4, 'Color', 'blue');endtitle('实时车道线检测');drawnow;% 写入视频frameWithLanes = getframe(gcf);writeVideo(videoWriter, frameWithLanes.cdata);hold off;
end% 关闭视频写入器
close(videoWriter);
disp('视频处理完成');

在这里插入图片描述

五、进阶优化与挑战

5.1 优化建议

我们的基础版本已经可以工作了,但还有很大优化空间:

  1. 动态ROI调整:根据车辆速度调整ROI区域大小
  2. 颜色信息利用:结合车道线颜色(黄、白)增强检测
  3. 卡尔曼滤波:平滑车道线检测结果,减少抖动
  4. 曲线车道检测:使用二次或三次多项式拟合曲线车道

5.2 常见问题与解决方案

问题1:在强光下检测效果差

  • 解决方案:使用自适应直方图均衡化(CLAHE)增强对比度
% 替换灰度转换和高斯滤波部分
labFrame = rgb2lab(frame);
L = labFrame(:,:,1)/100;
L = adapthisteq(L);
labFrame(:,:,1) = L*100;
enhancedFrame = lab2rgb(labFrame);
grayFrame = rgb2gray(enhancedFrame);

问题2:检测到非车道线的边缘

  • 解决方案:增加后处理步骤,如基于车道线几何约束的筛选

六、总结与展望

恭喜你!🎉 我们已经完成了一个完整的车道线检测系统。虽然它看起来简单,但这是自动驾驶的基础模块之一。通过这个项目,我们学习了:

  1. 图像预处理技术
  2. 边缘检测算法
  3. 霍夫变换原理与应用
  4. 车道线拟合方法

未来你可以尝试:

  • 实现更复杂的车道线检测算法
  • 集成到更大的自动驾驶系统中
  • 尝试使用深度学习的方法(如LaneNet)

希望这篇教程对你有所帮助!如果有任何问题或建议,欢迎在评论区留言讨论。Happy coding! 💻🚀


附录:完整代码下载
点击这里下载完整MATLAB代码包

参考文献

  1. MATLAB官方文档
  2. 《计算机视觉:算法与应用》Richard Szeliski
  3. 《自动驾驶中的计算机视觉》系列论文
http://www.xdnf.cn/news/273349.html

相关文章:

  • LeetCode 热题 100 54. 螺旋矩阵
  • MVC 安全
  • 表驱动 FSM 在 STM32 上的高效实现与内存压缩优化——源码、性能与实践
  • 4个纯CSS自定义的简单而优雅的滚动条样式
  • 使用 IDEA + Maven 搭建传统 Spring MVC 项目的详细步骤(非Spring Boot)
  • 深入解析Linux进程间通信(IPC):机制、应用与最佳实践
  • 新一代智能座舱娱乐系统软件架构设计文档
  • 理解MAC-IP映射、ARP协议与ARP欺骗及防护
  • 个人健康中枢的多元化AI网络革新与精准健康路径探析
  • Spring Cloud Gateway MVC 基于 Spring Boot 3.4 以 WAR 包形式部署于外部 Tomcat 实战
  • 软考-软件设计师中级备考 11、计算机网络
  • ASP.NET MVC​ 入门与提高指南九
  • 分布式系统中的 ActiveMQ:异步解耦与流量削峰(二)
  • EasyExcel使用总结
  • Tire 树(字典树/前缀树)
  • 数据同步实战篇
  • 面向对象编程(Object-Oriented Programming, OOP)是什么?
  • Kubernetes(k8s)学习笔记(六)--KubeSphere前置环境安装
  • Git 命令
  • go实现循环链表
  • 【数据结构】线性表--链表
  • 【图书管理系统】环境介绍、设计数据库和表、配置文件、引入依赖
  • OpenCv实战笔记(1)在win11搭建opencv4.11.1 + qt5.15.2 + vs2019_x64开发环境
  • Java捕获InterruptedException异常后,会自动清空中断状态
  • idea创建springboot工程-指定阿里云地址创建工程报错
  • QT数据库实验
  • Electron 从零开始:构建你的第一个桌面应用
  • Qt帮助文档框架
  • Qt .pro配置msvc相关命令(二)
  • GPU集群训练经验评估框架:运营经理经验分析篇