В этом примере показано, как обучить сеть семантической сегментации SqueezeSegV2 на 3-D организованных данных об облаке точек лидара.
SqueezeSegV2 [1] является сверточной нейронной сетью (CNN) для выполнения сквозной семантической сегментации организованного облака точек лидара. Метод обучения, показанный в этом примере, требует 2D сферических проецируемых изображений как входных параметров к нейронной сети для глубокого обучения.
Этот пример использует набор данных PandaSet от Hesai и Scale [2]. PandaSet содержит 4 800 неорганизованных сканов облака точек лидара различных городских сцен, полученных с помощью датчика Pandar 64. Набор данных обеспечивает метки семантической сегментации для 42 различных классов включая автомобиль, дорогу и пешехода.
Этот пример использует подмножество PandaSet, который содержит 2 560 предварительно обработанных организованных облаков точек. Каждое облако точек задано как 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
переменная в коде к местоположению загруженного файла.
Метод обучения для этого примера для организованных облаков точек. Для примера, показывающего, как преобразовать неорганизованный в организованные облака точек, смотрите Неорганизованный к Организованному Преобразованию Облаков точек Используя Сферическую Проекцию.
Загрузите предварительно обученную сеть, чтобы избежать необходимости ожидать обучения завершиться. Если вы хотите обучить сеть, установите doTraining
переменная к true
.
doTraining = false; pretrainedNetURL = ... 'https://ssd.mathworks.com/supportfiles/lidar/data/trainedSqueezeSegV2PandasetNet.zip'; if ~doTraining downloadPretrainedSqueezeSegV2Net(outputFolder, pretrainedNetURL); end
Используйте helperTransformOrganizedPointCloudToTrainingData
поддерживание функции, присоединенной к этому примеру, чтобы сгенерировать обучающие данные от облаков точек лидара. Функция использует данные об облаке точек, чтобы создать входные изображения с пятью каналами. Каждое учебное изображение задано как 64 1 856 5 массивами:
Высота каждого изображения составляет 64 пикселя.
Ширина каждого изображения составляет 1 856 пикселей.
Каждое изображение имеет пять каналов. Пять каналов задают 3-D координаты облака точек, интенсивности и области значений: .
Визуальное представление обучающих данных следует.
Сгенерируйте учебные изображения с пятью каналами.
imagesFolder = fullfile(outputFolder,'images');
helperTransformOrganizedPointCloudToTrainingData(lidarData,imagesFolder);
Preprocessing data 100% complete
Изображения с пятью каналами сохранены как файлы MAT.
Обработка может занять время. Код приостанавливает выполнение MATLAB®, пока обработка не завершена.
mageDatastore
и pixelLabelDatastore
Создайте imageDatastore
извлекать и хранить пять каналов 2D сферических изображений с помощью imageDatastore и helperImageMatReader поддерживающий функции, которая является пользовательским средством чтения файлов MAT. Эта функция присоединена к этому примеру как к вспомогательному файлу.
imds = imageDatastore(imagesFolder, ... 'FileExtensions', '.mat', ... 'ReadFcn', @helperImageMatReader);
Создайте пиксельный datastore метки с помощью pixelLabelDatastore
чтобы сохранить мудрые пикселем метки от пикселя помечают изображения. Объект сопоставляет каждую пиксельную метку с именем класса. В этом примере растительность, земля, дорога, дорожные разметки, тротуар, автомобили, грузовики, другие транспортные средства, пешеход, дорожный барьер, знаки и создания являются предметами интереса; все другие пиксели являются фоном. Задайте эти классы и присвойте уникальную метку ID каждому классу.
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
функция, заданная в разделе Supporting Functions этого примера.
% 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
функция, заданная в разделе Supporting Functions этого примера. Эта функция случайным образом инвертирует многоканальное 2D изображение и сопоставленные метки в горизонтальном направлении. Примените увеличение данных только к обучающему набору данных.
augmentedTrainingData = transform(trainingData, @(x) helperAugmentData(x));
Создайте стандартную сеть SqueezeSegV2 [1] при помощи squeezesegv2Layers
функция. В сети SqueezeSegV2 подсеть энкодера состоит из FireModules, вкрапленного макс. объединяющими слоями. Это расположение последовательно уменьшает разрешение входного изображения. Кроме того, сеть SqueezeSegV2 использует фокальную функцию потерь, чтобы смягчить последствие неустойчивого распределения класса на сетевой точности. Для получения дополнительной информации о том, как использовать фокальную функцию потерь в семантической сегментации, смотрите focalLossLayer
.
Выполните этот код, чтобы создать график слоев, который может использоваться, чтобы обучить сеть.
inputSize = [64 1856 5]; lgraph = squeezesegv2Layers(inputSize, ... numClasses,'NumEncoderModules',4,'NumContextAggregationModules',2);
Используйте analyzeNetwork
(Deep Learning Toolbox) функция, чтобы отобразить интерактивную визуализацию сетевой архитектуры.
analyzeNetwork(lgraph);
Используйте Adam
алгоритм оптимизации, чтобы обучить сеть. Используйте 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
. Если вы обучаете сеть, можно использовать центральный процессор или графический процессор. Используя графический процессор требует Parallel Computing 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
функция, заданная в разделе Supporting Functions этого примера, чтобы отобразить результат сегментации на облаке точек.
figure;
helperDisplayLabelOverlaidPointCloud(I, predictedResult);
view([39.2 90.0 60]);
title('Semantic Segmentation Result on Point Cloud');
Используйте evaluateSemanticSegmentation
функция, чтобы вычислить метрики семантической сегментации из результатов набора тестов.
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
helperDisplayLidarOverlaidImage
функционируйте накладывает карту семантической сегментации по каналу интенсивности 2D сферического изображения. Функция также изменяет размер наложенного изображения для лучшей визуализации.
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
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
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] Ву, Bichen, Сюаньюй Чжоу, Сычэн Чжао, Сянюй Юэ и Курт Койцер. “SqueezeSegV2: Улучшенная Структура модели и Безнадзорная Доменная Адаптация к Дорожно-объектной Сегментации от Облака точек LiDAR”. На 2 019 Международных конференциях по вопросам Робототехники и Автоматизации (ICRA), 4376–82. Монреаль, Qc, Канада: IEEE, 2019.https://doi.org/10.1109/ICRA.2019.8793495.
[2] Hesai и Scale. PandaSet. https://scale.com/open-datasets/pandaset