这里有一些东西可以帮助您入门。您要的是一个经典问题,称为image registration。图像配准旨在找到正确的单应性,将一张图像与另一张图像对齐。这涉及找到两个图像之间共有的兴趣点或关键点,并确定哪些关键点在两个图像之间匹配。一旦你有了这些点对,你就可以确定一个单应矩阵并扭曲其中一个图像,以便它们与另一个与这个矩阵对齐。
我将假设您拥有属于 MATLAB 的计算机视觉和图像处理工具箱。如果您不这样做,那么 Maurits 给出的答案是一个不错的选择,VLFeat Toolbox 也是我用过的。
首先,让我们直接从 StackOverflow 中读取图像:
im = imread('http://i.stack.imgur.com/vXqe8.png');
im2 = imread('http://i.stack.imgur.com/Pd7pt.png');
im_gray = rgb2gray(im);
im2_gray = rgb2gray(im2);
我们还需要转换为灰度,因为关键点检测算法需要灰度图像。接下来,我们可以使用任何属于 MATLAB CVST 的特征检测算法……我将使用SURF,因为它与 SIFT 基本相同,但有一些细微但关键的区别。您可以使用 detectSURFFeatures 函数,它是 CVST 工具箱的一部分,它接受灰度图像。输出是一个结构,其中包含有关算法为图像检测到的每个特征点的信息。让我们将其应用于两张图像(灰度)。
points = detectSURFFeatures(im_gray);
points2 = detectSURFFeatures(im2_gray);
一旦我们检测到特征,现在是时候提取描述这些关键点的描述符了。这可以通过extractFeatures 完成。这需要一个灰度图像和从detectSURFFeatures 输出的相应结构。输出是经过一些后处理后的一组特征和有效关键点。
[features1, validPoints1] = extractFeatures(im_gray, points);
[features2, validPoints2] = extractFeatures(im2_gray, points2);
现在是时候匹配两张图片之间的特征了。这可以通过matchFeatures 完成,它会吸收两个图像之间的特征:
indexPairs = matchFeatures(features1, features2);
indexPairs 是一个二维数组,其中第一列告诉您第一张图像中的哪个特征点与第二张图像中的特征点匹配,存储在第二列中。我们将使用它来索引我们的有效点以充实实际匹配的内容。
matchedPoints1 = validPoints1(indexPairs(:, 1), :);
matchedPoints2 = validPoints2(indexPairs(:, 2), :);
然后我们可以像这样使用showMatchedFeatures 来显示哪些点匹配。我们可以将两个图像并排放置,并在匹配的关键点之间画线,看看哪个匹配。
figure;
showMatchedFeatures(im, im2, matchedPoints1, matchedPoints2, 'montage');
这是我得到的:
它并不完美,但它肯定会在两张图片之间找到一致的匹配。
现在我们接下来需要做的是找到单应矩阵并扭曲图像。我将使用estimateGeometricTransform,以便我们可以找到一个将一组点扭曲到另一组的转换。正如 Dima 在下面给我的 cmets 中指出的那样,这个稳健地通过 RANSAC 确定了最佳单应矩阵。我们可以这样调用estimateGeometricTransform:
tform = estimateGeometricTransform(matchedPoints1.Location,...
matchedPoints2.Location, 'projective');
第一个输入接受一组 输入 点,这些点是您要转换的点。第二个输入接受一组 base points,它们是 reference 点。这些点是我们想要匹配的。
在我们的例子中,我们想要扭曲第一张图像中的点 - 站立的人并使其匹配第二张图像 - 倾斜的人,因此第一个输入是来自第一张图像的点,第二个输入是来自第二个图像的点。
对于匹配的点,我们希望引用Location 字段,因为它们包含两个图像之间实际匹配点的坐标。我们还使用projective 来说明缩放、剪切和旋转。输出是一个结构,其中包含我们的点变换。
我们接下来要做的是使用imwarp 来扭曲第一个图像,使其与第二个图像对齐。
out = imwarp(im, tform);
out 将包含我们扭曲的图像。如果我们并排显示第二张图像和这个输出图像:
figure;
subplot(1,2,1);
imshow(im2);
subplot(1,2,2);
imshow(out);
这是我们得到的:
我会说这很不错,你不觉得吗?
为了您的复制和粘贴乐趣,完整的代码如下所示:
im = imread('http://i.stack.imgur.com/vXqe8.png');
im2 = imread('http://i.stack.imgur.com/Pd7pt.png');
im_gray = rgb2gray(im);
im2_gray = rgb2gray(im2);
points = detectSURFFeatures(im_gray);
points2 = detectSURFFeatures(im2_gray);
[features1, validPoints1] = extractFeatures(im_gray, points);
[features2, validPoints2] = extractFeatures(im2_gray, points2);
indexPairs = matchFeatures(features1, features2);
matchedPoints1 = validPoints1(indexPairs(:, 1), :);
matchedPoints2 = validPoints2(indexPairs(:, 2), :);
figure;
showMatchedFeatures(im, im2, matchedPoints1, matchedPoints2, 'montage');
tform = estimateGeometricTransform(matchedPoints1.Location,...
matchedPoints2.Location, 'projective');
out = imwarp(im, tform);
figure;
subplot(1,2,1);
imshow(im2);
subplot(1,2,2);
imshow(out);
一边
请记住,我对所有内容都使用了 默认 参数...所以detectSURFFeatures、matchFeatures 等。您可能需要使用这些参数才能在不同的环境中获得一致的结果您尝试的图像对。我会把它留给你作为练习。查看我在上面链接的关于每个函数的所有链接,以便您可以根据自己的喜好调整参数。
玩得开心,祝你好运!