我认为您的代码不是问题。相反,似乎要么你的特征描述符不够强大,要么你的比较方法不够强大,或者两者兼而有之。这为我们提供了几种探索问题解决方案的选择。
特征描述符
您正在构建由骨架交点之间的距离组成的图像特征。这是一种不寻常的方法,也是一种非常有趣的方法。它让我想起了巅峰星座,这是 Shazam 用于音频指纹歌曲的一项功能。如果您有兴趣探索更复杂的技术,请查看 Avery Li-Chun Wang 的 "An Industrial Strength Audio Search Algorithm"。我相信您可以将他们的特征描述符调整到您的应用程序中。
但是,如果您想要更简单的解决方案,还有其他一些选择。您当前的描述符使用unique 来查找骨架交点之间的一组唯一距离。看看下面的直线和等边三角形的图像,它们都有 5 个单位线长。如果我们使用顶点之间的唯一距离来制作特征,那么两幅图像具有相同的特征,但我们也可以统计直方图中每个长度的行数。
直方图保留了更多图像结构作为特征的一部分。使用直方图可能有助于更好地区分相似和不同的情况。
这里有一些使用 Matlab 演示图像 pears.png 和 peppers.png 的直方图功能演示代码。我在从您提供的图像中提取骨架时遇到了困难,但您应该能够轻松地将此代码调整到您的应用程序中。
I1 = = im2bw(imread('peppers.png'));
I2 = = im2bw(imread('pears.png'));
I1_skel = bwmorph(I1,'skel',Inf);
I2_skel = bwmorph(I2,'skel',Inf);
[i1,j1] = ind2sub(size(I1_skel),find(bwmorph(bwmorph(I1_skel,'thin',Inf),'branchpoint') == 1));
[i2,j2] = ind2sub(size(I2_skel),find(bwmorph(bwmorph(I2_skel,'thin',Inf),'branchpoint') == 1));
%You used a for loop to find the distance between each pair of
%intersections. There is a function for this.
d1 = round(pdist2([i1, j1], [i1, j1]));
d2 = round(pdist2([i2, j2], [i2, j2]));
%Choose a number of bins for the histogram.
%This will be the length of the feature.
%More bins will preserve more structure.
%Fewer bins will help generalize between similar but not identical images.
num_bins = 100;
%Instead of using `unique` to remove repetitions use `histcounts` in R2014b
%feature1 = histcounts(d1(:), num_bins);
%feature2 = histcounts(d2(:), num_bins);
%Use `hist` for pre R2014b Matlab versions
feature1 = hist(d1(:), num_bins);
feature2 = hist(d2(:), num_bins);
%Normalize the features
feature1 = feature1 ./ norm(feature1);
feature2 = feature2 ./ norm(feature2);
figure; bar([feature1; feature2]');
title('Features'); legend({'Feature 1', 'Feature 2'});
xlim([0, num_bins]);
以下是每张图像中检测到的交点
以下是生成的功能。您可以看到图像之间的明显差异。
功能比较
要考虑的第二部分是您如何比较您的功能。目前,您只是在寻找 >20 个相似的距离。使用 Matlab 分发的“peppers.png”和“pears.png”测试图像,我在一张图像中找到了 2000 多个交点,在另一张图像中找到了 260 个。有这么多的点,重叠超过 20 个相似距离是微不足道的。在您的图像中,交叉点的数量要少得多。您可以仔细调整相似距离的阈值,但我认为这个指标可能过于简单化。
在机器学习中,比较两个特征向量的一种简单方法是向量相似度或距离。您可以探索多种距离指标。常见的有
- 余弦距离
score_cosine = feature1 * feature2'; %Cosine distance between vectors
%Set a threshold for cosine similarity [0, 1] where 1 is identical and 0 is perpendicular
cosine_threshold = .9;
disp('Cosine Compare')
disp(score_cosine)
if score_cosine > cosine_threshold
disp('similar images');
else
disp('dissimilar images');
end
- 欧几里得距离
score_euclidean = pdist2(feature1, feature2);
%Set a threshold for euclidean similarity where smaller is more similar
euclidean_threshold = 0.1;
disp('Euclidean Compare')
disp(score_euclidean)
if score_euclidean < euclidean_threshold
disp('similar images');
else
disp('dissimilar images');
end
如果这些都不起作用,您可能需要训练分类器以找到更复杂的函数来区分相似和不同的图像。