dhash-vips 0.1.0.3 → 0.1.1.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/README.md +15 -42
- data/Rakefile +11 -3
- data/dhash-vips.gemspec +4 -3
- data/extconf.rb +14 -9
- data/lib/dhash-vips-post-install-test.rb +13 -1
- data/lib/dhash-vips.rb +19 -5
- metadata +16 -16
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: e462c5c41c5f2c5916223c083f22d16ae37a062b
|
4
|
+
data.tar.gz: 3261d15852334f30b59bd53cbfdd03e4a6db8758
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 80c90dd232d5c9ea5ccfd65d715c48bafb56ca94aac70e45ced117ad27e748ae81030010f4eb62f963b86f0854d1a9c6d3f4174de730cb8f763fd7dcfcf60f89
|
7
|
+
data.tar.gz: bbe1bee6c35949f68fe886512668d3ea5215daa2207f49fe3f2db51b5ea3c1829d2fb7c69a4d3b05a05afab6df7d243ba37d10d6de39aae1088b404189d43326
|
data/README.md
CHANGED
@@ -93,10 +93,6 @@ end
|
|
93
93
|
|
94
94
|
* The above `15` and `25` constants are found empirically and just work enough well for 8-byte hashes. To find these thresholds we can run a rake task with hardcoded test cases (pairs of photos from the same photosession are not the same but are considered to be enough 'similar' for the purpose of this benchmark):
|
95
95
|
|
96
|
-
$ vips -v
|
97
|
-
vips-8.9.2-Tue Apr 21 09:26:11 UTC 2020
|
98
|
-
$ identify -version | head -1
|
99
|
-
Version: ImageMagick 6.9.11-24 Q16 x86_64 2020-07-18 https://imagemagick.org
|
100
96
|
$ rake compare_quality
|
101
97
|
|
102
98
|
Dhash Phamilie DHashVips::DHash DHashVips::IDHash DHashVips::IDHash(4)
|
@@ -111,45 +107,9 @@ end
|
|
111
107
|
|
112
108
|
* Methods were renamed from `#calculate` to `#fingerprint` and from `#hamming` to `#distance`.
|
113
109
|
* The `DHash#calculate` accepts `hash_size` optional parameter that is 8 by default. The `IDHash#fingerprint`'s optional parameter is called `power` and works in a bit different way: 3 means 8 and 4 means 16 -- other sizes are not supported because they don't seem to be useful (higher fingerprint resolution makes it vulnerable to image shifts and croppings, also `#distance` becomes much slower). Because IDHash's fingerprint is more complex than DHash's one it's not that straight forward to compare them so under the hood the `#distance` method have to check the size of fingerprint. If you are sure that fingerprints were made with power=3 then to skip the check you may use the `#distance3` method directly.
|
114
|
-
* The `#distance3` method will use Ruby C extension that is around 15 times faster than pure Ruby implementation -- native extension
|
110
|
+
* The `#distance3` method will try to compile and use the Ruby C extension that is around 15 times faster than pure Ruby implementation -- native extension currently works on macOS rbenv Ruby from 2.3.8 to 2.4.9 installed with rbenv `-k` flag. So the full benchmark:
|
115
111
|
|
116
|
-
* Ruby 2.
|
117
|
-
|
118
|
-
$ bundle exec rake compare_speed
|
119
|
-
|
120
|
-
load the image and calculate the fingerprint:
|
121
|
-
user system total real
|
122
|
-
Dhash 12.400000 0.820000 13.220000 ( 13.329952)
|
123
|
-
DHashVips::DHash 1.330000 0.230000 1.560000 ( 1.509826)
|
124
|
-
DHashVips::IDHash 1.060000 0.090000 1.150000 ( 1.100332)
|
125
|
-
DHashVips::IDHash 4 1.030000 0.080000 1.110000 ( 1.089148)
|
126
|
-
|
127
|
-
measure the distance (32*32*1000 times):
|
128
|
-
user system total real
|
129
|
-
Dhash hamming 3.140000 0.020000 3.160000 ( 3.179392)
|
130
|
-
DHashVips::DHash hamming 3.040000 0.020000 3.060000 ( 3.095190)
|
131
|
-
DHashVips::IDHash distance 8.170000 0.040000 8.210000 ( 8.279950)
|
132
|
-
DHashVips::IDHash distance3 6.720000 0.030000 6.750000 ( 6.790900)
|
133
|
-
DHashVips::IDHash distance 4 24.430000 0.130000 24.560000 ( 24.652625)
|
134
|
-
|
135
|
-
* Ruby 2.3.3 seems to have some bit arithmetics improvement compared to 2.0:
|
136
|
-
|
137
|
-
load the image and calculate the fingerprint:
|
138
|
-
user system total real
|
139
|
-
Dhash 13.110000 0.950000 14.060000 ( 14.537057)
|
140
|
-
DHashVips::DHash 1.480000 0.310000 1.790000 ( 1.808787)
|
141
|
-
DHashVips::IDHash 1.080000 0.100000 1.180000 ( 1.156446)
|
142
|
-
DHashVips::IDHash 4 1.030000 0.090000 1.120000 ( 1.076117)
|
143
|
-
|
144
|
-
measure the distance (32*32*1000 times):
|
145
|
-
user system total real
|
146
|
-
Dhash hamming 1.770000 0.010000 1.780000 ( 1.815612)
|
147
|
-
DHashVips::DHash hamming 1.810000 0.010000 1.820000 ( 1.875666)
|
148
|
-
DHashVips::IDHash distance 4.250000 0.020000 4.270000 ( 4.350071)
|
149
|
-
DHashVips::IDHash distance3 3.430000 0.020000 3.450000 ( 3.499031)
|
150
|
-
DHashVips::IDHash distance 4 8.210000 0.110000 8.320000 ( 8.510735)
|
151
|
-
|
152
|
-
* Ruby 2.3.8p459 (2.4.6, 2.5.5 and 2.6.3 are all similar) with newer CPU (`sysctl -n machdep.cpu.brand_string #=> Intel(R) Core(TM) i5-7360U CPU @ 2.30GHz`):
|
112
|
+
* Ruby 2.3.8p459:
|
153
113
|
|
154
114
|
load the image and calculate the fingerprint:
|
155
115
|
user system total real
|
@@ -169,6 +129,19 @@ end
|
|
169
129
|
DHashVips::IDHash distance3_c 0.210000 0.000000 0.210000 ( 0.212864)
|
170
130
|
DHashVips::IDHash distance 4 8.300000 0.120000 8.420000 ( 8.499735)
|
171
131
|
|
132
|
+
* There is now a benchmark that runs both speed and quality tests summing results to a single table where lower numbers are better:
|
133
|
+
|
134
|
+
ruby 2.3.8p459 (2018-10-18 revision 65136) [x86_64-darwin18]
|
135
|
+
vips-8.9.2-Tue Apr 21 09:26:11 UTC 2020
|
136
|
+
Version: ImageMagick 6.9.11-24 Q16 x86_64 2020-07-18
|
137
|
+
Intel(R) Core(TM) i5-7360U CPU @ 2.30GHz
|
138
|
+
|
139
|
+
Fingerprint Compare 1/FMI^2
|
140
|
+
Phamilie 3.943 0.630 4.000
|
141
|
+
Dhash 4.969 1.097 1.375
|
142
|
+
DHash 0.434 1.089 1.556
|
143
|
+
IDHash 0.396 0.126 1.250
|
144
|
+
|
172
145
|
* Also note that to make `#distance` able to assume the fingerprint resolution from the size of Integer that represents it, the change in its structure was needed (left half of bits was swapped with right one), so fingerprints between versions 0.0.4 and 0.0.5 became incompatible, but you probably can convert them manually. Otherwise if we put the version or structure information inside fingerprint it would became slow to (de)serialize and store.
|
173
146
|
|
174
147
|
## Development notes
|
data/Rakefile
CHANGED
@@ -1,7 +1,11 @@
|
|
1
|
-
|
2
|
-
|
1
|
+
begin
|
2
|
+
# for `rake release`
|
3
|
+
require "bundler/gem_tasks"
|
4
|
+
rescue LoadError
|
5
|
+
puts "consider to `gem install bundler` to be able to `rake release`"
|
6
|
+
end
|
3
7
|
|
4
|
-
require "
|
8
|
+
require "pp"
|
5
9
|
|
6
10
|
visualize_hash = lambda do |hash|
|
7
11
|
puts hash.to_s(2).rjust(64, ?0).gsub(/(?<=.)/, '\0 ').scan(/.{16}/)
|
@@ -346,6 +350,10 @@ task :benchmark do
|
|
346
350
|
fmi
|
347
351
|
end
|
348
352
|
|
353
|
+
puts RUBY_DESCRIPTION
|
354
|
+
system "vips -v"
|
355
|
+
system "identify -version | /usr/bin/head -1"
|
356
|
+
system "sysctl -n machdep.cpu.brand_string"
|
349
357
|
require "mll"
|
350
358
|
puts MLL::grid.call %w{ \ Fingerprint Compare 1/FMI^2 }.zip(*[
|
351
359
|
%w{ Phamilie Dhash DHash IDHash },
|
data/dhash-vips.gemspec
CHANGED
@@ -1,9 +1,9 @@
|
|
1
1
|
Gem::Specification.new do |spec|
|
2
2
|
spec.name = "dhash-vips"
|
3
|
-
spec.version = "0.1.0
|
3
|
+
spec.version = "0.1.1.0"
|
4
4
|
spec.author = "Victor Maslov"
|
5
5
|
spec.email = "nakilon@gmail.com"
|
6
|
-
spec.summary = "dHash and IDHash
|
6
|
+
spec.summary = "dHash and IDHash perceptual image hashing/fingerprinting"
|
7
7
|
spec.homepage = "https://github.com/nakilon/dhash-vips"
|
8
8
|
spec.license = "MIT"
|
9
9
|
|
@@ -20,12 +20,13 @@ Gem::Specification.new do |spec|
|
|
20
20
|
|
21
21
|
spec.add_development_dependency "rake"
|
22
22
|
spec.add_development_dependency "minitest"
|
23
|
-
spec.add_development_dependency "get_process_mem"
|
24
23
|
|
25
24
|
spec.add_development_dependency "rmagick", "~>2.16"
|
26
25
|
spec.add_development_dependency "phamilie"
|
27
26
|
spec.add_development_dependency "dhash"
|
28
27
|
|
28
|
+
spec.add_development_dependency "get_process_mem"
|
29
|
+
|
29
30
|
spec.add_development_dependency "mll"
|
30
31
|
spec.add_development_dependency "byebug"
|
31
32
|
end
|
data/extconf.rb
CHANGED
@@ -1,13 +1,17 @@
|
|
1
1
|
require "mkmf"
|
2
2
|
|
3
3
|
File.write "Makefile", dummy_makefile(?.).join
|
4
|
-
unless Gem::Platform.local.os == "darwin" &&
|
4
|
+
unless Gem::Platform.local.os == "darwin" && ENV["RBENV_ROOT"] && ENV["RBENV_VERSION"]
|
5
5
|
else
|
6
|
-
|
7
|
-
|
8
|
-
append_cppflags "-I#{Dir.glob("#{`rbenv root`.chomp}/sources/#{`rbenv version-name`.chomp}/*/").first}"
|
9
|
-
rescue
|
6
|
+
if Gem::Version.new(RUBY_VERSION) < Gem::Version.new("2.3.8") ||
|
7
|
+
Gem::Version.new(RUBY_VERSION) > Gem::Version.new("2.4.9")
|
10
8
|
else
|
9
|
+
if Gem::Version.new(RUBY_VERSION) < Gem::Version.new("2.4")
|
10
|
+
else
|
11
|
+
append_cppflags "-DRUBY_EXPORT"
|
12
|
+
end
|
13
|
+
# https://github.com/rbenv/rbenv/issues/1199
|
14
|
+
append_cppflags "-I#{Dir.glob("#{ENV["RBENV_ROOT"]}/sources/#{ENV["RBENV_VERSION"]}/ruby-*/").first}"
|
11
15
|
create_makefile "idhash"
|
12
16
|
# Why this hack?
|
13
17
|
# 1. Because I want to use Ruby and ./idhash.bundle for tests, not C.
|
@@ -21,10 +25,11 @@ else
|
|
21
25
|
end
|
22
26
|
|
23
27
|
# Cases to check:
|
24
|
-
# 0.
|
25
|
-
# `rm -rf idhash.o idhash.bundle pkg && bundle exec rake install`
|
26
|
-
# `
|
27
|
-
# `bundle
|
28
|
+
# 0. everything is ok
|
29
|
+
# `rm -rf idhash.o idhash.bundle idhash.so pkg && bundle exec rake install`
|
30
|
+
# `bundle exec rake -rdhash-vips -e "p DHashVips::IDHash.method(:distance3).source_location"` # => # ["/Users/nakilon/_/dhash-vips/lib/dhash-vips.rb", 32] # currently falsely says that gem install failed idk why
|
31
|
+
# `rm -f idhash.o idhash.bundle idhash.so Makefile && ruby extconf.rb && make`
|
32
|
+
# `bundle exec rake -rdhash-vips -e "p DHashVips::IDHash.method(:distance3).source_location"` # => # ["/Users/nakilon/_/dhash-vips/lib/dhash-vips.rb", 53]
|
28
33
|
# 1. not macOS && rbenv
|
29
34
|
# 2. fail during append_cppflags
|
30
35
|
# 3. failed compilation
|
@@ -20,8 +20,20 @@ ss = s.repeated_permutation(4).map do |s1, s2, s3, s4|
|
|
20
20
|
end
|
21
21
|
end
|
22
22
|
fail unless :distance3 == DHashVips::IDHash.method(:distance3).original_name
|
23
|
+
if Gem::Version.new(RUBY_VERSION) < Gem::Version.new("2.4")
|
24
|
+
check = lambda do |s1, s2|
|
25
|
+
s1.is_a?(Bignum) && s2.is_a?(Bignum)
|
26
|
+
end
|
27
|
+
else
|
28
|
+
require "rbconfig/sizeof"
|
29
|
+
check = lambda do |s1, s2|
|
30
|
+
# https://github.com/ruby/ruby/commit/de2f7416d2deb4166d78638a41037cb550d64484#diff-16b196bc6bfe8fba63951420f843cfb4R10
|
31
|
+
_FIXNUM_MAX = (1 << (8 * RbConfig::SIZEOF["long"] - 2)) - 1
|
32
|
+
s1 > _FIXNUM_MAX && s2 > _FIXNUM_MAX
|
33
|
+
end
|
34
|
+
end
|
23
35
|
ss.product ss do |s1, s2|
|
24
|
-
next unless
|
36
|
+
next unless check.call s1, s2
|
25
37
|
unless f[s1, s2] == DHashVips::IDHash.distance3_c(s1, s2)
|
26
38
|
p [s1, s2]
|
27
39
|
p [s1.to_s(16).rjust(64,?0)].pack("H*").unpack("N*").map{ |_| _.to_s(2).rjust(32, ?0) }
|
data/lib/dhash-vips.rb
CHANGED
@@ -37,11 +37,25 @@ module DHashVips
|
|
37
37
|
rescue LoadError
|
38
38
|
alias_method :distance3, :distance3_ruby
|
39
39
|
else
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
40
|
+
# we can't just do `defined? Bignum` because it's defined but deprecated (some internal CONST_DEPRECATED flag)
|
41
|
+
if Gem::Version.new(RUBY_VERSION) < Gem::Version.new("2.4")
|
42
|
+
def distance3 a, b
|
43
|
+
if a.is_a?(Bignum) && b.is_a?(Bignum)
|
44
|
+
distance3_c a, b
|
45
|
+
else
|
46
|
+
distance3_ruby a, b
|
47
|
+
end
|
48
|
+
end
|
49
|
+
else
|
50
|
+
# https://github.com/ruby/ruby/commit/de2f7416d2deb4166d78638a41037cb550d64484#diff-16b196bc6bfe8fba63951420f843cfb4R10
|
51
|
+
require "rbconfig/sizeof"
|
52
|
+
FIXNUM_MAX = (1 << (8 * RbConfig::SIZEOF["long"] - 2)) - 1
|
53
|
+
def distance3 a, b
|
54
|
+
if a > FIXNUM_MAX && b > FIXNUM_MAX
|
55
|
+
distance3_c a, b
|
56
|
+
else
|
57
|
+
distance3_ruby a, b
|
58
|
+
end
|
45
59
|
end
|
46
60
|
end
|
47
61
|
end
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: dhash-vips
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.1.0
|
4
|
+
version: 0.1.1.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Victor Maslov
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2020-07-
|
11
|
+
date: 2020-07-26 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: ruby-vips
|
@@ -53,35 +53,35 @@ dependencies:
|
|
53
53
|
- !ruby/object:Gem::Version
|
54
54
|
version: '0'
|
55
55
|
- !ruby/object:Gem::Dependency
|
56
|
-
name:
|
56
|
+
name: rmagick
|
57
57
|
requirement: !ruby/object:Gem::Requirement
|
58
58
|
requirements:
|
59
|
-
- - "
|
59
|
+
- - "~>"
|
60
60
|
- !ruby/object:Gem::Version
|
61
|
-
version: '
|
61
|
+
version: '2.16'
|
62
62
|
type: :development
|
63
63
|
prerelease: false
|
64
64
|
version_requirements: !ruby/object:Gem::Requirement
|
65
65
|
requirements:
|
66
|
-
- - "
|
66
|
+
- - "~>"
|
67
67
|
- !ruby/object:Gem::Version
|
68
|
-
version: '
|
68
|
+
version: '2.16'
|
69
69
|
- !ruby/object:Gem::Dependency
|
70
|
-
name:
|
70
|
+
name: phamilie
|
71
71
|
requirement: !ruby/object:Gem::Requirement
|
72
72
|
requirements:
|
73
|
-
- - "
|
73
|
+
- - ">="
|
74
74
|
- !ruby/object:Gem::Version
|
75
|
-
version: '
|
75
|
+
version: '0'
|
76
76
|
type: :development
|
77
77
|
prerelease: false
|
78
78
|
version_requirements: !ruby/object:Gem::Requirement
|
79
79
|
requirements:
|
80
|
-
- - "
|
80
|
+
- - ">="
|
81
81
|
- !ruby/object:Gem::Version
|
82
|
-
version: '
|
82
|
+
version: '0'
|
83
83
|
- !ruby/object:Gem::Dependency
|
84
|
-
name:
|
84
|
+
name: dhash
|
85
85
|
requirement: !ruby/object:Gem::Requirement
|
86
86
|
requirements:
|
87
87
|
- - ">="
|
@@ -95,7 +95,7 @@ dependencies:
|
|
95
95
|
- !ruby/object:Gem::Version
|
96
96
|
version: '0'
|
97
97
|
- !ruby/object:Gem::Dependency
|
98
|
-
name:
|
98
|
+
name: get_process_mem
|
99
99
|
requirement: !ruby/object:Gem::Requirement
|
100
100
|
requirements:
|
101
101
|
- - ">="
|
@@ -174,9 +174,9 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
174
174
|
version: '0'
|
175
175
|
requirements: []
|
176
176
|
rubyforge_project:
|
177
|
-
rubygems_version: 2.
|
177
|
+
rubygems_version: 2.6.14.4
|
178
178
|
signing_key:
|
179
179
|
specification_version: 4
|
180
|
-
summary: dHash and IDHash
|
180
|
+
summary: dHash and IDHash perceptual image hashing/fingerprinting
|
181
181
|
test_files:
|
182
182
|
- test.rb
|