這個例子展示了如何根據(jù)已知的地面真值評估車道邊界檢測的性能。在本例中,您將通過計算擬合度來描述每幀車道邊界檢測算法的性能。此測量方法可用于確定、可視化和理解底層算法中的故障模式。
37.1 概述
隨著人們對基于視覺的自動駕駛問題解決方案的興趣越來越大,能夠評估和驗證檢測算法的準確性變得非常重要。對于那些具有多個參數(shù)的檢測算法來說,驗證準確性尤為重要,這些參數(shù)可以通過調(diào)整來實現(xiàn)滿足預(yù)定義質(zhì)量要求的結(jié)果。這個例子通過一個這樣的工作流程,其中可以測量車道邊界的準確性水平。該工作流有助于在每幀基礎(chǔ)上精確確定這些算法中的故障模式,以及描述其整體性能。該工作流程還可以幫助直觀、定量地了解算法的性能。然后,可以利用這種理解來調(diào)整算法以提高其性能。
37.2 加載地面真實數(shù)據(jù)
本例中使用的數(shù)據(jù)集是來自于車輛行駛在街道上的前裝攝像頭的視頻文件。車道邊界的地面真值已經(jīng)用地面真值標示器應(yīng)用在視頻上手動標示,使用標示為 "LaneBoundary "的Line ROI。這段視頻長8秒,也就是250幀。它有三個交叉路口,幾輛車(停放和移動),以及車道邊界(雙線,單線和虛線)。要為自己的視頻創(chuàng)建一個地面真值車道邊界數(shù)據(jù)集,你可以使用地面真值標簽器應(yīng)用。
% Load MATfile with ground truth dataloaded =load('caltech_cordova1_laneAndVehicleGroundTruth.mat');
加載的結(jié)構(gòu)包含三個字段:
groundTruthData,一個有兩列的時間表, LaneBoundaries和Vehicles。LaneBoundaries包含被控車道邊界(左、右)的地真點,用XY點組成的單元數(shù)組表示,形成一條多線。Vehicles包含攝像機視圖中車輛的地面真點邊界框,用M乘4的[x,y,width,height]數(shù)組表示。
sensor, 一個monoCamera對象,包含安裝在車輛上的校準相機的屬性。這個對象可以讓你估計車輛與前方物體之間的實際距離。
videoName,一個字符數(shù)組,包含存儲幀的視頻的文件名。
從這個結(jié)構(gòu)中的數(shù)據(jù),通過使用VideoReader循環(huán)瀏覽幀來打開視頻文件。VideoReader對象使用一個helperMonoSensor對象來檢測視頻幀中的車道和物體,使用sensor中存儲的攝像頭設(shè)置。存儲在gtdata中的時間表變量持有地面真實數(shù)據(jù)。這個變量包含了以后用于分析的每幀數(shù)據(jù)。
%Create a VideoReader object to read frames of the video.videoname = loaded.videoName;fileReader= VideoReader(videoName); % Theground truth data is organized in a timetable.gtdata =loaded.groundTruthData; %Display the first few rows of the ground truth data.head(gtdata)ans = 8x2 timetable Time Vehicles LaneBoundaries ____________ ____________ ______________ 0 sec {6x4 double} {2x1 cell} 0.033333 sec {6x4 double} {2x1 cell} 0.066667 sec {6x4 double} {2x1 cell} 0.1 sec {6x4 double} {2x1 cell} 0.13333 sec {6x4 double} {2x1 cell} 0.16667 sec {6x4 double} {2x1 cell} 0.2 sec {6x4 double} {2x1 cell} 0.23333 sec {5x4 double} {2x1 cell}
gtdata時間表有兩列Vehicle和LaneBoundaries。在每個時間戳上,Vehicles列持有一個M乘4的車輛邊界框數(shù)組,LaneBoundaries列持有一個左、右車道邊界點的雙元素單元格數(shù)組。
首先,可視化加載一個圖像幀的地面真實數(shù)據(jù)。
% Readthe first frame of the video.frame =readframe(fileReader); %Extract all lane points in the first frame.lanePoints= gtdata.LaneBoundaries{1}; %Extract vehicle bounding boxes in the first frame.vehicleBBox= gtdata.Vehicles{1}; %Superimpose the right lane points and vehicle bounding boxes.frame =insertMarker(frame, lanePoints{2}, 'X');frame =insertObjectAnnotation(frame, 'rectangle', vehicleBBox, 'Vehicle'); %Display ground truth data on the first frame.figureimshow(frame)
37.3 運行車道邊界檢測算法
使用視頻幀和monoCamera參數(shù),可以自動估計車道邊界的位置。為了說明這一點,這里使用helperMonoSensor類的processframe方法來檢測車道邊界(作為拋物線LaneBoundary對象)和車輛(作為[x,y,width,height]邊界框矩陣)。在本例中,這是車道邊界檢測 "被測算法"。您可以使用相同的模式來評估自定義車道邊界檢測算法,其中processframe被替換為自定義檢測函數(shù)。車輛坐標中的地面真點也存儲在gtdata時間表的LanesInVehicleCoord列中。這樣一來,以后就可以在鳥瞰圖顯示中直觀地看到它們了。首先,用傳感器配置helperMonoSensor對象。helperMonoSensor類集合了運行車道邊界檢測算法所需的所有必要步驟。
% Setup monoSensorHelper to process video.monoCameraSensor= loaded.sensor;monoSensorHelper= helperMonoSensor(monoCameraSensor); %Create new timetable with same Time vector for measurements.measurements= timetable(gtdata.Time); % Setup timetable columns for holding lane boundary and vehicle data.numframes =floor(fileReader.frameRate*fileReader.Duration);measurements.LaneBoundaries = cell(numframes, 2);measurements.VehicleDetections= cell(numframes, 1);gtdata.LanesInVehicleCoord = cell(numframes, 2); %Rewind the video to t = 0, and create a frame index to hold current%frame.fileReader.CurrentTime= 0;frameIndex = 0; % Loopthrough the videoFile until there are no new frames.whilehasframe(fileReader) frameIndex = frameIndex+1; frame = readframe(fileReader); % Use the processframemethod to compute detections. % This method can bereplaced with a custom lane detection method. detections = processframe(monoSensorHelper,frame); % Store the estimatedlane boundaries and vehicle detections. measurements.LaneBoundaries{frameIndex} =[detections.leftEgoBoundary ... detections.rightEgoBoundary]; measurements.VehicleDetections{frameIndex}= detections.vehicleBoxes; % To facilitatecomparison, convert the ground truth lane points to the % vehicle coordinatesystem. gtPointsThisframe =gtdata.LaneBoundaries{frameIndex}; vehiclePoints = cell(1,numel(gtPointsThisframe)); for ii =1:numel(gtPointsThisframe) vehiclePoints{ii} =imageToVehicle(monoCameraSensor, gtPointsThisframe{ii}); end % Store ground truthpoints expressed in vehicle coordinates. gtdata.LanesInVehicleCoord{frameIndex} =vehiclePoints;end現(xiàn)在,已經(jīng)用車道檢測算法處理了視頻,請驗證地面真實點是否正確地轉(zhuǎn)化為車輛坐標系。gtdata時間表的LanesInVehicleCoord列的第一個條目包含第一幀的車輛坐標。將這些地面真點繪制在鳥瞰圖的第一幀上。
%Rewind video to t = 0.fileReader.CurrentTime= 0; % Readthe first frame of the video.frame =readframe(fileReader);birdsEyeImage= transformImage(monoSensorHelper.BirdsEyeConfig, frame); %Extract right lane points for the first frame in Bird's-Eye View.firstframeVehiclePoints= gtdata.LanesInVehicleCoord{1};pointsInBEV= vehicleToImage(monoSensorHelper.BirdsEyeConfig, firstframeVehiclePoints{2}); %Superimpose points on the frame.birdsEyeImage= insertMarker(birdsEyeImage, pointsInBEV, 'X', 'Size', 6); %Display transformed points in Bird's-Eye View.figureimshow(birdsEyeImage)
37.4 測量檢測誤差
計算車道邊界檢測的誤差是驗證幾個下游子系統(tǒng)性能的重要步驟。這些子系統(tǒng)包括車道偏離警告系統(tǒng),它們依賴于車道檢測子系統(tǒng)的準確性。
你可以通過測量擬合度的好壞來估計這個精度。有了地面真點和計算出的估計值,您現(xiàn)在可以對它們進行比較和可視化,以了解檢測算法的性能如何。
擬合度可以在每幀或整個視頻中進行測量。每幀統(tǒng)計數(shù)據(jù)提供了有關(guān)特定場景的詳細信息,例如檢測算法性能可能會發(fā)生變化的道路拐彎處的行為。全局統(tǒng)計提供了錯過檢測的車道數(shù)量的全局估計。
使用evaluateLaneBoundaries函數(shù)返回全局檢測統(tǒng)計數(shù)據(jù)和一個分配數(shù)組。這個數(shù)組將估計的車道邊界對象與相應(yīng)的地面真點進行匹配。
evaluateLaneBoundaries函數(shù)中的閾值參數(shù)表示車輛坐標中的最大橫向距離,以符合與估計的拋物線車道邊界的匹配。
threshold =0.25; % in meters [numMatches,numMisses, numFalsePositives, assignments] = ... evaluateLaneBoundaries(measurements.LaneBoundaries, ... gtdata.LanesInVehicleCoord, ... threshold); disp(['Number ofmatches: ', num2str(numMatches)]);disp(['Number ofmisses: ', num2str(numMisses)]);disp(['Number offalse positives: ', num2str(numFalsePositives)]);Number ofmatches: 321Number ofmisses: 124Number offalse positives: 25
使用賦值數(shù)組,可以計算有用的每條車道指標,例如估計值與地面真點之間的平均橫向距離。這些指標表明算法的性能如何。要計算平均距離度量,請使用本例末尾定義的輔助函數(shù) helperComputeLaneStatistics。
averageDistance= helperComputeLaneStatistics(measurements.LaneBoundaries, ... gtdata.LanesInVehicleCoord, ... assignments,@m(xù)ean); % Plotaverage distance between estimates and ground truth.figurestem(gtdata.Time,averageDistance)title('AverageDistance Between Estimates and Ground Truth')grid onylabel('Distancein Meters')legend('LeftBoundary','Right Boundary')
可視化并檢視地面真值與你的算法之間的差異性。
現(xiàn)在已經(jīng)對車道檢測算法的準確性有了定量的了解。然而,僅根據(jù)上一節(jié)的圖譜是不可能完全理解故障的。因此,查看視頻并以每幀為基礎(chǔ)將錯誤可視化對于識別特定的故障模式至關(guān)重要,可以通過完善算法來改進這些模式。
可以使用Ground Truth Labeler應(yīng)用程序作為可視化工具來查看包含地面真值數(shù)據(jù)和估計車道邊界的視頻。driving.connect.Connector類提供了一個接口,用于將自定義的可視化工具附加到Ground Truth Labeler。
使用parabolicLaneBoundary數(shù)組和地面真值數(shù)據(jù)來計算估計點的車輛坐標位置。parabolicLaneBoundary數(shù)組定義了一條線,而地面真值數(shù)據(jù)則有道路上標記的離散點。助手GetCorrespondingPoints函數(shù)估計估計線上的點,這些點與車輛的Y軸距離一致。這個輔助函數(shù)在例子的最后定義。
現(xiàn)在,地面真值點和估計點被包含在一個新的時間表中,以便在地面真值標簽器應(yīng)用程序中可視化。然后,創(chuàng)建的groundTruth對象將被存儲為一個MAT文件。
%Compute the estimated point locations using the monoCamera.[estVehiclePoints,estImagePoints] = helperGetCorrespondingPoints(monoCameraSensor, ... measurements.LaneBoundaries, ... gtdata.LanesInVehicleCoord, ... assignments); % Addestimated lanes to the measurements timetable.measurements.EstimatedLanes = estImagePoints;measurements.LanesInVehicleCoord= estVehiclePoints; %Create a new timetable with all the variables needed for visualization.names = {'LanePoints'; 'DetectedLanePoints'};types =labelType({'Line'; 'Line'});labelDefs =table(names, types, 'VariableNames', {'Name','Type'}); visualizeInframe= timetable(gtdata.Time, ... gtdata.LaneBoundaries, ... measurements.EstimatedLanes, ... 'VariableNames', names); %Create groundTruth object.dataSource= groundTruthDataSource(videoName);dataToVisualize= groundTruth(dataSource, labelDefs, visualizeInframe); % Saveall the results of the previous section in distanceData.mat in a% temporaryfolder.dataToLoad= [tempdir 'distanceData.mat'];save(dataToLoad,'monoSensorHelper', 'videoName', 'measurements', 'gtdata', 'averageDistance');
helperCustomUI類使用從MAT文件中加載的數(shù)據(jù)(如您剛剛創(chuàng)建的文件)創(chuàng)建繪圖和鳥眼視圖。Ground Truth Labeler 應(yīng)用程序的 Connector 接口通過 helperUIConnector 類與 helperCustomUI 類進行交互,以同步視頻與平均距離圖和鳥眼視圖。這種同步使您能夠以分析和可視化的方式分析每幀結(jié)果。
按照這些步驟來可視化結(jié)果,如下面的圖片所示。
進入保存distanceData.mat的臨時目錄,打開Ground Truth Labeler應(yīng)用程序。然后啟動Ground Truth Labeler應(yīng)用程序,使用以下命令將連接器句柄指定為helperUIConnector。
>> origdir = pwd;>> cd(tempdir)>> groundTruthLabeler(dataSource,'ConnectorTargetHandle', @helperUIConnector)。
導(dǎo)入標簽。在圖像坐標中可視化地面真值車道標記和估計車道。從應(yīng)用工具條中,點擊導(dǎo)入標簽。然后選擇 "來自工作區(qū) "選項,并將dataToVisualize地面真值加載到應(yīng)用程序中。主應(yīng)用程序窗口現(xiàn)在包含車道標記的注釋。
現(xiàn)在可以瀏覽視頻并檢查錯誤。要返回到原始目錄,可以鍵入。
>> cd(origdir)
從這個可視化中,你可以對算法和地面真實數(shù)據(jù)的質(zhì)量做出幾個推斷。
左側(cè)車道的準確率一直比右側(cè)車道的準確率差。在鳥瞰圖顯示中仔細觀察,地面真實數(shù)據(jù)被標記為雙線的外邊界,而估計車道邊界一般位于雙線標記的中心。這說明左側(cè)車道估計很可能比數(shù)字描繪的更準確,明確定義的地面真實數(shù)據(jù)集對此類觀測至關(guān)重要。
2.3秒和4秒左右的檢測間隙對應(yīng)的是道路上的交叉口,而這些交叉口的前面都是人行道。這說明算法在有十字路口的情況下表現(xiàn)不佳。
6.8秒左右,當車輛接近第三個十字路口時,被控車道會分化成一條左側(cè)專用車道和一條直行車道。在這里,算法也未能精確捕獲到左側(cè)車道,而地真數(shù)據(jù)也不包含任何信息的5幀。
37.5 總結(jié)結(jié)語
這個例子展示了如何使用Ground Truth Labeler應(yīng)用程序測量車道邊界檢測算法的準確性并將其可視化。您可以將這一概念擴展到其他自定義算法,以簡化這些工作流程,并擴展應(yīng)用程序的功能以進行自定義測量。
37.6 支持功能helperComputeLaneStatistics
這個輔助函數(shù)計算車道邊界檢測與地面真實點相比的統(tǒng)計數(shù)據(jù)。它接收一個函數(shù)句柄,可以用來概括需要計算的統(tǒng)計量,包括@均值和@中值。
function stat =helperComputeLaneStatistics(estModels, gtPoints, assignments, fcnHandle) numframes = length(estModels); % Make left and rightestimates NaN by default to represent lack of % data. stat = NaN*ones(numframes, 2); for frameInd = 1:numframes % Make left and rightestimates NaN by default. stat(frameInd, :) = NaN*ones(2, 1); for idx =1:length(estModels{frameInd}) % Ignore false positiveassignments. if assignments{frameInd}(idx)== 0 continue; end % The kth boundary inestModelInframe is matched to kth % element indexed byassignments in gtPointsInframe. thisModel =estModels{frameInd}(idx); thisGT = gtPoints{frameInd}{assignments{frameInd}(idx)}; thisGTModel =driving.internal.piecewiseLinearBoundary(thisGT); ifmean(thisGTModel.Points(:,2)) > 0 % left lane xPoints =thisGTModel.Points(:,1); yDist = zeros(size(xPoints)); for index = 1:numel(xPoints) gtYPoints =thisGTModel.computeBoundaryModel(xPoints(index)); testYPoints =thisModel.computeBoundaryModel(xPoints(index)); yDist(index) =abs(testYPoints-gtYPoints); end stat(frameInd, 1) =fcnHandle(yDist); else% right lane xPoints =thisGTModel.Points(:,1); yDist = zeros(size(xPoints)); for index = 1:numel(xPoints) gtYPoints =thisGTModel.computeBoundaryModel(xPoints(index)); testYPoints =thisModel.computeBoundaryModel(xPoints(index)); yDist(index) = abs(testYPoints-gtYPoints); end stat(frameInd, 2) =fcnHandle(yDist); end end endendhelperGetCorrespondingPoints(對應(yīng)點)
該輔助功能在X軸位置創(chuàng)建與地面真實點相匹配的車輛和圖像坐標點。
function[vehiclePoints, imagePoints] = helperGetCorrespondingPoints(monoCameraSensor,estModels, gtPoints, assignments) numframes = length(estModels); imagePoints = cell(numframes, 1); vehiclePoints = cell(numframes, 1); for frameInd = 1:numframes ifisempty(assignments{frameInd}) imagePointsInframe = []; vehiclePointsInframe = []; else estModelInframe =estModels{frameInd}; gtPointsInframe =gtPoints{frameInd}; imagePointsInframe = cell(length(estModelInframe),1); vehiclePointsInframe =cell(length(estModelInframe), 1); for idx =1:length(estModelInframe) % Ignore false positiveassignments. if assignments{frameInd}(idx)== 0 imagePointsInframe{idx} =[NaN NaN]; continue; end % The kth boundary inestModelInframe is matched to kth % element indexed byassignments in gtPointsInframe. thisModel =estModelInframe(idx); thisGT =gtPointsInframe{assignments{frameInd}(idx)}; xPoints = thisGT(:, 1); yPoints =thisModel.computeBoundaryModel(xPoints); vehiclePointsInframe{idx} =[xPoints, yPoints]; imagePointsInframe{idx} =vehicleToImage(monoCameraSensor, [xPoints yPoints]); end end vehiclePoints{frameInd} = vehiclePointsInframe; imagePoints{frameInd} = imagePointsInframe; % Make imagePoints []instead of {} to comply with groundTruth object. ifisempty(imagePoints{frameInd}) imagePoints{frameInd} = []; end ifisempty(vehiclePoints{frameInd}) vehiclePoints{frameInd} = []; end endend
原文標題 : 基于MATLAB&SIMUlink開發(fā)自動駕駛系統(tǒng)第三十七講根據(jù)地面實況對車道邊界檢測進行評估和可視化