В этом примере показано, как обнаружить, классифицируйте и отследите транспортные средства при помощи данных об облаке точек лидара, собранных датчиком лидара, смонтированным на автомобиле, оборудованном датчиком. Данные о лидаре, используемые в этом примере, зарегистрированы из управляющего магистралью сценария. В этом примере данные об облаке точек сегментируются, чтобы определить класс объектов с помощью PointSeg
сеть. Средство отслеживания объединенной вероятностной ассоциации данных (JPDA) с интерактивным фильтром многоуровневой модели используется, чтобы отследить обнаруженные транспортные средства.
Модуль восприятия играет важную роль в достижении полной автономии для транспортных средств с системой ADAS. Лидар и камера являются существенными датчиками в рабочем процессе восприятия. Лидар способен извлекать точную информацию о глубине объектов, в то время как камера производит богатую и подробную информацию среды, которая полезна для предметной классификации.
Этот пример в основном включает эти части:
Оснуйте плоскую сегментацию
Семантическая сегментация
Ориентированный подбор кривой ограничительной рамки
Отслеживание ориентированных ограничительных рамок
Блок-схема дает обзор целой системы.
Датчик лидара генерирует данные об облаке точек или в организованном формате или в неорганизованном формате. Данные, используемые в этом примере, собраны с помощью Изгнания датчик лидара OS1. Этот лидар производит организованное облако точек с 64 горизонтальными строками развертки. Данные об облаке точек состоят из трех каналов, представляя x-, y-, и z-координаты точек. Каждый канал имеет размер 64 1024.
dataFile = 'highwayData.mat';
data = load(dataFile);
Этот пример использует гибридный подход, который использует segmentGroundFromLidarData
(Computer Vision Toolbox) и pcfitplane
(Computer Vision Toolbox) функции. Во-первых, оцените наземные параметры плоскости с помощью segmentGroundFromLidarData
функция. Предполагаемая наземная плоскость разделена на полосы вдоль направления транспортного средства для того, чтобы соответствовать плоскости, с помощью pcfitplane
функция на каждой полосе. Этот гибридный подход надежно приспосабливает наземную плоскость кусочным способом и обрабатывает изменения облака точек.
% Load point cloud ptClouds = data.ptCloudData; 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
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');
Загрузите предварительно обученную сеть и запуск вперед вывод на одной системе координат.
% Pretrained PointSeg model file modelfile = 'pretrainedPointSegModel.mat'; if ~exist('net', 'var') load(modelfile); 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('ModelFile',modelfile, 'XLimits', xLimit,... 'YLimit', yLimit, 'ZLimit', zLimit); % Prepare 5-D lidar data inputData = helperPrepareData(data.ptCloudData); % 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
[1] Сяо Чжан, Вэньда Сюй, Чиюй Дун и Джон М. Долан, "Эффективная L-форма, соответствующая обнаружению транспортного средства Используя лазерные сканеры", IEEE интеллектуальный симпозиум транспортных средств, июнь 2017
[2] И. Ван, Т. Ши, П. Юнь, Л. Тай и М. Лю, “Pointseg: семантическая сегментация в реальном времени на основе 3-го облака точек лидара”, arXiv предварительно распечатывают arXiv:1807.06288, 2018.