Лидар и калибровка фотоаппарата

Этот пример показывает вам, как оценить твердое преобразование между 3-D лидаром и камерой. В конце этого примера вы сможете использовать твердую матрицу преобразования, чтобы объединить данные о лидаре и камере.

Эта схема объясняет рабочий процесс для лидара и калибровки фотоаппарата (LCC) процесс.

Обзор

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

Матрица преобразования в форме ориентации и относительных положений между этими двумя датчиками является предшественником объединения данных от этих двух датчиков. Калибровка фотоаппарата лидара помогает в оценке матрицы преобразования между 3-D лидаром и камерой, смонтированной на автономном транспортном средстве. В этом примере вы будете использовать данные из двух различных датчиков лидара, HDL64 и VLP16. HDL64 данные собраны средой Gazebo как показано в этом рисунке.

Данные собраны в форме набора изображений PNG и соответствующих облаков точек PCD. Этот пример принимает, что внутренние параметры камеры известны. Для получения дополнительной информации об извлечении внутренних параметров камеры смотрите Одну Калибровку фотоаппарата.

Загрузка данных

Загрузите данные о датчике Velodyne HDL-64 из Gazebo.

imagePath = fullfile(toolboxdir('lidar'), 'lidardata', 'lcc', 'HDL64', 'images');
ptCloudPath = fullfile(toolboxdir('lidar'), 'lidardata', 'lcc', 'HDL64', 'pointCloud');
cameraParamsPath = fullfile(imagePath, 'calibration.mat');

intrinsic = load(cameraParamsPath); % Load camera intrinsics
imds = imageDatastore(imagePath); % Load images using imageDatastore
pcds = fileDatastore(ptCloudPath, 'ReadFcn', @pcread); % Load point cloud files

imageFileNames = imds.Files;
ptCloudFileNames = pcds.Files;

squareSize = 200; % Square size of the checkerboard

% Set random seed to generate reproducible results.
rng('default'); 

Угловое обнаружение шахматной доски

Этот пример использует шаблон шахматной доски в качестве функции сравнения. Ребра шахматной доски оцениваются с помощью датчиков лидара и камеры. Используйте estimateCheckerboardCorners3d вычислить координаты углов шахматной доски и размер фактической шахматной доски в мм. Углы оцениваются в 3-D относительно системы координат камеры. Для получения дополнительной информации о системах координат камеры, seeCoordinate Системы в Lidar Toolbox

[imageCorners3d, checkerboardDimension, dataUsed] = ...
    estimateCheckerboardCorners3d(imageFileNames, intrinsic.cameraParams, squareSize);
imageFileNames = imageFileNames(dataUsed); % Remove image files that are not used

Результаты могут визуализироваться с помощью функции помощника helperShowImageCorners.

% Display Checkerboard corners
helperShowImageCorners(imageCorners3d, imageFileNames, intrinsic.cameraParams);

Figure contains an axes and an object of type uipanel. The axes contains 9 objects of type image, line.

Обнаружение шахматной доски в лидаре

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

% Extract ROI from the detected image corners
roi = helperComputeROI(imageCorners3d, 5);

% Filter point cloud files corresponding to the detected images
ptCloudFileNames = ptCloudFileNames(dataUsed);
[lidarCheckerboardPlanes, framesUsed, indices] = ...
    detectRectangularPlanePoints(ptCloudFileNames, checkerboardDimension, 'ROI', roi);

% Remove ptCloud files that are not used
ptCloudFileNames = ptCloudFileNames(framesUsed);
% Remove image files 
imageFileNames = imageFileNames(framesUsed);
% Remove 3D corners from images
imageCorners3d = imageCorners3d(:, :, framesUsed);

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

helperShowCheckerboardPlanes(ptCloudFileNames, indices);

Figure contains an axes and an object of type uipanel. The axes contains an object of type scatter.

Калибровка лидара и камеры

Используйте estimateLidarCameraTransform to оцените твердую матрицу преобразования между лидаром и камерой.

[tform, errors] = estimateLidarCameraTransform(lidarCheckerboardPlanes, ...
    imageCorners3d, 'CameraIntrinsic', intrinsic.cameraParams);

После того, как калибровка завершается, можно использовать калибровочную матрицу двумя способами:

  • Облако точек Лидара проекта на изображении.

  • Улучшите облако точек Лидара с помощью цветной информации от изображения.

Используйте helperFuseLidarCamera function визуализировать лидар и данные изображения, сплавленные вместе.

helperFuseLidarCamera(imageFileNames, ptCloudFileNames, indices, ...
    intrinsic.cameraParams, tform);

Figure contains 2 axes and other objects of type uipanel. Axes 1 contains an object of type scatter. Axes 2 contains 2 objects of type image, line.

Ошибочная визуализация

Три типа ошибок заданы, чтобы оценить точность калибровки:

  • Ошибка перевода: Среднее значение различия между центроидом углов шахматной доски в лидаре и спроектированными углами в 3-D от изображения.

  • Ошибка вращения: Среднее значение различия между нормалями шахматной доски в облаке точек и спроектированных углов в 3-D от изображения.

  • Ошибка перепроекции: Среднее значение различия между центроидом углов изображений и спроектированными углами лидара на изображении.

Постройте предполагаемые ошибочные значения при помощи helperShowError.

helperShowError(errors)

Figure Error Plots contains 3 axes and other objects of type uipanel. Axes 1 contains 2 objects of type bar, line. This object represents Overall Mean Translation Error:0.0033408 in m. Axes 2 contains 2 objects of type bar, line. This object represents Overall Mean Rotation Error:0.7986 in deg. Axes 3 contains 2 objects of type bar, line. This object represents Overall Mean Reprojection Error:0.99477 in pixel.

Результаты

После калибровочной проверки на данные с высокими калибровочными ошибками и повторно выполненный калибровка.

outlierIdx = errors.RotationError < mean(errors.RotationError);
[newTform, newErrors] = estimateLidarCameraTransform(lidarCheckerboardPlanes(outlierIdx), ...
        imageCorners3d(:, :, outlierIdx), 'CameraIntrinsic', intrinsic.cameraParams);
    helperShowError(newErrors);

Figure Error Plots contains 3 axes and other objects of type uipanel. Axes 1 contains 2 objects of type bar, line. This object represents Overall Mean Translation Error:0.0036375 in m. Axes 2 contains 2 objects of type bar, line. This object represents Overall Mean Rotation Error:0.39698 in deg. Axes 3 contains 2 objects of type bar, line. This object represents Overall Mean Reprojection Error:1.1785 in pixel.

Тестирование на действительных данных

Протестируйте рабочий процесс LCC на фактических данных о Лидаре VLP-16, чтобы оценить его эффективность.

clear;
imagePath = fullfile(toolboxdir('lidar'), 'lidardata', 'lcc', 'vlp16', 'images');
ptCloudPath = fullfile(toolboxdir('lidar'), 'lidardata', 'lcc', 'vlp16', 'pointCloud');
cameraParamsPath = fullfile(imagePath, 'calibration.mat');

intrinsic = load(cameraParamsPath); % Load camera intrinscs
imds = imageDatastore(imagePath); % Load images using imageDatastore
pcds = fileDatastore(ptCloudPath, 'ReadFcn', @pcread); % Loadr point cloud files

imageFileNames = imds.Files;
ptCloudFileNames = pcds.Files;

squareSize = 81; % Square size of the checkerboard

% Set random seed to generate reproducible results.
rng('default');

% Extract Checkerboard corners from the images
[imageCorners3d, checkerboardDimension, dataUsed] = ...
    estimateCheckerboardCorners3d(imageFileNames, intrinsic.cameraParams, squareSize);

imageFileNames = imageFileNames(dataUsed); % Remove image files that are not used

% Filter point cloud files corresponding to the detected images
ptCloudFileNames = ptCloudFileNames(dataUsed);

% Extract ROI from the detected image corners
roi = helperComputeROI(imageCorners3d, 5);

%Extract Checkerboard in lidar data
[lidarCheckerboardPlanes, framesUsed, indices] = detectRectangularPlanePoints(...
    ptCloudFileNames, checkerboardDimension, 'RemoveGround', true, 'ROI', roi);
imageCorners3d = imageCorners3d(:, :, framesUsed);
% Remove ptCloud files that are not used
ptCloudFileNames = ptCloudFileNames(framesUsed);
% Remove image files 
imageFileNames = imageFileNames(framesUsed);
[tform, errors] = estimateLidarCameraTransform(lidarCheckerboardPlanes, ...
    imageCorners3d, 'CameraIntrinsic', intrinsic.cameraParams);
helperFuseLidarCamera(imageFileNames, ptCloudFileNames, indices,...
    intrinsic.cameraParams, tform);

Figure contains 2 axes and other objects of type uipanel. Axes 1 contains an object of type scatter. Axes 2 contains 2 objects of type image, line.

% Plot the estimated error values
helperShowError(errors);

Figure Error Plots contains 3 axes and other objects of type uipanel. Axes 1 contains 2 objects of type bar, line. This object represents Overall Mean Translation Error:0.010932 in m. Axes 2 contains 2 objects of type bar, line. This object represents Overall Mean Rotation Error:1.7377 in deg. Axes 3 contains 2 objects of type bar, line. This object represents Overall Mean Reprojection Error:4.1914 in pixel.

Сводные данные

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

Ссылки

[1] Липу Чжоу и Зимо Ли и Майкл Кэесс, "Автоматическая Внешняя Калибровка Камеры и 3D Линии использования LiDAR и Плоских Соответствий", "IEEE/RSJ Intl. Конференция по Интеллектуальным Роботам и Системам, IROS", октябрь 2018.

[2] К. С. Арун, Т. С. Хуан и С. Д. Блоштайн, “Подбор кривой Наименьших квадратов двух 3-D наборов точки”, Транзакции IEEE согласно Анализу Шаблона и Искусственному интеллекту, изданию PAMI-9, № 5, стр 698–700, сентябрь 1987.