1

2 つの画像を比較して、同一かどうかを確認しようとしています。それらは同じサイズである必要があり、同じサイズである場合もありますが、コンテンツは時々変更されるため、それを検出できるようにしたいと考えています。

私の場合、2 つの方法があります。1 つは、各画像の色数を取得することです。(私の場合は画像が違うと色数が変わります)

または、実際に画像プロセッサを使用してファイルを比較します。ruby-vips8よりもはるかに高速であることが知られているため、使用することを選択しましRMagickた。私の場合、パフォーマンスが重要です。

でいくつかのスクラッチを作成しましたruby-vips8が、2 つの画像を比較したり、色の数を取得したりする方法が見つかりません (したがって、この方法を使用して比較できます)。

何か助けはありますか?

ruby-vips8は libvips のラッパーです

http://www.rubydoc.info/gems/ruby-vips8/0.1.0/Vips/ http://www.vips.ecs.soton.ac.uk/index.php?title=VIPS

アップデート:

ユーザーAetherusruby-vips8の回答により、そのようなタスクを実行する必要さえないことに気付きました。ファイルを文字列として比較しています(彼が提案したように)。それは私にとって非常にうまく機能しており、また非常に高速です。

私の質問では、ruby-vips8. lib固有のシナリオだったので、そのような状況ではuser894763の回答がより適切です。

4

2 に答える 2

8

画像の類似性を測定するには何百もの方法があるはずです。それは巨大な分野です。それらは、考慮しようとする画像の特徴によって (ほとんど) 異なります。

スコットが言ったように、一連の類似性尺度はヒストグラムに基づいています。これらの手法では、ピクセルが空間的にどのように配置されているかを考慮していないため、2 つの画像が 45 度回転している場合、2 つの画像は同じと見なされる可能性があります。ヒストグラムを見つけるのが速いので、それらも高速です。

単純なヒストグラム マッチャーは次のようになります。2 つの入力画像のヒストグラムを見つけ、正規化 (2 つのヒストの面積が同じになるように...これにより画像サイズの違いが取り除かれます)、減算、二乗、および合計。現在、数値が小さいほど一致が良好であることを意味し、数値が大きいほど一致が悪化することを意味します。

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 のグリッド (チェス盤のようなもの) に分割し、各正方形の平均ピクセル値を取得してから、正方形の平均が上か下かに応じて、その正方形を 0 または 1 に設定することです。画像全体の平均。これにより、画像のフィンガープリントのようなものが得られ、64 ビット int にきれいに保存できます。ノイズ、スケールの変化、小さな回転などの影響を受けません。

2 つの画像の類似性をテストするには、それらのフィンガープリントを XOR し、結果の設定ビット数を数えます。繰り返しますが、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とその友人を参照してください。画像の小さな領域を見つけるのに役立つ場合があります。

多くの洗練された画像類似度メトリックは、さまざまなアルゴリズムを使用してすべてを実行し、一連の重み係数を使用して全体的な類似度を計算します。

于 2016-04-11T13:05:28.720 に答える
0

「同じ」と「同じに見える」は別物です。

2 つの画像が「同じ」かどうかを確認したい場合は、それらを 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 つの画像が「同じに見える」かどうかを確認するのは非常に難しい作業です。たとえば、PNG と JPG は同じに見えるかもしれませんが、同じピクセル配列を持つことはほとんどありません。2 つの画像が同じタイプであっても、同じように見えるかもしれませんが、実際には 2 番目の画像は最初の画像と比較して 1 ピクセル オフセットであるか、2 つの画像間の彩度が少し異なります。または ...

私はそれをやったことがなく、それが実行可能かどうかわかりません。

于 2016-04-10T01:06:12.637 に答える