deepstack 0.0.1 → 1.2.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/lib/{deepstack → deep_stack}/custom.rb +4 -5
- data/lib/deep_stack/deep_stack.rb +120 -0
- data/lib/{deepstack → deep_stack}/detection.rb +3 -4
- data/lib/{deepstack → deep_stack}/face.rb +9 -13
- data/lib/{deepstack → deep_stack}/scene.rb +3 -3
- data/lib/deep_stack/version.rb +9 -0
- data/lib/deepstack.rb +1 -109
- metadata +15 -13
- data/lib/deepstack/version.rb +0 -9
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: caf4cf801a5a99ff308e5afc06ed19dac86d8348388c519880770d482fd1bb0b
|
|
4
|
+
data.tar.gz: de77bacb1bd1ffb46c4dff277ab16e1195ef423f005ad98394b49cab6e248fa3
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 6836c3bc1e6dc367542c4bd9e3e089ddf2cf3a7e612d6230dfabf3f3a38a4651965eead00bba50dd5916e5a9d8fcc44c624f3743b17165fbda24cff8c9ea7ec8
|
|
7
|
+
data.tar.gz: 5f5c98987f6fae82a67ef8fa57a557aa300bd22da6108a8575eabe6e3ac8d1f301f57caad1f86b533629b503d53db4bb40e101ff630abddce1b2659637e2b177
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
class DeepStack
|
|
4
4
|
# Custom Model
|
|
5
5
|
module Custom
|
|
6
6
|
#
|
|
@@ -28,16 +28,15 @@ module Deepstack
|
|
|
28
28
|
#
|
|
29
29
|
# @param [String] model custom model name
|
|
30
30
|
# @param [Object] image binary data or a File object
|
|
31
|
-
# @param [Hash] options additional fields for
|
|
31
|
+
# @param [Hash] options additional fields for DeepStack, e.g. min_confidence: 0.5
|
|
32
32
|
#
|
|
33
|
-
# @return [Array] if successful, an array of
|
|
33
|
+
# @return [Array] if successful, an array of DeepStack predictions
|
|
34
34
|
#
|
|
35
35
|
# @return [nil] if error
|
|
36
36
|
#
|
|
37
37
|
def custom_inference(model, image, **options)
|
|
38
38
|
target = "vision/custom/#{model}"
|
|
39
|
-
api_post(target, image, options)
|
|
40
|
-
predictions
|
|
39
|
+
api_post(target, image, options)&.dig('predictions')
|
|
41
40
|
end
|
|
42
41
|
end
|
|
43
42
|
end
|
|
@@ -0,0 +1,120 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require 'net/http'
|
|
4
|
+
require 'json'
|
|
5
|
+
require_relative 'face'
|
|
6
|
+
require_relative 'detection'
|
|
7
|
+
require_relative 'scene'
|
|
8
|
+
require_relative 'custom'
|
|
9
|
+
require_relative 'version'
|
|
10
|
+
|
|
11
|
+
# DeepStack API
|
|
12
|
+
class DeepStack
|
|
13
|
+
include DeepStack::Face
|
|
14
|
+
include DeepStack::Detection
|
|
15
|
+
include DeepStack::Scene
|
|
16
|
+
include DeepStack::Custom
|
|
17
|
+
|
|
18
|
+
#
|
|
19
|
+
# Create a deepstack object connected to the given URL
|
|
20
|
+
#
|
|
21
|
+
# @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
|
|
24
|
+
#
|
|
25
|
+
# @example
|
|
26
|
+
# DeepStack.new('http://127.0.0.1:5000')
|
|
27
|
+
#
|
|
28
|
+
def initialize(base_url, api_key: nil, admin_key: nil)
|
|
29
|
+
@base_url = base_url
|
|
30
|
+
@auth = { api_key: api_key, admin_key: admin_key }.select { |_k, v| v } # remove nil values
|
|
31
|
+
@http_mutex = Mutex.new
|
|
32
|
+
end
|
|
33
|
+
|
|
34
|
+
#
|
|
35
|
+
# Make a POST request to DeepStack path target
|
|
36
|
+
#
|
|
37
|
+
# @param [String] path to the DeepStack API URL
|
|
38
|
+
# @param [Array] images zero or more images to post
|
|
39
|
+
# @param [Hash] args additional named fields to post
|
|
40
|
+
#
|
|
41
|
+
# @return [Hash] if successful, the json data returned by DeepStack, nil otherwise
|
|
42
|
+
#
|
|
43
|
+
def api_post(path, *images, **args)
|
|
44
|
+
uri = build_uri(path)
|
|
45
|
+
args = @auth.merge(args)
|
|
46
|
+
|
|
47
|
+
result = nil
|
|
48
|
+
10.times do
|
|
49
|
+
result = images ? post_files(uri, images.flatten, **args) : post(uri, args)
|
|
50
|
+
break unless result.is_a?(Net::HTTPRedirection)
|
|
51
|
+
|
|
52
|
+
uri.path = result['location']
|
|
53
|
+
end
|
|
54
|
+
raise Net::HTTPClientException, 'Too many redirections' if result.is_a?(Net::HTTPRedirection)
|
|
55
|
+
|
|
56
|
+
process_result(result)
|
|
57
|
+
end
|
|
58
|
+
|
|
59
|
+
#
|
|
60
|
+
# Close the HTTP connection to DeepStack server
|
|
61
|
+
#
|
|
62
|
+
def close
|
|
63
|
+
@http_mutex.synchronize do
|
|
64
|
+
@http&.finish
|
|
65
|
+
@http = nil
|
|
66
|
+
end
|
|
67
|
+
end
|
|
68
|
+
|
|
69
|
+
private
|
|
70
|
+
|
|
71
|
+
def build_uri(path)
|
|
72
|
+
URI.join(@base_url, '/v1/', path)
|
|
73
|
+
end
|
|
74
|
+
|
|
75
|
+
def post(uri, **args)
|
|
76
|
+
Net::HTTP.post_form(uri, args)
|
|
77
|
+
end
|
|
78
|
+
|
|
79
|
+
def post_files(uri, *images, **args)
|
|
80
|
+
form_data = combine_images_and_args(images.flatten, **args)
|
|
81
|
+
req = Net::HTTP::Post.new(uri)
|
|
82
|
+
req.set_form(form_data, 'multipart/form-data')
|
|
83
|
+
@http_mutex.synchronize do
|
|
84
|
+
@http ||= Net::HTTP.start(uri.hostname, uri.port)
|
|
85
|
+
@http.request(req)
|
|
86
|
+
end
|
|
87
|
+
end
|
|
88
|
+
|
|
89
|
+
def combine_images_and_args(*images, **args)
|
|
90
|
+
stringify_keys(args).concat(image_form_data(images.flatten))
|
|
91
|
+
end
|
|
92
|
+
|
|
93
|
+
def stringify_keys(hash)
|
|
94
|
+
hash.map { |k, v| [k.to_s, v] }
|
|
95
|
+
end
|
|
96
|
+
|
|
97
|
+
#
|
|
98
|
+
# Return an array of image entries for form data.
|
|
99
|
+
# The field name is 'image' for a single image
|
|
100
|
+
# For multiple images, the field names will be 'image1', 'image2', ...
|
|
101
|
+
#
|
|
102
|
+
# @param [Array<Object>] images an array of raw image data or a File object
|
|
103
|
+
#
|
|
104
|
+
# @return [Array] the image entries for set_form
|
|
105
|
+
#
|
|
106
|
+
def image_form_data(*images)
|
|
107
|
+
images = images.flatten
|
|
108
|
+
return [image_entry('image', images.first)] if images.length == 1
|
|
109
|
+
|
|
110
|
+
images.map.with_index(1) { |image, i| image_entry("image#{i}", image) }
|
|
111
|
+
end
|
|
112
|
+
|
|
113
|
+
def image_entry(name, image)
|
|
114
|
+
[name, image].tap { |result| result << { filename: "#{name}.jpg" } unless image.instance_of? File }
|
|
115
|
+
end
|
|
116
|
+
|
|
117
|
+
def process_result(result)
|
|
118
|
+
result.is_a?(Net::HTTPSuccess) ? JSON.parse(result.body) : nil
|
|
119
|
+
end
|
|
120
|
+
end
|
|
@@ -1,20 +1,19 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
class DeepStack
|
|
4
4
|
# APIs related to object detection
|
|
5
5
|
module Detection
|
|
6
6
|
#
|
|
7
7
|
# Perform object detection
|
|
8
8
|
#
|
|
9
9
|
# @param [Object] image raw image data or a File object of an image file
|
|
10
|
-
# @param [Hash] options additional fields for
|
|
10
|
+
# @param [Hash] options additional fields for DeepStack, e.g. min_confidence: 0.5
|
|
11
11
|
#
|
|
12
12
|
# @return [Array] a list of predictions, or nil on error
|
|
13
13
|
#
|
|
14
14
|
def detect_objects(image, **options)
|
|
15
15
|
target = 'vision/detection'
|
|
16
|
-
api_post(target, image, **options)
|
|
17
|
-
predictions
|
|
16
|
+
api_post(target, image, **options)&.dig('predictions')
|
|
18
17
|
end
|
|
19
18
|
end
|
|
20
19
|
end
|
|
@@ -1,36 +1,34 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
class DeepStack
|
|
4
4
|
# APIs related to face recognition
|
|
5
5
|
module Face
|
|
6
6
|
#
|
|
7
7
|
# Perform face recognition
|
|
8
8
|
#
|
|
9
9
|
# @param [Object] image binary data or a File object
|
|
10
|
-
# @param [Hash] options additional fields for
|
|
10
|
+
# @param [Hash] options additional fields for DeepStack, e.g. min_confidence: 0.5
|
|
11
11
|
#
|
|
12
|
-
# @return [Array] if successful, an array of
|
|
12
|
+
# @return [Array] if successful, an array of DeepStack predictions
|
|
13
13
|
#
|
|
14
14
|
# @return [nil] if error
|
|
15
15
|
#
|
|
16
16
|
def recognize_faces(image, **options)
|
|
17
17
|
target = 'vision/face/recognize'
|
|
18
|
-
api_post(target, image, **options)
|
|
19
|
-
predictions
|
|
18
|
+
api_post(target, image, **options)&.dig('predictions')
|
|
20
19
|
end
|
|
21
20
|
|
|
22
21
|
#
|
|
23
22
|
# Detect faces in an image
|
|
24
23
|
#
|
|
25
24
|
# @param [Object] image binary data or a File object
|
|
26
|
-
# @param [Hash] options additional fields for
|
|
25
|
+
# @param [Hash] options additional fields for DeepStack, e.g. min_confidence: 0.5
|
|
27
26
|
#
|
|
28
|
-
# @return [Array] if successful, an array of
|
|
27
|
+
# @return [Array] if successful, an array of DeepStack predictions
|
|
29
28
|
#
|
|
30
29
|
def detect_faces(image, **options)
|
|
31
30
|
target = 'vision/face/' # the URL ends with a slash
|
|
32
|
-
api_post(target, image, **options)
|
|
33
|
-
predictions
|
|
31
|
+
api_post(target, image, **options)&.dig('predictions')
|
|
34
32
|
end
|
|
35
33
|
|
|
36
34
|
#
|
|
@@ -64,8 +62,7 @@ module Deepstack
|
|
|
64
62
|
#
|
|
65
63
|
def delete_face(userid)
|
|
66
64
|
target = 'vision/face/delete'
|
|
67
|
-
api_post(target, userid: userid)
|
|
68
|
-
success?
|
|
65
|
+
api_post(target, userid: userid)&.dig('success') == true
|
|
69
66
|
end
|
|
70
67
|
|
|
71
68
|
#
|
|
@@ -78,8 +75,7 @@ module Deepstack
|
|
|
78
75
|
#
|
|
79
76
|
def register_face(userid, *images)
|
|
80
77
|
target = 'vision/face/register'
|
|
81
|
-
api_post(target, images, userid: userid)
|
|
82
|
-
success?
|
|
78
|
+
api_post(target, images, userid: userid)&.dig('success') == true
|
|
83
79
|
end
|
|
84
80
|
end
|
|
85
81
|
end
|
|
@@ -1,15 +1,15 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
class DeepStack
|
|
4
4
|
# Scene Recognition
|
|
5
5
|
module Scene
|
|
6
6
|
#
|
|
7
7
|
# Return
|
|
8
8
|
#
|
|
9
9
|
# @param [Object] image binary data or a File object
|
|
10
|
-
# @param [Hash] options additional fields for
|
|
10
|
+
# @param [Hash] options additional fields for DeepStack, e.g. min_confidence: 0.5
|
|
11
11
|
#
|
|
12
|
-
# @return [Hash] if successful,
|
|
12
|
+
# @return [Hash] if successful, DeepStack result hash {'label' => 'scene', 'confidence' => 2.2}
|
|
13
13
|
#
|
|
14
14
|
# @return [nil] if error
|
|
15
15
|
def identify_scene(image, **options)
|
data/lib/deepstack.rb
CHANGED
|
@@ -1,111 +1,3 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
2
|
|
|
3
|
-
|
|
4
|
-
require 'net/http'
|
|
5
|
-
require 'json'
|
|
6
|
-
require_relative 'deepstack/face'
|
|
7
|
-
require_relative 'deepstack/detection'
|
|
8
|
-
require_relative 'deepstack/scene'
|
|
9
|
-
require_relative 'deepstack/custom'
|
|
10
|
-
require_relative 'deepstack/version'
|
|
11
|
-
|
|
12
|
-
module Deepstack
|
|
13
|
-
# Deepstack API
|
|
14
|
-
class API
|
|
15
|
-
include Deepstack::Face
|
|
16
|
-
include Deepstack::Detection
|
|
17
|
-
include Deepstack::Scene
|
|
18
|
-
include Deepstack::Custom
|
|
19
|
-
|
|
20
|
-
attr_reader :duration, :predictions, :success
|
|
21
|
-
|
|
22
|
-
# Create a deepstack object connected to the given URL
|
|
23
|
-
def initialize(base_url)
|
|
24
|
-
@base_url = base_url
|
|
25
|
-
end
|
|
26
|
-
|
|
27
|
-
#
|
|
28
|
-
# The result of the last call
|
|
29
|
-
#
|
|
30
|
-
# @return [Boolean] true if the last call was successful
|
|
31
|
-
#
|
|
32
|
-
def success?
|
|
33
|
-
@success == true
|
|
34
|
-
end
|
|
35
|
-
|
|
36
|
-
#
|
|
37
|
-
# Make a POST request to Deepstack path target
|
|
38
|
-
#
|
|
39
|
-
# @param [String] path to the Deepstack API URL
|
|
40
|
-
# @param [Array] images zero or more images to post
|
|
41
|
-
# @param [Hash] args additional named fields to post
|
|
42
|
-
#
|
|
43
|
-
# @return [Hash] if successful, the json data returned by Deepstack, nil otherwise
|
|
44
|
-
#
|
|
45
|
-
def api_post(path, *images, **args)
|
|
46
|
-
uri = build_uri(path)
|
|
47
|
-
|
|
48
|
-
result = nil
|
|
49
|
-
10.times do
|
|
50
|
-
result = images ? post_files(uri, images.flatten, **args) : post(uri, args)
|
|
51
|
-
break unless result.is_a?(Net::HTTPRedirection)
|
|
52
|
-
|
|
53
|
-
uri.path = result['location']
|
|
54
|
-
end
|
|
55
|
-
raise Net::HTTPClientException, 'Too many redirections' if result.is_a?(Net::HTTPRedirection)
|
|
56
|
-
|
|
57
|
-
process_result(result)
|
|
58
|
-
end
|
|
59
|
-
|
|
60
|
-
private
|
|
61
|
-
|
|
62
|
-
def build_uri(path)
|
|
63
|
-
URI.join(@base_url, '/v1/', path)
|
|
64
|
-
end
|
|
65
|
-
|
|
66
|
-
def post(uri, **args)
|
|
67
|
-
Net::HTTP.post_form(uri, args)
|
|
68
|
-
end
|
|
69
|
-
|
|
70
|
-
def post_files(uri, *images, **args)
|
|
71
|
-
form_data = combine_images_and_args(images.flatten, **args)
|
|
72
|
-
req = Net::HTTP::Post.new(uri)
|
|
73
|
-
req.set_form(form_data, 'multipart/form-data')
|
|
74
|
-
Net::HTTP.start(uri.hostname, uri.port) { |http| http.request(req) }
|
|
75
|
-
end
|
|
76
|
-
|
|
77
|
-
def combine_images_and_args(*images, **args)
|
|
78
|
-
stringify_keys(args).concat(image_form_data(images.flatten))
|
|
79
|
-
end
|
|
80
|
-
|
|
81
|
-
def stringify_keys(hash)
|
|
82
|
-
hash.map { |k, v| [k.to_s, v] }
|
|
83
|
-
end
|
|
84
|
-
|
|
85
|
-
#
|
|
86
|
-
# Return an array of image entries for form data.
|
|
87
|
-
# The field name is 'image' for a single image
|
|
88
|
-
# For multiple images, the field names will be 'image1', 'image2', ...
|
|
89
|
-
#
|
|
90
|
-
# @param [Array<Object>] images an array of raw image data or a File object
|
|
91
|
-
#
|
|
92
|
-
# @return [Array] the image entries for set_form
|
|
93
|
-
#
|
|
94
|
-
def image_form_data(*images)
|
|
95
|
-
images = images.flatten
|
|
96
|
-
return [image_entry('image', images.first)] if images.length == 1
|
|
97
|
-
|
|
98
|
-
images.map.with_index(1) { |image, i| image_entry("image#{i}", image) }
|
|
99
|
-
end
|
|
100
|
-
|
|
101
|
-
def image_entry(name, image)
|
|
102
|
-
[name, image].tap { |result| result << { filename: "#{name}.jpg" } unless image.instance_of? File }
|
|
103
|
-
end
|
|
104
|
-
|
|
105
|
-
def process_result(result)
|
|
106
|
-
@result = result.is_a?(Net::HTTPSuccess) ? JSON.parse(result.body) : nil
|
|
107
|
-
%w[success duration predictions].each { |attrib| instance_variable_set("@#{attrib}", @result&.dig(attrib)) }
|
|
108
|
-
@result
|
|
109
|
-
end
|
|
110
|
-
end
|
|
111
|
-
end
|
|
3
|
+
require_relative 'deep_stack/deep_stack'
|
metadata
CHANGED
|
@@ -1,36 +1,38 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: deepstack
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version:
|
|
4
|
+
version: 1.2.0
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Jimmy Tanagra
|
|
8
|
-
autorequire:
|
|
8
|
+
autorequire:
|
|
9
9
|
bindir: bin
|
|
10
10
|
cert_chain: []
|
|
11
|
-
date: 2022-05-
|
|
11
|
+
date: 2022-05-11 00:00:00.000000000 Z
|
|
12
12
|
dependencies: []
|
|
13
|
-
description:
|
|
13
|
+
description:
|
|
14
14
|
email:
|
|
15
15
|
- jcode@tanagra.id.au
|
|
16
16
|
executables: []
|
|
17
17
|
extensions: []
|
|
18
18
|
extra_rdoc_files: []
|
|
19
19
|
files:
|
|
20
|
+
- lib/deep_stack/custom.rb
|
|
21
|
+
- lib/deep_stack/deep_stack.rb
|
|
22
|
+
- lib/deep_stack/detection.rb
|
|
23
|
+
- lib/deep_stack/face.rb
|
|
24
|
+
- lib/deep_stack/scene.rb
|
|
25
|
+
- lib/deep_stack/version.rb
|
|
20
26
|
- lib/deepstack.rb
|
|
21
|
-
- lib/deepstack/custom.rb
|
|
22
|
-
- lib/deepstack/detection.rb
|
|
23
|
-
- lib/deepstack/face.rb
|
|
24
|
-
- lib/deepstack/scene.rb
|
|
25
|
-
- lib/deepstack/version.rb
|
|
26
27
|
homepage: https://github.com/jimtng/deepstack-ruby
|
|
27
28
|
licenses:
|
|
28
29
|
- EPL-2.0
|
|
29
30
|
metadata:
|
|
30
31
|
homepage_uri: https://github.com/jimtng/deepstack-ruby
|
|
31
32
|
source_code_uri: https://github.com/jimtng/deepstack-ruby
|
|
33
|
+
documentation_uri: https://rubydoc.info/gems/deepstack
|
|
32
34
|
changelog_uri: https://github.com/jimtng/deepstack-ruby/blob/main/CHANGELOG.md
|
|
33
|
-
post_install_message:
|
|
35
|
+
post_install_message:
|
|
34
36
|
rdoc_options: []
|
|
35
37
|
require_paths:
|
|
36
38
|
- lib
|
|
@@ -45,8 +47,8 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
|
45
47
|
- !ruby/object:Gem::Version
|
|
46
48
|
version: '0'
|
|
47
49
|
requirements: []
|
|
48
|
-
rubygems_version: 3.3.
|
|
49
|
-
signing_key:
|
|
50
|
+
rubygems_version: 3.0.3.1
|
|
51
|
+
signing_key:
|
|
50
52
|
specification_version: 4
|
|
51
|
-
summary: A Ruby wrapper for
|
|
53
|
+
summary: A Ruby wrapper for DeepStack API
|
|
52
54
|
test_files: []
|