Welcome toVigges Developer Community-Open, Learning,Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
976 views
in Technique[技术] by (71.8m points)

opencv - Detecting artifact differences between two images

I want to programmatically detect a "material difference" between two images ignoring cropping and scaling changes.

In other words, if image A shows a tree, a car, and a cloud, and image B is just a (slightly) cropped and (slightly) smaller copy of A (but all other features are untouched) and lower quality, then I want to consider these a match. But if B has a different cloud, or the car has moved (etc), then the images are different.

Example: Here is image A:

image A

And here, image B, is just a cropped and resized version of A:

enter image description here

But now, here image C is not only cropped/resized but also has a yellow asterisk.

enter image description here

I would like to detect changes of the kind between A and C, but ignore the differences between A and B. I have tried imagemagick subimage search but it is both (1) extremely slow and (2) fails to find the subimage no matter what metric I use (probably because image B has higher jpg compression, aka lower quality). A perceptual hash scores the images as "similar" despite the asterisk because the pictures are largely similar. Perhaps something based on feature detection with OpenCV might be my best bet?

question from:https://stackoverflow.com/questions/65862499/detecting-artifact-differences-between-two-images

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Answer

0 votes
by (71.8m points)

Histograms work well for this kind of change detection. Differences in rotation, sharpness and scale won't have much effect, but things like adding a yellow star will show strongly.

For example, using ruby-vips (since I know it well):

require "ruby-vips"

a = Vips::Image.new_from_file ARGV[0], access: :sequential  
b = Vips::Image.new_from_file ARGV[1], access: :sequential

# peak normalised difference in histograms
mx = (a.hist_find.hist_norm - b.hist_find.hist_norm).abs.max

puts "peak difference = #{mx}"

I see:

john@kiwi:~/try$ ./hdiff.rb ~/pics/A.png ~/pics/B.png 
peak difference = 53.0
john@kiwi:~/try$ ./hdiff.rb ~/pics/B.png ~/pics/C.png 
peak difference = 140.0

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome to Vigges Developer Community for programmer and developer-Open, Learning and Share
...