是否可以使用 ruby-vips8 检测两个图像是否相同?
Is possible to detect if two images are the same using ruby-vips8?
我正在尝试比较两张图片,看看它们是否相同。它们应该具有相同的尺寸,可能具有相同的大小,但内容有时会发生变化,我希望能够检测到它。
在我的案例中,我有两种方法:一种是获取每张图像中的颜色数。 (在我的例子中,如果图像不同,颜色的数量会改变)
或者确实使用图像处理器比较文件。
我选择使用 ruby-vips8
,因为众所周知它比 RMagick
快得多,而且在我的情况下,性能很重要。
我用 ruby-vips8
进行了一些修改,但我找不到比较两个图像或获取颜色数量的方法(所以我可以使用这种方法进行比较)。
有什么帮助吗?
ruby-vips8 is a wrapper of libvips.
http://www.rubydoc.info/gems/ruby-vips8/0.1.0/Vips/
http://www.vips.ecs.soton.ac.uk/index.php?title=VIPS
更新:
根据用户 Aetherus 的回答,我才意识到我什至不需要 ruby-vips8
来完成这样的任务。我将文件作为字符串进行比较(正如他所建议的)。它对我来说效果很好,而且速度也非常快。
我没有将他的答案标记为最佳答案,因为我的问题是问是否可以使用 ruby-vips8
这样做。是特定于库的场景,因此在这种情况下,user894763 答案更合适。
"Are the same" 和 "look the same" 是两个不同的东西。
如果你想验证是否有 2 张图片 "are the same",那么只需将它们读入 2 个字符串并进行比较。
def same_image?(path1, path2)
return true if path1 == path2
image1 = File.read(path1, 'rb')
image2 = File.read(path2, 'rb')
image1 == image2
end
或者如果你的图像很大,那么就逐字节读取它们并进行比较。
def same_image?(path1, path2)
return true if path1 == path2
File.open(path1, 'rb') do |image1|
File.open(path2, 'rb') do |image2|
return false if image1.size != image2.size
while (b1 = image1.read(1024)) and (b2 = image2.read(1024))
return false if b1 != b2
end
end
end
true
end
验证是否有 2 张图像 "look the same" 是一项非常艰巨的工作。例如,PNG 和 JPG 可能看起来相同,但它们几乎从不具有相同的像素阵列。即使两张图像是同一类型,它们可能看起来相同,但实际上第二张图像与第一张图像相比有一个像素偏移,或者两张图像之间的饱和度略有不同,或者 ...
我从来没有这样做过,我不确定它是否可行。
衡量图像相似度的方法肯定有数百种,这是一个巨大的领域。他们(主要)在他们试图考虑图像的哪些特征方面有所不同。
正如 Scott 所说,一系列相似性度量基于直方图。这些技术不考虑您的像素在空间上的排列方式,因此如果将一个图像旋转 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}"
在我的桌面上,对于一对 2k x 3k JPEG 图像,这 运行 秒大约需要 0.5 秒。
很多匹配器都是基于空间分布的。一个简单的方法是将图像分成 8x8 的网格(如棋盘),取每个方格的平均像素值,然后根据方格的平均值是高于还是低于整个图像的平均值。这为图像提供了类似于指纹的东西,您可以将其整齐地存储在 64 位 int 中。它对噪音、比例变化或小旋转等事物不敏感。
要测试两个图像的相似性,请对它们的指纹进行异或并计算结果中设置的位数。同样,0 将是一个完美的匹配,更大的数字会不太好。
在 ruby-vips 中,您可以将其编码为:
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]
同样,对于 2k x 3k JPEG,这 运行 秒大约需要 0.5 秒。
还有一个家庭将基于相关性,请参阅 spcor 和朋友。它们对于查找图像的小区域可能更有用。
许多更高级的图像相似性度量将采用各种算法,运行 所有算法,并使用一组加权因子来计算整体相似性度量。
我正在尝试比较两张图片,看看它们是否相同。它们应该具有相同的尺寸,可能具有相同的大小,但内容有时会发生变化,我希望能够检测到它。
在我的案例中,我有两种方法:一种是获取每张图像中的颜色数。 (在我的例子中,如果图像不同,颜色的数量会改变)
或者确实使用图像处理器比较文件。
我选择使用 ruby-vips8
,因为众所周知它比 RMagick
快得多,而且在我的情况下,性能很重要。
我用 ruby-vips8
进行了一些修改,但我找不到比较两个图像或获取颜色数量的方法(所以我可以使用这种方法进行比较)。
有什么帮助吗?
ruby-vips8 is a wrapper of libvips.
http://www.rubydoc.info/gems/ruby-vips8/0.1.0/Vips/ http://www.vips.ecs.soton.ac.uk/index.php?title=VIPS
更新:
根据用户 Aetherus 的回答,我才意识到我什至不需要 ruby-vips8
来完成这样的任务。我将文件作为字符串进行比较(正如他所建议的)。它对我来说效果很好,而且速度也非常快。
我没有将他的答案标记为最佳答案,因为我的问题是问是否可以使用 ruby-vips8
这样做。是特定于库的场景,因此在这种情况下,user894763 答案更合适。
"Are the same" 和 "look the same" 是两个不同的东西。
如果你想验证是否有 2 张图片 "are the same",那么只需将它们读入 2 个字符串并进行比较。
def same_image?(path1, path2)
return true if path1 == path2
image1 = File.read(path1, 'rb')
image2 = File.read(path2, 'rb')
image1 == image2
end
或者如果你的图像很大,那么就逐字节读取它们并进行比较。
def same_image?(path1, path2)
return true if path1 == path2
File.open(path1, 'rb') do |image1|
File.open(path2, 'rb') do |image2|
return false if image1.size != image2.size
while (b1 = image1.read(1024)) and (b2 = image2.read(1024))
return false if b1 != b2
end
end
end
true
end
验证是否有 2 张图像 "look the same" 是一项非常艰巨的工作。例如,PNG 和 JPG 可能看起来相同,但它们几乎从不具有相同的像素阵列。即使两张图像是同一类型,它们可能看起来相同,但实际上第二张图像与第一张图像相比有一个像素偏移,或者两张图像之间的饱和度略有不同,或者 ...
我从来没有这样做过,我不确定它是否可行。
衡量图像相似度的方法肯定有数百种,这是一个巨大的领域。他们(主要)在他们试图考虑图像的哪些特征方面有所不同。
正如 Scott 所说,一系列相似性度量基于直方图。这些技术不考虑您的像素在空间上的排列方式,因此如果将一个图像旋转 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}"
在我的桌面上,对于一对 2k x 3k JPEG 图像,这 运行 秒大约需要 0.5 秒。
很多匹配器都是基于空间分布的。一个简单的方法是将图像分成 8x8 的网格(如棋盘),取每个方格的平均像素值,然后根据方格的平均值是高于还是低于整个图像的平均值。这为图像提供了类似于指纹的东西,您可以将其整齐地存储在 64 位 int 中。它对噪音、比例变化或小旋转等事物不敏感。
要测试两个图像的相似性,请对它们的指纹进行异或并计算结果中设置的位数。同样,0 将是一个完美的匹配,更大的数字会不太好。
在 ruby-vips 中,您可以将其编码为:
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]
同样,对于 2k x 3k JPEG,这 运行 秒大约需要 0.5 秒。
还有一个家庭将基于相关性,请参阅 spcor 和朋友。它们对于查找图像的小区域可能更有用。
许多更高级的图像相似性度量将采用各种算法,运行 所有算法,并使用一组加权因子来计算整体相似性度量。