exponenta event banner

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

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

Введение

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

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

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

  • Конфигурация балки - '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);

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

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');

Данные облака точек собираются с датчика Velodine HDL-64. Укажите следующие параметры, указанные в техническом описании устройства [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);

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

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);

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

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] У, Бичэнь, Элвин Вань, Сянъю Юэ и Курт Кеутцер. «SqueezeSeg: сверточные нейронные сети с текущим CRF для сегментации Дорожного Объекта в реальном времени от 3D облака пункта LiDAR». В 2018 году Международная конференция IEEE по робототехнике и автоматизации (ICRA), 1887-93. Брисбен, QLD: IEEE, 2018. https://doi.org/10.1109/ICRA.2018.8462926.

[2] Милиото, Андрес, Игнасио Виццо, Йенс Бехли и Сирил Стахнисс. «RureNet++: быстрая и точная семантическая сегментация LiDAR». В 2019 году IEEE/RSJ Международная конференция по интеллектуальным роботам и системам (IROS), 4213-20. Макао, Китай: IEEE, 2019. https://doi.org/10.1109/IROS40897.2019.8967762.

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

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

[5] Велодин Лидар. «HDL-64E Прочный объемный датчик Лидара». Доступно 22 декабря 2020 года. https://velodynelidar.com/products/hdl-64e/.

[6] «Набор открытых наборов данных PandaSet - масштаб». Доступно 22 декабря 2020 года. https://scale.com/open-datasets/pandaset.

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