deepstack 1.0.0 → 1.1.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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: dc0409e409422c065962aa065244f20658c764c904462935936b05c1950e771a
4
- data.tar.gz: 074e0f2e9f309f72aaa402ef5e1b3bd469da172bbb60679a2a59b218f4a2a7ac
3
+ metadata.gz: b13995c10316b274d2b292316076cf96c96f945ac7304835ca5dc25fd873eaeb
4
+ data.tar.gz: 585b76987b8d1db73e05e78b777bf6fcd716e38f40c7c1e9b9150a7c833d84ec
5
5
  SHA512:
6
- metadata.gz: '0923fd828175f78a7bc90a40623c6ed7ec8ce8681876ab340697309c9557bdbf2551f10567b4df4dd861c2121e2cd37c62b47f06803e08f8cc0b1a5739e68d89'
7
- data.tar.gz: b9be9f1439d69f939f2dbf66842264a750e47d8cba455ff528b7879f115f3510e45690f8ff7a804e1b23428a5313c44c147049b3bcc269db31b4887f7c03b34e
6
+ metadata.gz: 41f4207559f4976ebf42864186661a538f6d45978958ec22a951c2e1ddac17685c67a2050de1064fe070c10f39fd9d3b954807be40bd04b14be5cf4e24221e5c
7
+ data.tar.gz: ceac07d54df401e92619d2c48e493ced1e6b2543a71bfe8dc79ccb5b1be53e34aa96d38eaf395b6bfbd919739c7476a886fac54fdb1fb9bf945a60cce6c0bba4
@@ -1,6 +1,6 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- module DeepStackModule
3
+ class DeepStack
4
4
  # Custom Model
5
5
  module Custom
6
6
  #
@@ -36,8 +36,7 @@ module DeepStackModule
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,110 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'pp'
4
+ require 'net/http'
5
+ require 'json'
6
+ require_relative 'face'
7
+ require_relative 'detection'
8
+ require_relative 'scene'
9
+ require_relative 'custom'
10
+ require_relative 'version'
11
+
12
+ # DeepStack API
13
+ class DeepStack
14
+ include DeepStack::Face
15
+ include DeepStack::Detection
16
+ include DeepStack::Scene
17
+ include DeepStack::Custom
18
+
19
+ # Create a deepstack object connected to the given URL
20
+ def initialize(base_url)
21
+ @base_url = base_url
22
+ @http_mutex = Mutex.new
23
+ end
24
+
25
+ #
26
+ # Make a POST request to DeepStack path target
27
+ #
28
+ # @param [String] path to the DeepStack API URL
29
+ # @param [Array] images zero or more images to post
30
+ # @param [Hash] args additional named fields to post
31
+ #
32
+ # @return [Hash] if successful, the json data returned by DeepStack, nil otherwise
33
+ #
34
+ def api_post(path, *images, **args)
35
+ uri = build_uri(path)
36
+
37
+ result = nil
38
+ 10.times do
39
+ result = images ? post_files(uri, images.flatten, **args) : post(uri, args)
40
+ break unless result.is_a?(Net::HTTPRedirection)
41
+
42
+ uri.path = result['location']
43
+ end
44
+ raise Net::HTTPClientException, 'Too many redirections' if result.is_a?(Net::HTTPRedirection)
45
+
46
+ process_result(result)
47
+ end
48
+
49
+ #
50
+ # Close the HTTP connection to DeepStack server
51
+ #
52
+ def close
53
+ @http_mutex.synchronize do
54
+ @http&.finish
55
+ @http = nil
56
+ end
57
+ end
58
+
59
+ private
60
+
61
+ def build_uri(path)
62
+ URI.join(@base_url, '/v1/', path)
63
+ end
64
+
65
+ def post(uri, **args)
66
+ Net::HTTP.post_form(uri, args)
67
+ end
68
+
69
+ def post_files(uri, *images, **args)
70
+ form_data = combine_images_and_args(images.flatten, **args)
71
+ req = Net::HTTP::Post.new(uri)
72
+ req.set_form(form_data, 'multipart/form-data')
73
+ @http_mutex.synchronize do
74
+ @http ||= Net::HTTP.start(uri.hostname, uri.port)
75
+ @http.request(req)
76
+ end
77
+ end
78
+
79
+ def combine_images_and_args(*images, **args)
80
+ stringify_keys(args).concat(image_form_data(images.flatten))
81
+ end
82
+
83
+ def stringify_keys(hash)
84
+ hash.map { |k, v| [k.to_s, v] }
85
+ end
86
+
87
+ #
88
+ # Return an array of image entries for form data.
89
+ # The field name is 'image' for a single image
90
+ # For multiple images, the field names will be 'image1', 'image2', ...
91
+ #
92
+ # @param [Array<Object>] images an array of raw image data or a File object
93
+ #
94
+ # @return [Array] the image entries for set_form
95
+ #
96
+ def image_form_data(*images)
97
+ images = images.flatten
98
+ return [image_entry('image', images.first)] if images.length == 1
99
+
100
+ images.map.with_index(1) { |image, i| image_entry("image#{i}", image) }
101
+ end
102
+
103
+ def image_entry(name, image)
104
+ [name, image].tap { |result| result << { filename: "#{name}.jpg" } unless image.instance_of? File }
105
+ end
106
+
107
+ def process_result(result)
108
+ result.is_a?(Net::HTTPSuccess) ? JSON.parse(result.body) : nil
109
+ end
110
+ end
@@ -1,6 +1,6 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- module DeepStackModule
3
+ class DeepStack
4
4
  # APIs related to object detection
5
5
  module Detection
6
6
  #
@@ -13,8 +13,7 @@ module DeepStackModule
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,6 +1,6 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- module DeepStackModule
3
+ class DeepStack
4
4
  # APIs related to face recognition
5
5
  module Face
6
6
  #
@@ -15,8 +15,7 @@ module DeepStackModule
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
  #
@@ -29,8 +28,7 @@ module DeepStackModule
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 DeepStackModule
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 DeepStackModule
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,6 +1,6 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- module DeepStackModule
3
+ class DeepStack
4
4
  # Scene Recognition
5
5
  module Scene
6
6
  #
@@ -5,5 +5,5 @@
5
5
  #
6
6
  class DeepStack
7
7
  # @return [String] Version of DeepStack helper libraries
8
- VERSION = '1.0.0'
8
+ VERSION = '1.1.1'
9
9
  end
data/lib/deepstack.rb CHANGED
@@ -1,109 +1,3 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require 'pp'
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
- # DeepStack API
13
- class DeepStack
14
- include DeepStackModule::Face
15
- include DeepStackModule::Detection
16
- include DeepStackModule::Scene
17
- include DeepStackModule::Custom
18
-
19
- attr_reader :duration, :predictions, :success
20
-
21
- # Create a deepstack object connected to the given URL
22
- def initialize(base_url)
23
- @base_url = base_url
24
- end
25
-
26
- #
27
- # The result of the last call
28
- #
29
- # @return [Boolean] true if the last call was successful
30
- #
31
- def success?
32
- @success == true
33
- end
34
-
35
- #
36
- # Make a POST request to DeepStack path target
37
- #
38
- # @param [String] path to the DeepStack API URL
39
- # @param [Array] images zero or more images to post
40
- # @param [Hash] args additional named fields to post
41
- #
42
- # @return [Hash] if successful, the json data returned by DeepStack, nil otherwise
43
- #
44
- def api_post(path, *images, **args)
45
- uri = build_uri(path)
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
- private
60
-
61
- def build_uri(path)
62
- URI.join(@base_url, '/v1/', path)
63
- end
64
-
65
- def post(uri, **args)
66
- Net::HTTP.post_form(uri, args)
67
- end
68
-
69
- def post_files(uri, *images, **args)
70
- form_data = combine_images_and_args(images.flatten, **args)
71
- req = Net::HTTP::Post.new(uri)
72
- req.set_form(form_data, 'multipart/form-data')
73
- Net::HTTP.start(uri.hostname, uri.port) { |http| http.request(req) }
74
- end
75
-
76
- def combine_images_and_args(*images, **args)
77
- stringify_keys(args).concat(image_form_data(images.flatten))
78
- end
79
-
80
- def stringify_keys(hash)
81
- hash.map { |k, v| [k.to_s, v] }
82
- end
83
-
84
- #
85
- # Return an array of image entries for form data.
86
- # The field name is 'image' for a single image
87
- # For multiple images, the field names will be 'image1', 'image2', ...
88
- #
89
- # @param [Array<Object>] images an array of raw image data or a File object
90
- #
91
- # @return [Array] the image entries for set_form
92
- #
93
- def image_form_data(*images)
94
- images = images.flatten
95
- return [image_entry('image', images.first)] if images.length == 1
96
-
97
- images.map.with_index(1) { |image, i| image_entry("image#{i}", image) }
98
- end
99
-
100
- def image_entry(name, image)
101
- [name, image].tap { |result| result << { filename: "#{name}.jpg" } unless image.instance_of? File }
102
- end
103
-
104
- def process_result(result)
105
- @result = result.is_a?(Net::HTTPSuccess) ? JSON.parse(result.body) : nil
106
- %w[success duration predictions].each { |attrib| instance_variable_set("@#{attrib}", @result&.dig(attrib)) }
107
- @result
108
- end
109
- 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: 1.0.0
4
+ version: 1.1.1
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-09 00:00:00.000000000 Z
11
+ date: 2022-05-10 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.7
49
- signing_key:
50
+ rubygems_version: 3.0.3.1
51
+ signing_key:
50
52
  specification_version: 4
51
53
  summary: A Ruby wrapper for DeepStack API
52
54
  test_files: []