dhash-vips 0.1.0.1 → 0.1.0.3
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/README.md +42 -30
- data/Rakefile +86 -3
- data/dhash-vips.gemspec +7 -3
- data/test.rb +10 -8
- metadata +2 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 2b90b4abcd617f0e285dd3399338b4114d921624
|
4
|
+
data.tar.gz: d47a8e51a8e7a2bf28b60d0259dc350f8b5e4fa0
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 3b8b2ce65f3bdfd90d03e3a069e30c61be4a9bf1fc40f9d4beace8216165383d7f54572e996e101ab9fd6f056b260676a9ed465b8860bd1a6e17a4228b859909
|
7
|
+
data.tar.gz: 2ea40198fa4c6ed05183d610b2ca558a6ad67a386e69c127dbc0afac5723686025bd4644cc7297c300d9173b212788cc1ab4f242ad849ed7ee50dbc462dd5f08
|
data/README.md
CHANGED
@@ -1,4 +1,4 @@
|
|
1
|
-
[![Gem Version](https://badge.fury.io/rb/dhash-vips.svg)](http://badge.fury.io/rb/dhash-vips)
|
1
|
+
[![Gem Version](https://badge.fury.io/rb/dhash-vips.svg)](http://badge.fury.io/rb/dhash-vips) [![Docker Image](https://github.com/nakilon/dhash-vips/workflows/Docker%20Image/badge.svg)](https://hub.docker.com/repository/docker/nakilonishe/dhash-vips/general)
|
2
2
|
|
3
3
|
# dHash and IDHash gem powered by ruby-vips
|
4
4
|
|
@@ -7,28 +7,16 @@ The **IDHash** is the new algorithm that has some improvements over dHash -- I'l
|
|
7
7
|
|
8
8
|
You can read about the dHash and perceptual hashing in the article ["Kind of Like That" at "The Hacker Factor Blog"](http://www.hackerfactor.com/blog/index.php?/archives/529-Kind-of-Like-That.html) (21 January 2013). The idea is that you resize the otiginal image to 8x9 and then convert it to 8x8 array of bits -- each tells if the corresponding segment of the image is brighter or darker than the one on the right (or left). Then you apply the [Hamming distance](https://en.wikipedia.org/wiki/Hamming_distance) to such arrays to measure how much they are different.
|
9
9
|
|
10
|
-
There were several Ruby implementations on Github already but they all depended on ImageMagick. My implementation takes an advantage of speed of the libvips (the `ruby-vips` gem) -- it fingerprints images much faster
|
11
|
-
|
12
|
-
load the image and calculate the fingerprint:
|
13
|
-
user system total real
|
14
|
-
Dhash 6.191731 0.230885 6.422616 ( 6.428763)
|
15
|
-
DHashVips::DHash 0.858045 0.144820 1.002865 ( 0.924308)
|
16
|
-
|
17
|
-
`Dhash` here is [another gem](https://github.com/maccman/dhash) that I used earlier in my projects before I decided to make this one.
|
18
|
-
Unfortunately both gems made slightly different fingerprints for two image files that are supposed to have the same fingerprint because from the human point of view they are the same (photo by Jordan Voth):
|
19
|
-
![](https://storage.googleapis.com/dhash-vips.nakilon.pro/dhash_issue_example.png)
|
20
|
-
The distance here appeared to be equal to 5. This is why I've decided to improve the algorithm and this is how the "IDHash" appeared.
|
10
|
+
There were several Ruby implementations on Github already but they all depended on ImageMagick. My implementation takes an advantage of speed of the libvips (the `ruby-vips` gem) -- it fingerprints images much faster. For even more speed the fingerprint comparison function is made as native C extension.
|
21
11
|
|
22
12
|
## IDHash (the Important Difference Hash)
|
23
13
|
|
24
|
-
The main improvement over the dHash is what makes it insensitive to the resizing algorithm
|
14
|
+
The main improvement over the dHash is what makes it insensitive to the resizing algorithm and possible errors due to color scheme conversion.
|
25
15
|
|
26
16
|
* The "Importance" is an array of extra 64 bits that tells the comparing function which half of 64 bits is important (when the difference between neighbors was enough significant) and which is not. So not every bit in a fingerprint is being compared but only half of them.
|
27
17
|
* It subtracts not only horizontally but also vertically -- that adds 128 more bits.
|
28
18
|
* Instead of resizing to 8x9 it resizes to 8x8 and puts the image on a torus so it subtracts the very left column from the very right one and the top from the bottom.
|
29
19
|
|
30
|
-
You could see in fingerprint calculation benchmark earlier that these improvements didn't make it slower than dHash because most of the time is spent on image resizing. Distance measurement is what became slower.
|
31
|
-
|
32
20
|
### Example
|
33
21
|
|
34
22
|
Here are two photos (by Brian Lauer):
|
@@ -49,6 +37,8 @@ Here in each of 64 cells, there are two circles that color the difference betwee
|
|
49
37
|
* [Finding the closest pair between two sets of points on the hypercube](https://cstheory.stackexchange.com/q/16322/27420)
|
50
38
|
* [Would PCA work for boolean data types?](https://stats.stackexchange.com/q/159705/1125)
|
51
39
|
* [Using pHash to search agaist a huge image database, what is the best approach?](https://stackoverflow.com/q/18257641/322020)
|
40
|
+
* [How do I speed up this BIT_COUNT query for hamming distance?](https://stackoverflow.com/q/35065675/322020)
|
41
|
+
* [Hamming distance on binary strings in SQL](https://stackoverflow.com/q/4777070/322020)
|
52
42
|
|
53
43
|
## Installation
|
54
44
|
|
@@ -101,19 +91,23 @@ end
|
|
101
91
|
|
102
92
|
### Notes and benchmarks
|
103
93
|
|
104
|
-
* The above `15` and `25` constants are found empirically and just work enough well for 8-byte hashes. To find these
|
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):
|
105
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
|
106
100
|
$ rake compare_quality
|
107
101
|
|
108
|
-
Dhash Phamilie DHashVips::DHash DHashVips::IDHash DHashVips::IDHash(4)
|
109
|
-
The same image: 0..0 0..0 0..0 0..0 0..0
|
110
|
-
'Jordan Voth case':
|
111
|
-
Similar images: 1..
|
112
|
-
Different images:
|
113
|
-
1/FMI^2 =
|
114
|
-
FP, FN = [
|
102
|
+
Dhash Phamilie DHashVips::DHash DHashVips::IDHash DHashVips::IDHash(4)
|
103
|
+
The same image: 0..0 0..0 0..0 0..0 0..0
|
104
|
+
'Jordan Voth case': 2 2 4 0 0
|
105
|
+
Similar images: 1..15 14..34 2..23 6..22 53..166
|
106
|
+
Different images: 10..54 22..42 10..50 17..65 120..233
|
107
|
+
1/FMI^2 = 1.375 4.0 1.556 1.25 1.306
|
108
|
+
FP, FN = [3, 0] [0, 6] [1, 2] [2, 0] [1, 1]
|
115
109
|
|
116
|
-
The `FMI` line here is the "quality of algorithm", i.e. the best achievable function from the ["Fowlkes–Mallows index"](https://en.wikipedia.org/wiki/Fowlkes%E2%80%93Mallows_index) value if you take the "similar" and "different" test pairs and try to draw the
|
110
|
+
The `FMI` line here is the "quality of algorithm", i.e. the best achievable function from the ["Fowlkes–Mallows index"](https://en.wikipedia.org/wiki/Fowlkes%E2%80%93Mallows_index) value if you take the "similar" and "different" test pairs and try to draw the threshold line. Smaller number is better. The last line shows number of false positives (`FP`) and false negatives (`FN`) in case of the best achieved FMI. Here I've added the [`phamilie` gem](https://github.com/toy/phamilie) that is DCT based (not a kind of dhash).
|
117
111
|
|
118
112
|
* Methods were renamed from `#calculate` to `#fingerprint` and from `#hamming` to `#distance`.
|
119
113
|
* 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.
|
@@ -130,7 +124,7 @@ end
|
|
130
124
|
DHashVips::IDHash 1.060000 0.090000 1.150000 ( 1.100332)
|
131
125
|
DHashVips::IDHash 4 1.030000 0.080000 1.110000 ( 1.089148)
|
132
126
|
|
133
|
-
measure the distance (1000 times):
|
127
|
+
measure the distance (32*32*1000 times):
|
134
128
|
user system total real
|
135
129
|
Dhash hamming 3.140000 0.020000 3.160000 ( 3.179392)
|
136
130
|
DHashVips::DHash hamming 3.040000 0.020000 3.060000 ( 3.095190)
|
@@ -147,7 +141,7 @@ end
|
|
147
141
|
DHashVips::IDHash 1.080000 0.100000 1.180000 ( 1.156446)
|
148
142
|
DHashVips::IDHash 4 1.030000 0.090000 1.120000 ( 1.076117)
|
149
143
|
|
150
|
-
measure the distance (1000 times):
|
144
|
+
measure the distance (32*32*1000 times):
|
151
145
|
user system total real
|
152
146
|
Dhash hamming 1.770000 0.010000 1.780000 ( 1.815612)
|
153
147
|
DHashVips::DHash hamming 1.810000 0.010000 1.820000 ( 1.875666)
|
@@ -165,7 +159,7 @@ end
|
|
165
159
|
DHashVips::IDHash 0.769975 0.071087 0.841062 ( 0.790470)
|
166
160
|
DHashVips::IDHash 4 0.805311 0.077918 0.883229 ( 0.825897)
|
167
161
|
|
168
|
-
measure the distance (2000 times):
|
162
|
+
measure the distance (32*32*2000 times):
|
169
163
|
user system total real
|
170
164
|
Dhash hamming 1.810000 0.000000 1.810000 ( 1.824719)
|
171
165
|
Phamilie distance 1.000000 0.010000 1.010000 ( 1.006127)
|
@@ -177,7 +171,21 @@ end
|
|
177
171
|
|
178
172
|
* 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.
|
179
173
|
|
180
|
-
## Development
|
174
|
+
## Development notes
|
175
|
+
|
176
|
+
$ ruby test.rb
|
177
|
+
|
178
|
+
* You might need to prepend `bundle exec` to all the `rake` commands.
|
179
|
+
|
180
|
+
* You get this:
|
181
|
+
|
182
|
+
Can't install RMagick 2.16.0. Can't find MagickWand.h.
|
183
|
+
|
184
|
+
because Imagemagick sucks but we need it to benchmark alternative gems, so:
|
185
|
+
|
186
|
+
$ brew install imagemagick@6
|
187
|
+
$ brew unlink imagemagick@7
|
188
|
+
$ brew link imagemagick@6 --force
|
181
189
|
|
182
190
|
* OS X El Captain and rbenv may cause environment issues that would make you do things like:
|
183
191
|
|
@@ -202,10 +210,14 @@ end
|
|
202
210
|
|
203
211
|
$ PKG_CONFIG_PATH="/usr/local/Cellar/imagemagick@6/6.9.10-74/lib/pkgconfig" bundle install
|
204
212
|
|
205
|
-
* You might need to prepend `bundle exec` to all the `rake` commands.
|
206
|
-
|
207
213
|
* Execute the `rake compare_quality` at least once before executing other rake tasks because it's currently the only one that downloads the test images.
|
208
214
|
|
215
|
+
* The tag `v0.0.0.4` is not semver and not real gem version -- it's only for Github Actions testing purposes.
|
216
|
+
|
217
|
+
* To quickly find out what does the dhash-vips Docker image include: `docker run --rm <image_name> sh -c "cat /etc/alpine-release; ruby -v; vips -v; gem list dhash-vips` (TODO: write in this README about the existing Docker image).
|
218
|
+
|
219
|
+
* Phamilie works with filenames instead of fingerprints and caches them but not distances.
|
220
|
+
|
209
221
|
## Credits
|
210
222
|
|
211
223
|
[John Cupitt](https://github.com/jcupitt) (libvips and ruby-vips maintainer) helped me a lot.
|
data/Rakefile
CHANGED
@@ -201,8 +201,7 @@ task :compare_images do |_|
|
|
201
201
|
a.join(b, :horizontal, shim: 15).write_to_file "ab.png"
|
202
202
|
end
|
203
203
|
|
204
|
-
|
205
|
-
desc "Benchmarks Dhash, DHashVips::DHash and DHashVips::IDHash"
|
204
|
+
desc "Benchmark speed of Dhash, DHashVips::DHash, DHashVips::IDHash and Phamilie"
|
206
205
|
task :compare_speed do
|
207
206
|
require "dhash"
|
208
207
|
require "phamilie"
|
@@ -247,10 +246,11 @@ task :compare_speed do
|
|
247
246
|
end
|
248
247
|
|
249
248
|
# for `distance`, `distance3_ruby` and `distance3_c` we use the same hashes
|
249
|
+
# this array manipulation converts [1, 2, 3, 4, 5] into [1, 2, 3, 4, 4, 4, 5]
|
250
250
|
hashes[-1, 1] = hashes[-2, 2]
|
251
251
|
hashes[-1, 1] = hashes[-2, 2]
|
252
252
|
|
253
|
-
puts "\nmeasure the distance (2000 times):"
|
253
|
+
puts "\nmeasure the distance (32*32*2000 times):"
|
254
254
|
Benchmark.bm 32 do |bm|
|
255
255
|
[
|
256
256
|
[Dhash, :hamming],
|
@@ -271,3 +271,86 @@ task :compare_speed do
|
|
271
271
|
end
|
272
272
|
|
273
273
|
end
|
274
|
+
|
275
|
+
desc "Benchmarks everything about Dhash, DHashVips::DHash, DHashVips::IDHash and Phamilie"
|
276
|
+
task :benchmark do
|
277
|
+
abort "provide a folder with images grouped by similarity" unless 2 === ARGV.size
|
278
|
+
abort "invalid folder provided" unless Dir.exist?(dir = ARGV.last)
|
279
|
+
|
280
|
+
require "dhash"
|
281
|
+
require "phamilie"
|
282
|
+
phamilie = Phamilie.new
|
283
|
+
require_relative "lib/dhash-vips"
|
284
|
+
|
285
|
+
filenames = Dir.glob("#{dir}/*").map{ |_| Dir.glob "#{_}/*" }
|
286
|
+
puts "image groups sizes: #{filenames.map(&:size)}"
|
287
|
+
require "benchmark"
|
288
|
+
|
289
|
+
puts "step 1 / 3 (fingerprinting)"
|
290
|
+
hashes = []
|
291
|
+
bm1 = [
|
292
|
+
[phamilie, :fingerprint],
|
293
|
+
[Dhash, :calculate],
|
294
|
+
[DHashVips::DHash, :calculate],
|
295
|
+
[DHashVips::IDHash, :fingerprint],
|
296
|
+
].map do |m, calc, power|
|
297
|
+
Benchmark.realtime do
|
298
|
+
hashes.push filenames.flatten.map{ |filename| m.send calc, filename, *power }
|
299
|
+
end
|
300
|
+
end
|
301
|
+
|
302
|
+
puts "step 2 / 3 (comparing fingerprints)"
|
303
|
+
combs = filenames.flatten.size ** 2
|
304
|
+
n = 10_000_000_000_000 / Dir.glob("#{dir}/*/*").map(&File.method(:size)).inject(:+) / combs
|
305
|
+
bm2 = [
|
306
|
+
[phamilie, :distance, nil, filenames.flatten],
|
307
|
+
[Dhash, :hamming],
|
308
|
+
[DHashVips::DHash, :hamming],
|
309
|
+
[DHashVips::IDHash, :distance3_c],
|
310
|
+
].zip(hashes).map do |(m, dm, power, ii), hs|
|
311
|
+
Benchmark.realtime do
|
312
|
+
_ = ii || hs
|
313
|
+
_.product _ do |h1, h2|
|
314
|
+
n.times{ m.public_send dm, h1, h2 }
|
315
|
+
end
|
316
|
+
end
|
317
|
+
end
|
318
|
+
|
319
|
+
puts "step 3 / 3 (looking for the best threshold)"
|
320
|
+
bm3 = [
|
321
|
+
[phamilie, :fingerprint, :distance, nil, 0],
|
322
|
+
[Dhash, :calculate, :hamming],
|
323
|
+
[DHashVips::DHash, :calculate, :hamming],
|
324
|
+
[DHashVips::IDHash, :fingerprint, :distance],
|
325
|
+
].map do |m, calc, dm, power, ii|
|
326
|
+
require_relative "common"
|
327
|
+
hashes = Dir.glob("#{dir}/*").flat_map{ |_| Dir.glob "#{_}/*" }.map{ |filename| [filename, m.public_send(calc, filename, *power)] }
|
328
|
+
report = Struct.new(:same, :sim, :not_sim).new [], [], []
|
329
|
+
hashes.size.times.to_a.repeated_combination(2) do |i, j|
|
330
|
+
report[
|
331
|
+
case
|
332
|
+
when i == j ; :same
|
333
|
+
when File.split(File.split(hashes[i][0]).first).last ==
|
334
|
+
File.split(File.split(hashes[j][0]).first).last && i < j ; :sim
|
335
|
+
else ; :not_sim
|
336
|
+
end
|
337
|
+
].push m.method(dm).call hashes[i][ii||1], hashes[j][ii||1]
|
338
|
+
end
|
339
|
+
min, max = [*report.sim, *report.not_sim].minmax
|
340
|
+
fmi, fp, fn = (min..max+1).map do |b|
|
341
|
+
fp = report.not_sim.count{ |_| _ < b }
|
342
|
+
tp = report.sim.count{ |_| _ < b }
|
343
|
+
fn = report.sim.count{ |_| _ >= b }
|
344
|
+
[((tp + fp) * (tp + fn)).fdiv(tp * tp), fp, fn]
|
345
|
+
end.reject{ |_,| _.nan? }.min_by(&:first)
|
346
|
+
fmi
|
347
|
+
end
|
348
|
+
|
349
|
+
require "mll"
|
350
|
+
puts MLL::grid.call %w{ \ Fingerprint Compare 1/FMI^2 }.zip(*[
|
351
|
+
%w{ Phamilie Dhash DHash IDHash },
|
352
|
+
*[bm1, bm2].map{ |bm| bm.map{ |_| "%.3f" % _ } },
|
353
|
+
bm3.map{ |_| "%.3f" % _ }
|
354
|
+
].transpose).transpose, spacings: [1.5, 0], alignment: :right
|
355
|
+
puts "(lower numbers are better)"
|
356
|
+
end
|
data/dhash-vips.gemspec
CHANGED
@@ -1,16 +1,20 @@
|
|
1
1
|
Gem::Specification.new do |spec|
|
2
2
|
spec.name = "dhash-vips"
|
3
|
-
spec.version = "0.1.0.
|
3
|
+
spec.version = "0.1.0.3"
|
4
4
|
spec.author = "Victor Maslov"
|
5
5
|
spec.email = "nakilon@gmail.com"
|
6
6
|
spec.summary = "dHash and IDHash powered by Vips"
|
7
7
|
spec.homepage = "https://github.com/nakilon/dhash-vips"
|
8
8
|
spec.license = "MIT"
|
9
9
|
|
10
|
-
spec.test_files = %w{ test.rb }
|
11
|
-
spec.files = `git ls-files -z`.split("\x0") - spec.test_files - %w{ .gitignore } - Dir.glob("example_ocr/**")
|
12
10
|
spec.require_path = "lib"
|
11
|
+
spec.test_files = %w{ test.rb }
|
13
12
|
spec.extensions = %w{ extconf.rb }
|
13
|
+
spec.files = `git ls-files -z`.split("\x0") -
|
14
|
+
spec.test_files -
|
15
|
+
%w{ .gitignore Dockerfile } -
|
16
|
+
Dir.glob("example_*/**/*") -
|
17
|
+
Dir.glob(".github/**/*")
|
14
18
|
|
15
19
|
spec.add_dependency "ruby-vips", "~>2.0.16"
|
16
20
|
|
data/test.rb
CHANGED
@@ -6,6 +6,7 @@ require "dhash-vips"
|
|
6
6
|
|
7
7
|
[
|
8
8
|
[DHashVips::DHash, :hamming, :calculate, 2, 23, 18, 50, 4],
|
9
|
+
# vips-8.9.1-Tue Jan 28 13:05:46 UTC 2020
|
9
10
|
# [[0, 14, 26, 27, 31, 27, 32, 28, 43, 43, 34, 37, 37, 34, 35, 42],
|
10
11
|
# [14, 0, 28, 25, 39, 35, 32, 32, 43, 43, 38, 41, 41, 38, 37, 50],
|
11
12
|
# [26, 28, 0, 13, 35, 41, 28, 30, 41, 41, 36, 33, 35, 32, 27, 36],
|
@@ -23,22 +24,23 @@ require "dhash-vips"
|
|
23
24
|
# [35, 37, 27, 26, 40, 34, 23, 27, 28, 28, 29, 30, 26, 21, 0, 23],
|
24
25
|
# [42, 50, 36, 33, 31, 27, 34, 34, 27, 27, 18, 19, 23, 26, 23, 0]]
|
25
26
|
[DHashVips::IDHash, :distance, :fingerprint, 6, 22, 23, 65, 0],
|
26
|
-
#
|
27
|
-
#
|
27
|
+
# vips-8.9.1-Tue Jan 28 13:05:46 UTC 2020
|
28
|
+
# [[0, 16, 32, 35, 57, 45, 51, 50, 48, 47, 54, 48, 60, 50, 47, 56],
|
29
|
+
# [16, 0, 30, 34, 58, 47, 55, 56, 47, 50, 57, 49, 62, 52, 52, 61],
|
28
30
|
# [32, 30, 0, 9, 47, 54, 45, 41, 65, 62, 42, 37, 51, 44, 49, 49],
|
29
|
-
# [35,
|
31
|
+
# [35, 34, 9, 0, 54, 64, 42, 40, 57, 56, 48, 39, 50, 40, 41, 51],
|
30
32
|
# [57, 58, 47, 54, 0, 22, 43, 45, 64, 61, 48, 47, 35, 43, 47, 48],
|
31
|
-
# [45,
|
32
|
-
# [51,
|
33
|
-
# [50,
|
33
|
+
# [45, 47, 54, 64, 22, 0, 53, 54, 55, 54, 40, 46, 39, 42, 43, 42],
|
34
|
+
# [51, 55, 45, 42, 43, 53, 0, 6, 33, 35, 52, 43, 46, 45, 44, 47],
|
35
|
+
# [50, 56, 41, 40, 45, 54, 6, 0, 38, 41, 53, 50, 48, 45, 41, 42],
|
34
36
|
# [48, 47, 65, 57, 64, 55, 33, 38, 0, 9, 51, 53, 47, 47, 41, 46],
|
35
|
-
# [47,
|
37
|
+
# [47, 50, 62, 56, 61, 54, 35, 41, 9, 0, 51, 57, 50, 49, 44, 43],
|
36
38
|
# [54, 57, 42, 48, 48, 40, 52, 53, 51, 51, 0, 10, 33, 36, 38, 25],
|
37
39
|
# [48, 49, 37, 39, 47, 46, 43, 50, 53, 57, 10, 0, 27, 30, 37, 27],
|
38
40
|
# [60, 62, 51, 50, 35, 39, 46, 48, 47, 50, 33, 27, 0, 20, 23, 28],
|
39
41
|
# [50, 52, 44, 40, 43, 42, 45, 45, 47, 49, 36, 30, 20, 0, 35, 39],
|
40
42
|
# [47, 52, 49, 41, 47, 43, 44, 41, 41, 44, 38, 37, 23, 35, 0, 19],
|
41
|
-
# [56,
|
43
|
+
# [56, 61, 49, 51, 48, 42, 47, 42, 46, 43, 25, 27, 28, 39, 19, 0]]
|
42
44
|
].each do |lib, dm, calc, min_similar, max_similar, min_not_similar, max_not_similar, bw_exceptional|
|
43
45
|
|
44
46
|
describe lib do
|
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.0.3
|
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-
|
11
|
+
date: 2020-07-25 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: ruby-vips
|