Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add dupe check passing two fingerprints #50

Merged
merged 1 commit into from
Nov 7, 2016
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 8 additions & 2 deletions lib/phashion.rb
Original file line number Diff line number Diff line change
Expand Up @@ -12,9 +12,9 @@ module Phashion
TextHashPoint = Struct.new :hash, :index
TextMatch = Struct.new :first_index, :second_index, :length

DEFAULT_DUPE_THRESHOLD = 15

class Image
DEFAULT_DUPE_THRESHOLD = 15

attr_reader :filename
def initialize(filename)
@filename = filename
Expand Down Expand Up @@ -52,6 +52,12 @@ def self.so_file
extname = RbConfig::CONFIG['DLEXT']
File.join File.dirname(__FILE__), "phashion_ext.#{extname}"
end

def self.duplicate?(fingerprint1, fingerprint2, opts={})
threshold = opts[:threshold] || DEFAULT_DUPE_THRESHOLD

Phashion.hamming_distance(fingerprint1, fingerprint2) <= threshold
end
end

require 'phashion_ext'
42 changes: 26 additions & 16 deletions test/test_phashion.rb
Original file line number Diff line number Diff line change
Expand Up @@ -122,19 +122,19 @@ def test_multiple_types
assert_duplicate gif, png
assert_duplicate jpg, gif
end

def test_fingerprint_png_is_different
png1 = Phashion::Image.new(File.dirname(__FILE__) + '/png/Broccoli_Super_Food.png')
png2 = Phashion::Image.new(File.dirname(__FILE__) + '/png/linux.png')
png3 = Phashion::Image.new(File.dirname(__FILE__) + '/png/grass.png')
png4 = Phashion::Image.new(File.dirname(__FILE__) + '/png/Broccoli_Super_Food.png')

fingerprints = []
fingerprints << png1.fingerprint
fingerprints << png2.fingerprint
fingerprints << png3.fingerprint
fingerprints << png4.fingerprint

assert fingerprints.uniq.size == 3, "array should contain 3 unique fingerprints"
end

Expand All @@ -145,8 +145,8 @@ def test_duplicate_with_custom_distance_threshold
jpg = Phashion::Image.new(File.dirname(__FILE__) + '/jpg/Broccoli_Super_Food.jpg')
jpg_x = Phashion::Image.new(File.dirname(__FILE__) + '/jpg/Broccoli_Super_Food.100px.jpg')

refute(jpg.duplicate?(jpg_x, threshold: 1))
assert(jpg.duplicate?(jpg_x, threshold: 2))
refute(jpg.duplicate?(jpg_x, threshold: 1))
assert(jpg.duplicate?(jpg_x, threshold: 2))
end


Expand All @@ -161,28 +161,28 @@ def test_distance_from_jpg_to_png_dupe
def test_distance_from_lossy_jpg
jpg = Phashion::Image.new(File.dirname(__FILE__) + '/jpg/Broccoli_Super_Food.jpg')
jpg_x = Phashion::Image.new(File.dirname(__FILE__) + '/jpg/Broccoli_Super_Food.lossy.jpg')

assert_equal(jpg.distance_from(jpg_x), 0)
end

def test_distance_from_smaller_jpg
jpg = Phashion::Image.new(File.dirname(__FILE__) + '/jpg/Broccoli_Super_Food.jpg')
jpg_x = Phashion::Image.new(File.dirname(__FILE__) + '/jpg/Broccoli_Super_Food.100px.jpg')

assert_equal(jpg.distance_from(jpg_x), 2)
end

def test_distance_from_color_correction
jpg = Phashion::Image.new(File.dirname(__FILE__) + '/jpg/Broccoli_Super_Food.jpg')
jpg_x = Phashion::Image.new(File.dirname(__FILE__) + '/jpg/Broccoli_Super_Food.color-corrected.jpg')

assert_equal(jpg.distance_from(jpg_x), 2)
end

def test_distance_from_black_and_white
jpg = Phashion::Image.new(File.dirname(__FILE__) + '/jpg/Broccoli_Super_Food.jpg')
jpg_x = Phashion::Image.new(File.dirname(__FILE__) + '/jpg/Broccoli_Super_Food.bw.jpg')

assert_equal(jpg.distance_from(jpg_x), 2)
end

Expand All @@ -191,33 +191,43 @@ def test_distance_from_bounding_box
# from 500x349 to 466x312
jpg = Phashion::Image.new(File.dirname(__FILE__) + '/jpg/Broccoli_Super_Food.jpg')
jpg_x = Phashion::Image.new(File.dirname(__FILE__) + '/jpg/Broccoli_Super_Food.bounding-box.jpg')

assert_equal(jpg.distance_from(jpg_x), 12)
end

def test_distance_from_rotation_of_5degrees_c2
jpg = Phashion::Image.new(File.dirname(__FILE__) + '/jpg/Broccoli_Super_Food.jpg')
jpg_x = Phashion::Image.new(File.dirname(__FILE__) + '/jpg/Broccoli_Super_Food.rotate5cw.jpg')

assert_equal(jpg.distance_from(jpg_x), 14)
end


def test_distance_from_horizontal_flip
jpg = Phashion::Image.new(File.dirname(__FILE__) + '/jpg/Broccoli_Super_Food.jpg')
jpg_x = Phashion::Image.new(File.dirname(__FILE__) + '/jpg/Broccoli_Super_Food.horizontal-flip.jpg')
assert_operator(jpg.distance_from(jpg_x), :>, Phashion::Image::DEFAULT_DUPE_THRESHOLD)

assert_operator(jpg.distance_from(jpg_x), :>, Phashion::DEFAULT_DUPE_THRESHOLD)
end

private
def test_duplicate_with_module_method
jpg = Phashion::Image.new(File.dirname(__FILE__) + '/jpg/Broccoli_Super_Food.jpg')
jpg_x = Phashion::Image.new(File.dirname(__FILE__) + '/jpg/Broccoli_Super_Food.bw.jpg')

assert_duplicate_with_module_method(jpg, jpg_x)
end

private

def assert_duplicate(a, b)
assert a.duplicate?(b), "#{a.filename} not dupe of #{b.filename}"
end

def assert_not_duplicate(a, b)
assert !a.duplicate?(b), "#{a.filename} dupe of #{b.filename}"
end
end

def assert_duplicate_with_module_method(a, b)
assert Phashion.duplicate?(a.fingerprint, b.fingerprint), "#{a.filename} not dupe of #{b.filename}"
end
end