Skip to content

Instantly share code, notes, and snippets.

@angelfan
Forked from rasefon/si.rb
Created March 21, 2016 02:03
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save angelfan/ced2baa571db278ff881 to your computer and use it in GitHub Desktop.
Save angelfan/ced2baa571db278ff881 to your computer and use it in GitHub Desktop.
Similar Image Compare
require 'RMagick'
$scale_size = 256.0
$img_fn1 = ARGV[0]
$img_fn2 = ARGV[1]
$scale_size = ARGV[2].to_f if ARGV[2]
def calculate_threshold(img_fn)
dir_name = File.dirname(img_fn)
img = Magick::Image.read(img_fn).first
img.scale!($scale_size, $scale_size)
img = img.quantize(256, Magick::GRAYColorspace)
img = img.negate(true)
# record negative image
img.write(File.join(dir_name, "ng_#{img_fn}"))
rows = img.rows
cols = img.columns
pixels = img.export_pixels(0, 0, cols, rows, "I").map { |p| p / 256 }
total_pixels = pixels.size
# Calculate histogram
histogram = Array.new(256, 0)
pixels.each do |p|
histogram[p] += 1
end
#p histogram
sum = 0.0
256.times { |i| sum += i * histogram[i] }
sum_b = 0.0
w_b, w_f = 0, 0
max_cache = 0.0
threshold = 0
256.times do |t|
w_b += histogram[t]
next if 0 == w_b
w_f = total_pixels - w_b
break if 0 == w_f
sum_b += t * histogram[t]
m_b = sum_b / w_b
m_f = (sum - sum_b) / w_f
#puts "mb:#{m_b} mf:#{m_f} wb:#{w_b} wf:#{w_f}"
between = w_b * w_f * (m_b - m_f) ** 2
if between > max_cache
max_cache = between
threshold = t
end
end
#puts threshold
img = img.threshold(threshold * 256)
img.write(File.join(dir_name, "threshold_#{img_fn}"))
result = Hash.new
result["threshold"] = threshold
result["bw_img"] = img
result
end
def hamming_dist(img_fn1, img_fn2)
img_result1 = calculate_threshold(img_fn1)
img_result2 = calculate_threshold(img_fn2)
img1 = img_result1["bw_img"]
pixels1 = img1.export_pixels(0, 0, img1.columns, img1.rows, "I").map { |p| p / 65535 }
img2 = img_result2["bw_img"]
pixels2 = img2.export_pixels(0, 0, img2.columns, img2.rows, "I").map { |p| p / 65535 }
hd = 0
difference_pixels = []
pixels1.each_index do |i|
pixel = pixels1[i] ^ pixels2[i]
hd += pixel
difference_pixels[i] = pixel * 65535
end
[hd, difference_pixels]
end
result = hamming_dist($img_fn1, $img_fn2)
hd = result[0]
difference_rate = hd / $scale_size ** 2 * 100
puts "Hamming distance: #{hd}"
puts "Difference rate: #{difference_rate}%"
if 0 != hd
d_img = Magick::Image.new($scale_size, $scale_size)
d_img.import_pixels(0, 0, $scale_size, $scale_size, "I", result[1])
fn1 = File.basename($img_fn1, File.extname($img_fn1))
fn2 = File.basename($img_fn2, File.extname($img_fn2))
d_img.write(File.join("#{fn1}_#{fn2}_diff_img.png"))
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment