visioner 0.3.0 → 1.0.0
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/README.md +14 -17
- data/bin/visioner +16 -12
- data/lib/visioner/version.rb +1 -1
- data/lib/visioner.rb +76 -65
- metadata +1 -1
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 751787ddc448eff5b61ed2980e6019dd754d2c7c
|
4
|
+
data.tar.gz: 68b9330468e2a53a066d771de4fbfd5f58573fdd
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 93b4dbb190ea6cec388289d7cbfe5b36c9ccc4e9038bed721d7ffd0925a72e6e697aedc3908227a842d27c64ae66c7d682efc886aad665e4f35ccd0891258648
|
7
|
+
data.tar.gz: c1c07d5fd8b62c1841de6c296fa9236d83a947debf525ab53c8b3317151b3f79490eaaf802c327993969d03ffaf28b6ada01a5ec5867c5be7a0a9788679bcfdb
|
data/README.md
CHANGED
@@ -14,32 +14,29 @@ Automatically rename your pictures using Google Vision API and metadata.
|
|
14
14
|
|
15
15
|
**Options:**
|
16
16
|
|
17
|
-
-
|
18
|
-
|
19
|
-
-i, --city Adds city to the new filename (ex: seoul)
|
20
|
-
|
21
|
-
-d, --date Adds date to the new filename (ex: 29/07/2016)
|
17
|
+
-f, --format FORMAT Desired format for the new filenames
|
22
18
|
|
23
19
|
-h, --help Displays help
|
24
20
|
|
21
|
+
Format directives:
|
22
|
+
label - uses google vision API to find a label
|
23
|
+
locality - uses metadata to find the locality / city
|
24
|
+
country - uses metadata to find the country
|
25
|
+
date - uses metadata to find the original date
|
26
|
+
Format example: date_country_label
|
27
|
+
|
25
28
|
**Examples:**
|
26
29
|
|
27
30
|
$ export GOOGLE_VISION_API_KEY=BI34SyB5DhqV5ReVnkmIM79812yux9UFazNdynD
|
28
31
|
|
29
|
-
$ bin/visioner /Desktop/travel-south-korea-2016-2/*.jpg
|
32
|
+
$ bin/visioner --format label /Desktop/travel-south-korea-2016-2/*.jpg
|
30
33
|
/Desktop/travel-south-korea-2016-2/IMG_213.jpg -> sea.jpg
|
31
34
|
/Desktop/travel-south-korea-2016-2/IMG_214.jpg -> tower.jpg
|
32
35
|
/Desktop/travel-south-korea-2016-2/IMG_215.jpg -> people.jpg
|
33
36
|
/Desktop/travel-south-korea-2016-2/IMG_216.jpg -> sea2.jpg
|
34
37
|
|
35
|
-
$ bin/visioner --
|
36
|
-
/Desktop/travel-south-korea-2016-
|
37
|
-
/Desktop/travel-south-korea-2016-
|
38
|
-
/Desktop/travel-south-korea-2016-
|
39
|
-
/Desktop/travel-south-korea-2016-
|
40
|
-
|
41
|
-
$ bin/visioner --country --date /Desktop/travel-south-korea-2016-4/*.jpg
|
42
|
-
/Desktop/travel-south-korea-2016-4/IMG_213.jpg -> south-korea_02-28-2015_sea.jpg
|
43
|
-
/Desktop/travel-south-korea-2016-4/IMG_214.jpg -> south-korea_03-15-2015_tower.jpg
|
44
|
-
/Desktop/travel-south-korea-2016-4/IMG_215.jpg -> south-korea_03-28-2015_people.jpg
|
45
|
-
/Desktop/travel-south-korea-2016-4/IMG_216.jpg -> south-korea_04-02-2015_sea2.jpg
|
38
|
+
$ bin/visioner --format country_locality_date_label /Desktop/travel-south-korea-2016-4/*.jpg
|
39
|
+
/Desktop/travel-south-korea-2016-4/IMG_213.jpg -> south-korea_seoul_02-28-2015_sea.jpg
|
40
|
+
/Desktop/travel-south-korea-2016-4/IMG_214.jpg -> south-korea_seoul_03-15-2015_tower.jpg
|
41
|
+
/Desktop/travel-south-korea-2016-4/IMG_215.jpg -> south-korea_seoul_03-28-2015_people.jpg
|
42
|
+
/Desktop/travel-south-korea-2016-4/IMG_216.jpg -> south-korea_seoul_04-02-2015_sea2.jpg
|
data/bin/visioner
CHANGED
@@ -6,18 +6,12 @@ require 'optparse'
|
|
6
6
|
options = {}
|
7
7
|
opts = OptionParser.new
|
8
8
|
|
9
|
-
opts.banner = "Visioner automatically renames your pictures using Google API Visioner and metadata.\
|
9
|
+
opts.banner = "Visioner automatically renames your pictures using Google API Visioner and metadata.\n"
|
10
|
+
opts.banner = opts.banner + "Make sure you have set GOOGLE_API_KEY in your env.\n"
|
11
|
+
opts.banner = opts.banner + "Usage: visioner [options] image ..."
|
10
12
|
|
11
|
-
opts.on("-
|
12
|
-
options[:
|
13
|
-
end
|
14
|
-
|
15
|
-
opts.on("-l", "--locality", "Adds locality / city to the new filename (ex: seoul)") do |l|
|
16
|
-
options[:locality] = l
|
17
|
-
end
|
18
|
-
|
19
|
-
opts.on("-d", "--date", "Adds date to the new filename (ex: 29/07/2016)") do |d|
|
20
|
-
options[:date] = d
|
13
|
+
opts.on("-f", "--format FORMAT", "Desired format for the new filenames") do |f|
|
14
|
+
options[:format] = f
|
21
15
|
end
|
22
16
|
|
23
17
|
opts.on("-h", "--help", "Displays help") do
|
@@ -27,7 +21,17 @@ end
|
|
27
21
|
|
28
22
|
opts.parse!
|
29
23
|
|
30
|
-
if
|
24
|
+
if options[:format].nil?
|
25
|
+
puts "Missing option: format"
|
26
|
+
puts "Format directives:"
|
27
|
+
puts " label - uses google vision API to find a label"
|
28
|
+
puts " locality - uses metadata to find the locality / city"
|
29
|
+
puts " country - uses metadata to find the country"
|
30
|
+
puts " date - uses metadata to find the original date"
|
31
|
+
puts "Format example: date_country_label"
|
32
|
+
puts opts
|
33
|
+
exit 1
|
34
|
+
elsif ARGV.empty?
|
31
35
|
puts opts
|
32
36
|
exit 1
|
33
37
|
else
|
data/lib/visioner/version.rb
CHANGED
data/lib/visioner.rb
CHANGED
@@ -32,6 +32,52 @@ module Visioner
|
|
32
32
|
return place
|
33
33
|
end
|
34
34
|
|
35
|
+
def self.get_label(image_name)
|
36
|
+
# Convert image to Base 64
|
37
|
+
begin
|
38
|
+
b64_data = Base64.encode64(File.open(image_name, "rb").read)
|
39
|
+
rescue
|
40
|
+
puts "Error: can't read file. Exiting..."
|
41
|
+
end
|
42
|
+
|
43
|
+
# Prepare request
|
44
|
+
api_key = ENV['GOOGLE_API_KEY']
|
45
|
+
content_type = "Content-Type: application/json"
|
46
|
+
url = "https://vision.googleapis.com/v1/images:annotate?key=#{api_key}"
|
47
|
+
data = {
|
48
|
+
"requests": [
|
49
|
+
{
|
50
|
+
"image": {
|
51
|
+
"content": b64_data
|
52
|
+
},
|
53
|
+
"features": [
|
54
|
+
{
|
55
|
+
"type": "LABEL_DETECTION",
|
56
|
+
"maxResults": 1
|
57
|
+
}
|
58
|
+
]
|
59
|
+
}
|
60
|
+
]
|
61
|
+
}.to_json
|
62
|
+
url = URI(url)
|
63
|
+
req = Net::HTTP::Post.new(url, initheader = {'Content-Type' =>'application/json'})
|
64
|
+
req.body = data
|
65
|
+
res = Net::HTTP.new(url.host, url.port)
|
66
|
+
res.use_ssl = true
|
67
|
+
|
68
|
+
label = 'unknown'
|
69
|
+
res.start do |http|
|
70
|
+
resp = http.request(req)
|
71
|
+
json = JSON.parse(resp.body)
|
72
|
+
if json && json["responses"] && json["responses"][0]["labelAnnotations"] && json["responses"][0]["labelAnnotations"][0]["description"]
|
73
|
+
label = json['responses'][0]['labelAnnotations'][0]['description']
|
74
|
+
label = label.tr(" ", "-")
|
75
|
+
end
|
76
|
+
end
|
77
|
+
|
78
|
+
return label
|
79
|
+
end
|
80
|
+
|
35
81
|
def self.rename_all(images, options)
|
36
82
|
images.each do |image_name|
|
37
83
|
|
@@ -41,81 +87,46 @@ module Visioner
|
|
41
87
|
next
|
42
88
|
end
|
43
89
|
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
rescue
|
49
|
-
puts "Error: can't read file. Exiting..."
|
90
|
+
label = ''
|
91
|
+
if options[:format].include? 'label'
|
92
|
+
label = 'unknown' # Fallback
|
93
|
+
label = self.get_label(image_name)
|
50
94
|
end
|
51
95
|
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
"requests": [
|
58
|
-
{
|
59
|
-
"image": {
|
60
|
-
"content": b64_data
|
61
|
-
},
|
62
|
-
"features": [
|
63
|
-
{
|
64
|
-
"type": "LABEL_DETECTION",
|
65
|
-
"maxResults": 1
|
66
|
-
}
|
67
|
-
]
|
68
|
-
}
|
69
|
-
]
|
70
|
-
}.to_json
|
71
|
-
url = URI(url)
|
72
|
-
req = Net::HTTP::Post.new(url, initheader = {'Content-Type' =>'application/json'})
|
73
|
-
req.body = data
|
74
|
-
res = Net::HTTP.new(url.host, url.port)
|
75
|
-
res.use_ssl = true
|
76
|
-
|
77
|
-
# Rename file
|
78
|
-
name = ""
|
79
|
-
res.start do |http|
|
80
|
-
resp = http.request(req)
|
81
|
-
json = JSON.parse(resp.body)
|
82
|
-
if json && json["responses"] && json["responses"][0]["labelAnnotations"] && json["responses"][0]["labelAnnotations"][0]["description"]
|
83
|
-
name = json['responses'][0]['labelAnnotations'][0]['description']
|
84
|
-
name = name.tr(" ", "-")
|
85
|
-
end
|
96
|
+
date = ''
|
97
|
+
if options[:format].include? 'date'
|
98
|
+
date = File.mtime(image_name).strftime('%m-%d-%Y') # Fallback
|
99
|
+
exif = EXIFR::JPEG.new(image_name)
|
100
|
+
date = exif.date_time_original.strftime('%m-%d-%Y') if exif && exif.date_time_original
|
86
101
|
end
|
87
102
|
|
88
|
-
|
89
|
-
|
90
|
-
|
91
|
-
counter = 1 if counter == nil
|
92
|
-
counter = counter.to_i + 1
|
93
|
-
end
|
94
|
-
|
103
|
+
country = ''
|
104
|
+
if options[:format].include? 'country'
|
105
|
+
country = 'unknown' # Fallback
|
95
106
|
exif = EXIFR::JPEG.new(image_name)
|
107
|
+
country = self.get_place(exif.gps.latitude, exif.gps.longitude, 'country') if exif && exif.gps_latitude && exif.gps_longitude
|
108
|
+
end
|
96
109
|
|
97
|
-
|
98
|
-
|
99
|
-
|
100
|
-
|
101
|
-
|
110
|
+
locality = ''
|
111
|
+
if options[:format].include? 'locality'
|
112
|
+
locality = 'unknown' # Fallback
|
113
|
+
locality = self.get_place(exif.gps.latitude, exif.gps.longitude, 'locality') if exif.gps_latitude && exif.gps_longitude
|
114
|
+
end
|
102
115
|
|
103
|
-
|
104
|
-
|
105
|
-
|
106
|
-
|
107
|
-
end
|
116
|
+
options[:format].sub! 'label', label
|
117
|
+
options[:format].sub! 'date', date
|
118
|
+
options[:format].sub! 'locality', locality
|
119
|
+
options[:format].sub! 'country', country
|
108
120
|
|
109
|
-
|
110
|
-
|
111
|
-
|
112
|
-
|
113
|
-
|
121
|
+
counter = nil
|
122
|
+
while File.exist?(File.dirname(image_name) + "/" + options[:format] + counter.to_s + File.extname(image_name)) do
|
123
|
+
counter = 1 if counter == nil
|
124
|
+
counter = counter.to_i + 1
|
125
|
+
end
|
114
126
|
|
115
|
-
|
127
|
+
puts "#{image_name} -> #{options[:format] + counter.to_s + File.extname(image_name)}"
|
116
128
|
|
117
|
-
|
118
|
-
end
|
129
|
+
File.rename(image_name, File.dirname(image_name) + "/" + options[:format] + counter.to_s + File.extname(image_name))
|
119
130
|
|
120
131
|
end
|
121
132
|
end
|