当前位置: 首页 > 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. 《自动驾驶中的计算机视觉》系列论文

相关文章:

  • 【Linux】日志与策略模式、线程池
  • 基于k8s系统的API网关-kong网关
  • Kubernetes(k8s)学习笔记(六)--KubeSphere前置环境安装
  • PowerShell 备份 Windows10/11 还原计算机驱动程序SOP
  • 复杂网络系列:第 5 部分 — 社区检测和子图
  • USB布局布线
  • 【iOS】 方法交换
  • C++负载均衡远程调用学习之Agent代理模块基础构建
  • 修复笔记:SkyReels-V2 项目中的 torch.load 警告
  • 使用 IDEA + Maven 搭建传统 Spring MVC 项目的详细步骤(非Spring Boot)
  • Linux中的粘滞位和开发工具和文本编辑器vim
  • 神经网络发展的时间线——积跬步至千里
  • terraform resource创建了5台阿里云ecs,如要使用terraform删除其中一台主机,如何删除?
  • 【ThinkBook 16+ 电脑重做系统type-c接口部分功能失效解决方案】
  • Ubuntu 系统上广受好评的浏览器推荐
  • Python 数据智能实战 (12):效果评估 - 超越传统指标
  • Monorepo项目多项目一次性启动工具对比与实践
  • 修复笔记:获取 torch._dynamo 的详细日志信息
  • 如何使用python保存字典
  • 【Java idea配置】
  • 上千游客深夜滞留张家界大喊退票?当地通报情况并致歉
  • 巴菲特掌舵伯克希尔60年后将卸任CEO,库克:认识他是人生中最珍贵的经历之一
  • 李在明涉嫌违反《公职选举法》案将于15日进行首次重审公审
  • 美伊谈判因“后勤原因”推迟,伊朗:视美国做法再定谈判日期
  • 缔造“水饺皇后”的香港,也是被移民塑造的香港
  • 中国空间站多项太空实验已取得成果,未来将陆续开展千余项研究