dhash-vips 0.0.3.1 → 0.0.3.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/Rakefile +148 -3
- data/lib/dhash-vips.rb +5 -8
- data/lib/dhash-vips/version.rb +1 -1
- 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: ef9b532c31699dd2445292844b5d0760a9e79351
|
4
|
+
data.tar.gz: b4e52489d194424a01c9954053bd38a910178124
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: f8a286f3b357af1b1fddfc20bda62bb018868b68952f4e706c2a2a336ae12ca24f15d32a0b267ed574295740cb3e3b8efcb83fbf3a8eb75be2f5894662c46444
|
7
|
+
data.tar.gz: f643c1d3b9e6bd13a269cf3ceb5b9ea6ec7dffc27927c4d1cc9384201285be74b335e62a167faf89c5cb0295936a449f10c0201eb987937ae4f050119d662fff
|
data/Rakefile
CHANGED
@@ -2,6 +2,7 @@ STDOUT.sync = true
|
|
2
2
|
|
3
3
|
require "bundler/gem_tasks"
|
4
4
|
|
5
|
+
|
5
6
|
task :default => %w{ spec }
|
6
7
|
|
7
8
|
require "rspec/core/rake_task"
|
@@ -9,11 +10,13 @@ RSpec::Core::RakeTask.new :spec do |t|
|
|
9
10
|
t.verbose = false
|
10
11
|
end
|
11
12
|
|
13
|
+
|
12
14
|
visualize_hash = lambda do |hash|
|
13
15
|
puts hash.to_s(2).rjust(64, ?0).gsub(/(?<=.)/, '\0 ').scan(/.{16}/)
|
14
16
|
end
|
15
17
|
|
16
|
-
|
18
|
+
desc "Compare how Vips and ImageMagick resize images to 9x8"
|
19
|
+
task :compare_pixelation do |_|
|
17
20
|
require_relative "lib/dhash-vips"
|
18
21
|
require "dhash"
|
19
22
|
|
@@ -33,9 +36,10 @@ task :compare_pixelation do |_, args|
|
|
33
36
|
end
|
34
37
|
end
|
35
38
|
|
36
|
-
|
39
|
+
desc "Compare how Vips resizes image to 9x8 with different kernels"
|
40
|
+
task :compare_kernels do |_|
|
37
41
|
require_relative "lib/dhash-vips"
|
38
|
-
require "dhash"
|
42
|
+
# require "dhash"
|
39
43
|
|
40
44
|
%i{ nearest linear cubic lanczos2 lanczos3 }.each do |kernel|
|
41
45
|
hashes = ARGV.drop(1).map do |arg|
|
@@ -45,3 +49,144 @@ task :compare_kernels do |_, args|
|
|
45
49
|
puts "kernel: #{kernel}, distance: #{DHashVips::DHash.hamming *hashes}"
|
46
50
|
end
|
47
51
|
end
|
52
|
+
|
53
|
+
|
54
|
+
desc "Compare the quality of Dhash, DHashVips::DHash and DHashVips::IDHash -- run it only after `rake test`"
|
55
|
+
task :compare_matrixes do |_|
|
56
|
+
require "dhash"
|
57
|
+
require_relative "lib/dhash-vips"
|
58
|
+
require "mll"
|
59
|
+
[Dhash, DHashVips::DHash, DHashVips::IDHash].each do |m|
|
60
|
+
hashes = %w{
|
61
|
+
71662d4d4029a3b41d47d5baf681ab9a.jpg
|
62
|
+
ad8a37f872956666c3077a3e9e737984.jpg
|
63
|
+
1d468d064d2e26b5b5de9a0241ef2d4b.jpg
|
64
|
+
92d90b8977f813af803c78107e7f698e.jpg
|
65
|
+
309666c7b45ecbf8f13e85a0bd6b0a4c.jpg
|
66
|
+
3f9f3db06db20d1d9f8188cd753f6ef4.jpg
|
67
|
+
df0a3b93e9412536ee8a11255f974141.jpg
|
68
|
+
679634ff89a31279a39f03e278bc9a01.jpg
|
69
|
+
}.map{ |filename| m.calculate "images/#{filename}" }
|
70
|
+
table = MLL::table[m.method(:hamming), [hashes], [hashes]]
|
71
|
+
array = Array.new(4){ [] }
|
72
|
+
hashes.size.times.to_a.repeated_combination(2) do |i, j|
|
73
|
+
array[i == j ? 0 : (j - i).abs == 1 && (i + j - 1) % 4 == 0 ? [i, j] == [0, 1] ? 1 : 2 : 3].push table[i][j]
|
74
|
+
end
|
75
|
+
p array.map &:sort
|
76
|
+
end
|
77
|
+
end
|
78
|
+
|
79
|
+
# ruby -c Rakefile && rm -f ab.png && rake compare_images -- fc762fa286489d8afc80adc8cdcb125e.jpg 9c2c240ec02356472fb532f404d28dde.jpg 2>/dev/null && ql ab.png
|
80
|
+
desc "Visualizes the IDHash difference measurement between two images"
|
81
|
+
task :compare_images do |_|
|
82
|
+
abort "there should be two image filenames passed as arguments" unless ARGV.size == 3
|
83
|
+
require_relative "lib/dhash-vips"
|
84
|
+
ha, hb = ARGV.drop(1).map &DHashVips::IDHash.method(:calculate)
|
85
|
+
puts "distance: #{DHashVips::IDHash.hamming ha, hb}"
|
86
|
+
|
87
|
+
require "delegate"
|
88
|
+
class ImageMutable < SimpleDelegator
|
89
|
+
%i{ draw_line draw_circle }.each do |m|
|
90
|
+
define_method "#{m}!" do |*args|
|
91
|
+
__setobj__ self.send m, *args
|
92
|
+
self
|
93
|
+
end
|
94
|
+
end
|
95
|
+
end
|
96
|
+
a, b = ARGV.drop(1).map do |filename|
|
97
|
+
image = Vips::Image.new_from_file filename
|
98
|
+
ImageMutable.new image.resize(8.fdiv(image.width), vscale: 8.fdiv(image.height)).colourspace("b-w").
|
99
|
+
resize(100, vscale: 100, kernel: :nearest).colourspace("srgb")
|
100
|
+
end
|
101
|
+
|
102
|
+
ad = ha >> 128
|
103
|
+
ai = ha - (ad << 128)
|
104
|
+
bd = hb >> 128
|
105
|
+
bi = hb - (bd << 128)
|
106
|
+
|
107
|
+
n = 0
|
108
|
+
[[a, ad, ai], [b, bd, bi]].each do |image, xd, xi|
|
109
|
+
127.downto(0).each do |i|
|
110
|
+
if i > 63
|
111
|
+
y, x = (127 - i).divmod 8
|
112
|
+
else
|
113
|
+
x, y = (63 - i).divmod 8
|
114
|
+
end
|
115
|
+
x = (image.width * (x + 0.5) / 8).round
|
116
|
+
y = (image.height * (y + 0.5) / 8).round
|
117
|
+
if i > 63
|
118
|
+
(x-2..x+2).map do |x| [
|
119
|
+
[x, y , x, (y + image.height / 16 - 1) % image.height],
|
120
|
+
[x, (y + image.height / 16 + 1) % image.height, x, (y + image.height / 8 ) % image.height],
|
121
|
+
] end
|
122
|
+
else
|
123
|
+
(y-2..y+2).map do |y| [
|
124
|
+
[ x , y, (x + image.width / 16 - 1) % image.width, y],
|
125
|
+
[(x + image.width / 16 + 1) % image.width, y, (x + image.width / 8 ) % image.width, y],
|
126
|
+
] end
|
127
|
+
end.each do |coords1, coords2|
|
128
|
+
n += 1
|
129
|
+
image.draw_line! (1 - xd[i]) * 255, *coords1
|
130
|
+
image.draw_line! xd[i] * 255, *coords2
|
131
|
+
end if ai[i] + bi[i] > 0 && ad[i] != bd[i]
|
132
|
+
cx, cy = if i > 63
|
133
|
+
[x, y + 20]
|
134
|
+
else
|
135
|
+
[x + 20, y]
|
136
|
+
end
|
137
|
+
image.draw_circle! xd[i] * 255, cx, cy, 11, fill: true if xi[i] > 0
|
138
|
+
image.draw_circle! (1 - xd[i]) * 255, cx, cy, 10, fill: true if xi[i] > 0
|
139
|
+
end
|
140
|
+
end
|
141
|
+
puts "distance: #{n / 10}"
|
142
|
+
|
143
|
+
a.join(b.__getobj__, :horizontal, shim: 10).write_to_file "ab.png"
|
144
|
+
end
|
145
|
+
|
146
|
+
desc "Benchmarks Dhash, DHashVips::DHash and DHashVips::IDHash"
|
147
|
+
task :compare_speed do
|
148
|
+
require "dhash"
|
149
|
+
require_relative "lib/dhash-vips"
|
150
|
+
|
151
|
+
filenames = %w{
|
152
|
+
71662d4d4029a3b41d47d5baf681ab9a.jpg
|
153
|
+
ad8a37f872956666c3077a3e9e737984.jpg
|
154
|
+
1d468d064d2e26b5b5de9a0241ef2d4b.jpg
|
155
|
+
92d90b8977f813af803c78107e7f698e.jpg
|
156
|
+
309666c7b45ecbf8f13e85a0bd6b0a4c.jpg
|
157
|
+
3f9f3db06db20d1d9f8188cd753f6ef4.jpg
|
158
|
+
df0a3b93e9412536ee8a11255f974141.jpg
|
159
|
+
679634ff89a31279a39f03e278bc9a01.jpg
|
160
|
+
}.flat_map do |filename|
|
161
|
+
image = Vips::Image.new_from_file "images/#{filename}"
|
162
|
+
[0, 1, 2, 3].map do |a|
|
163
|
+
"benchmark/#{a}_#{filename}".tap do |filename|
|
164
|
+
next if File.exist? filename
|
165
|
+
FileUtils.mkdir_p "benchmark"
|
166
|
+
image.rot(a).write_to_file filename
|
167
|
+
end
|
168
|
+
end
|
169
|
+
end
|
170
|
+
|
171
|
+
require "benchmark"
|
172
|
+
puts "load and calculate:"
|
173
|
+
hashes = []
|
174
|
+
Benchmark.bm 18 do |bm|
|
175
|
+
[Dhash, DHashVips::DHash, DHashVips::IDHash].each do |m|
|
176
|
+
bm.report m do
|
177
|
+
hashes.push filenames.map &m.method(:calculate)
|
178
|
+
end
|
179
|
+
end
|
180
|
+
end
|
181
|
+
puts "hamming (1000 times):"
|
182
|
+
Benchmark.bm 18 do |bm|
|
183
|
+
[Dhash, DHashVips::DHash, DHashVips::IDHash].zip(hashes) do |m, hs|
|
184
|
+
bm.report m do
|
185
|
+
hs.product hs do |h1, h2|
|
186
|
+
1000.times{ m.hamming h1, h2 }
|
187
|
+
end
|
188
|
+
end
|
189
|
+
end
|
190
|
+
end
|
191
|
+
|
192
|
+
end
|
data/lib/dhash-vips.rb
CHANGED
@@ -1,10 +1,9 @@
|
|
1
1
|
require_relative "dhash-vips/version"
|
2
2
|
require "vips"
|
3
|
-
require "mll"
|
4
3
|
|
5
4
|
module DHashVips
|
6
|
-
module DHash
|
7
5
|
|
6
|
+
module DHash
|
8
7
|
extend self
|
9
8
|
|
10
9
|
def hamming a, b
|
@@ -28,15 +27,13 @@ module DHashVips
|
|
28
27
|
|
29
28
|
end
|
30
29
|
|
30
|
+
require "mll"
|
31
31
|
module IDHash
|
32
32
|
extend self
|
33
33
|
|
34
34
|
def hamming a, b
|
35
|
-
|
36
|
-
|
37
|
-
bd = b >> 128
|
38
|
-
bi = b - (bd << 128)
|
39
|
-
((ai | bi) & (ad ^ bd)).to_s(2).count "1"
|
35
|
+
# TODO: the hash_size=8 is hardcoded here
|
36
|
+
((a | b) & (a >> 128 ^ b >> 128)).to_s(2).count "1"
|
40
37
|
end
|
41
38
|
|
42
39
|
def median array
|
@@ -72,7 +69,7 @@ module DHashVips
|
|
72
69
|
d.flatten.map{ |c| c.abs >= m ? 1 : 0 }.join.to_i(2),
|
73
70
|
]
|
74
71
|
end
|
75
|
-
(((((d1 <<
|
72
|
+
(((((d1 << hash_size * hash_size) + d2) << hash_size * hash_size) + i1) << hash_size * hash_size) + i2
|
76
73
|
end
|
77
74
|
|
78
75
|
end
|
data/lib/dhash-vips/version.rb
CHANGED
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.0.3.
|
4
|
+
version: 0.0.3.2
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Victor Maslov
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2017-
|
11
|
+
date: 2017-10-11 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: ruby-vips
|