deepstack 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA256:
3
+ metadata.gz: 6bd245c6bb369aed6c65f88277a186cd283d396b5eeafa28bc10e854dfbd027c
4
+ data.tar.gz: b428c594d92837534124004c0ff0ef4f0b0c2aad0a2cf40ef4faa69f38d904d3
5
+ SHA512:
6
+ metadata.gz: 1f4d4c306447142dd071a6a4a28ce8f36f2170cf23160401e7cbf1786d9b8124e9c72e1a144c13096b62ad03a361fe4684f0aa8d9fab4aee0b921017ed0fff8c
7
+ data.tar.gz: 2a7c706fbfe815f7faf5ce06294f1eff65c2c9aeec3cdddb865e97348475cf1ee3478b9152444e4a92ae3697eeae3ad4e97a1fd47edff3247578eae52b340953
@@ -0,0 +1,43 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Deepstack
4
+ # Custom Model
5
+ module Custom
6
+ #
7
+ # Register a custom inference method for convenience.
8
+ # The custom method is called "identify_<modelname>"
9
+ # Example:
10
+ # deepstack.register_custom_model('license_plate')
11
+ # deepstack.identify_license_plate(image)
12
+ #
13
+ # @param [Array] models a list of one or more custom model names to register
14
+ #
15
+ # @return [<Type>] <description>
16
+ #
17
+ def self.register_model(*models)
18
+ models.flatten.each do |model|
19
+ method_name = 'identify_'.concat model.gsub(/-+/, '_') # convert - to _
20
+ define_method(method_name) do |image, **options|
21
+ custom_inference(model, image, options)
22
+ end
23
+ end
24
+ end
25
+
26
+ #
27
+ # Return predictions using a custom model
28
+ #
29
+ # @param [String] model custom model name
30
+ # @param [Object] image binary data or a File object
31
+ # @param [Hash] options additional fields for Deepstack, e.g. min_confidence: 0.5
32
+ #
33
+ # @return [Array] if successful, an array of Deepstack predictions
34
+ #
35
+ # @return [nil] if error
36
+ #
37
+ def custom_inference(model, image, **options)
38
+ target = "vision/custom/#{model}"
39
+ api_post(target, image, options)
40
+ predictions
41
+ end
42
+ end
43
+ end
@@ -0,0 +1,20 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Deepstack
4
+ # APIs related to object detection
5
+ module Detection
6
+ #
7
+ # Perform object detection
8
+ #
9
+ # @param [Object] image raw image data or a File object of an image file
10
+ # @param [Hash] options additional fields for Deepstack, e.g. min_confidence: 0.5
11
+ #
12
+ # @return [Array] a list of predictions, or nil on error
13
+ #
14
+ def detect_objects(image, **options)
15
+ target = 'vision/detection'
16
+ api_post(target, image, **options)
17
+ predictions
18
+ end
19
+ end
20
+ end
@@ -0,0 +1,85 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Deepstack
4
+ # APIs related to face recognition
5
+ module Face
6
+ #
7
+ # Perform face recognition
8
+ #
9
+ # @param [Object] image binary data or a File object
10
+ # @param [Hash] options additional fields for Deepstack, e.g. min_confidence: 0.5
11
+ #
12
+ # @return [Array] if successful, an array of Deepstack predictions
13
+ #
14
+ # @return [nil] if error
15
+ #
16
+ def recognize_faces(image, **options)
17
+ target = 'vision/face/recognize'
18
+ api_post(target, image, **options)
19
+ predictions
20
+ end
21
+
22
+ #
23
+ # Detect faces in an image
24
+ #
25
+ # @param [Object] image binary data or a File object
26
+ # @param [Hash] options additional fields for Deepstack, e.g. min_confidence: 0.5
27
+ #
28
+ # @return [Array] if successful, an array of Deepstack predictions
29
+ #
30
+ def detect_faces(image, **options)
31
+ target = 'vision/face/' # the URL ends with a slash
32
+ api_post(target, image, **options)
33
+ predictions
34
+ end
35
+
36
+ #
37
+ # Get a list of registered faces
38
+ #
39
+ # @return [Array] a list of userids
40
+ #
41
+ def face_list
42
+ target = 'vision/face/list'
43
+ api_post(target)&.dig('faces')
44
+ # {"success"=>true, "faces"=>["face_1", "face_2"], "duration"=>0}
45
+ end
46
+
47
+ #
48
+ # Delete the given list of faces / userids
49
+ #
50
+ # @param [Array] userids a list of userids to delete
51
+ #
52
+ # @return [Hash] A hash of `userid => boolean` that indicates success/failure
53
+ #
54
+ def delete_faces(*userids)
55
+ userids.flatten.compact.to_h { |userid| [userid, delete_face(userid)] }
56
+ end
57
+
58
+ #
59
+ # Delete the given face / userid
60
+ #
61
+ # @param [String] userid to delete
62
+ #
63
+ # @return [Boolean] true when successful
64
+ #
65
+ def delete_face(userid)
66
+ target = 'vision/face/delete'
67
+ api_post(target, userid: userid)
68
+ success?
69
+ end
70
+
71
+ #
72
+ # Register a face
73
+ #
74
+ # @param [String] userid to register
75
+ # @param [Array] images facial image data in binary form or File object
76
+ #
77
+ # @return [Boolean] true when successful
78
+ #
79
+ def register_face(userid, *images)
80
+ target = 'vision/face/register'
81
+ api_post(target, images, userid: userid)
82
+ success?
83
+ end
84
+ end
85
+ end
@@ -0,0 +1,20 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Deepstack
4
+ # Scene Recognition
5
+ module Scene
6
+ #
7
+ # Return
8
+ #
9
+ # @param [Object] image binary data or a File object
10
+ # @param [Hash] options additional fields for Deepstack, e.g. min_confidence: 0.5
11
+ #
12
+ # @return [Hash] if successful, Deepstack result hash {'label' => 'scene', 'confidence' => 2.2}
13
+ #
14
+ # @return [nil] if error
15
+ def identify_scene(image, **options)
16
+ target = 'vision/scene'
17
+ api_post(target, image, **options)
18
+ end
19
+ end
20
+ end
@@ -0,0 +1,9 @@
1
+ # frozen_string_literal: true
2
+
3
+ #
4
+ # Holds project version constant
5
+ #
6
+ module Deepstack
7
+ # @return [String] Version of Deepstack helper libraries
8
+ VERSION = '0.0.1'
9
+ end
data/lib/deepstack.rb ADDED
@@ -0,0 +1,111 @@
1
+ # frozen_string_literal: true
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
+ 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
metadata ADDED
@@ -0,0 +1,52 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: deepstack
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.0.1
5
+ platform: ruby
6
+ authors:
7
+ - Jimmy Tanagra
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2022-05-09 00:00:00.000000000 Z
12
+ dependencies: []
13
+ description:
14
+ email:
15
+ - jcode@tanagra.id.au
16
+ executables: []
17
+ extensions: []
18
+ extra_rdoc_files: []
19
+ files:
20
+ - 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
+ homepage: https://github.com/jimtng/deepstack-ruby
27
+ licenses:
28
+ - EPL-2.0
29
+ metadata:
30
+ homepage_uri: https://github.com/jimtng/deepstack-ruby
31
+ source_code_uri: https://github.com/jimtng/deepstack-ruby
32
+ changelog_uri: https://github.com/jimtng/deepstack-ruby/blob/main/CHANGELOG.md
33
+ post_install_message:
34
+ rdoc_options: []
35
+ require_paths:
36
+ - lib
37
+ required_ruby_version: !ruby/object:Gem::Requirement
38
+ requirements:
39
+ - - ">="
40
+ - !ruby/object:Gem::Version
41
+ version: 2.6.0
42
+ required_rubygems_version: !ruby/object:Gem::Requirement
43
+ requirements:
44
+ - - ">="
45
+ - !ruby/object:Gem::Version
46
+ version: '0'
47
+ requirements: []
48
+ rubygems_version: 3.3.7
49
+ signing_key:
50
+ specification_version: 4
51
+ summary: A Ruby wrapper for Deepstack API
52
+ test_files: []