exponenta event banner

Семантическая сегментация Lidar Point Cloud с использованием SqueezeSegV2 сети глубокого обучения

В этом примере показано, как обучить SqueezeSegV2 семантическую сеть сегментации на 3-D организованных данных облака точек лидара.

SqueezeSegV2 [1] - сверточная нейронная сеть (CNN) для выполнения сквозной семантической сегментации организованного лидарного точечного облака. Процедура обучения, показанная в этом примере, требует 2-D сферических проекционных изображений в качестве входных данных для сети глубокого обучения.

В этом примере используется набор данных PandaSet из Hesai и Scale [2]. PandaSet содержит 4800 неорганизованных сканирований облака точек лидара различных городских сцен, захваченных с помощью датчика Pandar 64. Набор данных предоставляет семантические метки сегментации для 42 различных классов, включая автомобиль, дорогу и пешехода.

Загрузить набор данных Lidar

В этом примере используется подмножество PandaSet, которое содержит 2560 предварительно обработанных организованных облаков точек. Каждое облако точек задается как матрица 64 на 1856. Соответствующая истина основания содержит семантические метки сегментации для 12 классов. Облака точек хранятся в формате PCD, а наземные истинные данные хранятся в формате PNG. Размер набора данных составляет 5,2 ГБ. Выполните этот код для загрузки набора данных.

url = 'https://ssd.mathworks.com/supportfiles/lidar/data/Pandaset_LidarData.tar.gz';
outputFolder = fullfile(tempdir,'Pandaset');
lidarDataTarFile = fullfile(outputFolder,'Pandaset_LidarData.tar.gz');
if ~exist(lidarDataTarFile, 'file')
    mkdir(outputFolder);
    disp('Downloading Pandaset Lidar driving data (5.2 GB)...');
    websave(lidarDataTarFile, url);
    untar(lidarDataTarFile,outputFolder);
end
% Check if tar.gz file is downloaded, but not uncompressed.
if (~exist(fullfile(outputFolder,'Lidar'), 'file'))...
        &&(~exist(fullfile(outputFolder,'semanticLabels'), 'file'))
    untar(lidarDataTarFile,outputFolder);
end
lidarData =  fullfile(outputFolder,'Lidar');
labelsFolder = fullfile(outputFolder,'semanticLabels');

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

Процедура обучения для этого примера предназначена для организованных облаков точек. Пример преобразования неорганизованных облаков точек в организованные см. в разделе Неорганизованное преобразование облаков точек с помощью сферической проекции (панель инструментов Lidar).

Загрузить предварительно обученную сеть

Загрузите предварительно обученную сеть, чтобы избежать необходимости ждать завершения обучения. Если вы хотите обучить сеть, установите doTraining переменная для true.

doTraining = false;
pretrainedNetURL = ...
'https://ssd.mathworks.com/supportfiles/lidar/data/trainedSqueezeSegV2PandasetNet.zip';
if ~doTraining
    downloadPretrainedSqueezeSegV2Net(outputFolder, pretrainedNetURL);
end

Подготовка данных для обучения

Загрузка облаков точек Лидара и меток классов

Используйте helperTransformOrganizedPointCloudToTrainingData вспомогательная функция, присоединенная к этому примеру, для генерации обучающих данных из облаков точек лидара. Функция использует данные облака точек для создания пятиканальных входных изображений. Каждый обучающий образ задается как массив 64 на 1856 на 5:

  • Высота каждого изображения составляет 64 пиксела.

  • Ширина каждого изображения - 1856 пикселей.

  • Каждое изображение имеет пять каналов. Пять каналов определяют 3-D координаты облака точек, интенсивность и диапазон: r = x2 + y2 + z2.

Ниже приведено визуальное представление обучающих данных.

Создание пятиканальных обучающих изображений.

imagesFolder = fullfile(outputFolder,'images');
helperTransformOrganizedPointCloudToTrainingData(lidarData,imagesFolder);
Preprocessing data 100% complete

Пятиканальные изображения сохраняются в виде файлов MAT.

Обработка может занять некоторое время. Код приостанавливает выполнение MATLAB ® до завершения обработки.

Создать imageDatastore и pixelLabelDatastore

Создание imageDatastore для извлечения и хранения пяти каналов 2-D сферических изображений с использованием imageDatastore и поддерживающей функции helperImageMatReader, которая является пользовательским устройством чтения файлов MAT. Эта функция присоединена к этому примеру как вспомогательный файл.

imds = imageDatastore(imagesFolder, ...
    'FileExtensions', '.mat', ...
    'ReadFcn', @helperImageMatReader);

Создание хранилища данных меток пикселей с помощью pixelLabelDatastore (Computer Vision Toolbox) для хранения пиксельных меток из изображений пиксельных меток. Объект сопоставляет каждую пиксельную метку с именем класса. В этом примере представляющими интерес объектами являются растительность, грунт, дорога, дорожная разметка, тротуар, автомобили, грузовики, другие транспортные средства, пешеходы, дорожный барьер, знаки и здания; все остальные пикселы являются фоном. Укажите эти классы и присвойте каждому классу уникальный идентификатор метки.

classNames = ["unlabelled"
              "Vegetation"
              "Ground"
              "Road"
              "RoadMarkings"
              "SideWalk"
              "Car"
              "Truck"
              "OtherVehicle"
              "Pedestrian"
              "RoadBarriers"
              "Signs"
              "Buildings"];
numClasses = numel(classNames);
% Specify label IDs from 1 to the number of classes.
labelIDs = 1 : numClasses;
pxds = pixelLabelDatastore(labelsFolder, classNames, labelIDs);

Загрузите и отобразите одно из помеченных изображений, наложив его на соответствующее изображение интенсивности с помощью helperDisplayLidarOverlaidImage , определенной в разделе «Вспомогательные функции» данного примера.

% Point cloud (channels 1, 2, and 3 are for location, channel 4 is for intensity, and channel 5 is for range).
I = read(imds);
labelMap = read(pxds);
figure;
helperDisplayLidarOverlaidImage(I, labelMap{1,1}, classNames);
title('Ground Truth');

Подготовка обучающих, валидационных и тестовых наборов

Используйте helperPartitionLidarSegmentationDataset вспомогательная функция, присоединенная к этому примеру, для разделения данных на обучающие, валидационные и тестовые наборы. Можно разделить данные обучения в соответствии с процентом, указанным в trainingDataPercentage. Разделите остальные данные в соотношении 2:1 на данные проверки и тестирования. Значение по умолчанию trainingDataPercentage является 0.7.

[imdsTrain, imdsVal, imdsTest, pxdsTrain, pxdsVal, pxdsTest] = ...
helperPartitionLidarSegmentationDataset(imds, pxds, 'trainingDataPercentage', 0.75);

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

trainingData = combine(imdsTrain, pxdsTrain);
validationData = combine(imdsVal, pxdsVal);

Увеличение объема данных

Увеличение данных используется для повышения точности сети путем случайного преобразования исходных данных во время обучения. С помощью увеличения данных можно добавить большее разнообразие к обучающим данным без фактического увеличения количества маркированных обучающих образцов.

Дополните учебные данные с помощью transform с пользовательскими операциями предварительной обработки, указанными helperAugmentData , определенной в разделе «Вспомогательные функции» данного примера. Эта функция случайным образом разворачивает многоканальное изображение 2-D и связанные с ним метки в горизонтальном направлении. Применение увеличения данных только к набору данных обучения.

augmentedTrainingData = transform(trainingData, @(x) helperAugmentData(x));

Определение сетевой архитектуры

Создайте стандартную сеть SqueezeSegV2 [1] с помощью squeezesegv2Layers(Панель инструментов Lidar). В SqueezeSegV2 сети подсеть кодера состоит из FireModules, чередующихся с уровнями максимального пула. Эта компоновка последовательно уменьшает разрешение входного изображения. Кроме того, SqueezeSegV2 сеть использует функцию фокальных потерь для уменьшения влияния несбалансированного распределения классов на точность сети. Дополнительные сведения об использовании функции фокусных потерь в семантической сегментации см. в разделе focalLossLayer(Панель инструментов компьютерного зрения).

Выполните этот код, чтобы создать график уровня, который можно использовать для обучения сети.

inputSize = [64 1856 5];
lgraph = squeezesegv2Layers(inputSize, ...
numClasses,'NumEncoderModules',4,'NumContextAggregationModules',2);

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

analyzeNetwork(lgraph);

Укажите параметры обучения

Использовать Аdam алгоритм оптимизации для обучения сети. Используйте trainingOptions для задания гиперпараметров.

maxEpochs = 30;
initialLearningRate = 1e-3;
miniBatchSize = 8;
l2reg = 2e-4;
options = trainingOptions('adam', ...
    'InitialLearnRate', initialLearningRate, ...
    'L2Regularization', l2reg, ...
    'MaxEpochs', maxEpochs, ...
    'MiniBatchSize', miniBatchSize, ...
    'LearnRateSchedule', 'piecewise', ...
    'LearnRateDropFactor', 0.1, ...
    'LearnRateDropPeriod', 10, ...
    'ValidationData', validationData, ...
    'Plots', 'training-progress', ...
    'VerboseFrequency', 20);

Примечание.Уменьшить miniBatchSize значение для управления использованием памяти при обучении.

Железнодорожная сеть

Вы можете обучить сеть самостоятельно, установив doTraining аргумент для true. При обучении сети можно использовать ЦП или графический процессор. Для использования графического процессора требуется Toolbox™ параллельных вычислений и поддерживаемое устройство графического процессора. Сведения о поддерживаемых устройствах см. в разделе Поддержка графического процессора по выпуску (Parallel Computing Toolbox). В противном случае загрузите предварительно подготовленную сеть.

if doTraining
    [net, info] = trainNetwork(trainingData, lgraph, options);
else
    load(fullfile(outputFolder,'trainedSqueezeSegV2PandasetNet.mat'),'net');
end

Прогнозирование результатов в облаке контрольных точек

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

Отображение фигуры с сегментацией в виде наложения.

I = read(imdsTest);
predictedResult = semanticseg(I, net);
figure;
helperDisplayLidarOverlaidImage(I, predictedResult, classNames);
title('Semantic Segmentation Result');

Используйте helperDisplayLabelOverlaidPointCloud функция, определенная в разделе «Вспомогательные функции» данного примера, для отображения результата сегментации в облаке точек.

figure;
helperDisplayLabelOverlaidPointCloud(I, predictedResult);                          
view([39.2 90.0 60]);
title('Semantic Segmentation Result on Point Cloud');

Оценка сети

Используйте evaluateSemanticSegmentation Функция (Computer Vision Toolbox) для вычисления показателей семантической сегментации по результатам тестового набора.

outputLocation = fullfile(tempdir, 'output');
if ~exist(outputLocation,'dir')
    mkdir(outputLocation);
end
pxdsResults = semanticseg(imdsTest, net, ...
    'MiniBatchSize', 4, ...
    'WriteLocation', outputLocation, ...
    'Verbose', false);
metrics = evaluateSemanticSegmentation(pxdsResults, pxdsTest, 'Verbose', false);

Величину перекрытия в классе можно измерить с помощью метрики пересечение-объединение (IoU).

evaluateSemanticSegmentation функция возвращает метрики для всего набора данных, для отдельных классов и для каждого тестового образа. Для просмотра метрик на уровне набора данных используйте metrics.DataSetMetrics собственность.

metrics.DataSetMetrics
ans=1×5 table
    GlobalAccuracy    MeanAccuracy    MeanIoU    WeightedIoU    MeanBFScore
    ______________    ____________    _______    ___________    ___________

       0.89724          0.61685       0.54431      0.81806        0.74537  

Метрики набора данных обеспечивают общий обзор производительности сети. Чтобы увидеть влияние каждого класса на общую производительность, проверьте метрики для каждого класса с помощью metrics.ClassMetrics собственность.

metrics.ClassMetrics 
ans=13×3 table
                    Accuracy      IoU      MeanBFScore
                    ________    _______    ___________

    unlabelled         0.94      0.9005      0.99911  
    Vegetation      0.77873     0.64819      0.95466  
    Ground          0.69019     0.59089      0.60657  
    Road            0.94045     0.83663      0.99084  
    RoadMarkings    0.37802     0.34149      0.77073  
    SideWalk         0.7874     0.65668      0.93687  
    Car              0.9334     0.81065      0.95448  
    Truck           0.30352     0.27401      0.37273  
    OtherVehicle    0.64397     0.58108      0.47253  
    Pedestrian      0.26214     0.20896      0.45918  
    RoadBarriers    0.23955     0.21971      0.19433  
    Signs           0.17276     0.15613      0.44275  
    Buildings       0.94891     0.85117      0.96929  

Хотя общая производительность сети хорошая, метрики классов для некоторых классов, как RoadMarkings и Truck указывают на то, что для повышения производительности требуется больше данных по обучению.

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

Функция для увеличения данных

helperAugmentData функция случайным образом разворачивает сферическое изображение и связанные с ним метки в горизонтальном направлении.

function out = helperAugmentData(inp)
% Apply random horizontal flipping.
out = cell(size(inp));
% Randomly flip the five-channel image and pixel labels horizontally.
I = inp{1};
sz = size(I);
tform = randomAffine2d('XReflection',true);
rout = affineOutputView(sz,tform,'BoundsStyle','centerOutput');
out{1} = imwarp(I,tform,'OutputView',rout);
out{2} = imwarp(inp{2},tform,'OutputView',rout);
end

Функция, чтобы показать карту сегментации лидара, наложенную на 2-м сферическом изображении

helperDisplayLidarOverlaidImage функция перекрывает семантическую карту сегментации по каналу интенсивности 2-D сферического изображения. Функция также изменяет размер наложенного изображения для улучшения визуализации.

function helperDisplayLidarOverlaidImage(lidarImage, labelMap, classNames)
% helperDisplayLidarOverlaidImage Overlay labels over the intensity image. 
%
%  helperDisplayLidarOverlaidImage(lidarImage, labelMap, classNames)
%  displays the overlaid image. lidarImage is a five-channel lidar input.
%  labelMap contains pixel labels and classNames is an array of label
%  names.
% Read the intensity channel from the lidar image.
intensityChannel = uint8(lidarImage(:,:,4));
% Load the lidar color map.
cmap = helperPandasetColorMap;
% Overlay the labels over the intensity image.
B = labeloverlay(intensityChannel,labelMap,'Colormap',cmap,'Transparency',0.4);
% Resize for better visualization.
B = imresize(B,'Scale',[3 1],'method','nearest');
imshow(B);
helperPixelLabelColorbar(cmap, classNames);
end

Функция, чтобы показать карту сегментации лидара, наложенную на 3D облаке пункта

helperDisplayLabelOverlaidPointCloud функция накладывает результат сегментации на 3-D организованное облако точек.

function helperDisplayLabelOverlaidPointCloud(I,predictedResult)
% helperDisplayLabelOverlaidPointCloud Overlay labels over point cloud object.
%  helperDisplayLabelOverlaidPointCloud(I, predictedResult)
%  displays the overlaid pointCloud object. I is the 5 channels organized
%  input image. predictedResult contains pixel labels.
ptCloud = pointCloud(I(:,:,1:3),'Intensity',I(:,:,4));
cmap = helperPandasetColorMap;
B = ...
labeloverlay(uint8(ptCloud.Intensity),predictedResult,'Colormap',cmap,'Transparency',0.4);
pc = pointCloud(ptCloud.Location,'Color',B);
figure;
ax = pcshow(pc);
set(ax,'XLim',[-70 70],'YLim',[-70 70]);
zoom(ax,3.5);
end

Функция для определения карты цветов Lidar

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

function cmap = helperPandasetColorMap
cmap = [[30,30,30];      % Unlabeled
        [0,255,0];       % Vegetation
        [255, 150, 255]; % Ground
        [255,0,255];     % Road
        [255,0,0];       % Road Markings
        [90, 30, 150];   % Sidewalk
        [245,150,100];   % Car
        [250, 80, 100];  % Truck
        [150, 60, 30];   % Other Vehicle
        [255, 255, 0];   % Pedestrian
        [0, 200, 255];   % Road Barriers
        [170,100,150];   % Signs
        [30, 30, 255]];  % Building
cmap = cmap./255;
end

Функция для отображения цветовой панели метки пикселя

helperPixelLabelColorbar функция добавляет панель цветов к текущей оси. Панель цветов отформатирована для отображения имен классов с цветом.

function helperPixelLabelColorbar(cmap, classNames)
colormap(gca, cmap);
% Add a colorbar to the current figure.
c = colorbar('peer', gca);
% Use class names for tick marks.
c.TickLabels = classNames;
numClasses = size(classNames, 1);
% Center tick labels.
c.Ticks = 1/(numClasses * 2):1/numClasses:1;
% Remove tick marks.
c.TickLength = 0;
end

Функция для загрузки предварительно обученной модели

downloadPretrainedSqueezeSegV2Net загружает предварительно подготовленную модель.

function downloadPretrainedSqueezeSegV2Net(outputFolder, pretrainedNetURL)
    preTrainedMATFile = fullfile(outputFolder,'trainedSqueezeSegV2PandasetNet.mat');
    preTrainedZipFile = fullfile(outputFolder,'trainedSqueezeSegV2PandasetNet.zip');
    
    if ~exist(preTrainedMATFile,'file')
        if ~exist(preTrainedZipFile,'file')
            disp('Downloading pretrained model (5 MB)...');
            websave(preTrainedZipFile, pretrainedNetURL);
        end
        unzip(preTrainedZipFile, outputFolder);   
    end       
end

Ссылки

[1] У, Бичэнь, Сюанью Чжоу, Сичэн Чжао, Сянъу Юэ и Курт Кэйцзер. «SqueezeSegV2: Улучшенная структура модели и незарегистрированная адаптация домена для сегментации дорожных объектов из облака точек LiDAR». В 2019 году Международная конференция по робототехнике и автоматизации (ICRA), 4376-82. Монреаль, КК, Канада: IEEE, 2019.https://doi.org/10.1109/ICRA.2019.8793495.

[2] Хесай и масштаб. PandaSet. https://scale.com/open-datasets/pandaset