eikon 0.1.4 → 0.1.6
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/.rubocop.yml +1 -1
- data/Gemfile +1 -2
- data/Gemfile.lock +1 -13
- data/README.md +1 -1
- data/lib/eikon/comparator.rb +2 -1
- data/lib/eikon/image_processor.rb +1 -0
- data/lib/eikon/version.rb +2 -1
- data/lib/eikon/video_processor.rb +65 -14
- data/lib/eikon.rb +4 -4
- metadata +3 -4
- data/eikon-0.1.0.gem +0 -0
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 366b24652f24e8fd05b78fc1200ab2d17dc9ca358fff8675602d3d0276151e33
|
4
|
+
data.tar.gz: d9e6e4059614085ff8cc86fed30162c7762e14ae3bbb965feae755ae162760e1
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 0fdacf27e83df61edce31ed9eda68003910cdcd9695b1996534c53b7d468f445cbcac1e9543eb230da51f39bc1972a1dc45e4b621f870fc278fac277df4d73b4
|
7
|
+
data.tar.gz: e35e71275bdba7a2826539c72ee331e23ab55fb11d150996a58b427e658a58599154c2f85d72baad547a32f3eb20431e90a71db043e49e77bd6a284bdb7a90c2
|
data/.rubocop.yml
CHANGED
data/Gemfile
CHANGED
data/Gemfile.lock
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
PATH
|
2
2
|
remote: .
|
3
3
|
specs:
|
4
|
-
eikon (0.1.
|
4
|
+
eikon (0.1.5)
|
5
5
|
ruby-vips (~> 2.1)
|
6
6
|
sorbet-runtime (>= 0.5.9204)
|
7
7
|
terrapin (~> 0.6.0)
|
@@ -29,9 +29,7 @@ GEM
|
|
29
29
|
tzinfo (~> 2.0)
|
30
30
|
ast (2.4.2)
|
31
31
|
builder (3.2.4)
|
32
|
-
byebug (11.1.3)
|
33
32
|
climate_control (0.2.0)
|
34
|
-
coderay (1.1.3)
|
35
33
|
concurrent-ruby (1.1.10)
|
36
34
|
crass (1.0.6)
|
37
35
|
diff-lcs (1.5.0)
|
@@ -53,9 +51,6 @@ GEM
|
|
53
51
|
parallel (1.22.1)
|
54
52
|
parser (3.1.2.1)
|
55
53
|
ast (~> 2.4.1)
|
56
|
-
pry (0.13.1)
|
57
|
-
coderay (~> 1.1)
|
58
|
-
method_source (~> 1.0)
|
59
54
|
racc (1.6.0)
|
60
55
|
rack (2.2.4)
|
61
56
|
rack-test (2.0.2)
|
@@ -115,10 +110,6 @@ GEM
|
|
115
110
|
ruby-progressbar (1.11.0)
|
116
111
|
ruby-vips (2.1.4)
|
117
112
|
ffi (~> 1.12)
|
118
|
-
ruby_jard (0.3.1)
|
119
|
-
byebug (>= 9.1, < 12.0)
|
120
|
-
pry (~> 0.13.0)
|
121
|
-
tty-screen (~> 0.8.1)
|
122
113
|
sorbet (0.5.10549)
|
123
114
|
sorbet-static (= 0.5.10549)
|
124
115
|
sorbet-runtime (0.5.10549)
|
@@ -151,7 +142,6 @@ GEM
|
|
151
142
|
terrapin (0.6.0)
|
152
143
|
climate_control (>= 0.0.3, < 1.0)
|
153
144
|
thor (1.2.1)
|
154
|
-
tty-screen (0.8.1)
|
155
145
|
tzinfo (2.0.5)
|
156
146
|
concurrent-ruby (~> 1.0)
|
157
147
|
unicode-display_width (2.3.0)
|
@@ -170,7 +160,6 @@ PLATFORMS
|
|
170
160
|
ruby
|
171
161
|
|
172
162
|
DEPENDENCIES
|
173
|
-
byebug
|
174
163
|
eikon!
|
175
164
|
minitest (~> 5.0)
|
176
165
|
rake (~> 12.0)
|
@@ -178,7 +167,6 @@ DEPENDENCIES
|
|
178
167
|
rubocop-rails
|
179
168
|
rubocop-rails_config
|
180
169
|
ruby-vips
|
181
|
-
ruby_jard
|
182
170
|
sorbet-static-and-runtime
|
183
171
|
tapioca
|
184
172
|
terrapin
|
data/README.md
CHANGED
@@ -4,7 +4,7 @@ This is an implementation of the DHash image matching algorithm in pure Ruby, as
|
|
4
4
|
https://www.hackerfactor.com/blog/?/archives/529-Kind-of-Like-That.html. Its main use is reverse
|
5
5
|
image searching.
|
6
6
|
|
7
|
-
This library is fully
|
7
|
+
This library is fully typed in Sorbet.
|
8
8
|
|
9
9
|
## Installation
|
10
10
|
|
data/lib/eikon/comparator.rb
CHANGED
@@ -1,4 +1,5 @@
|
|
1
1
|
# typed: strict
|
2
|
+
|
2
3
|
require "sorbet-runtime"
|
3
4
|
|
4
5
|
module Eikon
|
@@ -8,7 +9,7 @@ module Eikon
|
|
8
9
|
def self.compare(dhash_1, dhash_2)
|
9
10
|
hamming_distance = 0
|
10
11
|
dhash_1.chars.each_with_index do |character, index|
|
11
|
-
hamming_distance += 1 if character != dhash_2
|
12
|
+
hamming_distance += 1 if character != dhash_2[index]
|
12
13
|
end
|
13
14
|
|
14
15
|
hamming_distance + (dhash_1.length - dhash_2.length).abs
|
data/lib/eikon/version.rb
CHANGED
@@ -29,25 +29,46 @@ module Eikon
|
|
29
29
|
raise "Folder already exists for this export"
|
30
30
|
end
|
31
31
|
|
32
|
+
# Get length of video
|
33
|
+
line = Terrapin::CommandLine.new("ffmpeg", "-i :file_name 2>&1 | grep Duration | cut -d ' ' -f 4 | sed s/,//")
|
34
|
+
time = line.run(file_name: @file_name).chomp
|
35
|
+
|
36
|
+
# Turn the time into total seconds (with two points of precision)
|
37
|
+
time_parts = time.split(":")
|
38
|
+
total_time = Integer(time_parts[0]) * 60 * 60 # Hours
|
39
|
+
total_time += Integer(time_parts[1]) * 60 # Minutes
|
40
|
+
total_time += Float(time_parts[2]) # Seconds
|
41
|
+
|
32
42
|
# Figure out the number of frames per minute given the number of frames we want, default to every ten seconds out of sixty
|
33
|
-
|
34
|
-
unless number_of_frames.zero?
|
35
|
-
# Get length of video
|
36
|
-
line = Terrapin::CommandLine.new("ffmpeg", "-i :file_name 2>&1 | grep Duration | cut -d ' ' -f 4 | sed s/,//")
|
37
|
-
time = line.run(file_name: @file_name).chomp
|
38
|
-
|
39
|
-
# Turn the time into total seconds (with two points of precision)
|
40
|
-
time_parts = time.split(":")
|
41
|
-
total_time = Integer(time_parts[0]) * 60 * 60 # Hours
|
42
|
-
total_time += Integer(time_parts[1]) * 60 # Minutes
|
43
|
-
total_time += Float(time_parts[2]) # Seconds
|
43
|
+
if number_of_frames.positive?
|
44
44
|
|
45
45
|
fps = number_of_frames / total_time
|
46
|
+
line = Terrapin::CommandLine.new("ffmpeg", "-i :file_name -vf fps=#{fps} :folder_name")
|
47
|
+
line.run(file_name: @file_name, folder_name: "#{output_folder_path}/#{file_name}_%d.png")
|
48
|
+
else
|
49
|
+
# Scene detect the video
|
50
|
+
line = Terrapin::CommandLine.new("ffmpeg", "-i :file_name -filter:v \"select='gt(scene,0.4)',showinfo\" -vsync 0 :output_directory/%05d.png")
|
51
|
+
line.run(file_name: @file_name, output_directory: output_folder_path)
|
52
|
+
|
53
|
+
# Screenshot the second second and second to last second
|
54
|
+
# ffmpeg -ss 01:23:45 -i input -frames:v 1 -q:v 2 output.jpg
|
55
|
+
last_time = "#{time_parts[0]}:#{time_parts[1]}:#{time_parts[2].to_f - 1}"
|
56
|
+
ffmpeg_command = "-ss 00:00:02 -i :file_name " +
|
57
|
+
"-ss :last_time -i :file_name " +
|
58
|
+
"-map 0:v -vframes 1 :output_directory/:output_file_name_start " +
|
59
|
+
"-map 1:v -vframes 1 :output_directory/:output_file_name_end"
|
60
|
+
line = Terrapin::CommandLine.new("ffmpeg", ffmpeg_command)
|
61
|
+
line.run(
|
62
|
+
file_name: @file_name,
|
63
|
+
last_time: last_time,
|
64
|
+
output_directory: output_folder_path,
|
65
|
+
output_file_name_start: "#{SecureRandom.uuid}.png",
|
66
|
+
output_file_name_end: "#{SecureRandom.uuid}.png"
|
67
|
+
)
|
68
|
+
|
69
|
+
remove_blank_shots(output_folder_path)
|
46
70
|
end
|
47
71
|
|
48
|
-
# ffmpeg -i pexels-ron-lach-7121125.mp4 -vf fps=10/60 out%d.png
|
49
|
-
line = Terrapin::CommandLine.new("ffmpeg", "-i :file_name -vf fps=#{fps} :folder_name")
|
50
|
-
line.run(file_name: @file_name, folder_name: "#{output_folder_path}/#{file_name}_%d.png")
|
51
72
|
output_folder_path
|
52
73
|
end
|
53
74
|
|
@@ -85,5 +106,35 @@ module Eikon
|
|
85
106
|
make_dir_command.run
|
86
107
|
rescue Terrapin::ExitStatusError; end
|
87
108
|
end
|
109
|
+
|
110
|
+
sig { params(folder_path: String).void }
|
111
|
+
def remove_blank_shots(folder_path)
|
112
|
+
# Scan through the directory getting all images (naïvely)
|
113
|
+
# Find the average size of the files, then choose files that are less than 20% of the average size
|
114
|
+
# This means they're probably mostly one color, so we delete them
|
115
|
+
|
116
|
+
# Filter the '.' and '..' directories from the current directory's file list
|
117
|
+
file_names = Dir.entries(folder_path).filter do |entry|
|
118
|
+
!entry.start_with?(".") ||
|
119
|
+
entry.downcase.end_with?(".png") ||
|
120
|
+
entry.downcase.end_with?(".jpg") ||
|
121
|
+
entry.downcase.end_with?(".jpeg")
|
122
|
+
end
|
123
|
+
|
124
|
+
# Get the average size of the files
|
125
|
+
total_size = file_names.reduce(0) do |sum, file_name|
|
126
|
+
sum + File.size("#{folder_path}/#{file_name}")
|
127
|
+
end
|
128
|
+
|
129
|
+
average_size = total_size / file_names.count
|
130
|
+
|
131
|
+
# Delete files that are less than 20% of the average size
|
132
|
+
file_names.each do |file_name|
|
133
|
+
file_path = "#{folder_path}/#{file_name}"
|
134
|
+
file_size = File.size(file_path)
|
135
|
+
|
136
|
+
File.delete(file_path) if file_size < (average_size * 0.2)
|
137
|
+
end
|
138
|
+
end
|
88
139
|
end
|
89
140
|
end
|
data/lib/eikon.rb
CHANGED
@@ -1,10 +1,10 @@
|
|
1
1
|
# typed: strict
|
2
|
+
|
2
3
|
require "eikon/version"
|
3
4
|
require "eikon/comparator"
|
4
5
|
require "eikon/video_processor"
|
5
6
|
require "eikon/image_processor"
|
6
7
|
require "vips"
|
7
|
-
require "ruby_jard"
|
8
8
|
require "sorbet-runtime"
|
9
9
|
|
10
10
|
module Eikon
|
@@ -20,10 +20,10 @@ module Eikon
|
|
20
20
|
image.byte_array
|
21
21
|
end
|
22
22
|
|
23
|
-
sig { params(filename: String).returns(T::Array[T::Hash[String, T.any(Integer, String)]]) }
|
24
|
-
def self.dhash_for_video(filename)
|
23
|
+
sig { params(filename: String, number_of_frames: Integer).returns(T::Array[T::Hash[String, T.any(Integer, String)]]) }
|
24
|
+
def self.dhash_for_video(filename, number_of_frames = 0)
|
25
25
|
video_processor = Eikon::VideoProcessor.new(filename)
|
26
|
-
storage_path = video_processor.split_video_into_images
|
26
|
+
storage_path = video_processor.split_video_into_images(number_of_frames)
|
27
27
|
dhashes = video_processor.get_frames_dhash(storage_path)
|
28
28
|
dhashes
|
29
29
|
end
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: eikon
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.1.
|
4
|
+
version: 0.1.6
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Christopher Guess
|
8
8
|
autorequire:
|
9
9
|
bindir: exe
|
10
10
|
cert_chain: []
|
11
|
-
date:
|
11
|
+
date: 2023-05-15 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: ruby-vips
|
@@ -73,7 +73,6 @@ files:
|
|
73
73
|
- bin/console
|
74
74
|
- bin/setup
|
75
75
|
- bin/tapioca
|
76
|
-
- eikon-0.1.0.gem
|
77
76
|
- eikon.gemspec
|
78
77
|
- lib/eikon.rb
|
79
78
|
- lib/eikon/comparator.rb
|
@@ -134,7 +133,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
134
133
|
- !ruby/object:Gem::Version
|
135
134
|
version: '0'
|
136
135
|
requirements: []
|
137
|
-
rubygems_version: 3.
|
136
|
+
rubygems_version: 3.4.9
|
138
137
|
signing_key:
|
139
138
|
specification_version: 4
|
140
139
|
summary: A small pure-Ruby (for now) implementation of DHash
|
data/eikon-0.1.0.gem
DELETED
Binary file
|