Этот пример показывает, как автоматически создать обзор с помощью основанных на функции регистрационных методов изображений.
Выявление признаков и соответствие являются мощными методами, используемыми во многих приложениях компьютерного зрения, таких как регистрация изображений, отслеживание и обнаружение объектов. В этом примере основанные на функции методы используются, чтобы автоматически сшить вместе набор изображений. Процедура для изображения, сшивающего, является расширением основанной на функции регистрации изображений. Вместо того, чтобы указать одну пару изображений, пары повторного изображения последовательно указаны друг относительно друга, чтобы сформировать обзор.
Набор изображений, используемый в этом примере, содержит изображения создания. Они были взяты с некалиброванной камерой смартфона путем развертки камеры слева направо вдоль горизонта, получения всех частей создания.
Как замечено ниже, изображения относительно незатронуты любым искажением объектива, таким образом, калибровка фотоаппарата не требовалась. Однако, если искажение объектива присутствует, камера должна быть калибрована и изображения, неискаженные до создания обзора. Можно использовать Приложение cameraCalibrator
, чтобы калибровать камеру в случае необходимости.
% 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
относительно первого изображения. Это было удобным способом закодировать регистрационную процедуру изображений, потому что она позволила последовательную обработку всех изображений. Однако с помощью первого изображения, когда запуск обзора не производит наиболее эстетически приятный обзор, потому что это имеет тенденцию искажать большинство изображений, которые формируют обзор. Более хороший обзор может быть создан путем изменения преобразований, таким образом, что центр сцены является наименее искаженным. Это выполняется путем инвертирования преобразования для центрального изображения и применяния того преобразования ко всему другие.
Начните при помощи метода outputLimits
projective2d
находить выходные пределы для каждого преобразования. Выходные пределы затем используются, чтобы автоматически найти изображение, которое находится примерно в центре сцены.
% 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.