deepstack 1.4.0 → 1.6.1
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 +78 -0
- data/lib/deep_stack/deep_stack.rb +36 -15
- data/lib/deep_stack/face.rb +2 -2
- data/lib/deep_stack/image.rb +24 -0
- data/lib/deep_stack/scene.rb +3 -2
- data/lib/deep_stack/version.rb +1 -1
- data/spec/deepstack_spec.rb +217 -0
- metadata +92 -4
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 8894b856fe894840f7b0178501000f4bd3c05dc0f8e5d3199f3782ac3bfbff86
|
4
|
+
data.tar.gz: 4e42c6f313e00d6c909de463c7a5a3874861d48a06a73c62970c5a064beedf7c
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 6eff77cc8ea43965ba5ba60aaccc2eea39839d7986ff5c88304f7a09dd12487d758b83b62743a216b6bb98a1f1f27807815b3c0dcef085573b6878809c6eea89
|
7
|
+
data.tar.gz: aa7f18c4fbfb6e1cac966f315c540bcbb08e9d52d391283d264df849b78ad0a1b442ea0217d8ced45e888882b0260f156cd4a8768aaeec21cf5f744bc62669cc
|
data/README.md
ADDED
@@ -0,0 +1,78 @@
|
|
1
|
+
# DeepStack Ruby Wrapper
|
2
|
+
|
3
|
+
A Ruby wrapper for [DeepStack](https://www.deepstack.cc/) HTTP API
|
4
|
+
|
5
|
+
## Usage
|
6
|
+
|
7
|
+
Install the gem with `gem install deepstack`
|
8
|
+
|
9
|
+
~~~ ruby
|
10
|
+
require 'deepstack'
|
11
|
+
|
12
|
+
deepstack = DeepStack.new('http://192.168.1.10:2000')
|
13
|
+
image = File.read('image.jpg')
|
14
|
+
|
15
|
+
# Find bounding rects for objects
|
16
|
+
predictions = deepstack.detect_objects(image)
|
17
|
+
# => [{"confidence"=>0.86599416, "label"=>"dog", "y_min"=>355, "x_min"=>648, "y_max"=>540, "x_max"=>797},
|
18
|
+
# {"confidence"=>0.918332, "label"=>"person", "y_min"=>113, "x_min"=>442, "y_max"=>524, "x_max"=>601},
|
19
|
+
# {"confidence"=>0.9292374, "label"=>"person", "y_min"=>83, "x_min"=>294, "y_max"=>521, "x_max"=>447}]
|
20
|
+
|
21
|
+
# Find bounding rects for faces
|
22
|
+
faces = deepstack.detect_faces(image)
|
23
|
+
# => [{"confidence"=>0.86419886, "y_min"=>236, "x_min"=>876, "y_max"=>730, "x_max"=>1203},
|
24
|
+
# {"confidence"=>0.8811783, "y_min"=>164, "x_min"=>1617, "y_max"=>692, "x_max"=>1985}]
|
25
|
+
|
26
|
+
# Register a face for face recognition
|
27
|
+
deepstack.register_face('face1', image)
|
28
|
+
|
29
|
+
# List all the registered faces in the system
|
30
|
+
face_list = deepstack.face_list
|
31
|
+
# => ["face1", "face2"]
|
32
|
+
|
33
|
+
# Perform a face recognition, return identified userids
|
34
|
+
faces = deepstack.recognize_face(image)
|
35
|
+
# => [{"confidence"=>0, "userid"=>"unknown", "y_min"=>236, "x_min"=>876, "y_max"=>730, "x_max"=>1203},
|
36
|
+
# {"confidence"=>0.9824197, "userid"=>"face1", "y_min"=>164, "x_min"=>1617, "y_max"=>692, "x_max"=>1985}]
|
37
|
+
|
38
|
+
# Delete a face from the system
|
39
|
+
deepstack.delete_face('face1')
|
40
|
+
|
41
|
+
# Detect similarities between two face images
|
42
|
+
image2 = File.read('image2.jpg')
|
43
|
+
similarity = deepstack.face_match(image, image2)
|
44
|
+
# => 0.3333
|
45
|
+
|
46
|
+
# Perform Scene recognition
|
47
|
+
scene = deepstack.identify_scene(image)
|
48
|
+
# => {"success"=>true, "confidence"=>0.27867314, "label"=>"archive", "duration"=>0}
|
49
|
+
~~~
|
50
|
+
|
51
|
+
### Error Handling
|
52
|
+
|
53
|
+
The methods will:
|
54
|
+
|
55
|
+
* Raise an exception on a connection error.
|
56
|
+
* Return nil when DeepStack reports failure (`success=false`)
|
57
|
+
|
58
|
+
See the [documentation](https://www.rubydoc.info/gems/deepstack) for more details.
|
59
|
+
|
60
|
+
## Development
|
61
|
+
|
62
|
+
A Linux development machine is needed in order to run the tests. The test will launch DeepStack docker instances
|
63
|
+
to test against. By default, the deepstack docker will listen on ports `8001`-`8004`.
|
64
|
+
To change this, copy `rakelib/deepstack.yml.sample` to `rakelib/deepstack.yml` and change the port numbers as required.
|
65
|
+
|
66
|
+
To run the tests run `rake`.
|
67
|
+
|
68
|
+
To manually stop the DeepStack docker instance, run `rake deepstack:stop`
|
69
|
+
|
70
|
+
To install this gem onto your local machine, run `bundle exec rake install`.
|
71
|
+
|
72
|
+
## Contributing
|
73
|
+
|
74
|
+
Bug reports and pull requests are welcome on [GitHub](https://github.com/jimtng/deepstack-ruby).
|
75
|
+
|
76
|
+
## License
|
77
|
+
|
78
|
+
The gem is available as open source under the terms of the EPL 2.0 License
|
@@ -6,29 +6,53 @@ require_relative 'face'
|
|
6
6
|
require_relative 'detection'
|
7
7
|
require_relative 'scene'
|
8
8
|
require_relative 'custom_model'
|
9
|
+
require_relative 'image'
|
9
10
|
require_relative 'version'
|
10
11
|
|
11
|
-
#
|
12
|
+
#
|
13
|
+
# DeepStack API wrapper
|
14
|
+
#
|
15
|
+
# All the methods that communicate with the server can raise an +Errno::ECONNREFUSED+ exception
|
16
|
+
# if the server is down or the connection details are incorrect.
|
17
|
+
#
|
12
18
|
class DeepStack
|
13
19
|
include DeepStack::Face
|
14
20
|
include DeepStack::Detection
|
15
21
|
include DeepStack::Scene
|
22
|
+
include DeepStack::Image
|
16
23
|
include DeepStack::CustomModel
|
17
24
|
|
18
25
|
#
|
19
|
-
# Create a deepstack object
|
26
|
+
# Create a deepstack object for the given server URL. HTTP connections are not made within the constructor
|
27
|
+
# so the deepstack object can be created against a server that's currently down without
|
28
|
+
# raising an exception.
|
29
|
+
#
|
30
|
+
# A persistent HTTP connection will be initiated on the first method request.
|
20
31
|
#
|
21
32
|
# @param [String] base_url the url to DeepStack's server:port
|
22
|
-
# @param [String] api_key an optional API-KEY to use when connecting to DeepStack
|
23
|
-
# @param [String] admin_key an optional ADMIN-KEY to use when connecting to DeepStack
|
33
|
+
# @param [String] api_key an optional +API-KEY+ to use when connecting to DeepStack
|
34
|
+
# @param [String] admin_key an optional +ADMIN-KEY+ to use when connecting to DeepStack
|
35
|
+
# @param [Integer] verify_mode sets the flags for server the certification verification at
|
36
|
+
# beginning of an SSL/TLS session.
|
37
|
+
# +OpenSSL::SSL::VERIFY_NONE+ or +OpenSSL::SSL::VERIFY_PEER+ are acceptable.
|
38
|
+
# The default is +OpenSSL::SSL::VERIFY_PEER+.
|
24
39
|
#
|
25
40
|
# @example
|
26
41
|
# DeepStack.new('http://127.0.0.1:5000')
|
27
42
|
#
|
28
|
-
|
43
|
+
# # Using an API KEY
|
44
|
+
# DeepStack.new('http://127.0.0.1:5000', api_key: 'secret', admin_key: 'supersecret')
|
45
|
+
#
|
46
|
+
# # SSL connection with a self-signed certificate
|
47
|
+
# DeepStack.new('https://localhost:443', verify_mode: OpenSSL::SSL::VERIFY_NONE)
|
48
|
+
#
|
49
|
+
def initialize(base_url, api_key: nil, admin_key: nil, verify_mode: nil)
|
29
50
|
@base_url = base_url
|
30
51
|
@auth = { api_key: api_key, admin_key: admin_key }.select { |_k, v| v } # remove nil values
|
31
|
-
|
52
|
+
uri = URI(base_url)
|
53
|
+
@http = Net::HTTP.new(uri.hostname, uri.port)
|
54
|
+
@http.use_ssl = uri.instance_of?(URI::HTTPS)
|
55
|
+
@http.verify_mode = verify_mode if verify_mode
|
32
56
|
end
|
33
57
|
|
34
58
|
#
|
@@ -57,12 +81,12 @@ class DeepStack
|
|
57
81
|
end
|
58
82
|
|
59
83
|
#
|
60
|
-
# Close the HTTP connection to DeepStack server
|
84
|
+
# Close the persistent HTTP connection to DeepStack server. This should be called after
|
85
|
+
# a period of inactivity to close the TCP connection. Subsequent API calls will
|
86
|
+
# re-open the connection automatically.
|
61
87
|
#
|
62
88
|
def close
|
63
|
-
@
|
64
|
-
@http.finish if @http&.started?
|
65
|
-
end
|
89
|
+
@http.finish if @http&.started?
|
66
90
|
end
|
67
91
|
|
68
92
|
private
|
@@ -79,11 +103,8 @@ class DeepStack
|
|
79
103
|
form_data = combine_images_and_args(images.flatten, **args)
|
80
104
|
req = Net::HTTP::Post.new(uri)
|
81
105
|
req.set_form(form_data, 'multipart/form-data')
|
82
|
-
@
|
83
|
-
|
84
|
-
@http.start unless @http.started?
|
85
|
-
@http.request(req)
|
86
|
-
end
|
106
|
+
@http.start unless @http.started?
|
107
|
+
@http.request(req)
|
87
108
|
end
|
88
109
|
|
89
110
|
def combine_images_and_args(*images, **args)
|
data/lib/deep_stack/face.rb
CHANGED
@@ -86,8 +86,8 @@ class DeepStack
|
|
86
86
|
# image2 = File.read('obama2.jpg')
|
87
87
|
# puts deepstack.face_match(image1, image2) > 0.6 ? 'similar' : 'different'
|
88
88
|
#
|
89
|
-
# @param [Array]
|
90
|
-
# @param [kwargs]
|
89
|
+
# @param [Array] images two images to compare
|
90
|
+
# @param [kwargs] args optional arguments to the API call
|
91
91
|
#
|
92
92
|
# @return [Float] The similarity score (0-1)
|
93
93
|
# @return [nil] if failed
|
@@ -0,0 +1,24 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'base64'
|
4
|
+
|
5
|
+
class DeepStack
|
6
|
+
# Support Image Enhance feature
|
7
|
+
module Image
|
8
|
+
#
|
9
|
+
# Enhance image {https://docs.deepstack.cc/api-reference/index.html#image-enhance}
|
10
|
+
#
|
11
|
+
# @param [Image] image the raw image data or a File object of an image file
|
12
|
+
#
|
13
|
+
# @return [Image] the enhanced image object
|
14
|
+
# @return [nil] if failed
|
15
|
+
#
|
16
|
+
def enhance_image(image)
|
17
|
+
target = 'vision/enhance'
|
18
|
+
result = api_post(target, image)
|
19
|
+
return unless result&.dig('success') == true
|
20
|
+
|
21
|
+
Base64.decode64(result['base64'])
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
data/lib/deep_stack/scene.rb
CHANGED
@@ -4,14 +4,15 @@ class DeepStack
|
|
4
4
|
# Scene Recognition
|
5
5
|
module Scene
|
6
6
|
#
|
7
|
-
#
|
7
|
+
# Call the scene recognition API to classify an image into one of the supported scenes.
|
8
8
|
#
|
9
9
|
# @param [Object] image binary data or a File object
|
10
10
|
# @param [Hash] options additional fields for DeepStack, e.g. min_confidence: 0.5
|
11
11
|
#
|
12
|
-
# @return [Hash] if successful, DeepStack result hash {'label' => 'scene', 'confidence' => 2.2}
|
12
|
+
# @return [Hash] if successful, DeepStack result hash +{'label' => 'scene', 'confidence' => 2.2}+
|
13
13
|
#
|
14
14
|
# @return [nil] if error
|
15
|
+
#
|
15
16
|
def identify_scene(image, **options)
|
16
17
|
target = 'vision/scene'
|
17
18
|
api_post(target, image, **options)
|
data/lib/deep_stack/version.rb
CHANGED
@@ -0,0 +1,217 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'rake'
|
4
|
+
require 'pp'
|
5
|
+
require 'deepstack'
|
6
|
+
|
7
|
+
Rake.application.rake_require 'docker_support', ['rakelib']
|
8
|
+
Rake.application.rake_require 'deepstack', ['rakelib']
|
9
|
+
|
10
|
+
# http is used in persistence check below
|
11
|
+
class DeepStack
|
12
|
+
attr_reader :http
|
13
|
+
end
|
14
|
+
|
15
|
+
def deepstack
|
16
|
+
@deepstack ||= DeepStack.new("http://localhost:#{port[:no_auth][:http]}")
|
17
|
+
end
|
18
|
+
|
19
|
+
def auth_deepstack
|
20
|
+
@auth_deepstack ||= DeepStack.new("http://localhost:#{port[:auth][:http]}", api_key: 'myapikey',
|
21
|
+
admin_key: 'myadminkey')
|
22
|
+
end
|
23
|
+
|
24
|
+
def deepstack_ssl
|
25
|
+
@deepstack_ssl ||= DeepStack.new("https://localhost:#{port[:no_auth][:https]}",
|
26
|
+
verify_mode: OpenSSL::SSL::VERIFY_NONE)
|
27
|
+
end
|
28
|
+
|
29
|
+
def restart_deepstack_server
|
30
|
+
Rake::Task['deepstack:stop1'].execute
|
31
|
+
Rake::Task['deepstack:stop2'].execute
|
32
|
+
Rake::Task['deepstack:stop3'].execute
|
33
|
+
Rake::Task['deepstack:start'].execute
|
34
|
+
end
|
35
|
+
|
36
|
+
# rubocop:disable Metrics/BlockLength
|
37
|
+
RSpec.describe DeepStack do
|
38
|
+
image = File.read('spec/test_images/person-dog.jpg')
|
39
|
+
|
40
|
+
context 'Basic Usage' do
|
41
|
+
it 'can be initialized with a url' do
|
42
|
+
expect(deepstack).not_to be_nil
|
43
|
+
end
|
44
|
+
|
45
|
+
it 'can close and reopen its http connection' do
|
46
|
+
result = deepstack.face_list
|
47
|
+
expect(result).to be_an Array
|
48
|
+
expect(deepstack.http.started?).to be true
|
49
|
+
deepstack.close
|
50
|
+
expect(deepstack.http.started?).to be false
|
51
|
+
result = deepstack.face_list
|
52
|
+
expect(deepstack.http.started?).to be true
|
53
|
+
expect(result).to be_an Array
|
54
|
+
expect(deepstack.http.started?).to be true
|
55
|
+
end
|
56
|
+
|
57
|
+
it 'can recover from a server restart' do
|
58
|
+
result = deepstack.face_list
|
59
|
+
expect(result).to be_an Array
|
60
|
+
|
61
|
+
Rake::Task['deepstack:stop1'].execute
|
62
|
+
expect { deepstack.face_list }.to raise_exception(Errno::ECONNREFUSED)
|
63
|
+
Rake::Task['deepstack:start'].execute
|
64
|
+
sleep 1
|
65
|
+
|
66
|
+
result = deepstack.face_list
|
67
|
+
expect(result).to be_an Array
|
68
|
+
end
|
69
|
+
|
70
|
+
it 'can work with an api key' do
|
71
|
+
result = auth_deepstack.detect_objects(image)
|
72
|
+
expect(result).to be_an Array
|
73
|
+
end
|
74
|
+
|
75
|
+
it 'can use ssl' do
|
76
|
+
result = deepstack_ssl.face_list
|
77
|
+
expect(result).to be_an Array
|
78
|
+
end
|
79
|
+
|
80
|
+
it 'does not raise an exception in its constructor' do
|
81
|
+
result = DeepStack.new('http://192.168.254.254')
|
82
|
+
expect(result).to be_truthy
|
83
|
+
end
|
84
|
+
end
|
85
|
+
|
86
|
+
context 'Object Detection' do
|
87
|
+
it 'can detect objects' do
|
88
|
+
result = deepstack.detect_objects(image)
|
89
|
+
# pp result
|
90
|
+
expect(result).to be_an Array
|
91
|
+
expect(result.size).to be > 0
|
92
|
+
expect(result.first).to be_a Hash
|
93
|
+
expect(result.first.keys).to include(*%w[confidence label x_max x_min y_max y_min])
|
94
|
+
end
|
95
|
+
end
|
96
|
+
|
97
|
+
context 'Face Detection' do
|
98
|
+
it 'can detect faces' do
|
99
|
+
result = deepstack.detect_faces(image)
|
100
|
+
# pp result
|
101
|
+
expect(result).to be_an Array
|
102
|
+
expect(result.first).to be_a Hash
|
103
|
+
expect(result.first.keys).to include(*%w[confidence x_min y_min x_max y_max])
|
104
|
+
end
|
105
|
+
end
|
106
|
+
|
107
|
+
context 'Face Recognition' do
|
108
|
+
it 'can return a list of registered faces' do
|
109
|
+
faces = deepstack.face_list
|
110
|
+
expect(faces).to be_an Array
|
111
|
+
end
|
112
|
+
|
113
|
+
it 'can register a face with one image object' do
|
114
|
+
# image = File.read('spec/test_images/idriselba3.jpeg')
|
115
|
+
result = deepstack.register_face('user1', image)
|
116
|
+
expect(result).to be true
|
117
|
+
|
118
|
+
faces = deepstack.face_list
|
119
|
+
expect(faces).to include 'user1'
|
120
|
+
end
|
121
|
+
|
122
|
+
it 'can register a face given a File object of an image file' do
|
123
|
+
result = File.open('spec/test_images/person-dog.jpg') do |img|
|
124
|
+
deepstack.register_face('user2', img)
|
125
|
+
end
|
126
|
+
expect(result).to be true
|
127
|
+
|
128
|
+
faces = deepstack.face_list
|
129
|
+
expect(faces).to include 'user2'
|
130
|
+
end
|
131
|
+
|
132
|
+
it 'can register a face with multiple image objects' do
|
133
|
+
face_count_before = deepstack.face_list.size
|
134
|
+
images = []
|
135
|
+
images << File.read('spec/test_images/person-dog.jpg')
|
136
|
+
images << File.read('spec/test_images/person-dog.jpg')
|
137
|
+
images << File.read('spec/test_images/person-dog.jpg')
|
138
|
+
|
139
|
+
result = deepstack.register_face('user3', images)
|
140
|
+
expect(result).to be true
|
141
|
+
|
142
|
+
faces = deepstack.face_list
|
143
|
+
expect(faces).to include 'user3'
|
144
|
+
expect(faces.size).to be > face_count_before
|
145
|
+
end
|
146
|
+
|
147
|
+
it 'can register multiple faces/users' do
|
148
|
+
deepstack.delete_faces(deepstack.face_list)
|
149
|
+
faces = deepstack.face_list
|
150
|
+
expect(faces.size).to be 0
|
151
|
+
|
152
|
+
3.times do |i|
|
153
|
+
deepstack.register_face("user#{i}", image)
|
154
|
+
end
|
155
|
+
faces = deepstack.face_list
|
156
|
+
expect(faces.size).to be 3
|
157
|
+
|
158
|
+
3.times do |i|
|
159
|
+
expect(faces).to include "user#{i}"
|
160
|
+
end
|
161
|
+
end
|
162
|
+
|
163
|
+
it 'can recognize faces from an image' do
|
164
|
+
result = deepstack.recognize_faces(image)
|
165
|
+
# pp result
|
166
|
+
expect(result).to be_an Array
|
167
|
+
expect(result.first.keys).to include(*%w[confidence userid x_min y_min x_max y_max])
|
168
|
+
end
|
169
|
+
|
170
|
+
it 'can delete a registered face' do
|
171
|
+
face_count_before = deepstack.face_list.size
|
172
|
+
result = deepstack.delete_face('user1')
|
173
|
+
expect(result).to be true
|
174
|
+
expect(deepstack.face_list.size).to be < face_count_before
|
175
|
+
end
|
176
|
+
|
177
|
+
it 'can delete all registered faces' do
|
178
|
+
faces = deepstack.face_list
|
179
|
+
expect(faces.size).to be > 0
|
180
|
+
result = deepstack.delete_faces(faces)
|
181
|
+
expect(result).to be_a Hash
|
182
|
+
faces = deepstack.face_list
|
183
|
+
expect(faces.size).to eq 0
|
184
|
+
end
|
185
|
+
|
186
|
+
it 'can perform face matching' do
|
187
|
+
image2 = image
|
188
|
+
result = deepstack.face_match(image, image2)
|
189
|
+
expect(result).to be_a_kind_of(Numeric)
|
190
|
+
end
|
191
|
+
end
|
192
|
+
|
193
|
+
context 'Scene Recognition' do
|
194
|
+
it 'can detect scene' do
|
195
|
+
result = deepstack.identify_scene(image)
|
196
|
+
expect(result).to be_a Hash
|
197
|
+
# pp result
|
198
|
+
expect(result.keys).to include(*%w[confidence label])
|
199
|
+
end
|
200
|
+
end
|
201
|
+
|
202
|
+
# context 'Image Enhancer' do
|
203
|
+
# # before { skip('Skipping because this test is slow') }
|
204
|
+
# it 'can enhance image' do
|
205
|
+
# result = deepstack.enhance_image(image)
|
206
|
+
# expect(result).to be_truthy
|
207
|
+
# end
|
208
|
+
# end
|
209
|
+
|
210
|
+
context 'Custom Model' do
|
211
|
+
it 'can use a custom model' do
|
212
|
+
result = deepstack.custom_model('combined', image)
|
213
|
+
expect(result).to be_an Array
|
214
|
+
end
|
215
|
+
end
|
216
|
+
end
|
217
|
+
# rubocop:enable Metrics/BlockLength
|
metadata
CHANGED
@@ -1,15 +1,99 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: deepstack
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 1.
|
4
|
+
version: 1.6.1
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Jimmy Tanagra
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2022-05-
|
12
|
-
dependencies:
|
11
|
+
date: 2022-05-14 00:00:00.000000000 Z
|
12
|
+
dependencies:
|
13
|
+
- !ruby/object:Gem::Dependency
|
14
|
+
name: rake
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
16
|
+
requirements:
|
17
|
+
- - "~>"
|
18
|
+
- !ruby/object:Gem::Version
|
19
|
+
version: '13.0'
|
20
|
+
type: :development
|
21
|
+
prerelease: false
|
22
|
+
version_requirements: !ruby/object:Gem::Requirement
|
23
|
+
requirements:
|
24
|
+
- - "~>"
|
25
|
+
- !ruby/object:Gem::Version
|
26
|
+
version: '13.0'
|
27
|
+
- !ruby/object:Gem::Dependency
|
28
|
+
name: rspec
|
29
|
+
requirement: !ruby/object:Gem::Requirement
|
30
|
+
requirements:
|
31
|
+
- - "~>"
|
32
|
+
- !ruby/object:Gem::Version
|
33
|
+
version: '3.0'
|
34
|
+
type: :development
|
35
|
+
prerelease: false
|
36
|
+
version_requirements: !ruby/object:Gem::Requirement
|
37
|
+
requirements:
|
38
|
+
- - "~>"
|
39
|
+
- !ruby/object:Gem::Version
|
40
|
+
version: '3.0'
|
41
|
+
- !ruby/object:Gem::Dependency
|
42
|
+
name: rubocop
|
43
|
+
requirement: !ruby/object:Gem::Requirement
|
44
|
+
requirements:
|
45
|
+
- - "~>"
|
46
|
+
- !ruby/object:Gem::Version
|
47
|
+
version: '1.21'
|
48
|
+
type: :development
|
49
|
+
prerelease: false
|
50
|
+
version_requirements: !ruby/object:Gem::Requirement
|
51
|
+
requirements:
|
52
|
+
- - "~>"
|
53
|
+
- !ruby/object:Gem::Version
|
54
|
+
version: '1.21'
|
55
|
+
- !ruby/object:Gem::Dependency
|
56
|
+
name: rubocop-rake
|
57
|
+
requirement: !ruby/object:Gem::Requirement
|
58
|
+
requirements:
|
59
|
+
- - "~>"
|
60
|
+
- !ruby/object:Gem::Version
|
61
|
+
version: '0.6'
|
62
|
+
type: :development
|
63
|
+
prerelease: false
|
64
|
+
version_requirements: !ruby/object:Gem::Requirement
|
65
|
+
requirements:
|
66
|
+
- - "~>"
|
67
|
+
- !ruby/object:Gem::Version
|
68
|
+
version: '0.6'
|
69
|
+
- !ruby/object:Gem::Dependency
|
70
|
+
name: rubocop-rspec
|
71
|
+
requirement: !ruby/object:Gem::Requirement
|
72
|
+
requirements:
|
73
|
+
- - ">="
|
74
|
+
- !ruby/object:Gem::Version
|
75
|
+
version: '0'
|
76
|
+
type: :development
|
77
|
+
prerelease: false
|
78
|
+
version_requirements: !ruby/object:Gem::Requirement
|
79
|
+
requirements:
|
80
|
+
- - ">="
|
81
|
+
- !ruby/object:Gem::Version
|
82
|
+
version: '0'
|
83
|
+
- !ruby/object:Gem::Dependency
|
84
|
+
name: yard
|
85
|
+
requirement: !ruby/object:Gem::Requirement
|
86
|
+
requirements:
|
87
|
+
- - ">="
|
88
|
+
- !ruby/object:Gem::Version
|
89
|
+
version: '0'
|
90
|
+
type: :development
|
91
|
+
prerelease: false
|
92
|
+
version_requirements: !ruby/object:Gem::Requirement
|
93
|
+
requirements:
|
94
|
+
- - ">="
|
95
|
+
- !ruby/object:Gem::Version
|
96
|
+
version: '0'
|
13
97
|
description:
|
14
98
|
email:
|
15
99
|
- jcode@tanagra.id.au
|
@@ -17,13 +101,16 @@ executables: []
|
|
17
101
|
extensions: []
|
18
102
|
extra_rdoc_files: []
|
19
103
|
files:
|
104
|
+
- README.md
|
20
105
|
- lib/deep_stack/custom_model.rb
|
21
106
|
- lib/deep_stack/deep_stack.rb
|
22
107
|
- lib/deep_stack/detection.rb
|
23
108
|
- lib/deep_stack/face.rb
|
109
|
+
- lib/deep_stack/image.rb
|
24
110
|
- lib/deep_stack/scene.rb
|
25
111
|
- lib/deep_stack/version.rb
|
26
112
|
- lib/deepstack.rb
|
113
|
+
- spec/deepstack_spec.rb
|
27
114
|
homepage: https://github.com/jimtng/deepstack-ruby
|
28
115
|
licenses:
|
29
116
|
- EPL-2.0
|
@@ -51,4 +138,5 @@ rubygems_version: 3.0.3.1
|
|
51
138
|
signing_key:
|
52
139
|
specification_version: 4
|
53
140
|
summary: A Ruby wrapper for DeepStack API
|
54
|
-
test_files:
|
141
|
+
test_files:
|
142
|
+
- spec/deepstack_spec.rb
|