Автоматизируйте разметку достоверных данных для обнаружения транспортного средства Используя PointPillars

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

Приложение Lidar Labeler

Хорошие достоверные данные крайне важны для разработки автоматизированных ведущих алгоритмов и оценки эффективности. Однако создание и поддержание разнообразного, высококачественного, и набор маркированных данных требуют значительного усилия. Приложение Lidar Labeler служит основой, чтобы автоматизировать процесс маркировки с помощью AutomationAlgorithm интерфейс. Можно создать пользовательский алгоритм и использовать его в приложении, чтобы пометить целый набор данных. Можно также отредактировать результаты с учетом сложных сценариев, пропущенных алгоритмом.

В этом примере, вас:

  • Используйте предварительно обученную сеть обнаружения объектов PointPillars, чтобы обнаружить объекты класса 'vehicle'.

  • Создайте алгоритм автоматизации, который можно использовать в приложении Lidar Labeler, чтобы автоматически пометить транспортные средства в облаке точек с помощью сети PointPillars.

Обнаружьте транспортные средства Используя сеть PointPillars

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

Загрузите сеть PointPillars, которая обучена на наборе данных WPI.

pretrainedNetURL = 'https://ssd.mathworks.com/supportfiles/lidar/data/trainedPointPillars.zip';
preTrainedMATFile = fullfile(tempdir,'trainedPointPillarsNet.mat');
preTrainedZipFile = fullfile(tempdir,'trainedPointPillars.zip');
    
if ~exist(preTrainedMATFile,'file')
    if ~exist(preTrainedZipFile,'file')
        disp('Downloading pretrained detector (8.3 MB)...');
        websave(preTrainedZipFile, pretrainedNetURL);
    end
    unzip(preTrainedZipFile, tempdir);   
end

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

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

  • Добавьте папку, содержащую функции помощника к пути поиска файлов.

  • Считайте облако точек из lidardata.

  • Задайте поля привязки, которые являются предопределенными ограничительными рамками в формате {длина, ширина, высота, z-центр, угол рыскания}.

  • Задайте параметры сетки, чтобы обрезать облако полной точки наблюдения к виду спереди в формате {{xMin, yMin, zMin}, {xMax, yMax, zMax}, {xStep, yStep, dsFactor}, {Xn, Yn}} где Xn = вокруг (((xMax - xMin) / xStep)) и Yn = вокруг (((yMax - yMin) / yStep)).

  • Задайте имя метки для обнаруженного объекта.

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

  • Задайте порог перекрытия, чтобы удалить перекрывающиеся обнаружения.

  • Выберите видные столбы (P) на основе числа точек на столб (N).

  • Установите executionEnvironment.

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

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

  • Отобразите облако точек с ограничительными рамками.

% Add folder to path.
addpath(fullfile(matlabroot,'examples','deeplearning_shared','main'));
    
% Load the pretrained network.
pretrainedNet = load(preTrainedMATFile);

% Load a point cloud.
ptCloud = pcread(fullfile(toolboxdir('lidar'),'lidardata','highwayScene.pcd'));

% Anchor boxes.
anchorBoxes = {{3.9, 1.6, 1.56, -3.6, 0}, {3.9, 1.6, 1.56, -3.6, pi/2}};

% Cropping parameters.
gridParams = {{0.0,-39.68,-5.0},{69.12,39.68,5.0},{0.16,0.16,2.0},{432,496}};

% Label name for detected object.
classNames = {'vehicle'};

% Confidence threshold. 
confidenceThreshold = 0.45;

% Overlap threshold. 
overlapThreshold = 0.1;

% Number of prominent pillars.
P = 12000;

% Number of points per pillar.
N = 100;

% Set the execution environment.
executionEnvironment = "auto";

% Crop the front view of the point cloud. 
processedPointCloud = helperCropFrontViewFromLidarData(ptCloud, gridParams);

% Detect the bounding boxes.
[box, ~, ~] = generatePointPillarDetections(pretrainedNet.net, processedPointCloud, ...
                      anchorBoxes, gridParams, classNames, confidenceThreshold, ...
                      overlapThreshold, P, N, executionEnvironment);

% Display the detections on the point cloud.
figure
ax = pcshow(processedPointCloud.Location);
showShape('cuboid',box,'Parent',ax,'Opacity',0.1,'Color','red','LineWidth',0.5)
hold on
zoom(ax, 1.5)
title("Detected Vehicle on Point Cloud")

Подготовьте класс автоматизации детектора транспортного средства лидара

Создайте класс автоматизации для алгоритма детектора транспортного средства лидара. Класс наследовался vision.labeler.AutomationAlgorithm абстрактный базовый класс. Базовый класс задает свойства и подписи для методов что использование приложения, чтобы сконфигурировать и запустить пользовательский алгоритм. Приложение Lidar Labeler предоставляет первоначальный шаблон класса автоматизации. Для получения дополнительной информации смотрите, Создают Алгоритм Автоматизации для Маркировки. LidarVehicleDetector класс основан на этом шаблоне и предоставляет вам готовый к использованию класс автоматизации для обнаружения транспортного средства в облаке точек. Комментарии схемы класса основные шаги должны были реализовать каждый вызов API.

Свойства алгоритма

Шаг 1 содержит свойства, которые задают имя и описание алгоритма и направлений для использования алгоритма.

    % ----------------------------------------------------------------------
    % Step 1: Define the required properties describing the algorithm. This
    % includes Name, Description, and UserDirections.
    properties(Constant)
        
        % Name Algorithm Name
        %   Character vector specifying the name of the algorithm.
        Name = 'Lidar Vehicle Detector';
        
        % Description Algorithm Description
        %   Character vector specifying the short description of the algorithm.
        Description = 'Detect vehicles in point cloud using PointPillars network';
        
        % UserDirections Algorithm Usage Directions
        %   Cell array of character vectors specifying directions for
        %   algorithm users to follow to use the algorithm.
        UserDirections = {['ROI Label Definition Selection: select one of ' ...
            'the ROI definitions to be labeled'], ...
            ['Run: Press RUN to run the automation algorithm. '], ...
            ['Review and Modify: Review automated labels over the interval ', ...
            'using playback controls. Modify/delete/add ROIs that were not ' ...
            'satisfactorily automated at this stage. If the results are ' ...
            'satisfactory, click Accept to accept the automated labels.'], ...
            ['Change Settings and Rerun: If automated results are not ' ...
            'satisfactory, you can try to re-run the algorithm with ' ...
            'different settings. To do so, click Undo Run to undo ' ...
            'current automation run, click Settings, make changes to Settings,' ...
            'and press Run again.'], ...
            ['Accept/Cancel: If the results of automation are satisfactory, ' ...
            'click Accept to accept all automated labels and return to ' ...
            'manual labeling. If the results of automation are not ' ...
            'satisfactory, click Cancel to return to manual labeling ' ...
            'without saving the automated labels.']};
    end

Custom Properties

Шаг 2 содержит пользовательские свойства, необходимые для основного алгоритма.

    % ---------------------------------------------------------------------
    % Step 2: Define properties you want to use during the algorithm
    % execution.
    properties
        
        % SelectedLabelName 
        %   Name of the selected label. Vehicles detected by the algorithm 
        %   are assigned this variable name.
        SelectedLabelName
        
        % PretrainedNetwork
        %   PretrainedNetwork saves the pretrained PointPillars dlnetwork.
        PretrainedNetwork
        
        %   Range of point clouds along x,y,and z-axis used to crop
        %   full-view point clouds to front-view point clouds.
        %   These parameters guide the calculation of the size of the 
        %   input [xn,yn] passed to the network.

        %   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.
        
        %  Dimensions for the pseudo-image calculated as 
        %  round(((xMax - xMin) / xStep));.
        %  Xn = 432;
        %  Yn = 496;
        
        % GridParams 
        %  Parameter used to crop full-view point cloud to front-view,
        %  defined as {{xMin,yMin,zMin}, {xMax,yMax,zMax},
        %  {xStep,yStep,dsFactor}, {Xn,Yn}};
        GridParams = {{0.0,-39.68,-5.0}, {69.12,39.68,5.0}, {0.16,0.16,2.0}, {432,496}}
        
        % AnchorBoxes 
        %  Predefined bounding box dimensions based on the classes to
        %  detect, defined in the format {length, width, height,
        %  z-center, yaw angle}
        AnchorBoxes = {{3.9, 1.6, 1.56, -1.78, 0}, {3.9, 1.6, 1.56, -1.78, pi/2}};
        
        % P
        %  Number of prominent pillars.
        P = 12000;
        
        % N
        %  Number of points per pillar.
        N = 100;
        
        % ExecutionEnvironment
        %  Set the execution environment.
        ExecutionEnvironment = "auto";
        
        % ConfidenceThreshold
        %  Specify the confidence threshold to use only detections with 
        %  confidence scores above this value.
        ConfidenceThreshold = 0.45;
        
        % OverlapThreshold
        %  Specify the overlap threshold to remove overlapping detections.
        OverlapThreshold = 0.1;            
        
    end

Функциональные определения

Шаг 3 имеет дело с функциональными определениями.

checkSignalType функционируйте проверки, если данные сигнала поддерживаются для автоматизации. Детектор транспортного средства лидара поддерживает сигналы типа PointCloud.

        function isValid = checkSignalType(signalType)            
            % Only point cloud signal data is valid for the Lidar Vehicle
            % detector algorithm.
            isValid = (signalType == vision.labeler.loading.SignalType.PointCloud);           
        end

checkLabelDefinition функционируйте проверки, если определением метки является соответствующий тип для автоматизации. Детектор транспортного средства лидара требует Cuboid пометьте тип.

        function isValid = checkLabelDefinition(~, labelDef)            
            % Only cuboid ROI label definitions are valid for the Lidar
            % vehicle detector algorithm.
            isValid = labelDef.Type == labelType.Cuboid;
        end

checkSetup функционируйте проверки, если определение метки ROI выбрано для автоматизации.

        function isReady = checkSetup(algObj)            
            % Is there one selected ROI Label definition to automate.
            isReady = ~isempty(algObj.SelectedLabelDefinitions);
        end

settingsDialog функция получает и изменяет свойства, заданные на Шаге 2. Этот вызов API позволяет вам создать диалоговое окно, которое открывается, когда вы кликаете по Значку настроек во вкладке Automate. Чтобы создать это диалоговое окно, используйте dialog функционируйте, чтобы быстро создать простое модальное окно, чтобы опционально изменить пороги перекрытия и доверие. lidarVehicleDetectorSettings метод содержит код для шагов контроля ввода и настроек.

        function settingsDialog(algObj)
            % Invoke dialog with options for modifying the 
            % threshold and confidence threshold. 
            lidarVehicleDetectorSettings(algObj)
        end

Функции выполнения

Шаг 4 задает функции выполнения. initialize функция заполняет начальное состояние алгоритма на основе существующих меток в приложении. В этом примере, initialize функция выполняет следующие шаги:

  • Сохраните имя выбранного определения метки.

  • Добавьте папку, содержащую функции помощника к пути поиска файлов.

  • Загрузите предварительно обученную сеть обнаружения объектов PointPillars от tempdir и сохраните его в PretrainedNetwork свойство.

        function initialize(algObj,~)           
            % Store the name of the selected label definition. Use this
            % name to label the detected vehicles.
            algObj.SelectedLabelName = algObj.SelectedLabelDefinitions.Name;
            
            % Add the folder containing helper functions to the search path.
            addpath(fullfile(matlabroot,'examples','deeplearning_shared','main'))

            % Point to tempdir, where pretrainedNet was downloaded.
            preTrainedMATFile = fullfile(tempdir,'trainedPointPillarsNet.mat');
            assert(exist(preTrainedMATFile,'file'), ...
                sprintf(['File : %s does not exists \n Download Pretrained PointPillars ' ...
                'network with the link provided in the example'],preTrainedMATFile));
            pretrainedNet = load(preTrainedMATFile);
            algObj.PretrainedNetwork = pretrainedNet.net;           
        end

run функция задает базовый алгоритм детектора транспортного средства лидара этого класса автоматизации. run функция вызвана для каждой системы координат последовательности облака точек и ожидает, что класс автоматизации возвратит набор меток. Можно расширить алгоритм к любой категории, на которой обучена сеть. В целях этого примера ограничьте сеть, чтобы обнаружить объекты класса 'Vehicle'.

        function autoLabels = run(algObj, pointCloud)
            bBoxes = [];
            for i = 1:2           
                if i == 2
                    % Rotate the point cloud by 180 degrees.
                    thetha = pi;
                    rot = [cos(thetha) sin(thetha) 0; ...
                        -sin(thetha) cos(thetha) 0; ...
                        0  0  1];
                    trans = [0, 0, 0];
                    tform = rigid3d(rot, trans);
                    pointCloud = pctransform(pointCloud, tform);
                end
                
                % Crop the front view of the point clouds.
                processedPointCloud = helperCropFrontViewFromLidarData(pointCloud, ...
                    algObj.GridParams);
                
                % Detect vehicles using the PointPillars network.
                [box, ~, ~] = generatePointPillarDetections(algObj.PretrainedNetwork,  ...
                    processedPointCloud, algObj.AnchorBoxes, algObj.GridParams, ...
                    {algObj.SelectedLabelName}, algObj.ConfidenceThreshold, ...
                    algObj.OverlapThreshold, algObj.P, algObj.N, algObj.ExecutionEnvironment);

                if ~isempty(box)
                    if i == 2
                        box(:,1) = -box(:,1);
                        box(:,2) = -box(:,2);
                        box(:,9) = -box(:,9);
                    end
                    bBoxes = [bBoxes;box];
                end
            end
            if ~isempty(bBoxes)
                % Add automated labels at bounding box locations detected
                % by the vehicle detector, of type Cuboid and with the name
                % of the selected label.
                autoLabels.Name     = algObj.SelectedLabelName;
                autoLabels.Type     = labelType.Cuboid;
                autoLabels.Position = bBoxes;
            else
                autoLabels = [];
            end
        end

terminate сделаны указатели на функцию любая очистка или отключение, требуемое после автоматизации. Этот алгоритм не требует никакой очистки, таким образом, функция пуста.

Используйте класс автоматизации детектора транспортного средства лидара в приложении

Свойства и методы, описанные в предыдущем разделе, реализованы в LidarVehicleDetector файл класса алгоритма автоматизации. Используйте класс в приложении.

Во-первых, создайте структуру папок +vision/+labeler требуемый под текущей папкой и копией класс автоматизации в него.

    mkdir('+vision/+labeler');
    copyfile(fullfile(matlabroot,'examples','lidar','main','LidarVehicleDetector.m'), ...
        '+vision/+labeler');

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

Загрузите последовательность облака точек на временное местоположение.

    lidarURL = 'https://www.mathworks.com/supportfiles/lidar/data/WPI_LidarData.tar.gz';
    lidarDataFolder = fullfile(tempdir,'WPI_LidarData',filesep);        
    lidarDataTarFile = lidarDataFolder + "WPI_LidarData.tar.gz";

    if ~exist(lidarDataFolder)
        mkdir(lidarDataFolder)
    end

    if ~exist(lidarDataTarFile, 'file')       
        disp('Downloading WPI Lidar driving data (760 MB)...');
        websave(lidarDataTarFile, lidarURL);
        untar(lidarDataTarFile, lidarDataFolder);
    end
    
    % Check if lidar tar.gz file is downloaded, but not uncompressed.
    if ~exist(fullfile(lidarDataFolder, 'WPI_LidarData.mat'), 'file')
        untar(lidarDataTarFile, lidarDataFolder);
    end

Поддержки приложений Lidar Labeler загрузка последовательностей облака точек, состоявших из PCD или файлов PLY. Сохраните загруженные данные об облаке точек к файлам PCD. Этот пример использует только подмножество данных об облаке точек WPI от систем координат 920 - 940.

    % Load downloaded lidar data into the workspace.
    load(fullfile(lidarDataFolder, 'WPI_LidarData.mat'),'lidarData');
    lidarData = reshape(lidarData, size(lidarData,2),1);
    
    % Create new folder and write lidar data to PCD files.
    pcdDataFolder = lidarDataFolder + "lidarData";
    if ~exist(pcdDataFolder, 'dir')
        mkdir(fullfile(lidarDataFolder,'lidarData'));
    end

    disp('Saving WPI Lidar driving data to PCD files ...');
    for i = 920:940
        filename = strcat(fullfile(lidarDataFolder,'lidarData',filesep), ...
            num2str(i,'%06.0f'),'.pcd');
        pcwrite(lidarData{i}, filename);
    end

Откройте приложение Lidar Labeler и загрузите последовательность облака точек.

    pointCloudDir = fullfile(lidarDataFolder, 'lidarData');
    lidarLabeler(pointCloudDir);

Во вкладке ROI Labels на левой панели нажмите Label. Задайте метку ROI с именем Vehicle и Cuboid. Опционально, можно выбрать цвет. Нажать ОК.

Под Выбирают Algorithm, выбирают список Refresh. Затем выберите Algorithm> Lidar Vehicle Detector. Если вы не видите эту опцию, проверяете, что текущая рабочая папка имеет папку под названием +vision/+labeler, с файлом с именем LidarVehicleDetector.m в нем.

Нажмите Automate. Приложение открывает сеанс автоматизации для выбранных сигналов и направления отображений для использования алгоритма.

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

Нажмите Run. Созданный алгоритм выполняется на каждой системе координат последовательности и обнаруживает транспортные средства при помощи Vehicle пометьте тип. После того, как приложение завершает запущенную автоматизацию, используйте ползунок или клавиши со стрелками, чтобы просмотреть последовательность путем прокрутки, чтобы определить местоположение системы координат, где алгоритм автоматизации пометил неправильно. Используйте изменение масштаба, панорамирование и 3-D опции вращения для просмотра и вращения облака точек. Вручную настройте результаты путем корректировки обнаруженных ограничительных рамок или добавления новых ограничительных рамок.

Когда вы удовлетворены обнаруженными ограничительными рамками транспортного средства для целой последовательности, нажимаете кнопку Принять. Можно затем продолжить вручную настраивать метки или экспортировать помеченную основную истину в рабочее пространство MATLAB.

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

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

helperCropFrontViewFromLidarData

function processedData = helperCropFrontViewFromLidarData(ptCloud, gridParams)
% Function to crop the front view of the point clouds
   % Set the limits for the point cloud.
   [row, column] = find(ptCloud.Location(:,:,1) < gridParams{1,2}{1} ...
       & ptCloud.Location(:,:,1) > gridParams{1,1}{1} ...
       & ptCloud.Location(:,:,2) < gridParams{1,2}{2} ...
       & ptCloud.Location(:,:,2) > gridParams{1,1}{2} ...
       & ptCloud.Location(:,:,3) < gridParams{1,2}{3} ...
       & ptCloud.Location(:,:,3) > gridParams{1,1}{3});
   ptCloud = select(ptCloud, row, column, 'OutputSize', 'full');
   finalPC = removeInvalidPoints(ptCloud);
   processedData = finalPC;           
end