eikon 0.1.4 → 0.1.6

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: b1ad60cf41c77add0178d6372fdf1e8501ceb2e3f85c753e66acd3d91121de5c
4
- data.tar.gz: 877f7cb92526cf750a91fd53e2005e956b0abdfe1ddcafb0abc98761fed934b8
3
+ metadata.gz: 366b24652f24e8fd05b78fc1200ab2d17dc9ca358fff8675602d3d0276151e33
4
+ data.tar.gz: d9e6e4059614085ff8cc86fed30162c7762e14ae3bbb965feae755ae162760e1
5
5
  SHA512:
6
- metadata.gz: 2592bd8a187d0edecc53623e3eb83e566450103bf93de7b553e9e2aceb160d0e583503c7c6da4b5f7a665033ca565aa227621e1d5699a8994fc3fca93b600533
7
- data.tar.gz: e6e7371c75cb80fdba71ce4194753b57d8bcd6b57b7cc11a47a9095f3d4975330fcb375bd678263fb68b863bcb51f93dbf35cc50f9f36defb5b2baee929cb1ca
6
+ metadata.gz: 0fdacf27e83df61edce31ed9eda68003910cdcd9695b1996534c53b7d468f445cbcac1e9543eb230da51f39bc1972a1dc45e4b621f870fc278fac277df4d73b4
7
+ data.tar.gz: e35e71275bdba7a2826539c72ee331e23ab55fb11d150996a58b427e658a58599154c2f85d72baad547a32f3eb20431e90a71db043e49e77bd6a284bdb7a90c2
data/.rubocop.yml CHANGED
@@ -13,7 +13,7 @@ AllCops:
13
13
  - 'redis-stable/**/*'
14
14
  - 'bin/**/*'
15
15
  - 'vendor/**/*'
16
- TargetRubyVersion: 3.1
16
+ TargetRubyVersion: 3.2
17
17
 
18
18
  # This sets us to use the standard Rails format instead of Rubocop's
19
19
  # opinionated Ruby style.
data/Gemfile CHANGED
@@ -6,8 +6,7 @@ gemspec
6
6
  gem "rake", "~> 12.0"
7
7
  gem "minitest", "~> 5.0"
8
8
  gem "ruby-vips"
9
- gem "byebug"
10
- gem "ruby_jard"
9
+ # gem "debugger"
11
10
 
12
11
  gem "rubocop", "~> 1.27", require: false
13
12
  gem "rubocop-rails", require: false # Rails specific styles
data/Gemfile.lock CHANGED
@@ -1,7 +1,7 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- eikon (0.1.3)
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 types in Sorbet.
7
+ This library is fully typed in Sorbet.
8
8
 
9
9
  ## Installation
10
10
 
@@ -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.chars[index]
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
@@ -1,4 +1,5 @@
1
1
  # typed: strict
2
+
2
3
  require "sorbet-runtime"
3
4
 
4
5
  module Eikon
data/lib/eikon/version.rb CHANGED
@@ -1,4 +1,5 @@
1
1
  # typed: true
2
+
2
3
  module Eikon
3
- VERSION = "0.1.4".freeze
4
+ VERSION = "0.1.6".freeze
4
5
  end
@@ -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
- fps = 0.166 # 10/60
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
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: 2022-11-10 00:00:00.000000000 Z
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.3.9
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