В этом примере показано, как обнаружить, классифицируйте и отследите транспортные средства при помощи данных об облаке точек лидара, собранных датчиком лидара, смонтированным на автомобиле, оборудованном датчиком. Данные о лидаре, используемые в этом примере, зарегистрированы из управляющего магистралью сценария. В этом примере данные об облаке точек сегментируются, чтобы определить класс объектов с помощью PointSeg сеть. Средство отслеживания объединенной вероятностной ассоциации данных (JPDA) с интерактивным фильтром многоуровневой модели используется, чтобы отследить обнаруженные транспортные средства.
Модуль восприятия играет важную роль в достижении полной автономии для транспортных средств с системой ADAS. Лидар и камера являются существенными датчиками в рабочем процессе восприятия. Лидар способен извлекать точную информацию о глубине объектов, в то время как камера производит богатую и подробную информацию среды, которая полезна для предметной классификации.
Этот пример в основном включает эти части:
Оснуйте плоскую сегментацию
Семантическая сегментация
Ориентированный подбор кривой ограничительной рамки
Отслеживание ориентированных ограничительных рамок
Блок-схема дает обзор целой системы.

Датчик лидара генерирует данные об облаке точек или в организованном формате или в неорганизованном формате. Данные, используемые в этом примере, собраны с помощью Изгнания датчик лидара OS1. Этот лидар производит организованное облако точек с 64 горизонтальными строками развертки. Данные об облаке точек состоят из трех каналов, представляя x-, y-, и z-координаты точек. Каждый канал имеет размер 64 1024. Используйте функцию помощника helperDownloadData загружать данные и загружать их в рабочую область MATLAB®.
Примечание: Эта загрузка может занять несколько минут.
[ptClouds,pretrainedModel] = helperDownloadData;
Этот пример использует гибридный подход, который использует segmentGroundFromLidarData (Computer Vision Toolbox) и pcfitplane (Computer Vision Toolbox) функции. Во-первых, оцените наземные параметры плоскости с помощью segmentGroundFromLidarData функция. Предполагаемая наземная плоскость разделена на полосы вдоль направления транспортного средства для того, чтобы соответствовать плоскости, с помощью pcfitplane функция на каждой полосе. Этот гибридный подход надежно приспосабливает наземную плоскость кусочным способом и обрабатывает изменения облака точек.
% Load point cloud ptCloud = ptClouds{1}; % Define ROI for cropping point cloud xLimit = [-30,30]; yLimit = [-12,12]; zLimit = [-3,15]; roi = [xLimit,yLimit,zLimit]; % Extract ground plane [nonGround,ground] = helperExtractGround(ptCloud,roi); figure; pcshowpair(nonGround,ground); legend({'\color{white} Nonground','\color{white} Ground'},'Location','northeastoutside');

Этот пример использует предварительно обученный PointSeg сетевая модель. PointSeg сквозная сеть семантической сегментации в реальном времени, обученная для классов объектов как автомобили, грузовики и фон. Выход от сети является изображением маскированным с каждым пикселем, помеченным в его классе. Эта маска используется, чтобы отфильтровать различные типы объектов в облаке точек. Вход к сети является изображением с пятью каналами, которое является x, y, z, интенсивностью и областью значений. Для получения дополнительной информации о сети или как обучить сеть, отошлите к Семантической Сегментации Облака точек Лидара Используя Нейронную сеть для глубокого обучения PointSeg (Lidar Toolbox) пример.
helperPrepareData функция генерирует данные с пятью каналами из загруженных данных об облаке точек.
% Load and visualize a sample frame frame = helperPrepareData(ptCloud); figure; subplot(5,1,1); imagesc(frame(:,:,1)); title('X channel'); subplot(5,1,2); imagesc(frame(:,:,2)); title('Y channel'); subplot(5,1,3); imagesc(frame(:,:,3)); title('Z channel'); subplot(5,1,4); imagesc(frame(:,:,4)); title('Intensity channel'); subplot(5,1,5); imagesc(frame(:,:,5)); title('Range channel');

Запустите прямой вывод на одной системе координат от загруженной предварительно обученной сети.
if ~exist('net','var') net = pretrainedModel.net; end % Define classes classes = ["background","car","truck"]; % Define color map lidarColorMap = [ 0.98 0.98 0.00 % unknown 0.01 0.98 0.01 % green color for car 0.01 0.01 0.98 % blue color for motorcycle ]; % Run forward pass pxdsResults = semanticseg(frame,net); % Overlay intensity image with segmented output segmentedImage = labeloverlay(uint8(frame(:,:,4)),pxdsResults,'Colormap',lidarColorMap,'Transparency',0.5); % Display results figure; imshow(segmentedImage); helperPixelLabelColorbar(lidarColorMap,classes);

Используйте сгенерированную семантическую маску, чтобы отфильтровать облака точек, содержащие грузовики. Точно так же отфильтруйте облака точек для других классов.
truckIndices = pxdsResults == 'truck'; truckPointCloud = select(nonGround,truckIndices,'OutputSize','full'); % Crop point cloud for better display croppedPtCloud = select(ptCloud,findPointsInROI(ptCloud,roi)); croppedTruckPtCloud = select(truckPointCloud,findPointsInROI(truckPointCloud,roi)); % Display ground and nonground points figure; pcshowpair(croppedPtCloud,croppedTruckPtCloud); legend({'\color{white} Nonvehicle','\color{white} Vehicle'},'Location','northeastoutside');

После извлечения облаков точек различных классов объектов объекты кластеризируются путем применения Евклидовой кластеризации с помощью pcsegdist (Computer Vision Toolbox) функция. Чтобы сгруппировать все точки, принадлежащие одному одному кластеру, облако точек, полученное как, кластер используется в качестве точек seed для роста области в неназемных точках. Используйте findNearestNeighbors (Computer Vision Toolbox) функционируйте, чтобы циклично выполниться по всем точкам, чтобы вырастить область. Извлеченный кластер приспособлен в ограничительной рамке L-формы с помощью pcfitcuboid (Lidar Toolbox) функция. Эти кластеры транспортных средств напоминают форму буквы L, когда замечено по нисходящему представлению. Эта функция помогает в оценке ориентации транспортного средства. Ориентированный подбор кривой ограничительной рамки помогает в оценке угла рыскания объектов, который полезен в приложениях, таких как планирование пути и трафик маневрирования трафика.
Контуры кубоида кластеров могут также быть вычислены путем нахождения минимальных и максимальных пространственных степеней в каждом направлении. Однако этот метод перестал работать в оценке ориентации обнаруженных транспортных средств. Различие между этими двумя методами показано на рисунке.

[labels,numClusters] = pcsegdist(croppedTruckPtCloud,1); % Define cuboid parameters params = zeros(0,9); for clusterIndex = 1:numClusters ptsInCluster = labels == clusterIndex; pc = select(croppedTruckPtCloud,ptsInCluster); location = pc.Location; xl = (max(location(:,1)) - min(location(:,1))); yl = (max(location(:,2)) - min(location(:,2))); zl = (max(location(:,3)) - min(location(:,3))); % Filter small bounding boxes if size(location,1)*size(location,2) > 20 && any(any(pc.Location)) && xl > 1 && yl > 1 indices = zeros(0,1); objectPtCloud = pointCloud(location); for i = 1:size(location,1) seedPoint = location(i,:); indices(end+1) = findNearestNeighbors(nonGround,seedPoint,1); end % Remove overlapping indices indices = unique(indices); % Fit oriented bounding box model = pcfitcuboid(select(nonGround,indices)); params(end+1,:) = model.Parameters; end end % Display point cloud and detected bounding box figure; pcshow(croppedPtCloud.Location,croppedPtCloud.Location(:,3)); showShape('cuboid',params,"Color","red","Label","Truck");

Используйте helperLidarObjectDetectionDisplay класс, чтобы визуализировать полный рабочий процесс в одном окне. Размещение окна визуализации разделено на следующие разделы:
Изображение Области значений лидара: изображение облака точек в 2D как изображение области значений
Сегментированное Изображение: Обнаруженные метки, сгенерированные от сети семантической сегментации, наложенной с изображением интенсивности или четвертым каналом данных
Ориентированное Обнаружение Ограничительной рамки: 3-D облако точек с ориентированными ограничительными рамками
Вид сверху: Вид сверху облака точек с ориентированными ограничительными рамками
display = helperLidarObjectDetectionDisplay;
helperLidarObjectDetection класс является оберткой, инкапсулирующей всю сегментацию, кластеризацию и шаги подбора кривой ограничительной рамки, упомянутые в вышеупомянутых разделах. Используйте findDetections функционируйте, чтобы извлечь обнаруженные объекты.
% Initialize lidar object detector lidarDetector = helperLidarObjecDetector('Model',net,'XLimits',xLimit,... 'YLimit',yLimit,'ZLimit',zLimit); % Prepare 5-D lidar data inputData = helperPrepareData(ptClouds); % Set random number generator for reproducible results. S = rng(2018); % Initialize the display initializeDisplay(display); numFrames = numel(inputData); for count = 1:numFrames % Get current data input = inputData{count}; rangeImage = input(:,:,5); % Extact bounding boxes from lidar data [boundingBox,coloredPtCloud,pointLabels] = detectBbox(lidarDetector,input); % Update display with colored point cloud updatePointCloud(display,coloredPtCloud); % Update bounding boxes updateBoundingBox(display,boundingBox); % Update segmented image updateSegmentedImage(display,pointLabels,rangeImage); drawnow('limitrate'); end

В этом примере вы используете средство отслеживания объединенной вероятностной ассоциации данных (JPDA). Временной шаг dt установлен в 0,1 секунды, поскольку набор данных получен на уровне 10 Гц. Модель в пространстве состояний, используемая в средстве отслеживания, основана на модели кубоида параметрами, . Для получения дополнительной информации о том, как отследить ограничительные рамки в данных о лидаре, смотрите, что Транспортные средства Дорожки Используют Лидар: От Облака точек до примера Списка Дорожек. В этом примере информация о классе предоставляется с помощью ObjectAttributes свойство objectDetection object. При создании новых треков, инициализация фильтра function, заданное использование помощника функционирует helperMultiClassInitIMMFilter использует класс обнаружения, чтобы настроить начальные размерности объекта. Это помогает средству отслеживания настроить модель измерения ограничительной рамки с соответствующими размерностями дорожки.
Настройте объект средства отслеживания JPDA этими параметрами.
assignmentGate = [10 100]; % Assignment threshold; confThreshold = [7 10]; % Confirmation threshold for history logi delThreshold = [2 3]; % Deletion threshold for history logic Kc = 1e-5; % False-alarm rate per unit volume % IMM filter initialization function filterInitFcn = @helperMultiClassInitIMMFilter; % A joint probabilistic data association tracker with IMM filter tracker = trackerJPDA('FilterInitializationFcn',filterInitFcn,... 'TrackLogic','History',... 'AssignmentThreshold',assignmentGate,... 'ClutterDensity',Kc,... 'ConfirmationThreshold',confThreshold,... 'DeletionThreshold',delThreshold,'InitializationThreshold',0); allTracks = struct([]); time = 0; dt = 0.1; % Define Measurement Noise measNoise = blkdiag(0.25*eye(3),25,eye(3)); numTracks = zeros(numFrames,2);
Обнаруженные объекты собраны как массив ячеек objectDetection (Automated Driving Toolbox) объекты с помощью helperAssembleDetections функция.
display = helperLidarObjectDetectionDisplay; initializeDisplay(display); for count = 1:numFrames time = time + dt; % Get current data input = inputData{count}; rangeImage = input(:,:,5); % Extact bounding boxes from lidar data [boundingBox,coloredPtCloud,pointLabels] = detectBbox(lidarDetector,input); % Assemble bounding boxes into objectDetections detections = helperAssembleDetections(boundingBox,measNoise,time); % Pass detections to tracker if ~isempty(detections) % Update the tracker [confirmedTracks,tentativeTracks,allTracks,info] = tracker(detections,time); numTracks(count,1) = numel(confirmedTracks); end % Update display with colored point cloud updatePointCloud(display,coloredPtCloud); % Update segmented image updateSegmentedImage(display,pointLabels,rangeImage); % Update the display if the tracks are not empty if ~isempty(confirmedTracks) updateTracks(display,confirmedTracks); end drawnow('limitrate'); end

Этот пример показал, как обнаружить и классифицировать транспортные средства, снабженные ориентированной ограничительной рамкой на данных о лидаре. Вы также изучили, как использовать фильтр IMM для отслеживаемых объектов с несколькими, классифицируют информацию. Результаты семантической сегментации могут быть улучшены далее путем добавления большего количества обучающих данных.
function multiChannelData = helperPrepareData(input) % Create 5-channel data as x, y, z, intensity and range % of size 64-by-1024-by-5 from pointCloud. if isa(input, 'cell') numFrames = numel(input); multiChannelData = cell(1, numFrames); for i = 1:numFrames inputData = input{i}; x = inputData.Location(:,:,1); y = inputData.Location(:,:,2); z = inputData.Location(:,:,3); intensity = inputData.Intensity; range = sqrt(x.^2 + y.^2 + z.^2); multiChannelData{i} = cat(3, x, y, z, intensity, range); end else x = input.Location(:,:,1); y = input.Location(:,:,2); z = input.Location(:,:,3); intensity = input.Intensity; range = sqrt(x.^2 + y.^2 + z.^2); multiChannelData = cat(3, x, y, z, intensity, range); end end
function helperPixelLabelColorbar(cmap, classNames) % Add a colorbar to the current axis. The colorbar is formatted % to display the class names with the color. colormap(gca,cmap) % Add colorbar to current figure. c = colorbar('peer', gca); % Use class names for tick marks. c.TickLabels = classNames; numClasses = size(cmap,1); % Center tick labels. c.Ticks = 1/(numClasses*2):1/numClasses:1; % Remove tick mark. c.TickLength = 0; end
function [ptCloudNonGround,ptCloudGround] = helperExtractGround(ptCloudIn,roi) % Crop the point cloud idx = findPointsInROI(ptCloudIn,roi); pc = select(ptCloudIn,idx,'OutputSize','full'); % Get the ground plane the indices using piecewise plane fitting [ptCloudGround,idx] = piecewisePlaneFitting(pc,roi); nonGroundIdx = true(size(pc.Location,[1,2])); nonGroundIdx(idx) = false; ptCloudNonGround = select(pc,nonGroundIdx,'OutputSize','full'); end function [groundPlane,idx] = piecewisePlaneFitting(ptCloudIn,roi) groundPtsIdx = ... segmentGroundFromLidarData(ptCloudIn, ... 'ElevationAngleDelta',5,'InitialElevationAngle',15); groundPC = select(ptCloudIn,groundPtsIdx,'OutputSize','full'); % Divide x-axis in 3 regions segmentLength = (roi(2) - roi(1))/3; x1 = [roi(1),roi(1) + segmentLength]; x2 = [x1(2),x1(2) + segmentLength]; x3 = [x2(2),x2(2) + segmentLength]; roi1 = [x1,roi(3:end)]; roi2 = [x2,roi(3:end)]; roi3 = [x3,roi(3:end)]; idxBack = findPointsInROI(groundPC,roi1); idxCenter = findPointsInROI(groundPC,roi2); idxForward = findPointsInROI(groundPC,roi3); % Break the point clouds in front and back ptBack = select(groundPC,idxBack,'OutputSize','full'); ptForward = select(groundPC,idxForward,'OutputSize','full'); [~,inliersForward] = planeFit(ptForward); [~,inliersBack] = planeFit(ptBack); idx = [inliersForward; idxCenter; inliersBack]; groundPlane = select(ptCloudIn, idx,'OutputSize','full'); end function [plane,inlinersIdx] = planeFit(ptCloudIn) [~,inlinersIdx, ~] = pcfitplane(ptCloudIn,1,[0, 0, 1]); plane = select(ptCloudIn,inlinersIdx,'OutputSize','full'); end
function mydetections = helperAssembleDetections(bboxes,measNoise,timestamp) % Assemble bounding boxes as cell array of objectDetection mydetections = cell(size(bboxes,1),1); for i = 1:size(bboxes,1) classid = bboxes(i,end); lidarModel = [bboxes(i,1:3), bboxes(i,end-1), bboxes(i,4:6)]; % To avoid direct confirmation by the tracker, the ClassID is passed as % ObjectAttributes. mydetections{i} = objectDetection(timestamp, ... lidarModel','MeasurementNoise',... measNoise,'ObjectAttributes',struct('ClassID',classid)); end end
function [lidarData, pretrainedModel] = helperDownloadData outputFolder = fullfile(tempdir,'WPI'); url = 'https://ssd.mathworks.com/supportfiles/lidar/data/lidarSegmentationAndTrackingData.tar.gz'; lidarDataTarFile = fullfile(outputFolder,'lidarSegmentationAndTrackingData.tar.gz'); if ~exist(lidarDataTarFile,'file') mkdir(outputFolder); websave(lidarDataTarFile,url); untar(lidarDataTarFile,outputFolder); end % Check if tar.gz file is downloaded, but not uncompressed if ~exist(fullfile(outputFolder,'WPI_LidarData.mat'),'file') untar(lidarDataTarFile,outputFolder); end % Load lidar data data = load(fullfile(outputFolder,'highwayData.mat')); lidarData = data.ptCloudData; % Download pretrained model url = 'https://ssd.mathworks.com/supportfiles/lidar/data/pretrainedPointSegModel.mat'; modelFile = fullfile(outputFolder,'pretrainedPointSegModel.mat'); if ~exist(modelFile,'file') websave(modelFile,url); end pretrainedModel = load(fullfile(outputFolder,'pretrainedPointSegModel.mat')); end
[1] Сяо Чжан, Вэньда Сюй, Чиюй Дун и Джон М. Долан, "Эффективная L-форма, соответствующая обнаружению транспортного средства Используя лазерные сканеры", IEEE интеллектуальный симпозиум транспортных средств, июнь 2017
[2] И. Ван, Т. Ши, П. Юнь, Л. Тай и М. Лю, “Pointseg: семантическая сегментация в реальном времени на основе 3-го облака точек лидара”, arXiv предварительно распечатывают arXiv:1807.06288, 2018.