В этом примере показано, как автоматически создать панораму с помощью методов регистрации изображений на основе объектов.
Выявление признаков и соответствие являются мощными методами, используемыми во многих приложениях компьютерного зрения, таких как регистрация изображений, отслеживание и обнаружение объектов. В этом примере основанные на функции методы используются, чтобы автоматически сшить вместе набор изображений. Процедура для изображения, сшивающего, является расширением основанной на функции регистрации изображений. Вместо того, чтобы указать одну пару изображений, пары повторного изображения последовательно указаны друг относительно друга, чтобы сформировать панораму.
Набор изображений, используемый в этом примере, содержит изображения создания. Они были взяты с некалиброванной камерой смартфона путем развертки камеры слева направо вдоль горизонта, получения всех частей создания.
Как замечено ниже, изображения относительно незатронуты любым искажением объектива, таким образом, калибровка фотоаппарата не требовалась. Однако, если искажение объектива присутствует, камера должна быть калибрована и изображения, неискаженные до создания панорамы. Можно использовать Приложение Camera Calibrator, чтобы калибровать камеру в случае необходимости.
% Load images. buildingDir = fullfile(toolboxdir('vision'), 'visiondata', 'building'); buildingScene = imageDatastore(buildingDir); % Display images to be stitched montage(buildingScene.Files)
Чтобы создать панораму, запустите путем регистрации последовательных пар изображений с помощью следующей процедуры:
Обнаружьте и совпадайте с функциями между и .
Оцените геометрическое преобразование, , это сопоставляет к .
Вычислите преобразование, которое сопоставляет в панораму отображают как .
% 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) = estimateGeometricTransform(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
Теперь создайте начальную, пустую панораму, в которую будут отображены все изображения.
Используйте 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);
Используйте 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.