В этом примере показано, как оценить твердое преобразование между 3-D лидаром и камерой. В конце этого примера вы сможете использовать твердую матрицу преобразования, чтобы сплавить данные лидара и камеры.
Эта схема объясняет рабочий процесс для процесса лидара и калибровки камеры (LCC).
Лидары и камеры являются наиболее распространенными датчиками зрения в автономных ведущих приложениях. Камеры обеспечивают богатую цветовую информацию и другие функции, которые могут использоваться для извлечения различных характеристик обнаруженных объектов. Датчики Лидара, с другой стороны, обеспечивают точное 3-D расположение и структуру объектов. Чтобы улучшить трубопровод обнаружения и классификации объектов, данные с этих двух датчиков могут быть объединены вместе, чтобы получить более подробную и точную информацию об объектах.
Матрица преобразования в виде ориентации и относительных положений между двумя датчиками является предшественником сплавления данных с этих двух датчиков. Калибровка камеры Lidar помогает в оценке матрицы преобразования между 3-D лидаром и камерой, установленной на автономном транспортном средстве. В этом примере вы будете использовать данные из двух разных датчиков лидара, HDL64
и VLP16
. HDL64
данные собираются из окружения Gazebo, как показано на этом рисунке.
Данные получаются в виде набора изображений PNG и соответствующих облаков точек PCD. Этот пример принимает, что внутренние параметры камеры известны. Дополнительные сведения о извлечении внутренних параметров камеры см. в разделе Калибровка одиночной камеры.
Загрузите данные датчика HDL-64 Velodyne от 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 относительно системы координат камеры. Для получения дополнительной информации о системах координат камеры см. «Системы координат» в Lidar Toolbox
[imageCorners3d, checkerboardDimension, dataUsed] = ... estimateCheckerboardCorners3d(imageFileNames, intrinsic.cameraParams, squareSize); imageFileNames = imageFileNames(dataUsed); % Remove image files that are not used
Результаты могут быть визуализированы с помощью функции helper 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);
Чтобы визуализировать обнаруженную шахматную доску, используйте helperShowCheckerboardPlanes
функция.
helperShowCheckerboardPlanes(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 Lidar, чтобы оценить его эффективность.
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] Lipu Zhou and Zimo Li and Michael Kaess, "Automatic Extrinsic Calibration of a Camera and a 3D LiDAR using Line and Plane Consubsences", "IEEE/RSJ Intl. Conf. on Intelligent Robots and Systems, IROS ", окт. 2018.
[2] К. С. Арун, Т. С. Хуан и С. Д. Blostein, «методом наименьших квадратов подбора кривой из двух наборов 3-D точки», IEEE Transactions on Шаблона Analysis and Machine Intelligence, vol. PAMI-9, no. 5, pp. 698-700, Sept 1987.