Обнаружьте, классифицируйте и отследите транспортные средства Используя лидар

В этом примере показано, как обнаружить, классифицируйте и отследите транспортные средства при помощи данных об облаке точек лидара, собранных датчиком лидара, смонтированным на автомобиле, оборудованном датчиком. Данные о лидаре, используемые в этом примере, зарегистрированы из управляющего магистралью сценария. В этом примере данные об облаке точек сегментируются, чтобы определить класс объектов с помощью 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");

Setup визуализации

Используйте helperLidarObjectDetectionDisplay класс, чтобы визуализировать полный рабочий процесс в одном окне. Размещение окна визуализации разделено на следующие разделы:

  1. Изображение Области значений лидара: изображение облака точек в 2D как изображение области значений

  2. Сегментированное Изображение: Обнаруженные метки, сгенерированные от сети семантической сегментации, наложенной с изображением интенсивности или четвертым каналом данных

  3. Ориентированное Обнаружение Ограничительной рамки: 3-D облако точек с ориентированными ограничительными рамками

  4. Вид сверху: Вид сверху облака точек с ориентированными ограничительными рамками

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 Гц. Модель в пространстве состояний, используемая в средстве отслеживания, основана на модели кубоида параметрами, [x,y,z,ϕ,l,w,h]. Для получения дополнительной информации о том, как отследить ограничительные рамки в данных о лидаре, смотрите, что Транспортные средства Дорожки Используют Лидар: От Облака точек до Списка Дорожек. В этом примере информация о классе предоставляется с помощью 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 для отслеживаемых объектов с несколькими, классифицируют информацию. Результаты семантической сегментации могут быть улучшены далее путем добавления большего количества обучающих данных.

Вспомогательные Функции

helperPrepareData

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

pixelLabelColorbar

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

helperExtractGround

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

helperAssembleDetections

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.

Для просмотра документации необходимо авторизоваться на сайте