必须有数百种测量图像相似性的方式,这是一个巨大的领域。它们(主要)在他们试图考虑的图像的特征中有所不同。正如斯科特所说,一组相似性度量是基于直方图的。这些技术没有考虑像素在空间上的排列方式,因此如果旋转了45度,那么您的两幅图像可能会被视为相同。它们也很快,因为找到直方图很快。
一个简单的直方图匹配器可能是:找到两个输入图像的直方图,归一化(所以两个主题有相同的区域...这消除了图像大小的差异),减去,平方和和。现在少数意味着一个好的搭配,数字越大意味着越差的搭配。
在ruby-vips这将是:
require 'vips'
a = Vips::Image.new_from_file ARGV[0], access: :sequential
b = Vips::Image.new_from_file ARGV[1], access: :sequential
# find hists, normalise, difference, square
diff_hist = (a.hist_find.hist_norm - b.hist_find.hist_norm) ** 2
# find sum of squares ... find the average, then multiply by the size of the
# histogram
similarity = diff_hist.avg * diff_hist.width * diff_hist.height
puts "similarity = #{similarity}"
在我的桌面上,这个运行在大约0.5秒的一对一个2K x 3K JPEG图像。
许多匹配器都基于空间分布。一个简单的方法是将图像分成8x8的网格(如棋盘),取每个平方的平均像素值,然后根据平方的平均值是高于还是低于平均值将该平方设置为0或1整个图像的平均值。这样可以为图像提供类似指纹的图像,您可以将它们整齐地存储在64位整数中。它对噪音,尺度变化或小旋转等不敏感。
要测试两张图像的相似度,请对它们的指纹进行XOR并对结果中设置的位数进行计数。再次,0将是完美的匹配,更大的数字会不太好。
在红宝石贵宾,你可以为这个代码:
require 'vips'
a = Vips::Image.new_from_file ARGV[0], access: :sequential
# we need a mono image
a = a.colourspace "b-w"
# reduce to 8x8 with a box filter
a = a.shrink(a.width/8, a.height/8)
# set pixels to 0 for less than average, 255 for greater than average
a = a > a.avg
a.write_to_file ARGV[1]
这再次运行在大约0.5秒为一个2K x 3K JPEG。
另一个家庭将基于相关性,请参阅spcor和朋友。它们可能对找到图像的一个小区域更有用。
许多更漂亮的图像相似性度量将采用各种算法,将它们全部运行,并使用一组权重因子来计算整体相似性度量。
它看起来像vips支持直方图,并比较直方图是比较图像的一种方法https://stackoverflow.com/questions/6499491/comparing-two-histograms。 OpenCV可以提供更复杂的方式来比较图像https://stackoverflow.com/questions/11541154/checking-images-for-similarity-with-opencv –