Функция Сшивания На Основе Панорамного Изображения

В этом примере показано, как автоматически создать панораму с помощью методов регистрации изображений на основе объектов.

Обзор

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

Шаг 1 - изображения загрузки

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

Как замечено ниже, изображения относительно незатронуты любым искажением объектива, таким образом, калибровка фотоаппарата не требовалась. Однако, если искажение объектива присутствует, камера должна быть калибрована и изображения, неискаженные до создания панорамы. Можно использовать Приложение Camera Calibrator, чтобы калибровать камеру в случае необходимости.

% Load images.
buildingDir = fullfile(toolboxdir('vision'), 'visiondata', 'building');
buildingScene = imageDatastore(buildingDir);

% Display images to be stitched
montage(buildingScene.Files)

Шаг 2 - пары регистра изображений

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

  1. Обнаружьте и совпадайте с функциями между I(n) и I(n-1).

  2. Оцените геометрическое преобразование, T(n), это сопоставляет I(n) к I(n-1).

  3. Вычислите преобразование, которое сопоставляет I(n) в панораму отображают как T(n)*T(n-1)*...*T(1).

% Read the first image from the image set.
I = readimage(buildingScene, 1);

% Initialize features for I(1)
grayImage = rgb2gray(I);
points = detectSURFFeatures(grayImage);
[features, points] = extractFeatures(grayImage, points);

% Initialize all the transforms to the identity matrix. Note that the
% projective transform is used here because the building images are fairly
% close to the camera. Had the scene been captured from a further distance,
% an affine transform would suffice.
numImages = numel(buildingScene.Files);
tforms(numImages) = projective2d(eye(3));

% Initialize variable to hold image sizes.
imageSize = zeros(numImages,2);

% Iterate over remaining image pairs
for n = 2:numImages
    
    % Store points and features for I(n-1).
    pointsPrevious = points;
    featuresPrevious = features;
        
    % Read I(n).
    I = readimage(buildingScene, n);
    
    % Convert image to grayscale.
    grayImage = rgb2gray(I);    
    
    % Save image size.
    imageSize(n,:) = size(grayImage);
    
    % Detect and extract SURF features for I(n).
    points = detectSURFFeatures(grayImage);    
    [features, points] = extractFeatures(grayImage, points);
  
    % Find correspondences between I(n) and I(n-1).
    indexPairs = matchFeatures(features, featuresPrevious, 'Unique', true);
       
    matchedPoints = points(indexPairs(:,1), :);
    matchedPointsPrev = pointsPrevious(indexPairs(:,2), :);        
    
    % Estimate the transformation between I(n) and I(n-1).
    tforms(n) = estimateGeometricTransform2D(matchedPoints, matchedPointsPrev,...
        'projective', 'Confidence', 99.9, 'MaxNumTrials', 2000);
    
    % Compute T(n) * T(n-1) * ... * T(1)
    tforms(n).T = tforms(n).T * tforms(n-1).T; 
end

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

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

% Compute the output limits  for each transform
for i = 1:numel(tforms)           
    [xlim(i,:), ylim(i,:)] = outputLimits(tforms(i), [1 imageSize(i,2)], [1 imageSize(i,1)]);    
end

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

avgXLim = mean(xlim, 2);

[~, idx] = sort(avgXLim);

centerIdx = floor((numel(tforms)+1)/2);

centerImageIdx = idx(centerIdx);

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

Tinv = invert(tforms(centerImageIdx));

for i = 1:numel(tforms)    
    tforms(i).T = tforms(i).T * Tinv.T;
end

Шаг 3 - Инициализация Панорамы

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

Используйте outputLimits метод, чтобы вычислить минимальные и максимальные выходные пределы по всем преобразованиям. Эти значения используются, чтобы автоматически вычислить размер панорамы.

for i = 1:numel(tforms)           
    [xlim(i,:), ylim(i,:)] = outputLimits(tforms(i), [1 imageSize(i,2)], [1 imageSize(i,1)]);
end

maxImageSize = max(imageSize);

% Find the minimum and maximum output limits 
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.
panorama = zeros([height width 3], 'like', I);

Шаг 4 - Создание Панорамы

Используйте imwarp сопоставлять изображения в панораму и использовать vision.AlphaBlender накладывать изображения вместе.

blender = vision.AlphaBlender('Operation', 'Binary mask', ...
    'MaskSource', 'Input port');  

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

% Create the panorama.
for i = 1:numImages
    
    I = readimage(buildingScene, i);   
   
    % Transform I into the panorama.
    warpedImage = imwarp(I, tforms(i), 'OutputView', panoramaView);
                  
    % Generate a binary mask.    
    mask = imwarp(true(size(I,1),size(I,2)), tforms(i), 'OutputView', panoramaView);
    
    % Overlay the warpedImage onto the panorama.
    panorama = step(blender, panorama, warpedImage, mask);
end

figure
imshow(panorama)

Заключение

Этот пример показал вам, как автоматически создать панораму с помощью методов регистрации изображений на основе объектов. Дополнительные методы могут быть включены в пример, чтобы улучшить смешивание и выравнивание изображений панорамы [1].

Ссылки

[1] Мэтью Браун и Дэвид Г. Лоу. 2007. Автоматическое Панорамное Изображение, Сшивающее использование Инвариантных Функций. Int Дж. Компьют. Видение 74, 1 (август 2007), 59-73.