《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.pswp.cn/diannao/81631.shtml
繁體地址,請注明出處:http://hk.pswp.cn/diannao/81631.shtml
英文地址,請注明出處:http://en.pswp.cn/diannao/81631.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

模型部署——cuda編程入門

CUDA中的線程與線程束 kernel是在device上線程中并行執行的函數&#xff0c;核函數用__global__符號聲明&#xff0c;在調用時需要用<<<grid_size, block_size>>>來指定kernel要執行的線程數量。在CUDA中&#xff0c;每一個線程都要執行核函數&#xff0c;并…

WordPress不支持中文TAG標簽出現404的解決方法

我們在后臺編輯文章時輸入中文標簽會發現出現404的情況&#xff0c;其實中文TAG標簽鏈接無法打開的原因是WordPress不支持中文的編碼。那么解決的方法也很容易&#xff0c;只要改代碼讓WordPress能支持中文的編碼形式&#xff0c;也就是UTF-8和GBK編碼即可&#xff0c;無需用到…

金融信貸公司所需的技術和風控體系及其帶來的價值

金融信貸公司的技術架構通過集成傳統大型機系統與現代數據平臺&#xff0c;能夠有效支持金融信貸業務的運作&#xff0c;同時通過大數據、ETL、報表開發、數據倉庫等技術為公司帶來更高效的數據驅動決策、精準的風控分析和更靈活的業務支持。 一、公司技術架構 數據倉庫架構&…

《AI大模型應知應會100篇》第43篇:大模型幻覺問題的識別與緩解方法

第43篇&#xff1a;大模型幻覺問題的識別與緩解方法 摘要 當AI系統自信滿滿地編造"量子計算機使用香蕉皮作為能源"這類荒謬結論時&#xff0c;我們不得不正視大模型的幻覺問題。本文通過15個真實案例解析、6種檢測算法實現和3套工業級解決方案&#xff0c;帶您掌握…

計算方法實驗五 插值多項式的求法

【實驗性質】 綜合性驗 【實驗目的】 掌握Lagrange插值算法、Newton插值算法&#xff1b;理解Newton插值算法相對于Lagrange插值算法的優點。 【實驗內容】 先用C語言自帶的系統函數sin x求出 的值&#xff0c;然后分別用Lagrange、Newton方法求出的值&#xff0c;并與用…

文獻總結:TPAMI端到端自動駕駛綜述——End-to-End Autonomous Driving: Challenges and Frontiers

端到端自動駕駛綜述 1. 文章基本信息2. 背景介紹3. 端到端自動駕駛主要使用方法3. 1 模仿學習3.2 強化學習 4. 測試基準4.1 真實世界評估4.2 在線/閉環仿真測試4.3 離線/開環測試評價 5. 端到端自動駕駛面臨的挑戰5.1 多模態輸入5.2 對視覺表征的依賴5.3 基于模型的強化學習的世…

PostgreSQL:pgAdmin 4 使用教程

pgAdmin 4 是一個用于管理和維護 PostgreSQL 數據庫的強大工具。它提供了一個圖形化界面&#xff0c;使用戶能夠輕松地連接到數據庫、創建表、運行 SQL 語句以及執行其他數據庫管理任務。 安裝和使用 安裝 pgAdmin 4 安裝 pgAdmin 4 非常簡單。下載并運行安裝程序&#xff0…

Java學習手冊:關系型數據庫基礎

一、關系型數據庫概述 關系型數據庫是一種基于關系模型的數據庫&#xff0c;它將數據組織成一個或多個表&#xff08;或稱為關系&#xff09;&#xff0c;每個表由行和列組成。每一列都有一個唯一的名字&#xff0c;稱為屬性&#xff0c;表中的每一行是一個元組&#xff0c;代…

wpf CommandParameter 傳遞MouseWheelEventArgs參數

在 WPF 中通過 CommandParameter 傳遞 MouseWheelEventArgs 參數時&#xff0c;需結合 ?事件到命令的轉換機制? 和 ?參數轉換器? 來實現。以下是具體實現方案及注意事項&#xff1a; 一、核心實現方法 1. ?使用 EventToCommand 傳遞原始事件參數? 通過 Interaction.Tr…

八大排序之選擇排序

本篇文章將帶你詳細了解八大基本排序中的選擇排序 目錄 &#xff08;一&#xff09;選擇排序的時間復雜度和空間復雜度及穩定性分析 &#xff08;二&#xff09;代碼實現 (三)輸出結果 選擇排序的基本原理是&#xff1a;每次從待排序的數組中找出最大值和最小值。具體流程是…

【算法學習】哈希表篇:哈希表的使用場景和使用方法

算法學習&#xff1a; https://blog.csdn.net/2301_80220607/category_12922080.html?spm1001.2014.3001.5482 前言&#xff1a; 在之前學習數據結構時我們就學習了哈希表的使用方法&#xff0c;這里我們主要是針對哈希表的做題方法進行講解&#xff0c;都是leetcode上的經典…

Java 中如何實現自定義類加載器,應用場景是什么?

在 Java 中&#xff0c;可以通過繼承 java.lang.ClassLoader 類來實現自定義類加載器。自定義類加載器可以控制類的加載方式&#xff0c;實現一些特殊的應用場景。 實現自定義類加載器的步驟&#xff1a; 繼承 java.lang.ClassLoader 類。 重寫 findClass(String name) 方法 …

信創開發中跨平臺開發框架的選擇與實踐指南

&#x1f9d1; 博主簡介&#xff1a;CSDN博客專家、CSDN平臺優質創作者&#xff0c;高級開發工程師&#xff0c;數學專業&#xff0c;10年以上C/C, C#, Java等多種編程語言開發經驗&#xff0c;擁有高級工程師證書&#xff1b;擅長C/C、C#等開發語言&#xff0c;熟悉Java常用開…

WebRTC 服務器之Janus架構分析

1. Webrtc三種類型通信架構 1.1 1 對 1 通信 1 對 1 通信模型設計的主要?標是盡量讓兩個終端進?直聯&#xff0c;這樣即可以節省服務器的資源&#xff0c;?可以提? ?視頻的服務質量。WebRTC ?先嘗試兩個終端之間是否可以通過 P2P 直接進?通信&#xff0c;如果?法直接…

數字化轉型進階:26頁華為數字化轉型實踐分享【附全文閱讀】

本文分享了華為數字化轉型的實踐經驗和體會。華為通過數字化變革,致力于在客戶服務、供應鏈、產品管理等方面提高效率,并把數字世界帶入每個組織,構建萬物互聯的智能世界。華為的數字化轉型愿景是成為行業標桿,通過推進數字化戰略、構建面向業務數字化轉型的IT組織陣型、堅…

Hal庫下備份寄存器

首先要確保有外部電源給VBAT供電 生成后應該會有這兩個文件&#xff08;不知道為什么生成了好幾次都沒有&#xff0c;復制工程在試一次就有了&#xff09; 可以看到stm32f407有20個備份寄存器 讀寫函數 void HAL_RTCEx_BKUPWrite(RTC_HandleTypeDef *hrtc, uint32_t Backup…

使用 Vue3 + Webpack 和 Vue3 + Vite 實現微前端架構(基于 Qiankun)

在現代前端開發中&#xff0c;微前端架構逐漸成為一種流行的解決方案&#xff0c;尤其是在大型項目中。通過微前端&#xff0c;我們可以將一個復雜的單體應用拆分為多個獨立的小型應用&#xff0c;每個子應用可以獨立開發、部署和運行&#xff0c;同時共享主應用的基礎設施。本…

【c++】【STL】list詳解

目錄 list的作用list的接口構造函數賦值運算符重載迭代器相關sizeemptyfrontbackassignpush_frontpop_frontpush_backpop_backinserteraseswapresizeclearspliceremoveremove_ifuniquemergesortreverse關系運算符重載&#xff08;非成員函數&#xff09; list的模擬實現結點類迭…

Redis持久化:

什么是Redis持久化&#xff1a; Redis 持久化是指將 Redis 內存中的數據保存到硬盤等持久化存儲介質中&#xff0c;以便在 Redis 服務器重啟或出現故障時能夠恢復數據&#xff0c;保證數據的可靠性和持續性。Redis 提供了兩種主要的持久化方式&#xff1a;RDB&#xff08;Redi…

VBA 64位API聲明語句第009講

跟我學VBA&#xff0c;我這里專注VBA, 授人以漁。我98年開始&#xff0c;從源碼接觸VBA已經20余年了&#xff0c;隨著年齡的增長&#xff0c;越來越覺得有必要把這項技能傳遞給需要這項技術的職場人員。希望職場和數據打交道的朋友&#xff0c;都來學習VBA,利用VBA,起碼可以提高…