Неорганизованное в организованное преобразование облаков точек с помощью сферической проекции

В этом примере показано, как преобразовать неорганизованные облака точек в организованный формат с помощью сферической проекции.

Введение

3-D облако точек лидара обычно представлено как набор Декартовых координат (x, y, z). Облако точек может также содержать дополнительную информацию, такую как интенсивность и значения RGB. В отличие от распределения пикселей изображения, распределение лидара облака точек обычно является разреженным и нерегулярным. Обработка таких разреженных данных неэффективна. Чтобы получить компактное представление, вы проектируете лидар облаков точек на сферу, чтобы создать плотное, основанное на сетке представление, известное как организованное представление [1]. Для получения дополнительной информации о различиях между организованными и неорганизованными облаками точек см. Обзор обработки лидара. Для извлечения наземной плоскости и методов детектора ключевых точек требуются организованные облака точек. Кроме того, необходимо преобразовать облако точек в организованный формат, если необходимо использовать большинство сетей сегментации глубокого обучения, включая SqueezeSegV1, SqueezeSegV2, RangeNet + [2] и SalsaNext [3]. Пример, показывающий, как использовать глубокое обучение с организованным облаком точек, см. в Lidar Point Cloud Семантической Сегментации Использование SqueezeSegV2 Нейронной сети для глубокого обучения примера.

Параметры датчика Лидара

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

  • Строение луча - 'uniform'или' gradient'. Задайте 'uniform', если интервалы между балками равны. Задайте 'gradient'если балки в горизонте плотно упакованы, а балки в направлении к верхней и нижней частям поля зрения датчика более разнесены.

  • Вертикальное разрешение - Количество каналов в вертикальном направлении, то есть количество лазеров. Типичными значениями являются 32 и 64.

  • Вертикальные углы балки - Угловое положение каждого вертикального канала. Вы должны задать этот параметр, когда строение балки 'gradient'.

  • Вертикальное поле зрения вверх - Поле зрения в вертикальном направлении над горизонтом (в степенях).

  • Нисходящее вертикальное поле зрения - Поле зрения в вертикальном направлении ниже горизонта (в степенях).

  • Разрешение по горизонтали - Количество каналов в горизонтальном направлении. Типичными значениями являются 512 и 1024.

  • Горизонтальное угловое разрешение - угловое разрешение между каждым каналом в горизонтальном направлении. Вы должны задать этот параметр, когда горизонтальное разрешение не упомянуто в таблице данных.

  • Горизонтальное поле зрения - Поле зрения, пройденное в горизонтальном направлении (в степенях). В большинстве случаев это значение составляет 360 степени.

Датчик

OS-1 вытеснения

Чтение облака точек с помощью pcread функция.

fileName = fullfile(matlabroot,'examples','deeplearning_shared','data','ousterLidarDrivingData.pcd');
ptCloud = pcread(fileName);

Проверьте размер облака точки выборки. Если координаты облака точек в форме, M-by-N-by-3, облако точек является организованным облаком точек.

disp(size(ptCloud.Location))
          64        1024           3

Преобразуйте облако точек в неорганизованный формат с помощью removeInvalidPoints функция. Координаты неорганизованного облака точек имеют вид M-by-3.

ptCloudUnOrg = removeInvalidPoints(ptCloud);
disp(size(ptCloudUnOrg.Location))
       65536           3

Данные облака точек были собраны с датчика Ouster OS1 Gen1. Задайте следующие параметры, которые задаются таблицей данных устройства [4].

vResolution = 64;       
hResolution = 1024;     
vFOVUp = 16.6;     
vFOVDown = -16.6;    
hFOV = 360;
beamConfig = 'Uniform';

Вычислите углы балки в горизонтальном и вертикальном направлениях.

if strcmp(beamConfig,'Uniform')
    vbeamAngles = linspace(vFOVUp,vFOVDown,vResolution);
end
hbeamAngles = linspace(0,hFOV,hResolution);

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

ptCloudOrg = convertUnorgToOrg(ptCloudUnOrg,vResolution,hResolution,vbeamAngles,hbeamAngles);

Отображение канала интенсивности исходных и восстановленных организованных облаков точек.

figure
montage({uint8(ptCloud.Intensity),uint8(ptCloudOrg.Intensity)});
title("Intensity Channel of Original Point Cloud(Top) vs. Reconstructed Organized Point Cloud(Bottom)")

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

display1 = helperShowUnorgAndOrgPair();
display1.plotLidarScan(ptCloudUnOrg,ptCloudOrg,3.5);

Датчик Велодина

Чтение облака точек с помощью pcread функция.

ptCloudUnOrg = pcread('HDL64LidarData.pcd');

Данные облака точек собираются с датчика HDL-64 Velodyne. Укажите следующие параметры, заданные таблицей данных устройства [5].

vResolution = 64;       
hResolution = 1024;     
vFOVUp = 2;     
vFOVDown = -24.9;    
hFOV = 360;
beamConfig = 'Uniform';

Вычислите углы балки в горизонтальном и вертикальном направлениях.

if strcmp(beamConfig,'Uniform')
    vbeamAngles = linspace(vFOVUp,vFOVDown,vResolution);
end
hbeamAngles = linspace(0,hFOV,hResolution);

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

ptCloudOrg = convertUnorgToOrg(ptCloudUnOrg,vResolution,hResolution,vbeamAngles,hbeamAngles);

Отображение канала интенсивности восстановленного организованного облака точек. Замените NaNs нулями и измените размер изображения для лучшей визуализации.

intensityChannel = ptCloudOrg.Intensity;
intensityChannel(isnan(intensityChannel)) = 0;
figure
intensityChannel = imresize(intensityChannel,'Scale',[3 1]);
imshow(intensityChannel);

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

display2 = helperShowUnorgAndOrgPair();
display2.plotLidarScan(ptCloudUnOrg,ptCloudOrg,2.5);

Датчик Пандара

Чтение облака точек с помощью pcread функция. Облако точек получено из [6].

ptCloudUnOrg = pcread('Pandar64LidarData.pcd');

Данные облака точек собираются с помощью датчика Pandar-64. Задайте следующие параметры, которые задаются таблицей данных устройства [7].

vResolution = 64;       
hAngResolution = 0.2;
hFOV = 360;
beamConfig = 'gradient';

Конфигурация луча 'gradient', что означает, что интервал между лучами неоднороден. Задайте значения угла балки вдоль вертикального направления, заданные таблицей данных.

vbeamAngles = [15.0000   11.0000    8.0000    5.0000    3.0000    2.0000    1.8333    1.6667    1.5000    1.3333    1.1667    1.0000    0.8333    0.6667 ...
                0.5000    0.3333    0.1667         0   -0.1667   -0.3333   -0.5000   -0.6667   -0.8333   -1.0000   -1.1667   -1.3333   -1.5000   -1.6667 ...
               -1.8333   -2.0000   -2.1667   -2.3333   -2.5000   -2.6667   -2.8333   -3.0000   -3.1667   -3.3333   -3.5000   -3.6667   -3.8333   -4.0000 ...
               -4.1667   -4.3333   -4.5000   -4.6667   -4.8333   -5.0000   -5.1667   -5.3333   -5.5000   -5.6667   -5.8333   -6.0000   -7.0000   -8.0000 ...
               -9.0000  -10.0000  -11.0000  -12.0000  -13.0000  -14.0000  -19.0000  -25.0000];

Вычислите углы горизонтальной балки.

hResolution = round(360/hAngResolution);
hbeamAngles = linspace(0,hFOV,hResolution);

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

ptCloudOrg = convertUnorgToOrg(ptCloudUnOrg,vResolution,hResolution,vbeamAngles,hbeamAngles);

Отображение канала интенсивности восстановленного организованного облака точек. Замените NaNs нулями и измените размер изображения. Использование histeq для улучшения визуализации.

intensityChannel = ptCloudOrg.Intensity;
intensityChannel(isnan(intensityChannel)) = 0;
figure
intensityChannel = imresize(intensityChannel,'Scale',[3 1]);
histeq(intensityChannel./max(intensityChannel(:)));

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

display3 = helperShowUnorgAndOrgPair();
display3.plotLidarScan(ptCloudUnOrg,ptCloudOrg,4);

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

Используйте convertUnorgToOrg функция для поиска пиксельных координат проекционного изображения для всех (x, y, z) точек. Функция следует этим шагам.

  1. Вычислите угол тангажа и углы рыскания для каждой точки облака точек.

  2. Вычислите индексы строк и столбцов для каждой точки на основе углов балки, тангажа и рыскания.

  3. Создайте организованное облако точек на основе индексов строка и столбец.

function ptCloudOrganized = convertUnorgToOrg(ptCloud,vResolution,hResolution,vbeamAngles,hbeamAngles)

    locations = ptCloud.Location;
    
    if ~isempty(ptCloud.Intensity)
        intensity = ptCloud.Intensity;
    else
        intensity = zeros(size(ptCloud.Location,1),1);
    end  
    
    % Calculate the radial distance for every point.
    r = sqrt(locations(:,1).^2 + locations(:,2).^2);
    r(r==0) = 1e-6;
    
    % Calculate the pitch and yaw angles for each point in the point cloud.
    pitch = atan2d(locations(:,3),r);
    yaw = atan2d(locations(:,2),locations(:,1));
    
    % Shift the range of the yaw angle from [-pi,pi] to [0,2*pi]. 
    yaw = 180-yaw;    
    
    % Calculate the row indices for all points based on the bin in which the pitch angle for each point falls into.
    [~,~,rowIdx] = histcounts(pitch,flip(vbeamAngles));
    rowIdx(rowIdx == 0) = NaN;
    rowIdx = vResolution - rowIdx;
    
    % Calculate the column indices for all points based on the bin in which the yaw angle for each point falls into.
    [~,~,colIdx] = histcounts(yaw,hbeamAngles);
    colIdx(colIdx == 0) = NaN;
    
    % Create a pseudo image and fill in the values with the corresponding location and intensity values.
    pseduoImage = NaN(vResolution,hResolution,4);
    for i = 1:size(locations,1)
        if ~isnan(rowIdx(i,1)) && ~isnan(colIdx(i,1))
            pseduoImage(rowIdx(i,1),colIdx(i,1),1) = locations(i,1);
            pseduoImage(rowIdx(i,1),colIdx(i,1),2) = locations(i,2);
            pseduoImage(rowIdx(i,1),colIdx(i,1),3) = locations(i,3);
            pseduoImage(rowIdx(i,1),colIdx(i,1),4) = intensity(i,1);
        end
    end
    
    % Create a point cloud object from the locations and intensity.
    if ~isempty(ptCloud.Intensity)
        ptCloudOrganized = pointCloud(pseduoImage(:,:,1:3), 'Intensity', pseduoImage(:,:,4));
    else
        ptCloudOrganized = pointCloud(pseduoImage(:,:,1:3));
    end
end

Ссылки

[1] Wu, Bichen, Alvin Wan, Xiangyu Yue, and Kurt Keutzer. SqueezeSeg: сверточные нейронные сети с повторяющейся CRF для сегментации дорожного объекта в реальном времени из облака точек 3D LiDAR ". В 2018 году IEEE International Conference on Robotics and Automation (ICRA), 1887-93. Брисбен, QLD: IEEE, 2018. https://doi.org/10.1109/ICRA.2018.8462926.

[2] Милиото, Андрес, Игнасио Виццо, Йенс Бехли и Сайрилл Стахнисс. RangeNet++: быстрая и точная семантическая сегментация лИДАР. В 2019 году IEEE/RSJ International Conference on Intelligent Robots and Systems (IROS), 4213-20. Макао, Китай: IEEE, 2019. https://doi.org/10.1109/IROS40897.2019.8967762.

[3] Кортинхал, Тиаго, Джордж Целепис и Эрен Эрдал Аксой. SalsaNext: быстрая семантическая сегментация облаков точек лИДАР для автономного управления автомобилем с учетом неопределенности. ArXiv:2003.03653 [Cs], 9 июля 2020 года. https://arxiv.org/abs/2003.03653.

[4] Ким, Джейден. «UCS - Ouster LiDAR». Доступ к 22 декабря 2020 года. https://data.ouster.io/downloads/datasheets/datasheet-gen1-v1p13-os1.pdf.

[5] Велодин Лидар. HDL-64E Durable Surround Lidar Sensor (неопр.) (недоступная ссылка). Доступ к 22 декабря 2020 года. https://velodynelidar.com/products/hdl-64e/.

[6] «PandaSet Open Datasets - шкала». Доступ к 22 декабря 2020 года. https://scale.com/open-datasets/pandaset.

[7] «Pandar64 руководство пользователя». Доступ к 22 декабря 2020 года. https://hesaiweb2019.blob.core.chinacloudapi.cn/uploads/Pandar64_User's_Manual.pdf.