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 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