Этот пример показывает вам, как оценить твердое преобразование между 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);
Точно так же используйте 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);
Чтобы визуализировать обнаруженную шахматную доску, используйте helperShowLidarCorners
функция.
helperShowLidarCorners(ptCloudFileNames, indices);
Используйте estimateLidarCameraTransform to
оцените твердую матрицу преобразования между лидаром и камерой.
[tform, errors] = estimateLidarCameraTransform(lidarCheckerboardPlanes, ... imageCorners3d, 'CameraIntrinsic', intrinsic.cameraParams);
После того, как калибровка завершается, можно использовать калибровочную матрицу двумя способами:
Облако точек Лидара проекта на изображении.
Улучшите облако точек Лидара с помощью цветной информации от изображения.
Используйте helperFuseLidarCamera
function
визуализировать лидар и данные изображения, сплавленные вместе.
helperFuseLidarCamera(imageFileNames, ptCloudFileNames, indices, ...
intrinsic.cameraParams, tform);
Три типа ошибок заданы, чтобы оценить точность калибровки:
Ошибка перевода: Среднее значение различия между центроидом углов шахматной доски в лидаре и спроектированными углами в 3-D от изображения.
Ошибка вращения: Среднее значение различия между нормалями шахматной доски в облаке точек и спроектированных углов в 3-D от изображения.
Ошибка перепроекции: Среднее значение различия между центроидом углов изображений и спроектированными углами лидара на изображении.
Постройте предполагаемые ошибочные значения при помощи helperShowError.
helperShowError(errors)
После калибровочной проверки на данные с высокими калибровочными ошибками и повторно выполненный калибровка.
outlierIdx = errors.RotationError < mean(errors.RotationError); [newTform, newErrors] = estimateLidarCameraTransform(lidarCheckerboardPlanes(outlierIdx), ... imageCorners3d(:, :, outlierIdx), 'CameraIntrinsic', intrinsic.cameraParams); helperShowError(newErrors);
Протестируйте рабочий процесс 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);
% Plot the estimated error values
helperShowError(errors);
Этот пример дает обзор того, как начать с рабочим процессом калибровки фотоаппарата лидара, извлекать твердое преобразование между этими двумя датчиками. Этот пример также показывает вам, как использовать твердую матрицу преобразования, чтобы объединить данные о лидаре и камере.
[1] Липу Чжоу и Зимо Ли и Майкл Кэесс, "Автоматическая Внешняя Калибровка Камеры и 3D Линии использования LiDAR и Плоских Соответствий", "IEEE/RSJ Intl. Конференция по Интеллектуальным Роботам и Системам, IROS", октябрь 2018.
[2] К. С. Арун, Т. С. Хуан и С. Д. Блоштайн, “Подбор кривой Наименьших квадратов двух 3-D наборов точки”, Транзакции IEEE согласно Анализу Шаблона и Искусственному интеллекту, изданию PAMI-9, № 5, стр 698–700, сентябрь 1987.