Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
1.2k 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 Reply

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

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...