Лоцируйте 3-D обнаружение объектов Используя глубокое обучение PointPillars

В этом примере показано, как обучить сеть PointPillars для обнаружения объектов в облаках точек.

Данные об облаке точек лидара могут быть получены множеством датчиков лидара, включая Velodyne®, Pandar и датчики Изгнания. Эти датчики получают 3-D информацию о положении об объектах в сцене, которая полезна для многих приложений в автономном управлении автомобилем и дополненной реальности. Однако учебные устойчивые детекторы с данными об облаке точек сложны из-за разреженности данных на объект, объектные поглощения газов и шум датчика. Методы глубокого обучения, как показывали, обратились ко многим из этих проблем путем изучения устойчивых представлений функции непосредственно от данных об облаке точек. Один метод глубокого обучения для 3-D обнаружения объектов является PointPillars [1]. Используя подобную архитектуру к PointNet, извлечения сети PointPillars плотные, устойчивые функции от разреженных облаков точек вызвали столбы, затем используют 2D нейронную сеть для глубокого обучения с модифицированной сетью обнаружения объектов SSD, чтобы оценить объединенные 3-D ограничительные рамки, ориентации и предсказания класса.

Этот пример использует набор данных PandaSet [2] от Hesai и Scale. PandaSet содержит 8 240 неорганизованных сканов облака точек лидара различных городских сцен, полученных с помощью датчика Pandar64. Набор данных обеспечивает 3-D метки ограничительной рамки для 18 различных классов объектов, включая автомобиль, грузовик и пешехода.

Загрузите набор данных лидара

Этот пример использует подмножество PandaSet, который содержит 2 560 предварительно обработанных организованных облаков точек. Каждое облако точек покрытия 360o из представления, и задан как 64 1856 матрица. Облака точек хранятся в формате PCD, и их соответствующие достоверные данные хранится в PandaSetLidarGroundTruth.mat файл. Файл содержит 3-D информацию об ограничительной рамке для трех классов, которые являются автомобилем, грузовиком и пешеходом. Размер набора данных составляет 5,2 Гбайт.

Загрузите набор данных Pandaset с данного URL с помощью helperDownloadPandasetData функция помощника, заданная в конце этого примера.

doTraining = false;

outputFolder = fullfile(tempdir,'Pandaset');

lidarURL = ['https://ssd.mathworks.com/supportfiles/lidar/data/' ...
    'Pandaset_LidarData.tar.gz'];
helperDownloadPandasetData(outputFolder,lidarURL);

В зависимости от вашего Интернет-соединения может занять время процесс загрузки. Код приостанавливает выполнение MATLAB®, пока процесс загрузки не завершен. В качестве альтернативы можно загрузить набор данных на локальный диск с помощью веб-браузера и извлечь файл. Если вы делаете так, изменяете outputFolder переменная в коде к местоположению загруженного файла.

Загрузка данных

Создайте datastore файла, чтобы загрузить файлы PCD от заданного пути с помощью pcread функция.

path = fullfile(outputFolder,'Lidar');
lidarData = fileDatastore(path,'ReadFcn',@(x) pcread(x));

Загрузите 3-D метки ограничительной рамки объектов автомобиля и грузовика.

gtPath = fullfile(outputFolder,'Cuboids','PandaSetLidarGroundTruth.mat');
data = load(gtPath,'lidarGtLabels');
Labels = timetable2table(data.lidarGtLabels);
boxLabels = Labels(:,2:3);

Отобразите облако полной точки наблюдения.

figure
ptCld = read(lidarData);
ax = pcshow(ptCld.Location);
set(ax,'XLim',[-50 50],'YLim',[-40 40]);
zoom(ax,2.5);
axis off;

reset(lidarData);

Предварительная Обработка Данных

Данные PandaSet состоят из облаков полной точки наблюдения. В данном примере обрежьте облака полной точки наблюдения к облакам точек вида спереди с помощью стандартных параметров [1]. Эти параметры решают, что размер входа передал сети. Выбирание меньшей области значений облаков точек вдоль x, y, и оси z помогает обнаружить объекты, которые более близки началу координат, и также уменьшает полное учебное время сети.

xMin = 0.0;     % Minimum value along X-axis.
yMin = -39.68;  % Minimum value along Y-axis.
zMin = -5.0;    % Minimum value along Z-axis.
xMax = 69.12;   % Maximum value along X-axis.
yMax = 39.68;   % Maximum value along Y-axis.
zMax = 5.0;     % Maximum value along Z-axis.
xStep = 0.16;   % Resolution along X-axis.
yStep = 0.16;   % Resolution along Y-axis.
dsFactor = 2.0; % Downsampling factor.

% Calculate the dimensions for the pseudo-image.
Xn = round(((xMax - xMin) / xStep));
Yn = round(((yMax - yMin) / yStep));

% Define point cloud parameters.
pointCloudRange = [xMin,xMax,yMin,yMax,zMin,zMax];
voxelSize = [xStep,yStep];

Используйте cropFrontViewFromLidarData функция помощника, присоединенная к этому примеру как вспомогательный файл, к:

  • Обрежьте вид спереди от входного облака полной точки наблюдения.

  • Выберите метки поля, которые являются в ROI, заданном gridParams.

[croppedPointCloudObj,processedLabels] = cropFrontViewFromLidarData(...
    lidarData,boxLabels,pointCloudRange);
Processing data 100% complete

Отобразите обрезанное облако точек и метки основного блока истинности с помощью helperDisplay3DBoxesOverlaidPointCloud функция, определяемая помощника в конце примера.

pc = croppedPointCloudObj{1,1};
gtLabelsCar = processedLabels.Car{1};
gtLabelsTruck = processedLabels.Truck{1};

helperDisplay3DBoxesOverlaidPointCloud(pc.Location,gtLabelsCar,...
   'green',gtLabelsTruck,'magenta','Cropped Point Cloud');

reset(lidarData);

Создайте объекты Datastore для обучения

Разделите набор данных в наборы обучающих данных и наборы тестов. Выберите 70% данных для того, чтобы обучить сеть и остальных для оценки.

rng(1);
shuffledIndices = randperm(size(processedLabels,1));
idx = floor(0.7 * length(shuffledIndices));

trainData = croppedPointCloudObj(shuffledIndices(1:idx),:);
testData = croppedPointCloudObj(shuffledIndices(idx+1:end),:);

trainLabels = processedLabels(shuffledIndices(1:idx),:);
testLabels = processedLabels(shuffledIndices(idx+1:end),:);

Так, чтобы можно было легко получить доступ к хранилищам данных, сохраните обучающие данные как файлы PCD при помощи saveptCldToPCD функция помощника, присоединенная к этому примеру как вспомогательный файл. Можно установить writeFiles к "false" если ваши обучающие данные сохраняются в папке и поддерживаются pcread функция.

writeFiles = true;
dataLocation = fullfile(outputFolder,'InputData');
[trainData,trainLabels] = saveptCldToPCD(trainData,trainLabels,...
    dataLocation,writeFiles);
Processing data 100% complete

Создайте datastore файла с помощью fileDatastore загружать файлы PCD с помощью pcread функция.

lds = fileDatastore(dataLocation,'ReadFcn',@(x) pcread(x));

Поле Createa помечает datastore с помощью boxLabelDatastore для загрузки 3-D меток ограничительной рамки.

bds = boxLabelDatastore(trainLabels);

Используйте combine функционируйте, чтобы объединить облака точек и 3-D метки ограничительной рамки в один datastore для обучения.

cds = combine(lds,bds);

Увеличение данных

Этот пример использует увеличение достоверных данных и несколько других методов увеличения глобальных данных, чтобы добавить больше разнообразия в обучающие данные и соответствующие поля. Для получения дополнительной информации о типичных методах увеличения данных, используемых в 3-D рабочих процессах обнаружения объектов с данными о лидаре, смотрите Увеличения Данных для Обнаружения объектов Лидара Используя Глубокое обучение.

Считайте и отобразите облако точек перед увеличением с помощью helperDisplay3DBoxesOverlaidPointCloud функция помощника, заданная в конце примера..

augData = read(cds);
augptCld = augData{1,1};
augLabels = augData{1,2};
augClass = augData{1,3};

labelsCar = augLabels(augClass=='Car',:);
labelsTruck = augLabels(augClass=='Truck',:);

helperDisplay3DBoxesOverlaidPointCloud(augptCld.Location,labelsCar,'green',...
    labelsTruck,'magenta','Before Data Augmentation');

reset(cds);

Используйте sampleGroundTruthObjectsFromLidarData функция помощника, присоединенная к этому примеру как вспомогательный файл, чтобы извлечь все ограничительные рамки основной истины из обучающих данных.

classNames = {'Car','Truck'};
sampleLocation = fullfile(tempdir,'GTsamples');
[sampledGTData,indices] = sampleGroundTruthObjectsFromLidarData(cds,classNames,...
    'MinPoints',20,'sampleLocation',sampleLocation);

Используйте augmentGroundTruthObjectsToLidarData функция помощника, присоединенная к этому примеру как вспомогательный файл, чтобы случайным образом добавить постоянное число объектов класса автомобиля и грузовика к каждому облаку точек. Используйте transform функция, чтобы применить основную истину и пользовательские увеличения данных к обучающим данным.

numObjects = [10,10];
cdsAugmented = transform(cds,@(x) augmentGroundTruthObjectsToLidarData(x,...
    sampledGTData,indices,classNames,numObjects));

Кроме того, примените следующие увеличения данных к каждому облаку точек.

  • Случайное зеркальное отражение вдоль оси X

  • Случайное масштабирование на 5 процентов

  • Случайное вращение вдоль оси z от [-pi/4, пи/4]

  • Случайный перевод [0.2, 0.2, 0.1] метры вдоль x-, y-, и ось z соответственно

cdsAugmented = transform(cdsAugmented,@(x) augmentData(x));

Отобразитесь увеличенное облако точек наряду с основной истиной увеличило поля с помощью helperDisplay3DBoxesOverlaidPointCloud функция помощника, заданная в конце примера.

augData = read(cdsAugmented);
augptCld = augData{1,1};
augLabels = augData{1,2};
augClass = augData{1,3};

labelsCar = augLabels(augClass=='Car',:);
labelsTruck = augLabels(augClass=='Truck',:);

helperDisplay3DBoxesOverlaidPointCloud(augptCld.Location,labelsCar,'green',...
    labelsTruck,'magenta','After Data Augmentation');

reset(cdsAugmented);

Создайте детектор объектов PointPillars

Используйте pointPillarsObjectDetector функция, чтобы автоматически создать сеть обнаружения объектов PointPillars. Сеть PointPillars использует упрощенную версию сети PointNet, которая берет функции столба в качестве входа. Для каждой функции столба сеть применяет линейный слой, сопровождаемый слоями ReLU и нормализацией партии. Наконец, сеть применяет макс. объединяющую операцию по каналам, чтобы получить высокоуровневые закодированные функции. Эти закодированные функции рассеиваются назад к исходным местоположениям столба, чтобы создать псевдоизображение. Сеть затем обрабатывает псевдоизображение с 2D сверточной магистралью, сопровождаемой различными головами обнаружения SSD, чтобы предсказать 3-D ограничительные рамки наряду с его классами.

Сеть PointPillars, существующая в детекторе PointPillars, проиллюстрирована в следующей схеме.

Можно использовать Deep Network Designer (Deep Learning Toolbox), чтобы создать сеть, показанную в схеме.

pointPillarsObjectDetector функция требует, чтобы вы задали несколько входных параметров, которые параметрируют сеть PointPillars:

  • Имена классов

  • Поля привязки

  • Область значений облака точек

  • Размер вокселя

  • Количество видных столбов

  • Число точек на столб

% Define number of prominent pillars.
P = 12000; 

% Define number of points per pillar.
N = 100;   

% Estimate anchor boxes from training data.
anchorBoxes = calculateAnchorsPointPillars(trainLabels);
classNames = trainLabels.Properties.VariableNames;

% Define the PointPillars detector.
detector = pointPillarsObjectDetector(pointCloudRange,classNames,anchorBoxes,...
    'VoxelSize',voxelSize,'NumPillars',P,'NumPointsPerPillar',N);

Если больше управления требуется по архитектуре сети PointPillars, можно спроектировать сеть вручную. Для получения дополнительной информации см. Проект Сеть PointPillars.

Обучите детектор объектов Pointpillars

Задайте сетевые параметры обучения с помощью trainingOptions. Установите 'CheckpointPath' к временному местоположению, чтобы позволить сохранить частично обученных детекторов во время учебного процесса. Если обучение прервано, можно возобновить обучение с сохраненной контрольной точки.

Обучите детектор с помощью центрального процессора или графического процессора. Используя графический процессор требует Parallel Computing Toolbox™, и CUDA® включил NVIDIA® графический процессор. Для получения дополнительной информации смотрите Поддержку графического процессора Релизом (Parallel Computing Toolbox). Чтобы автоматически обнаружить, если вы имеете графический процессор в наличии, установите executionEnvironment к "auto". Если вы не имеете графического процессора или не хотите использовать один для обучения, устанавливать executionEnvironment к "cpu". Чтобы гарантировать использование графического процессора для обучения, установите executionEnvironment к "gpu".

executionEnvironment = "auto";
if canUseParallelPool
    dispatchInBackground = true;
else
    dispatchInBackground = false;
end

options = trainingOptions('adam',...
    'Plots',"none",...
    'MaxEpochs',60,...
    'MiniBatchSize',3,...
    'GradientDecayFactor',0.9,...
    'SquaredGradientDecayFactor',0.999,...
    'LearnRateSchedule',"piecewise",...
    'InitialLearnRate',0.0002,...
    'LearnRateDropPeriod',15,...
    'LearnRateDropFactor',0.8,...
    'ExecutionEnvironment',executionEnvironment,...
    'DispatchInBackground',dispatchInBackground,...
    'BatchNormalizationStatistics','moving',...
    'ResetInputNormalization',false,...
    'CheckpointPath',tempdir);

Используйте trainPointPillarsObjectDetector функция, чтобы обучить детектор объектов PointPillars, если doTraining верно. В противном случае загрузите предварительно обученный детектор.

if doTraining    
    [detector,info] = trainPointPillarsObjectDetector(cdsAugmented,detector,options);
else
    pretrainedDetector = load('pretrainedPointPillarsDetector.mat','detector');
    detector = pretrainedDetector.detector;
end

Сгенерируйте обнаружения

Используйте обучивший сеть, чтобы обнаружить объекты в тестовых данных:

  • Считайте облако точек из тестовых данных.

  • Запустите детектор в облаке тестовой точки, чтобы получить предсказанные ограничительные рамки и оценки достоверности.

  • Отобразите облако точек с ограничительными рамками с помощью helperDisplay3DBoxesOverlaidPointCloud функция помощника, заданная в конце примера.

ptCloud = testData{45,1};
gtLabels = testLabels(45,:);

% Specify the confidence threshold to use only detections with
% confidence scores above this value.
confidenceThreshold = 0.5;
[box,score,labels] = detect(detector,ptCloud,'Threshold',confidenceThreshold);

boxlabelsCar = box(labels'=='Car',:);
boxlabelsTruck = box(labels'=='Truck',:);

% Display the predictions on the point cloud.
helperDisplay3DBoxesOverlaidPointCloud(ptCloud.Location,boxlabelsCar,'green',...
    boxlabelsTruck,'magenta','Predicted Bounding Boxes');

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

Оцените обученный детектор объектов на большом наборе данных об облаке точек, чтобы измерить уровень.

numInputs = 50;

% Generate rotated rectangles from the cuboid labels.
bds = boxLabelDatastore(testLabels(1:numInputs,:));
groundTruthData = transform(bds,@(x) createRotRect(x));

% Set the threshold values.
nmsPositiveIoUThreshold = 0.5;
confidenceThreshold = 0.25;

detectionResults = detect(detector,testData(1:numInputs,:),...
    'Threshold',confidenceThreshold);

% Convert to rotated rectangles format for calculating metrics
for i = 1:height(detectionResults)
    box = detectionResults.Boxes{i};
    detectionResults.Boxes{i} = box(:,[1,2,4,5,7]);
end

metrics = evaluateDetectionAOS(detectionResults,groundTruthData,...
    nmsPositiveIoUThreshold);
disp(metrics(:,1:2))
               AOS        AP   
             _______    _______

    Car      0.89735    0.89735
    Truck      0.758      0.758

Функции помощника

function helperDownloadPandasetData(outputFolder,lidarURL)
% Download the data set from the given URL to the output folder.

    lidarDataTarFile = fullfile(outputFolder,'Pandaset_LidarData.tar.gz');
    
    if ~exist(lidarDataTarFile,'file')
        mkdir(outputFolder);
        
        disp('Downloading PandaSet Lidar driving data (5.2 GB)...');
        websave(lidarDataTarFile,lidarURL);
        untar(lidarDataTarFile,outputFolder);
    end
    
    % Extract the file.
    if (~exist(fullfile(outputFolder,'Lidar'),'dir'))...
            &&(~exist(fullfile(outputFolder,'Cuboids'),'dir'))
        untar(lidarDataTarFile,outputFolder);
    end

end

function helperDisplay3DBoxesOverlaidPointCloud(ptCld,labelsCar,carColor,...
    labelsTruck,truckColor,titleForFigure)
% Display the point cloud with different colored bounding boxes for different
% classes.
    figure;
    ax = pcshow(ptCld);
    showShape('cuboid',labelsCar,'Parent',ax,'Opacity',0.1,...
        'Color',carColor,'LineWidth',0.5);
    hold on;
    showShape('cuboid',labelsTruck,'Parent',ax,'Opacity',0.1,...
        'Color',truckColor,'LineWidth',0.5);
    title(titleForFigure);
    zoom(ax,1.5);
end

Ссылки

[1] Ленг, Алекс Х., Sourabh Vora, Хольгер Цезарь, Лубин Чжоу, Цзюн Ян и Оскар Бейджбом. "PointPillars: Быстрые Энкодеры для Обнаружения объектов От Облаков точек". На 2019 Конференциях IEEE/CVF по Компьютерному зрению и Распознаванию образов (CVPR), 12689-12697. Лонг-Бич, CA, США: IEEE, 2019. https://doi.org/10.1109/CVPR.2019.01298.

[2] Hesai и Scale. PandaSet. https://scale.com/open-datasets/pandaset.