В этом примере показов, как автоматически создать панораму с помощью методов регистрации изображений на основе объектов.
Обнаружение и согласование функций являются мощными методами, используемыми во многих приложениях компьютерного зрения, таких как регистрация изображений, отслеживание и обнаружение объектов. В этом примере методов, основанные на функциях, используются для автоматического сшивания набора изображений. Процедура сшивания изображений является расширением регистрации изображений на основе признаков. Вместо регистрации одной пары изображений несколько пар изображений последовательно регистрируются относительно друг друга, образуя панораму.
Набор изображений, используемый в этом примере, содержит изображения создания. Их взяли с помощью некалиброванной камеры смартфона, протащив камеру слева направо по горизонту, запечатлев все части создания.
Как показано ниже, изображения относительно не влияют на любое искажение объектива, поэтому калибровка камеры не требовалась. Однако, если присутствует искажение объектива, камера должна быть калибрована, а изображения не искажены до создания панорамы. Вы можете использовать Приложение 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 = im2gray(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 = im2gray(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
Теперь создайте начальную , пустую панораму, в которую будут отображены все изображения.
Используйте 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. Автоматическое панорамное сшивание изображений с использованием Invariant Features. Int. Дж. Компут. 74 зрения, 1 (август 2007), 59-73.