Создайте 360 ° Изображение птичьего глаза вокруг транспортного средства

В этом примере показано, как создать изображение вида птицы на 360 ° вокруг транспортного средства для использования в системе мониторинга вида вокруг.

Обзор

Мониторинг объемного обзора является важной функцией безопасности, предоставляемой передовыми системами помощи водителю (ADAS). Эти системы мониторинга уменьшают слепые зоны и помогают драйверам понять относительное положение своего транспортного средства относительно окружающей среды, делая плотные маневры парковки более легкими и безопасными. Типичная система контроля кругового обзора состоит из четырёх fisheye-камер» с полем зрения 180 °, установленных на четырех сторонах транспортного средства. На дисплее в автомобиле показан вид автомобиля спереди, слева, справа, сзади и птичьего полета. В то время как четыре вида с четырех камер являются тривиальными для отображения, создание вида птичьего полета окружающей среды транспортного средства требует внутренней и внешней калибровки камеры и сшивания изображения, чтобы объединить несколько поля зрения камеры.

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

Калибровка многокамерной системы

Во-первых, калибруйте многокамерную систему путем оценки внутренних и внешних параметров камеры путем построения monoCamera объект для каждой камеры в многокамерной системе. В целях рисунка этот пример использует изображения, сделанные с восьми направлений одной камерой с 78˚ полем зрения, покрывающим 360˚ вокруг транспортного средства. Настройка имитирует многокамерную систему, установленную на крыше транспортного средства.

Оценка внутренностей монокулярной камеры

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

В этом примере камера была калибрована с помощью шахматного калибровочного шаблона в приложении Single Camera Calibrator, и параметры камеры были экспортированы в cameraParams.mat. Загрузите эти предполагаемые внутренние параметры камеры.

ld = load("cameraParams.mat");

Поскольку этот пример имитирует восемь камер, скопируйте загруженные признаки восемь раз. Если вы используете восемь различных камер, калибруйте каждую камеру отдельно и сохраните их собственные параметры в массиве ячеек с именем intrinsics.

numCameras = 8;
intrinsics = cell(numCameras, 1);

intrinsics(:) = {ld.cameraParams.Intrinsics};

Оценка монокулярной внешности камеры

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

Поместите калибровочный шаблон в горизонтальную ориентацию параллельно земле и на соответствующую высоту так, чтобы все угловые точки массива были видны. Измерьте высоту после размещения калибровочного шаблона и размера квадрата в шахматной доске. В этом примере шаблон был размещен горизонтально на высоте 62,5 см, чтобы сделать шаблон видимым для камеры. Размер квадрата в шахматном порядке составлял 29 мм.

% Measurements in meters
patternOriginHeight = 0.625;
squareSize = 29e-3;

Следующий рисунок иллюстрирует правильную ориентацию калибровочного шаблона для камер вдоль четырех основных направлений относительно осей транспортного средства. Однако для генерации вида птичьего полета в этом примере используются четыре дополнительные камеры, ориентированные вдоль направлений, которые отличаются от основных направлений. Чтобы оценить внешнюю составляющую для этих камер, выберите и присвойте предпочтительную ориентацию среди четырех основных направлений. Для примера, если вы снимаете с фронтальной камеры, выровняйте оси X - и Y шаблона как показано на следующем рисунке.

Переменная patternPositions сохраняет предпочтительные варианты ориентации для всех восьми камер. Эти варианты определяют относительную ориентацию между осями шаблона и осями транспортного средства для estimateMonoCameraParameters функция. Отобразите изображения, расположенные по положениям их камеры относительно транспортного средства.

patternPositions = ["front", "left" , "left" , "back" ,...
                    "back" , "right", "right", "front"];
extrinsicsCalibrationImages = cell(1, numCameras);
for i = 1:numCameras
    filename = "extrinsicsCalibrationImage" +  string(i) + ".jpg";
    extrinsicsCalibrationImages{i} = imread(filename);
end
helperVisualizeScene(extrinsicsCalibrationImages, patternPositions)

Figure contains 9 axes. Axes 1 with title front contains an object of type image. Axes 2 with title left contains an object of type image. Axes 3 with title left contains an object of type image. Axes 4 with title back contains an object of type image. Axes 5 with title back contains an object of type image. Axes 6 with title right contains an object of type image. Axes 7 with title right contains an object of type image. Axes 8 with title front contains an object of type image. Axes 9 with title Ego Vehicle contains an object of type image.

Чтобы оценить внешние параметры одной монокулярной камеры, выполните следующие шаги:

  1. Удалите искажения в изображении.

  2. Обнаружение углов шахматного квадрата на изображении.

  3. Сгенерируйте мировые точки шахматной доски.

  4. Использование estimateMonoCameraParameters функция для оценки внешних параметров.

  5. Используйте внешние параметры, чтобы создать monoCamera объект, принимая, что расположение датчика в источник системы транспортного средства.

В этом примере в настройке используется одна камера, которая была повернута вручную вокруг подставки камеры. Хотя фокальный центр камеры перемещался во время этого движения, для простоты, этот пример принимает, что датчик остался в том же месте (в источник). Однако расстояния между камерами на реальном транспортном средстве могут быть измерены и введены в свойство местоположения датчика monoCamera.

monoCams = cell(1, numCameras);
for i = 1:numCameras
    % Undistort the image.
    undistortedImage = undistortImage(extrinsicsCalibrationImages{i}, intrinsics{i});
    
    % Detect checkerboard points.
    [imagePoints, boardSize] = detectCheckerboardPoints(undistortedImage,...
                                                        "PartialDetections", false);
    
    % Generate world points of the checkerboard.
    worldPoints = generateCheckerboardPoints(boardSize, squareSize);
    
    % Estimate extrinsic parameters of the monocular camera.
    [pitch, yaw, roll, height] = estimateMonoCameraParameters(intrinsics{i}, ...
                                     imagePoints, worldPoints, patternOriginHeight,...
                                     "PatternPosition", patternPositions(i));
    
    % Create a monoCamera object, assuming the camera is at origin.
    monoCams{i} = monoCamera(intrinsics{i}, height, ...
                             "Pitch", pitch, ...
                             "Yaw"  , yaw, ...
                             "Roll" , roll, ...
                             "SensorLocation", [0, 0]);
end

Создайте 360 ° Изображение вида птичьего глаза

Используйте monoCamera объекты, сконфигурированные с помощью предполагаемых параметров камеры, чтобы генерировать отдельные изображения вида птицы с восьми камер. Сшить их, чтобы создать 360 ° изображение с видом на птицу.

Снимите сцену с камер и загрузите изображения в рабочем пространстве MATLAB.

sceneImages = cell(1, numCameras);
for i = 1:numCameras
    filename = "sceneImage" + string(i) + ".jpg";
    sceneImages{i} = imread(filename);
end
helperVisualizeScene(sceneImages)

Figure contains 9 axes. Axes 1 contains an object of type image. Axes 2 contains an object of type image. Axes 3 contains an object of type image. Axes 4 contains an object of type image. Axes 5 contains an object of type image. Axes 6 contains an object of type image. Axes 7 contains an object of type image. Axes 8 contains an object of type image. Axes 9 contains an object of type image.

Преобразуйте изображения в вид «птичий глаз»

Укажите прямоугольную область вокруг транспортного средства, которую вы хотите преобразовать в вид птичьего полета, и размер выходного изображения. В этом примере самые дальние объекты на захваченных изображениях находятся на расстоянии около 4,5 м.

Создайте квадратный выходной вид, который покрывает радиус 4,5 м вокруг транспортного средства.

distFromVehicle = 4.5; % in meters
outView = [-distFromVehicle, distFromVehicle, ... % [xmin, xmax,
           -distFromVehicle, distFromVehicle];    %  ymin, ymax]
outImageSize = [640, NaN];

Чтобы создать изображение вида птицы из каждого monoCamera объект, следуйте этим шагам.

  1. Удалите искажения в изображении.

  2. Создайте birdsEyeView объект.

  3. Преобразуйте неискаженное изображение в изображение с видом на птичий глаз с помощью transformImage функция.

bevImgs = cell(1, numCameras);
birdsEye = cell(1, numCameras);
for i = 1:numCameras
    undistortedImage = undistortImage(sceneImages{i}, monoCams{i}.Intrinsics);
    birdsEye{i} = birdsEyeView(monoCams{i}, outView, outImageSize);
    bevImgs{i}  = transformImage(birdsEye{i}, undistortedImage);    
end
helperVisualizeScene(bevImgs)

Figure contains 9 axes. Axes 1 contains an object of type image. Axes 2 contains an object of type image. Axes 3 contains an object of type image. Axes 4 contains an object of type image. Axes 5 contains an object of type image. Axes 6 contains an object of type image. Axes 7 contains an object of type image. Axes 8 contains an object of type image. Axes 9 contains an object of type image.

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

tiled360DegreesBirdsEyeView = zeros(640, 640, 3);
for i = 1:numCameras
    tiled360DegreesBirdsEyeView = helperBlendImages(tiled360DegreesBirdsEyeView, bevImgs{i});
end
figure 
imshow(tiled360DegreesBirdsEyeView)

Figure contains an axes. The axes contains an object of type image.

В данном примере начальные результаты процесса оценки внешних данных содержат некоторые несоответствия. Однако они могут быть связаны с неправильным предположением, что камера была расположена в источник системы транспортного средства. Исправление расхождения требует регистрации изображения.

Регистр и стежок Bird 's-Eye-View Изображения

Во-первых, соответствовать функциям. Сравнение и визуализация результатов использования matchFeatures с matchFeaturesInRadius, что позволяет ограничивать контуры поиска с помощью геометрических ограничений. Согласование функции с ограничениями может улучшить результаты, когда шаблоны повторяются, например, на дорогах, где разметка дорожного покрытия и дорожные знаки являются стандартными. В заводских настройках можно разработать более подробное строение калибровочных шаблонов и текстурированного фона, которая дополнительно улучшает процесс калибровки и регистрации. Пример Feature Based Panoramic Image Stitching подробно объясняет, как зарегистрировать несколько изображений и сшить их, чтобы создать панораму. Результаты показывают, что ограничение функции соответствие с использованием matchFeaturesInRadius соответствует только соответствующим парам функций в этих двух изображениях и отбрасывает любые функции, соответствующие несвязанным репититивным шаблонам.

% The last two images of the scene best demonstrate the advantage of
% constrained feature matching as they have many repetitive pavement
% markings.
I = bevImgs{7};
J = bevImgs{8};

% Extract features from the two images.
grayImage = rgb2gray(I);
pointsPrev = detectKAZEFeatures(grayImage);
[featuresPrev, pointsPrev] = extractFeatures(grayImage, pointsPrev);

grayImage = rgb2gray(J);
points = detectKAZEFeatures(grayImage);
[features, points] = extractFeatures(grayImage, points);

% Match features using the two methods.
indexPairs1 = matchFeaturesInRadius(featuresPrev, features, points.Location, ...
                                   pointsPrev.Location, 15, ...
                                   "MatchThreshold", 10, "MaxRatio", 0.6);

indexPairs2 = matchFeatures(featuresPrev, features, "MatchThreshold", 10, ...
                            "MaxRatio", 0.6);

% Visualize the matched features.
tiledlayout(1,2)
nexttile
showMatchedFeatures(I, J, pointsPrev(indexPairs1(:,1)), points(indexPairs1(:,2)))
title(sprintf('%d pairs matched\n with spatial constraints', size(indexPairs1, 1)))

nexttile
showMatchedFeatures(I, J, pointsPrev(indexPairs2(:,1)), points(indexPairs2(:,2)))
title(sprintf('%d pairs matched\n without spatial constraints', size(indexPairs2,1)))

Figure contains 2 axes. Axes 1 with title 18 pairs matched with spatial constraints contains 4 objects of type image, line. Axes 2 with title 31 pairs matched without spatial constraints contains 4 objects of type image, line.

Функции helperRegisterImages и helperStitchImages были написаны на основе примера Feature Based Panoramic Image Stitching с использованием matchFeaturesInRadius. Обратите внимание, что традиционного панорамного сшивания недостаточно для этого приложения, поскольку каждое изображение регистрируется только относительно предыдущего изображения. Следовательно, последнее изображение может не выровняться точно с первым изображением, получая плохо выровненное объемное изображение 360 ° .

Этот недостаток в процессе регистрации можно преодолеть, зарегистрировав изображения пакетно:

  1. Зарегистрируйте и сшейте первые четыре изображения, чтобы сгенерировать изображение левой стороны транспортного средства.

  2. Зарегистрируйте и сшейте последние четыре изображения, чтобы сгенерировать изображение правой стороны транспортного средства.

  3. Зарегистрируйте и сшейте левую и правую сторону, чтобы получить полное 360 ° изображения сцены с видом на птицу.

Обратите внимание на использование большего радиуса соответствия для сшивания изображений на шаге 3 по сравнению с шагами 1 и 2. Это происходит из-за изменения относительных положений изображений во время первых двух шагов регистрации.

% Combine the first four images to get the stitched leftSideview and the
% spatial reference object Rleft.
radius = 15;
leftImgs = bevImgs(1:4);
tforms = helperRegisterImages(leftImgs, radius);
[leftSideView, Rleft] = helperStitchImages(leftImgs, tforms);
 
% Combine the last four images to get the stitched rightSideView.
rightImgs = bevImgs(5:8);
tforms = helperRegisterImages(rightImgs, radius);
rightSideView = helperStitchImages(rightImgs, tforms);
 
% Combine the two side views to get the 360° bird's-eye-view in
% surroundView and the spatial reference object Rsurround
radius = 50;
imgs = {leftSideView, rightSideView};
tforms = helperRegisterImages(imgs, radius);
[surroundView, Rsurround] = helperStitchImages(imgs, tforms);
figure
imshow(surroundView)

Figure contains an axes. The axes contains an object of type image.

Измерьте расстояния в 360 ° Bird's Eye-View

Одно из преимуществ использования изображений для измерения расстояний в виде птичьего глаза заключается в том, что расстояния могут быть вычислены на изображении благодаря планарной природе земли. Можно измерить различные расстояния, которые применяются для приложений ADAS, такие как указания по близости области значений чертежам и автомобилю , оборудованному датчиком контуров. Измерение расстояния включает преобразование мировых точек в системе координат транспортного средства в изображение вида птицы, которое можно сделать с помощью vehicleToImage функция. Однако обратите внимание, что каждое из восьми изображений вида птичьего глаза претерпело два геометрических преобразования в процессе регистрации изображения. Таким образом, в дополнение к использованию vehicleToImage функция, вы должны применить эти преобразования к точкам изображения. The helperVehicleToBirdsEyeView функция применяет эти преобразования. Точки проецируются на первое изображение вида птицы, поскольку это изображение претерпело наименьшее количество преобразований в процессе регистрации.

Нарисуйте руководства по области значений близости

Правила круговой области значений вокруг транспортного средства могут помочь драйверам маневрировать в плотных парковочных местах. Нарисуйте круговые инструкции на 2, 3 и 4 метрах на изображении с видом на птичий глаз 360 °:

  1. Преобразуйте центр транспортного средства и точку в круговом руководстве в системе координат транспортного средства в изображение вида птицы на 360 ° с помощью helperVehicleToBirdsEyeView функция.

  2. Вычислите радиус круговой направляющей в пикселях, найдя расстояние между двумя преобразованными точками.

  3. Нарисуйте инструкции, используя insertShape и пометьте инструкции, используя insertText функция.

proximityRange = [2, 3, 4]; % in meters
colors         = ["red", "yellow", "green"];
refBirdsEye    = birdsEye{1};
Rout           = {Rleft, Rsurround};
vehicleCenter  = [0, 0];
vehicleCenterInImage = helperVehicleToBirdsEyeView(refBirdsEye, vehicleCenter, Rout);

for i = 1:length(proximityRange)
    
    % Estimate the radius of the circular guidelines in pixels given its
    % radius in meters.
    circlePoint         = [0, proximityRange(i)];
    circlePointInImage  = helperVehicleToBirdsEyeView(refBirdsEye, circlePoint, Rout);        
    
    % Compute radius using euclidean norm.
    proximityRangeInPixels  = norm(circlePointInImage - vehicleCenterInImage, 2);
    
    surroundView = insertShape(surroundView, "Circle", [vehicleCenterInImage, proximityRangeInPixels], ...
                               "LineWidth", 1, ...
                               "Color", colors(i));
    
    labelText = string(proximityRange(i)) + " m";
    surroundView = insertText(surroundView, circlePointInImage, labelText,...
                              "TextColor", "White", ...
                              "FontSize", 14, ...
                              "BoxOpacity", 0);
end

imshow(surroundView)

Нарисуйте Автомобиль , оборудованный датчиком Контура

Граничные линии для транспортного средства помогают драйверу понять относительное положение транспортного средства относительно окружающей среды. Нарисуйте автомобиль , оборудованный датчиком контура с помощью такой же процедуры, как и в руководствах по близости чертежа. The helperGetVehicleBoundaryOnBEV функция возвращает угловые точки контура транспортного средства на изображении вида птицы на 360 °, учитывая положение и размер транспортного средства. Отображение инструкций на сцене с помощью showShape функция.

vehicleCenter = [0, 0];
vehicleSize   = [5.6, 2.4]; % length-by-width in meters
[polygonPoints, vehicleLength, vehicleWidth] = helperGetVehicleBoundaryOnBEV(refBirdsEye, ...                                                                             
                                                                             vehicleCenter, ...
                                                                             vehicleSize, ...
                                                                             Rout);
showShape("polygon", polygonPoints, "Label", "Ego Vehicle")

Figure contains an axes. The axes contains an object of type image.

Кроме того, вы также можете наложить моделируемое транспортное средство на сцену для визуально приятных результатов.

% Read the picture of the simulation vehicle.
egoVehicle = imread("vehicle.png", "BackgroundColor", [0 0 0]);

% Bring the simulation vehicle into the vehicle coordinate system.
egoVehicle = imresize(egoVehicle, [vehicleLength, vehicleWidth]);
vehicle    = zeros(size(surroundView), "uint8");
xIdx       = polygonPoints(1,1) + (1:vehicleWidth);
yIdx       = polygonPoints(1,2) + (1:vehicleLength);
vehicle(yIdx, xIdx, :) = egoVehicle;

% Overlay the simulation vehicle on the 360° bird's-eye-view image.
sceneBirdsEyeView = helperOverlayImage(vehicle, surroundView); 

Наконец, давайте исключим черные границы на изображении, выбрав меньшую область значений от источника системы координат транспортного средства.

distFromVehicle = 4.25; % in meters
[x, y, h, w] = helperGetImageBoundaryOnBEV(refBirdsEye, distFromVehicle, Rout);
croppedSceneBirdsEyeView = imcrop(sceneBirdsEyeView, [x, y, h, w]);
imshow(croppedSceneBirdsEyeView)

Figure contains an axes. The axes contains an object of type image.

Заключение

Процедура, показанная в этом примере, может быть расширена, чтобы создать систему контроля кругового обзора производственного класса. Это требует точной калибровки камеры, чтобы оценить положения монокулярной камеры с минимальными ошибками и настроить регистрационные гиперпараметры. Пример также может быть изменен, чтобы использовать fisheye-камеры.

Вспомогательные функции

helperVisualizeScene Функция

The helperVisualizeScene Функция отображает изображения, расположенные по положениям их камер относительно транспортного средства на размещении мозаичного графика 3 на 3, и опционально показывает текст заголовка для каждой плитки.

function helperVisualizeScene(images, varargin)
    
    numImages = numel(images);    
    if nargin == 2
        titleText = varargin{1};
    else
        titleText = strings(numImages,1);
    end
    
    % Define index locations to simulate the camera positions relative to the vehicle.
    cameraPosInFigureWindow = [1, 4, 7, 8, 9, 6, 3, 2];
    egoVehiclePosInFigureWindow = 5;
    
    figure
    t = tiledlayout(3, 3, "TileSpacing", "compact", "Padding", "compact");    
    for i = 1:numImages
        nexttile(cameraPosInFigureWindow(i)) 
        imshow(images{i})
        title(titleText(i))
    end
    
    % Visualize the vehicle on the scene.
    egoVehicle = imread("vehicle.png", "BackgroundColor", [1 1 1]);
    nexttile(egoVehiclePosInFigureWindow)
    imshow(egoVehicle)
    if nargin == 2
        title("Ego Vehicle")
        title(t, "Pattern positions");
    end
end

helperBlendImages Function

The helperBlendImages функция выполняет альфа-смешение с заданными двумя входными изображениями, I1 и I2, со значениями альфа, которые пропорциональны центральному шву каждого изображения. Область выхода Iout является линейной комбинацией входных изображений:

Iout=αI1+(1-α)I2

function outputImage = helperBlendImages(I1, I2) 
    arguments
        I1 uint8
        I2 uint8
    end
    % Identify the image regions in the two images by masking out the black
    % regions.
    mask1 = sum(I1, 3) ~= 0;
    mask2 = sum(I2, 3) ~= 0;
    maskc = mask1 & mask2;
    
    % Compute alpha values that are proportional to the center seam of the two
    % images.
    alpha1 = ones(size(mask1,1:2));
    alpha2 = ones(size(mask2,1:2));
    dist1  = bwdist(edge(mask1));
    dist2  = bwdist(edge(mask2));
    alpha1(maskc) = double(dist1(maskc) > dist2(maskc));    
    alpha2(maskc) = double(dist1(maskc) <= dist2(maskc));
    
    I1 = double(I1);
    I2 = double(I2);        
    outputImage = alpha1.*I1 + alpha2.*I2;    
    outputImage = uint8(outputImage);
end

helperRegisterImages Функция

The helperRegisterImages функция регистрирует массив ячеек images последовательно используя радиус поиска для matchFeaturesInRadius и возвращает преобразования, tforms.

function tforms = helperRegisterImages(images, radius)
    
    params.Radius         = radius;
    params.MatchThreshold = 10;
    params.MaxRatio       = 0.6;
    params.Confidence     = 99.9;
    params.MaxDistance    = 2;
    params.MaxNumTrials   = 2000;
    
    numImages = numel(images);
    
    % Store points and features for all images.
    features = cell(1,numImages);
    points   = cell(1,numImages);
    for i = 1:numImages
        grayImage = rgb2gray(images{i});
        points{i} = detectKAZEFeatures(grayImage);
        [features{i}, points{i}] = extractFeatures(grayImage, points{i});
    end

    % Initialize all the transforms to the identity matrix.
    tforms(numImages) =  affine2d(eye(3));
    
    % Set the seed for reproducibility.
    rng(0);
    
    % Find the relative transformations between each image pair.
    for i = 2:numImages
        % Find correspondences between images{i} and images{i-1} using
        % constrained feature matching.
        indexPairs = matchFeaturesInRadius(features{i-1}, features{i}, points{i}.Location, ...
                                           points{i-1}.Location, params.Radius, ...
                                           "MatchThreshold", params.MatchThreshold, ...
                                           "MaxRatio", params.MaxRatio);
        
        %  Estimate the transformation between images{i} and images{i-1}.
        matchedPointsPrev = points{i-1}(indexPairs(:,1), :);    
        matchedPoints     = points{i}(indexPairs(:,2), :);        
        tforms(i) = estimateGeometricTransform2D(matchedPoints, matchedPointsPrev,"similarity",...
                                                 "Confidence" , params.Confidence, ...
                                                 "MaxDistance", params.MaxDistance, ...
                                                 "MaxNumTrials",params.MaxNumTrials);
        
        % Compute the transformation that maps images{i} to the stitched
        % image as T(i)*T(i-1)*...*T(1).
        tforms(i).T = tforms(i).T*tforms(i-1).T;
    end
end

helperStitchImages Функция

The helperStitchImages функция применяет преобразования tforms к входу изображениям и смешивает их, чтобы создать outputImage. Это дополнительно возвращает outputView, который можно использовать, чтобы преобразовать любую точку из первого изображения в заданной последовательности изображений в выходное изображение.

function [outputImage, outputView] = helperStitchImages(images, tforms) 
    
    numImages = numel(images);
    imageSize = zeros(numImages,2);
    xlim = zeros(numImages,2);
    ylim = zeros(numImages,2);
    
    % Compute the output limits for each transform.
    for i = 1:numel(images)
        imageSize(i,:) = size(images{i}, 1:2);
        [xlim(i,:), ylim(i,:)] = outputLimits(tforms(i), ...
                                              [1 imageSize(i,2)], ...
                                              [1 imageSize(i,1)]);
    end    

    % Find the minimum and maximum output limits.
    maxImageSize = max(imageSize);
    
    xMin = min([1; xlim(:)]);
    xMax = max([maxImageSize(2); xlim(:)]);

    yMin = min([1; ylim(:)]);
    yMax = max([maxImageSize(1); ylim(:)]);

    % Width and height of panorama.
    width  = round(xMax - xMin);
    height = round(yMax - yMin);

    % Initialize the "empty" panorama.
    outputImage = zeros([height width 3], "like", images{1});

    % Create a 2-D spatial reference object defining the size of the panorama.
    xLimits = [xMin xMax];
    yLimits = [yMin yMax];
    outputView = imref2d([height width], xLimits, yLimits);

    % Step 7 - Stitch the images.
    for i = 1:numel(tforms)
        % Apply transformation.
        warpedImage = imwarp(images{i}, tforms(i), "OutputView", outputView);
        
        % Blend the images.
        outputImage = helperBlendImages(warpedImage, outputImage);
    end
end

helperVehicleToBirdsEyeView Функция

The helperVehicleToBirdsEyeView функция преобразует заданные мировые точки в системе координат транспортного средства в точки на изображении вида птицы на 360 °.

function tranformedImagePoints = helperVehicleToBirdsEyeView(birdsEye, vehiclePoints, Rout)

    % Transform the 3D worldPoints in vehicle coordinate system to 2D
    % imagePoints in the Bird's-Eye-View (BEV) image.
    imagePoints = vehicleToImage(birdsEye, vehiclePoints);
    
    % Transform these imagePoints from single BEV image to 360° bird's-eye-view images.
    [xPoints, yPoints] = worldToIntrinsic(Rout{1}, imagePoints(:,1), imagePoints(:,2));
    [xPoints, yPoints] = worldToIntrinsic(Rout{2}, xPoints, yPoints);
    
    tranformedImagePoints = [xPoints, yPoints];
end

helperGetImageBoundaryOnBEV Функция

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

function [x, y, h, w] = helperGetImageBoundaryOnBEV(birdsEye, distFromVehicle, Rout)
    
    % Define three corner points of the vehicle's bounding box.
    vehiclePoints = [ distFromVehicle, distFromVehicle;
                     -distFromVehicle, distFromVehicle; 
                     -distFromVehicle,-distFromVehicle];
    
    % Flip the x and y axes between the world and vehicle coordinate
    % systems.
    vehiclePoints = fliplr(vehiclePoints);
    
    imagePoints = helperVehicleToBirdsEyeView(birdsEye, vehiclePoints, Rout);
    x = imagePoints(1,1);
    y = imagePoints(1,2);
    h = abs(imagePoints(1,1) - imagePoints(2,1));
    w = abs(imagePoints(2,2) - imagePoints(3,2));
end

helperGetVehicleBoundaryOnBEV Функция

The helperGetVehicleBoundaryOnBEV функция возвращает угловые точки контура транспортного средства, учитывая его положение и размер.

function [polygonPoints, vehicleLength, vehicleWidth] = ...
          helperGetVehicleBoundaryOnBEV(birdsEye, vehicleCenter, vehicleSize, Rout)

    x = vehicleCenter(1);
    y = vehicleCenter(2);

    % Find half length and half width in a and b respectively.
    a = vehicleSize(1)/2;
    b = vehicleSize(2)/2;
    
    % Define vehiclePoints in the world coordinate system.    
    vehiclePoints = [ x+b, y+a;
                      x+b, y-a;
                      x-b, y-a;
                      x-b, y+a ];
    
    % Flip the x and y axes between the world and vehicle coordinate
    % systems.
    vehiclePoints      = fliplr(vehiclePoints);
    imagePoints = helperVehicleToBirdsEyeView(birdsEye, vehiclePoints, Rout);
    
    xPoints = ceil(imagePoints(:,1));
    yPoints = ceil(imagePoints(:,2));
    
    vehicleLength = abs(yPoints(1) - yPoints(2));
    vehicleWidth  = abs(xPoints(2) - xPoints(3));
    
    % x,y points as points on a polygon for showShape.
    polygonPoints = [xPoints   , yPoints;...
    % Close the polygon by setting the last point as first point.
                     xPoints(1), yPoints(1)]; 
end

helperOverlayImage Функция

The helperOverlayImage функция накладывает topImage на bottomImage и возвращает результат в outputImage.

function outputImage = helperOverlayImage(topImage, bottomImage) 
    
    blender = vision.AlphaBlender("Operation", "Binary mask", ...
              "MaskSource", "Input port");    
    mask = sum(topImage, 3) ~= 0;    
    outputImage = step(blender, bottomImage, topImage, mask);
end

См. также

Приложения

Функции

Объекты

Похожие темы