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

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

Обзор

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

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

Калибруйте мультисистему камеры

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

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

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

В этом примере камера была калибрована с помощью калибровочного шаблона шахматной доски в Использовании Одного Приложения 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 objects. Axes object 1 with title front contains an object of type image. Axes object 2 with title left contains an object of type image. Axes object 3 with title left contains an object of type image. Axes object 4 with title back contains an object of type image. Axes object 5 with title back contains an object of type image. Axes object 6 with title right contains an object of type image. Axes object 7 with title right contains an object of type image. Axes object 8 with title front contains an object of type image. Axes object 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 objects. Axes object 1 contains an object of type image. Axes object 2 contains an object of type image. Axes object 3 contains an object of type image. Axes object 4 contains an object of type image. Axes object 5 contains an object of type image. Axes object 6 contains an object of type image. Axes object 7 contains an object of type image. Axes object 8 contains an object of type image. Axes object 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 objects. Axes object 1 contains an object of type image. Axes object 2 contains an object of type image. Axes object 3 contains an object of type image. Axes object 4 contains an object of type image. Axes object 5 contains an object of type image. Axes object 6 contains an object of type image. Axes object 7 contains an object of type image. Axes object 8 contains an object of type image. Axes object 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 object. The axes object 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 objects. Axes object 1 with title 18 pairs matched with spatial constraints contains 4 objects of type image, line. Axes object 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 object. The axes object 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)

Проведите границу автомобиля, оборудованного датчиком

Границы для транспортного средства помогают драйверу понять относительную позицию транспортного средства относительно среды. Чертите граничное использование автомобиля, оборудованного датчиком подобной процедуры как то из рисования инструкций по близости. 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 object. The axes object 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 object. The axes object contains an object of type image.

Заключение

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

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

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

Смотрите также

Приложения

Функции

Объекты

Похожие темы