在 MATLAB 中匹配具有不同方向和比例的图像
Matching images with different orientations and scales in MATLAB
我有两张相似但方向和大小不同的图片。下面是一个示例:
有没有办法匹配这两张图片?
我用过Procrustes形状分析,还有其他方法吗?
您可以通过以下方式获得合理的结果:
- 检测两个图像中的 SIFT 点。例如 vlfeat lib.
- 使用 Lowe 规则匹配 SIFT 描述符,由 vlfeat 实现
vl_ubcmatch
- 使用 RANSAC 查找符合某些单应性 H 的匹配点子集。可以在 Peter Kovesi 的站点上看到使用 Harris 特征点的示例,旁边是 RANSAC 本身和其他有用的函数。
初步结果:
这里有一些可以帮助您入门的东西。您要问的是一个经典问题 image registration。图像配准旨在找到获取一张图像并将其与另一张图像对齐的正确单应性。这涉及找到两个图像之间共有的兴趣点或关键点,并确定哪些关键点在两个图像之间匹配。一旦你有了这些点对,你就可以确定一个单应矩阵并扭曲其中一个图像,使它们与另一个与这个矩阵对齐。
我假设您拥有作为 MATLAB 一部分的计算机视觉和图像处理工具箱。如果你不这样做,那么 Maurits 给出的答案是一个很好的选择,而 VLFeat 工具箱是我也使用过的。
首先,让我们直接从 Whosebug 读取图像:
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 的任何特征检测算法...。我将使用属于 CVST 工具箱的 SURF as it is essentially the same as SIFT, but with some minor but key differences. You can use the detectSURFFeatures
函数,它接受灰度图像。输出是一个结构,其中包含有关算法为图像检测到的每个特征点的一堆信息。让我们将其应用于两个图像(灰度)。
points = detectSURFFeatures(im_gray);
points2 = detectSURFFeatures(im2_gray);
一旦我们检测到特征,现在就可以提取描述符描述这些关键点。这可以用 extractFeatures
来完成。这需要一个灰度图像和从 detectSURFFeatures
输出的相应结构。经过一些 post 处理后,输出是一组特征和有效关键点。
[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');
第一个输入接受一组 input 点,这些点是您要转换的点。第二个输入接受一组 基点 ,它们是 参考 点。这些点就是我们要匹配的。
在我们的例子中,我们想要扭曲第一个图像中的点 - 站着的人并使其匹配第二个图像 - 靠在他身边的人,所以第一个输入是第一个图像中的点图像,第二个输入是来自第二个图像的点。
对于匹配点,我们要引用 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
等。您可能需要尝试一下使用参数在您尝试的不同图像对中获得一致的结果。我会把它留给你作为练习。查看我在上面链接的关于每个函数的所有链接,以便您可以根据自己的喜好调整参数。
玩得开心,祝你好运!
查看计算机视觉系统工具箱中的 Find Image Rotation and Scale Using Automated Feature Matching 示例。
它展示了如何检测兴趣点、提取和匹配特征描述符,以及计算两幅图像之间的变换。
这是一种与其他方法截然不同的方法。基于特征的注册方法更健壮,但我的方法可能对你的应用程序有用,所以我把它写在这里。
- 加载参考图像(我称之为模型)和您要与模型进行比较的图像
- 计算两张图片的直方图
- 比较两个直方图。有很多方法可以做到这一点。在这里,我将使用交集和相关性
Histogram Intersection : 计算直方图交集并通过将其除以模型直方图中的像素数对其进行归一化。这将为您提供 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。
我有两张相似但方向和大小不同的图片。下面是一个示例:
有没有办法匹配这两张图片?
我用过Procrustes形状分析,还有其他方法吗?
您可以通过以下方式获得合理的结果:
- 检测两个图像中的 SIFT 点。例如 vlfeat lib.
- 使用 Lowe 规则匹配 SIFT 描述符,由 vlfeat 实现
vl_ubcmatch
- 使用 RANSAC 查找符合某些单应性 H 的匹配点子集。可以在 Peter Kovesi 的站点上看到使用 Harris 特征点的示例,旁边是 RANSAC 本身和其他有用的函数。
初步结果:
这里有一些可以帮助您入门的东西。您要问的是一个经典问题 image registration。图像配准旨在找到获取一张图像并将其与另一张图像对齐的正确单应性。这涉及找到两个图像之间共有的兴趣点或关键点,并确定哪些关键点在两个图像之间匹配。一旦你有了这些点对,你就可以确定一个单应矩阵并扭曲其中一个图像,使它们与另一个与这个矩阵对齐。
我假设您拥有作为 MATLAB 一部分的计算机视觉和图像处理工具箱。如果你不这样做,那么 Maurits 给出的答案是一个很好的选择,而 VLFeat 工具箱是我也使用过的。
首先,让我们直接从 Whosebug 读取图像:
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 的任何特征检测算法...。我将使用属于 CVST 工具箱的 SURF as it is essentially the same as SIFT, but with some minor but key differences. You can use the detectSURFFeatures
函数,它接受灰度图像。输出是一个结构,其中包含有关算法为图像检测到的每个特征点的一堆信息。让我们将其应用于两个图像(灰度)。
points = detectSURFFeatures(im_gray);
points2 = detectSURFFeatures(im2_gray);
一旦我们检测到特征,现在就可以提取描述符描述这些关键点。这可以用 extractFeatures
来完成。这需要一个灰度图像和从 detectSURFFeatures
输出的相应结构。经过一些 post 处理后,输出是一组特征和有效关键点。
[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');
第一个输入接受一组 input 点,这些点是您要转换的点。第二个输入接受一组 基点 ,它们是 参考 点。这些点就是我们要匹配的。
在我们的例子中,我们想要扭曲第一个图像中的点 - 站着的人并使其匹配第二个图像 - 靠在他身边的人,所以第一个输入是第一个图像中的点图像,第二个输入是来自第二个图像的点。
对于匹配点,我们要引用 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
等。您可能需要尝试一下使用参数在您尝试的不同图像对中获得一致的结果。我会把它留给你作为练习。查看我在上面链接的关于每个函数的所有链接,以便您可以根据自己的喜好调整参数。
玩得开心,祝你好运!
查看计算机视觉系统工具箱中的 Find Image Rotation and Scale Using Automated Feature Matching 示例。
它展示了如何检测兴趣点、提取和匹配特征描述符,以及计算两幅图像之间的变换。
这是一种与其他方法截然不同的方法。基于特征的注册方法更健壮,但我的方法可能对你的应用程序有用,所以我把它写在这里。
- 加载参考图像(我称之为模型)和您要与模型进行比较的图像
- 计算两张图片的直方图
- 比较两个直方图。有很多方法可以做到这一点。在这里,我将使用交集和相关性
Histogram Intersection : 计算直方图交集并通过将其除以模型直方图中的像素数对其进行归一化。这将为您提供 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。