deepstack 1.6.0 → 1.6.1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/README.md +78 -0
- data/lib/deep_stack/deep_stack.rb +23 -11
- data/lib/deep_stack/face.rb +2 -2
- data/lib/deep_stack/version.rb +1 -1
- data/spec/deepstack_spec.rb +217 -0
- metadata +91 -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
|
@@ -9,7 +9,12 @@ require_relative 'custom_model'
|
|
9
9
|
require_relative 'image'
|
10
10
|
require_relative 'version'
|
11
11
|
|
12
|
-
#
|
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
|
+
#
|
13
18
|
class DeepStack
|
14
19
|
include DeepStack::Face
|
15
20
|
include DeepStack::Detection
|
@@ -18,31 +23,36 @@ class DeepStack
|
|
18
23
|
include DeepStack::CustomModel
|
19
24
|
|
20
25
|
#
|
21
|
-
# 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.
|
22
31
|
#
|
23
32
|
# @param [String] base_url the url to DeepStack's server:port
|
24
|
-
# @param [String] api_key an optional API-KEY to use when connecting to DeepStack
|
25
|
-
# @param [String]
|
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
|
26
35
|
# @param [Integer] verify_mode sets the flags for server the certification verification at
|
27
|
-
# beginning of SSL/TLS session.
|
36
|
+
# beginning of an SSL/TLS session.
|
28
37
|
# +OpenSSL::SSL::VERIFY_NONE+ or +OpenSSL::SSL::VERIFY_PEER+ are acceptable.
|
38
|
+
# The default is +OpenSSL::SSL::VERIFY_PEER+.
|
29
39
|
#
|
30
40
|
# @example
|
31
41
|
# DeepStack.new('http://127.0.0.1:5000')
|
32
42
|
#
|
33
|
-
# # Using API KEY
|
43
|
+
# # Using an API KEY
|
34
44
|
# DeepStack.new('http://127.0.0.1:5000', api_key: 'secret', admin_key: 'supersecret')
|
35
45
|
#
|
36
|
-
# #
|
46
|
+
# # SSL connection with a self-signed certificate
|
37
47
|
# DeepStack.new('https://localhost:443', verify_mode: OpenSSL::SSL::VERIFY_NONE)
|
38
48
|
#
|
39
49
|
def initialize(base_url, api_key: nil, admin_key: nil, verify_mode: nil)
|
40
50
|
@base_url = base_url
|
41
51
|
@auth = { api_key: api_key, admin_key: admin_key }.select { |_k, v| v } # remove nil values
|
42
52
|
uri = URI(base_url)
|
43
|
-
|
44
|
-
|
45
|
-
@http =
|
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
|
46
56
|
end
|
47
57
|
|
48
58
|
#
|
@@ -71,7 +81,9 @@ class DeepStack
|
|
71
81
|
end
|
72
82
|
|
73
83
|
#
|
74
|
-
# 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.
|
75
87
|
#
|
76
88
|
def close
|
77
89
|
@http.finish if @http&.started?
|
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
|
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.6.
|
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,6 +101,7 @@ 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
|
@@ -25,6 +110,7 @@ files:
|
|
25
110
|
- lib/deep_stack/scene.rb
|
26
111
|
- lib/deep_stack/version.rb
|
27
112
|
- lib/deepstack.rb
|
113
|
+
- spec/deepstack_spec.rb
|
28
114
|
homepage: https://github.com/jimtng/deepstack-ruby
|
29
115
|
licenses:
|
30
116
|
- EPL-2.0
|
@@ -52,4 +138,5 @@ rubygems_version: 3.0.3.1
|
|
52
138
|
signing_key:
|
53
139
|
specification_version: 4
|
54
140
|
summary: A Ruby wrapper for DeepStack API
|
55
|
-
test_files:
|
141
|
+
test_files:
|
142
|
+
- spec/deepstack_spec.rb
|