我有两个相似但方向和大小不同的图像。下面是一个例子:
有没有办法匹配这两个图像?
我使用了Procrustes形状分析,但还有其他方法吗?
查看计算机视觉系统工具箱中的Find Image Rotation and Scale Using Automated Feature Matching示例。
它显示了如何检测兴趣点,提取和匹配特征描述符,以及计算两个图像之间的转换。
这是让你入门的东西。你要求的是一个经典的问题,称为image registration。图像配准旨在找到一个正确的单应性,它可以拍摄一张图像并将其与另一张图像对齐。这涉及找到两个图像之间共同的兴趣或关键点,并确定哪两个关键点在两个图像之间匹配。一旦你有了这些点对,就可以确定单应矩阵并扭曲其中一个图像,使它们与另一个图像对齐。
我假设你有计算机视觉和图像处理工具箱,它们是MATLAB的一部分。如果你不这样做,那么Maurits给出的答案是一个很好的选择,VLFeat工具箱也是我用过的。
首先,让我们直接从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在下面给我的评论中指出的那样,这可以通过RANSAC强有力地确定最佳单应矩阵。我们可以这样称呼estimateGeometricTransform
:
tform = estimateGeometricTransform(matchedPoints1.Location,...
matchedPoints2.Location, 'projective');
第一个输入接受一组输入点,这是您要转换的点。第二个输入采用一组基点作为参考点。这些点是我们想要匹配的。
在我们的例子中,我们想要扭曲第一张图像中的点 - 站起来并使其与第二张图像匹配的人 - 靠在他身边的人,因此第一个输入是来自第一张图像的点,第二张图像是输入是第二个图像的点。
对于匹配点,我们想要引用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
等。您可能需要使用参数来获得您尝试的不同图像对的一致结果。我会把它留给你作为练习。看看我上面链接的所有链接与每个功能,以便您可以使用参数来满足您的口味。
玩得开心,祝你好运!
您可以通过以下方式获得合理的结果:
vl_ubcmatch
实现初步结果:
这是一种与其他方法不同的方法。基于特征的注册方法更加健壮,但我的方法可能对您的应用程序有用,所以我在这里写下来。
image = imread('Pd7pt.png');
model = imread('vXqe8.png');
grImage = rgb2gray(image);
grModel = rgb2gray(model);
hImage = imhist(grImage);
hModel = imhist(grModel);
normhistInterMeasure = sum(min(hImage, hModel))/sum(hModel)
corrMeasure = corr2(hImage, hModel)