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

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

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

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

В этом примере вы:

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

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

Обнаружение транспортных средств с помощью сети PointPillars

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

Загрузите сеть 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.

  • Задайте анкерные рамки, которые являются предопределенными ограничивающими рамками в формате {length, width, height, z-center, yaw angle}.

  • Задайте параметры сетки, чтобы обрезать полное облако точек до переднего вида в формате {{x Min, y Min, z Min}, {x Max, y Max, z Max}, {x Step, y Step, ds Factor}, {Xn, Yn} где Xn = round (((x max Max))

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

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

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

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

  • Задайте executionEnvironment.

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

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

  • Отображение облака точек с ограничивающими рамками.

% 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")

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

Создайте класс автоматизации для алгоритма детектора транспортного средства лидара. Класс наследует от vision.labeler.AutomationAlgorithm абстрактный базовый класс. Базовый класс определяет свойства и сигнатуры для методов, которые приложение использует для настройки и запуска пользовательского алгоритма. Приложение Lidar Labeler предоставляет начальный шаблон класса автоматизации. Для получения дополнительной информации смотрите Создать Алгоритм Автоматизации для Маркировки. The 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

Пользовательские свойства

Шаг 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 посвящен определениям функций.

The 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

The 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

The checkSetup функция проверяет, выбрано ли определение метки информация только для чтения для автоматизации.

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

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

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

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

Шаг 4 задает функции выполнения. The 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

The run функция задает основной алгоритм детектора транспортного средства лидара этого класса автоматизации. The 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

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

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

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

Сначала создайте структуру папки +vision/+labeler требуется в текущей папке и скопировать в нее класс автоматизации.

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

Загрузите последовательность облака точек (PCD) и последовательности изображений. В целях рисунка этот пример использует данные лидара WPI, собранные на шоссе с датчика Ouster OS1 lidar. Выполните следующий блок кода, чтобы загрузить и сохранить данные лидара во временной папке. В зависимости от вашего подключения к Интернету процесс загрузки может занять некоторое время. Код приостанавливает выполнение 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);

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

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

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

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

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

Когда вы удовлетворены обнаруженными транспортным средством ограничивающими рамками для всей последовательности, нажатия кнопки Accept. Затем можно продолжить ручную настройку меток или экспорт маркированных основных истин в Рабочее пространство 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