exponenta event banner

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

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

Обзор

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

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

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

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

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

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

В этом примере камера была откалибрована с использованием шаблона калибровки шахматной доски в приложении Single Camera Calibrator App, и параметры камеры были экспортированы в 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.

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

Регистрация и сшивание изображений птичьего взгляда

Сначала сопоставьте элементы. Сравнение и визуализация результатов использования matchFeatures с matchFeaturesInRadius, что позволяет ограничить границу поиска с помощью геометрических зависимостей. Сопоставление зависимых элементов может улучшить результаты при повторяющихся образцах, например на дорогах, где разметка дорожного покрытия и дорожные знаки являются стандартными. В заводских настройках можно разработать более сложную конфигурацию шаблонов калибровки и текстурированного фона, что еще больше улучшает процесс калибровки и регистрации. Пример сшивания панорамных изображений на основе элементов подробно объясняет, как зарегистрировать несколько изображений и сшить их для создания панорамы. Результаты показывают, что совпадение зависимых элементов с помощью 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 были написаны на основе примера сшивания панорамного изображения на основе элементов с использованием 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 °

Одно из преимуществ использования изображений с видом на птицу для измерения расстояний заключается в том, что расстояния могут быть вычислены по изображению из-за планарной природы земли. Можно измерять различные расстояния, полезные для приложений ADAS, такие как указания по диапазону близости и границы эго-транспортных средств. Измерение расстояния включает преобразование мировых точек в системе координат транспортного средства в изображение с высоты птичьего полета, что можно сделать с помощью vehicleToImage функция. Однако следует отметить, что каждое из восьми изображений с высоты птичьего полета претерпело два геометрических преобразования во время процесса регистрации изображения. Таким образом, в дополнение к использованию vehicleToImage необходимо применить эти преобразования к точкам изображения. 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)

Нарисуйте границу транспортного средства Ego

Граничные линии для транспортного средства помогают водителю понять относительное положение транспортного средства по отношению к окружающей среде. Нарисуйте границу эго-транспортного средства с помощью такой же процедуры, как и при рисовании руководящих принципов близости. 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.

Заключение

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

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

helperVisualizeScene Функция

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

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 Функция

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 Функция

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 Функция

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 Функция

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 Функция

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 Функция

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

См. также

Приложения

Функции

Объекты

Связанные темы