В этом примере показано, как преобразовать неорганизованные облака точек в организованный формат с помощью сферической проекции.
3-D облако точек лидара обычно представляется в виде набора Декартовых координат (x, y, z). Облако точек может также содержать дополнительную информацию, такую как интенсивность и значения RGB. В отличие от распределения пикселей изображения, распределение облака точек лидара обычно разреженно и неправильно. Обработка таких разреженных данных неэффективна. Чтобы получить компактное представление, вы проектируете облака точек лидара на сферу, чтобы создать плотное, основанное на сетке представление, известное как организованное представление [1]. Чтобы узнать больше о различиях между организованными и неорганизованными облаками точек, смотрите, что Лидар Обрабатывает Обзор. Оснуйте плоскую экстракцию, и методы детектора ключевого пункта требуют организованных облаков точек. Кроме того, необходимо преобразовать облако точек в организованный формат, если вы хотите использовать большинство сетей сегментации глубокого обучения, включая SqueezeSegV1, SqueezeSegV2, RangeNet ++ [2], и SalsaNext [3]. Для примера, показывающего, как использовать глубокое обучение для организованного облака точек, смотрите, что Семантическая Сегментация Облака точек Лидара Использует пример Нейронной сети для глубокого обучения SqueezeSegV2.
Чтобы преобразовать неорганизованное облако точек в организованный формат с помощью сферической проекции, необходимо указать, что параметры датчика лидара раньше создавали облако точек. Определите который параметры задать путем обращения к таблице данных для датчика. Можно задать следующие параметры.
Излучите настройку — 'uniform
'или 'gradient
'. Задайте 'uniform
'если лучи имеют равный интервал. Задайте 'gradient
'если лучи на горизонте плотно упаковываются, и те к верху и низу поля зрения датчика более растянуты.
Вертикальное разрешение — Количество каналов в вертикальном направлении, то есть, количество лазеров. Типичные значения равняются 32, и 64.
Вертикальные углы луча — Угловое положение каждого вертикального канала. Необходимо задать этот параметр, когда настройкой луча является 'gradient
'.
Вверх вертикальное поле зрения — Поле зрения в вертикальном направлении выше горизонта (в градусах).
Вниз вертикальное поле зрения — Поле зрения в вертикальном направлении ниже горизонта (в градусах).
Горизонтальное разрешение — Количество каналов в горизонтальном направлении. Типичные значения 512, и 1024.
Горизонтальное угловое разрешение — угловое разрешение между каждым каналом вдоль горизонтального направления. Необходимо задать этот параметр, когда горизонтальное разрешение не упоминается в таблице данных.
Горизонтальное поле зрения — Поле зрения, покрытое горизонтальным направлением (в градусах). В большинстве случаев это значение является 360 градусами.
Считайте облако точек с помощью pcread
функция.
fileName = fullfile(matlabroot,'examples','deeplearning_shared','data','ousterLidarDrivingData.pcd'); ptCloud = pcread(fileName);
Проверяйте размер облака точки выборки. Если координаты облака точек находятся в форме, M N 3, облако точек является организованным облаком точек.
disp(size(ptCloud.Location))
64 1024 3
Преобразуйте облако точек в неорганизованный формат с помощью removeInvalidPoints
функция. Координаты неорганизованного облака точек находятся в форме M-3.
ptCloudUnOrg = removeInvalidPoints(ptCloud); disp(size(ptCloudUnOrg.Location))
65536 3
Данные об облаке точек были собраны от датчика 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 функции помощника, заданной в конце примера.
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');
Данные об облаке точек собраны от датчика Velodyne 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);
Преобразуйте неорганизованное облако точек в организованный формат с помощью convertUnorgToOrg функции помощника, заданной в конце примера.
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 функции помощника, заданной в конце примера.
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) точками. Функция выполняет эти шаги.
Вычислите тангаж и углы рыскания для каждой точки облака точек.
Вычислите индексы строки и столбца для каждой точки на основе луча, тангажа и углов рыскания.
Создайте организованное облако точек на основе индексов строки и столбца.
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] Ву, Bichen, Элвин Вань, Сянюй Юэ и Курт Койцер. "SqueezeSeg: Сверточные Нейронные Сети с Текущим CRF для Дорожно-объектной Сегментации В реальном времени от 3D Облака точек LiDAR". На 2 018 Международных конференциях IEEE по вопросам Робототехники и Автоматизации (ICRA), 1887-93. Брисбен, QLD: IEEE, 2018. https://doi.org/10.1109/ICRA.2018.8462926.
[2] Milioto, Андрес, Игнасио Виссо, Йенс Белей и Кирилль Штахнисс. "RangeNet ++: Быстрая и Точная Семантическая Сегментация LiDAR". На 2019 Международных конференциях IEEE/RSJ по вопросам Интеллектуальных Роботов и Систем (IROS), 4213-20. Макао, Китай: IEEE, 2019. https://doi.org/10.1109/IROS40897.2019.8967762.
[3] Cortinhal, Тьягу, Джордж Целепис и Эрен Эрдэл Аксой. "SalsaNext: Быстрая, Осведомленная о неопределенности Семантическая Сегментация Облаков точек LiDAR для Автономного управления автомобилем". ArXiv:2003.03653 [Cs], 9 июля 2020. https://arxiv.org/abs/2003.03653.
[4] Ким, Джейден. "UCS - Изгнание LiDAR". Полученный доступ 22 декабря 2020. https://ucssolution.com/OS1-Mid-range-lidar-sensor.
[5] Лидар Velodyne. "Длительный 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.