我有两张相似但方向和大小不同的图像。下面是一个例子:
有没有办法匹配这两个图像?
我使用了Procrustes形状分析,但还有其他方法吗?
答案 0 :(得分:17)
这里有一些让你入门的东西。您要求的是一个称为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
等等。您可能需要使用参数来获取您尝试的不同图像对的一致结果。我会把它留给你作为练习。请查看我上面关于每个功能的所有链接,以便您可以根据自己的喜好调整参数。
玩得开心,祝你好运!
答案 1 :(得分:6)
查看计算机视觉系统工具箱中的Find Image Rotation and Scale Using Automated Feature Matching示例。
它展示了如何检测兴趣点,提取和匹配特征描述符,以及计算两个图像之间的转换。
答案 2 :(得分:3)
您可以通过以下方式获得合理的结果:
vl_ubcmatch
初步结果:
答案 3 :(得分:0)
这是一种与其他方法不同的方法。基于特征的注册方法更加健壮,但我的方法可能对您的应用程序有用,所以我在这里写下来。
直方图交点:计算直方图交点并将其除以模型直方图中的像素数进行标准化。这将为您提供0到1之间的值。
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)
对于交叉和相关,我分别得到0.2492和0.9999。