picguard 1.0.0 → 1.0.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (45) hide show
  1. checksums.yaml +4 -4
  2. data/.codeclimate.yml +10 -0
  3. data/.gitignore +9 -0
  4. data/.rspec +2 -0
  5. data/Gemfile +4 -0
  6. data/LICENSE.txt +21 -0
  7. data/README.md +81 -0
  8. data/Rakefile +6 -0
  9. data/bin/console +6 -0
  10. data/bin/setup +8 -0
  11. data/circle.yml +3 -0
  12. data/lib/configuration.rb +11 -0
  13. data/lib/google/apis/vision_v1.rb +37 -0
  14. data/lib/google/apis/vision_v1/classes.rb +1259 -0
  15. data/lib/google/apis/vision_v1/representations.rb +370 -0
  16. data/lib/google/apis/vision_v1/service.rb +91 -0
  17. data/lib/guard_validator.rb +58 -0
  18. data/lib/picguard.rb +40 -0
  19. data/lib/picguard/version.rb +3 -0
  20. data/lib/services/analyzer.rb +40 -0
  21. data/lib/services/builders/annotate_image.rb +16 -0
  22. data/lib/services/builders/batch.rb +15 -0
  23. data/lib/services/builders/feature.rb +16 -0
  24. data/lib/services/builders/image.rb +15 -0
  25. data/lib/services/builders/request.rb +27 -0
  26. data/lib/services/builders/vision.rb +17 -0
  27. data/lib/services/image_preparator.rb +46 -0
  28. data/lib/services/validators/likelihood.rb +31 -0
  29. data/picguard.gemspec +30 -0
  30. data/spec/guard_validator_spec.rb +72 -0
  31. data/spec/picguard_spec.rb +22 -0
  32. data/spec/services/analyzer_spec.rb +33 -0
  33. data/spec/services/builders/annotate_image_spec.rb +15 -0
  34. data/spec/services/builders/batch_spec.rb +18 -0
  35. data/spec/services/builders/feature_spec.rb +26 -0
  36. data/spec/services/builders/image_spec.rb +12 -0
  37. data/spec/services/builders/vision_spec.rb +14 -0
  38. data/spec/services/image_preparator_spec.rb +36 -0
  39. data/spec/services/validators/likelihood_spec.rb +26 -0
  40. data/spec/spec_helper.rb +10 -0
  41. data/spec/support/img/cat.jpg +0 -0
  42. data/spec/support/img/face-example.jpg +0 -0
  43. data/spec/support/img/gun-violence.jpg +0 -0
  44. data/spec/support/result_hash_stub.rb +212 -0
  45. metadata +64 -4
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: f8365bb34a7f9f59a6e3efe0342926c3ba6e9484
4
- data.tar.gz: 8dda3c17e5db843c0a45204880d5b0f066688c96
3
+ metadata.gz: 97758b22222ef4f51b940030b23d6bdc5f434aac
4
+ data.tar.gz: 452acbd8bdc5bfbca225e79659eab662e1a9da48
5
5
  SHA512:
6
- metadata.gz: b8b73b2958af6041216d703526de3f496a8a201919fa653950c7109319e97fc693d439de41d13012e5af8b94986792ee10ef0552411277b3b33eb78f714c9bfe
7
- data.tar.gz: 2ab01a7ec53aea767615f1a1a84aa53e7002177efc346d54f1814c7dbfd887c0aa85c21aa937ca8fd5d7d82c30b9d41c8a9b023b66939e5ace0a09a272a917d8
6
+ metadata.gz: 6d9ffb3845ac4ae51f51bd688ca61387bde74a994d994cefcd9a521a5ca664fdbd1a79d881c87472775a041b72efec88a56532d725868dee0692bb7547ae473f
7
+ data.tar.gz: d398879a6b644e0f80279d668b8b244545ae1f2f0da201cfe5e05a50c4a533c73b887ca6728fd8592ba86ca6b3c7bb580d5af8e332ce89b3ec4b1da4031a9a6f
@@ -0,0 +1,10 @@
1
+ engines:
2
+ rubocop:
3
+ enabled: false
4
+ ratings:
5
+ paths:
6
+ - lib/**
7
+ - "**.rb"
8
+ exclude_paths:
9
+ - lib/google/apis/**/*
10
+ - spec/**/*
@@ -0,0 +1,9 @@
1
+ /.bundle/
2
+ /.yardoc
3
+ /Gemfile.lock
4
+ /_yardoc/
5
+ /coverage/
6
+ /doc/
7
+ /pkg/
8
+ /spec/reports/
9
+ /tmp/
data/.rspec ADDED
@@ -0,0 +1,2 @@
1
+ --format documentation
2
+ --color
data/Gemfile ADDED
@@ -0,0 +1,4 @@
1
+ source 'https://rubygems.org'
2
+
3
+ # Specify your gem's dependencies in picguard.gemspec
4
+ gemspec
@@ -0,0 +1,21 @@
1
+ The MIT License (MIT)
2
+
3
+ Copyright (c) 2016 Szymon Baranowski
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in
13
+ all copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
21
+ THE SOFTWARE.
@@ -0,0 +1,81 @@
1
+ [![Code Climate](https://codeclimate.com/repos/56cdc29e7220a54948003189/badges/6455466a41f102f5f517/gpa.svg)](https://codeclimate.com/repos/56cdc29e7220a54948003189/feed) [![Test Coverage](https://codeclimate.com/repos/56cdc29e7220a54948003189/badges/6455466a41f102f5f517/coverage.svg)](https://codeclimate.com/repos/56cdc29e7220a54948003189/coverage)
2
+ [![Circle CI](https://circleci.com/gh/netguru/picguard.svg?style=svg)](https://circleci.com/gh/netguru/picguard)
3
+
4
+ # Picguard
5
+ Picguard guards your application by filtering out the pictures showing inappropriate content.
6
+ It uses Google Vision API to process the pictures that are being uploaded via your application.
7
+
8
+ # Why use Picguard?
9
+ Imagine a business application that allows user to upload a photo when creating his profile. The user is free to upload any kind of picture (including pictures showing violent scenes or adult content). The most popular solution for that is implementing a feature that allows other users to report the inappropriate content - which means you rely on your users when it comes to the safety of your application - not so great. Another scenario would be: what if for a profile picture an application should only allow the picture showing a human face? The soultion would be often the same as in the first example.
10
+ Picguard lets you configure your preferences (globally or separately for each model) for image filtering and gives you a clean solution to validate the picture before it's saved.
11
+
12
+ ## Installation
13
+
14
+ Add Picguard to your Gemfile:
15
+
16
+ ```ruby
17
+ gem 'picguard'
18
+ ```
19
+
20
+ And run `bundle install` within your app's directory.
21
+
22
+ ## Configuration
23
+ In your Rails app create a file such as `config/initializers/picguard.rb` and fill it up with your default configuration.
24
+ Example:
25
+
26
+ ```ruby
27
+ Picguard.configure do |config|
28
+ config.google_api_key = #{YOUR_GOOGLE_API_KEY}
29
+ config.threshold_adult = "POSSIBLE"
30
+ config.threshold_violence = "LIKELY"
31
+ config.threshold_face = 0.8
32
+ end
33
+ ```
34
+
35
+ ##### Let's go through all of the attributes you need to set up in the config:
36
+
37
+ `google_api_key` is the secret key that you use to authenticate to the Google Vision API, you can generate one that is connected to your Google Project. More about generating the key can be found [here](https://cloud.google.com/vision/docs/getting-started#setting_up_an_api_key). If you are completely new to the Google Cloud Platform you should probably start [here](https://cloud.google.com/vision/docs/getting-started).
38
+ `threshold_adult` and `threshold_violence` are the thresholds for the adult and violent content. This is the highest value that you consider acceptable, everything above this level will be categorised as unsafe. For all of the likelihood levels please check [this piece of documentation](https://cloud.google.com/vision/reference/rest/v1/images/annotate#Likelihood).
39
+ `threshold_face` is the threshold for face recognition. Google responds with a float value from 0 to 1 that reflects how sure the Google API is when it comes to face recognition. Only the picture with values above your threshold will be categorised as the ones containing human face.
40
+
41
+ ## Validations
42
+ To validate the content of the picture simply add the following validation to your model:
43
+
44
+ ```ruby
45
+ validates :image, guard: {
46
+ safe_search: true,
47
+ face_detection: true,
48
+ method_name: :img_path
49
+ }
50
+ ```
51
+ ###### where
52
+
53
+ `image` is the name of the model's attribute that should be validated
54
+ `guard` is the name of the picguard validator
55
+ `safe_search` and `face_detection` are the flags reflecting what should be validated for given model
56
+ `method_name` is the name of the `image`'s attribute method that returns image file path
57
+
58
+ ## Sample validations for popular file-uploading gems
59
+
60
+ ### CarrierWave
61
+
62
+ ```ruby
63
+ class User < ActiveRecord::Base
64
+ mount_uploader :avatar, AvatarUploader
65
+
66
+ validates :avatar, guard: {
67
+ safe_search: true,
68
+ face_detection: true,
69
+ method_name: :path
70
+ }
71
+ end
72
+ ```
73
+
74
+ ## License
75
+
76
+ The gem is available as open source under the terms of the [MIT License](http://opensource.org/licenses/MIT).
77
+
78
+ ### Core Team
79
+
80
+ * Szymon Baranowski (szymon.baranowski@netguru.co)
81
+ * Tomasz Jaśkiewicz (tomasz.jaskiewicz@netguru.co)
@@ -0,0 +1,6 @@
1
+ require "bundler/gem_tasks"
2
+ require "rspec/core/rake_task"
3
+
4
+ RSpec::Core::RakeTask.new(:spec)
5
+
6
+ task :default => :spec
@@ -0,0 +1,6 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require "bundler/setup"
4
+ require "picguard"
5
+ require "pry"
6
+ Pry.start
@@ -0,0 +1,8 @@
1
+ #!/usr/bin/env bash
2
+ set -euo pipefail
3
+ IFS=$'\n\t'
4
+ set -vx
5
+
6
+ bundle install
7
+
8
+ # Do any other automated setup that you need to do here
@@ -0,0 +1,3 @@
1
+ machine:
2
+ ruby:
3
+ version: 2.3.0
@@ -0,0 +1,11 @@
1
+ module Picguard
2
+ class Configuration
3
+ attr_accessor :google_api_key, :threshold_adult, :threshold_violence, :threshold_face
4
+
5
+ def initialize
6
+ @threshold_adult = "POSSIBLE"
7
+ @threshold_violence = "POSSIBLE"
8
+ @threshold_face = 0.7
9
+ end
10
+ end
11
+ end
@@ -0,0 +1,37 @@
1
+ # Copyright 2015 Google Inc.
2
+ #
3
+ # Licensed under the Apache License, Version 2.0 (the "License");
4
+ # you may not use this file except in compliance with the License.
5
+ # You may obtain a copy of the License at
6
+ #
7
+ # http://www.apache.org/licenses/LICENSE-2.0
8
+ #
9
+ # Unless required by applicable law or agreed to in writing, software
10
+ # distributed under the License is distributed on an "AS IS" BASIS,
11
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12
+ # See the License for the specific language governing permissions and
13
+ # limitations under the License.
14
+
15
+ require 'google/apis/vision_v1/service.rb'
16
+ require 'google/apis/vision_v1/classes.rb'
17
+ require 'google/apis/vision_v1/representations.rb'
18
+
19
+ module Google
20
+ module Apis
21
+ # Cloud Vision API
22
+ #
23
+ # The Google Cloud Vision API allows developers to easily integrate Google
24
+ # vision features, including image labeling, face, logo, and landmark detection,
25
+ # optical character recognition (OCR), and detection of explicit content, into
26
+ # applications.
27
+ #
28
+ # @see https://cloud.google.com/vision/
29
+ module VisionV1
30
+ VERSION = 'V1'
31
+ REVISION = '20160217'
32
+
33
+ # View and manage your data across Google Cloud Platform services
34
+ AUTH_CLOUD_PLATFORM = 'https://www.googleapis.com/auth/cloud-platform'
35
+ end
36
+ end
37
+ end
@@ -0,0 +1,1259 @@
1
+ # Copyright 2015 Google Inc.
2
+ #
3
+ # Licensed under the Apache License, Version 2.0 (the "License");
4
+ # you may not use this file except in compliance with the License.
5
+ # You may obtain a copy of the License at
6
+ #
7
+ # http://www.apache.org/licenses/LICENSE-2.0
8
+ #
9
+ # Unless required by applicable law or agreed to in writing, software
10
+ # distributed under the License is distributed on an "AS IS" BASIS,
11
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12
+ # See the License for the specific language governing permissions and
13
+ # limitations under the License.
14
+
15
+ require 'date'
16
+ require 'google/apis/core/base_service'
17
+ require 'google/apis/core/json_representation'
18
+ require 'google/apis/core/hashable'
19
+ require 'google/apis/errors'
20
+
21
+ module Google
22
+ module Apis
23
+ module VisionV1
24
+
25
+ # External image source (i.e. Google Cloud Storage image location).
26
+ class ImageSource
27
+ include Google::Apis::Core::Hashable
28
+
29
+ # Google Cloud Storage image URI. It must be in the following form:
30
+ # "gs://bucket_name/object_name". For more
31
+ # details, please see: https://cloud.google.com/storage/docs/reference-uris.
32
+ # NOTE: Cloud Storage object versioning is not supported!
33
+ # Corresponds to the JSON property `gcsImageUri`
34
+ # @return [String]
35
+ attr_accessor :gcs_image_uri
36
+
37
+ def initialize(**args)
38
+ update!(**args)
39
+ end
40
+
41
+ # Update properties of this object
42
+ def update!(**args)
43
+ @gcs_image_uri = args[:gcs_image_uri] if args.key?(:gcs_image_uri)
44
+ end
45
+ end
46
+
47
+ # Request for performing Vision tasks over a user-provided image, with
48
+ # user-requested features.
49
+ class AnnotateImageRequest
50
+ include Google::Apis::Core::Hashable
51
+
52
+ # Client image to perform Vision tasks over.
53
+ # Corresponds to the JSON property `image`
54
+ # @return [Google::Apis::VisionV1::Image]
55
+ attr_accessor :image
56
+
57
+ # Image context.
58
+ # Corresponds to the JSON property `imageContext`
59
+ # @return [Google::Apis::VisionV1::ImageContext]
60
+ attr_accessor :image_context
61
+
62
+ # Requested features.
63
+ # Corresponds to the JSON property `features`
64
+ # @return [Array<Google::Apis::VisionV1::Feature>]
65
+ attr_accessor :features
66
+
67
+ def initialize(**args)
68
+ update!(**args)
69
+ end
70
+
71
+ # Update properties of this object
72
+ def update!(**args)
73
+ @image = args[:image] if args.key?(:image)
74
+ @image_context = args[:image_context] if args.key?(:image_context)
75
+ @features = args[:features] if args.key?(:features)
76
+ end
77
+ end
78
+
79
+ # Response to an image annotation request.
80
+ class AnnotateImageResponse
81
+ include Google::Apis::Core::Hashable
82
+
83
+ # If present, label detection completed successfully.
84
+ # Corresponds to the JSON property `labelAnnotations`
85
+ # @return [Array<Google::Apis::VisionV1::EntityAnnotation>]
86
+ attr_accessor :label_annotations
87
+
88
+ # If present, landmark detection completed successfully.
89
+ # Corresponds to the JSON property `landmarkAnnotations`
90
+ # @return [Array<Google::Apis::VisionV1::EntityAnnotation>]
91
+ attr_accessor :landmark_annotations
92
+
93
+ # Set of features pertaining to the image, computed by various computer vision
94
+ # methods over safe-search verticals (for example, adult, spoof, medical,
95
+ # violence).
96
+ # Corresponds to the JSON property `safeSearchAnnotation`
97
+ # @return [Google::Apis::VisionV1::SafeSearchAnnotation]
98
+ attr_accessor :safe_search_annotation
99
+
100
+ # Stores image properties (e.g. dominant colors).
101
+ # Corresponds to the JSON property `imagePropertiesAnnotation`
102
+ # @return [Google::Apis::VisionV1::ImageProperties]
103
+ attr_accessor :image_properties_annotation
104
+
105
+ # If present, text (OCR) detection completed successfully.
106
+ # Corresponds to the JSON property `textAnnotations`
107
+ # @return [Array<Google::Apis::VisionV1::EntityAnnotation>]
108
+ attr_accessor :text_annotations
109
+
110
+ # If present, logo detection completed successfully.
111
+ # Corresponds to the JSON property `logoAnnotations`
112
+ # @return [Array<Google::Apis::VisionV1::EntityAnnotation>]
113
+ attr_accessor :logo_annotations
114
+
115
+ # If present, face detection completed successfully.
116
+ # Corresponds to the JSON property `faceAnnotations`
117
+ # @return [Array<Google::Apis::VisionV1::FaceAnnotation>]
118
+ attr_accessor :face_annotations
119
+
120
+ # The `Status` type defines a logical error model that is suitable for different
121
+ # programming environments, including REST APIs and RPC APIs. It is used by
122
+ # [gRPC](https://github.com/grpc). The error model is designed to be:
123
+ # - Simple to use and understand for most users
124
+ # - Flexible enough to meet unexpected needs
125
+ # # Overview
126
+ # The `Status` message contains three pieces of data: error code, error message,
127
+ # and error details. The error code should be an enum value of
128
+ # google.rpc.Code, but it may accept additional error codes if needed. The
129
+ # error message should be a developer-facing English message that helps
130
+ # developers *understand* and *resolve* the error. If a localized user-facing
131
+ # error message is needed, put the localized message in the error details or
132
+ # localize it in the client. The optional error details may contain arbitrary
133
+ # information about the error. There is a predefined set of error detail types
134
+ # in the package `google.rpc` which can be used for common error conditions.
135
+ # # Language mapping
136
+ # The `Status` message is the logical representation of the error model, but it
137
+ # is not necessarily the actual wire format. When the `Status` message is
138
+ # exposed in different client libraries and different wire protocols, it can be
139
+ # mapped differently. For example, it will likely be mapped to some exceptions
140
+ # in Java, but more likely mapped to some error codes in C.
141
+ # # Other uses
142
+ # The error model and the `Status` message can be used in a variety of
143
+ # environments, either with or without APIs, to provide a
144
+ # consistent developer experience across different environments.
145
+ # Example uses of this error model include:
146
+ # - Partial errors. If a service needs to return partial errors to the client,
147
+ # it may embed the `Status` in the normal response to indicate the partial
148
+ # errors.
149
+ # - Workflow errors. A typical workflow has multiple steps. Each step may
150
+ # have a `Status` message for error reporting purpose.
151
+ # - Batch operations. If a client uses batch request and batch response, the
152
+ # `Status` message should be used directly inside batch response, one for
153
+ # each error sub-response.
154
+ # - Asynchronous operations. If an API call embeds asynchronous operation
155
+ # results in its response, the status of those operations should be
156
+ # represented directly using the `Status` message.
157
+ # - Logging. If some API errors are stored in logs, the message `Status` could
158
+ # be used directly after any stripping needed for security/privacy reasons.
159
+ # Corresponds to the JSON property `error`
160
+ # @return [Google::Apis::VisionV1::Status]
161
+ attr_accessor :error
162
+
163
+ def initialize(**args)
164
+ update!(**args)
165
+ end
166
+
167
+ # Update properties of this object
168
+ def update!(**args)
169
+ @label_annotations = args[:label_annotations] if args.key?(:label_annotations)
170
+ @landmark_annotations = args[:landmark_annotations] if args.key?(:landmark_annotations)
171
+ @safe_search_annotation = args[:safe_search_annotation] if args.key?(:safe_search_annotation)
172
+ @image_properties_annotation = args[:image_properties_annotation] if args.key?(:image_properties_annotation)
173
+ @text_annotations = args[:text_annotations] if args.key?(:text_annotations)
174
+ @logo_annotations = args[:logo_annotations] if args.key?(:logo_annotations)
175
+ @face_annotations = args[:face_annotations] if args.key?(:face_annotations)
176
+ @error = args[:error] if args.key?(:error)
177
+ end
178
+ end
179
+
180
+ # Rectangle determined by min and max LatLng pairs.
181
+ class LatLongRect
182
+ include Google::Apis::Core::Hashable
183
+
184
+ # An object representing a latitude/longitude pair. This is expressed as a pair
185
+ # of doubles representing degrees latitude and degrees longitude. Unless
186
+ # specified otherwise, this must conform to the
187
+ # <a href="http://www.unoosa.org/pdf/icg/2012/template/WGS_84.pdf">WGS84
188
+ # standard</a>. Values must be within normalized ranges.
189
+ # Example of normalization code in Python:
190
+ # def NormalizeLongitude(longitude):
191
+ # """Wraps decimal degrees longitude to [-180.0, 180.0]."""
192
+ # q, r = divmod(longitude, 360.0)
193
+ # if r > 180.0 or (r == 180.0 and q <= -1.0):
194
+ # return r - 360.0
195
+ # return r
196
+ # def NormalizeLatLng(latitude, longitude):
197
+ # """Wraps decimal degrees latitude and longitude to
198
+ # [-180.0, 180.0] and [-90.0, 90.0], respectively."""
199
+ # r = latitude % 360.0
200
+ # if r <= 90.0:
201
+ # return r, NormalizeLongitude(longitude)
202
+ # elif r >= 270.0:
203
+ # return r - 360, NormalizeLongitude(longitude)
204
+ # else:
205
+ # return 180 - r, NormalizeLongitude(longitude + 180.0)
206
+ # assert 180.0 == NormalizeLongitude(180.0)
207
+ # assert -180.0 == NormalizeLongitude(-180.0)
208
+ # assert -179.0 == NormalizeLongitude(181.0)
209
+ # assert (0.0, 0.0) == NormalizeLatLng(360.0, 0.0)
210
+ # assert (0.0, 0.0) == NormalizeLatLng(-360.0, 0.0)
211
+ # assert (85.0, 180.0) == NormalizeLatLng(95.0, 0.0)
212
+ # assert (-85.0, -170.0) == NormalizeLatLng(-95.0, 10.0)
213
+ # assert (90.0, 10.0) == NormalizeLatLng(90.0, 10.0)
214
+ # assert (-90.0, -10.0) == NormalizeLatLng(-90.0, -10.0)
215
+ # assert (0.0, -170.0) == NormalizeLatLng(-180.0, 10.0)
216
+ # assert (0.0, -170.0) == NormalizeLatLng(180.0, 10.0)
217
+ # assert (-90.0, 10.0) == NormalizeLatLng(270.0, 10.0)
218
+ # assert (90.0, 10.0) == NormalizeLatLng(-270.0, 10.0)
219
+ # Corresponds to the JSON property `maxLatLng`
220
+ # @return [Google::Apis::VisionV1::LatLng]
221
+ attr_accessor :max_lat_lng
222
+
223
+ # An object representing a latitude/longitude pair. This is expressed as a pair
224
+ # of doubles representing degrees latitude and degrees longitude. Unless
225
+ # specified otherwise, this must conform to the
226
+ # <a href="http://www.unoosa.org/pdf/icg/2012/template/WGS_84.pdf">WGS84
227
+ # standard</a>. Values must be within normalized ranges.
228
+ # Example of normalization code in Python:
229
+ # def NormalizeLongitude(longitude):
230
+ # """Wraps decimal degrees longitude to [-180.0, 180.0]."""
231
+ # q, r = divmod(longitude, 360.0)
232
+ # if r > 180.0 or (r == 180.0 and q <= -1.0):
233
+ # return r - 360.0
234
+ # return r
235
+ # def NormalizeLatLng(latitude, longitude):
236
+ # """Wraps decimal degrees latitude and longitude to
237
+ # [-180.0, 180.0] and [-90.0, 90.0], respectively."""
238
+ # r = latitude % 360.0
239
+ # if r <= 90.0:
240
+ # return r, NormalizeLongitude(longitude)
241
+ # elif r >= 270.0:
242
+ # return r - 360, NormalizeLongitude(longitude)
243
+ # else:
244
+ # return 180 - r, NormalizeLongitude(longitude + 180.0)
245
+ # assert 180.0 == NormalizeLongitude(180.0)
246
+ # assert -180.0 == NormalizeLongitude(-180.0)
247
+ # assert -179.0 == NormalizeLongitude(181.0)
248
+ # assert (0.0, 0.0) == NormalizeLatLng(360.0, 0.0)
249
+ # assert (0.0, 0.0) == NormalizeLatLng(-360.0, 0.0)
250
+ # assert (85.0, 180.0) == NormalizeLatLng(95.0, 0.0)
251
+ # assert (-85.0, -170.0) == NormalizeLatLng(-95.0, 10.0)
252
+ # assert (90.0, 10.0) == NormalizeLatLng(90.0, 10.0)
253
+ # assert (-90.0, -10.0) == NormalizeLatLng(-90.0, -10.0)
254
+ # assert (0.0, -170.0) == NormalizeLatLng(-180.0, 10.0)
255
+ # assert (0.0, -170.0) == NormalizeLatLng(180.0, 10.0)
256
+ # assert (-90.0, 10.0) == NormalizeLatLng(270.0, 10.0)
257
+ # assert (90.0, 10.0) == NormalizeLatLng(-270.0, 10.0)
258
+ # Corresponds to the JSON property `minLatLng`
259
+ # @return [Google::Apis::VisionV1::LatLng]
260
+ attr_accessor :min_lat_lng
261
+
262
+ def initialize(**args)
263
+ update!(**args)
264
+ end
265
+
266
+ # Update properties of this object
267
+ def update!(**args)
268
+ @max_lat_lng = args[:max_lat_lng] if args.key?(:max_lat_lng)
269
+ @min_lat_lng = args[:min_lat_lng] if args.key?(:min_lat_lng)
270
+ end
271
+ end
272
+
273
+ # The `Status` type defines a logical error model that is suitable for different
274
+ # programming environments, including REST APIs and RPC APIs. It is used by
275
+ # [gRPC](https://github.com/grpc). The error model is designed to be:
276
+ # - Simple to use and understand for most users
277
+ # - Flexible enough to meet unexpected needs
278
+ # # Overview
279
+ # The `Status` message contains three pieces of data: error code, error message,
280
+ # and error details. The error code should be an enum value of
281
+ # google.rpc.Code, but it may accept additional error codes if needed. The
282
+ # error message should be a developer-facing English message that helps
283
+ # developers *understand* and *resolve* the error. If a localized user-facing
284
+ # error message is needed, put the localized message in the error details or
285
+ # localize it in the client. The optional error details may contain arbitrary
286
+ # information about the error. There is a predefined set of error detail types
287
+ # in the package `google.rpc` which can be used for common error conditions.
288
+ # # Language mapping
289
+ # The `Status` message is the logical representation of the error model, but it
290
+ # is not necessarily the actual wire format. When the `Status` message is
291
+ # exposed in different client libraries and different wire protocols, it can be
292
+ # mapped differently. For example, it will likely be mapped to some exceptions
293
+ # in Java, but more likely mapped to some error codes in C.
294
+ # # Other uses
295
+ # The error model and the `Status` message can be used in a variety of
296
+ # environments, either with or without APIs, to provide a
297
+ # consistent developer experience across different environments.
298
+ # Example uses of this error model include:
299
+ # - Partial errors. If a service needs to return partial errors to the client,
300
+ # it may embed the `Status` in the normal response to indicate the partial
301
+ # errors.
302
+ # - Workflow errors. A typical workflow has multiple steps. Each step may
303
+ # have a `Status` message for error reporting purpose.
304
+ # - Batch operations. If a client uses batch request and batch response, the
305
+ # `Status` message should be used directly inside batch response, one for
306
+ # each error sub-response.
307
+ # - Asynchronous operations. If an API call embeds asynchronous operation
308
+ # results in its response, the status of those operations should be
309
+ # represented directly using the `Status` message.
310
+ # - Logging. If some API errors are stored in logs, the message `Status` could
311
+ # be used directly after any stripping needed for security/privacy reasons.
312
+ class Status
313
+ include Google::Apis::Core::Hashable
314
+
315
+ # The status code, which should be an enum value of google.rpc.Code.
316
+ # Corresponds to the JSON property `code`
317
+ # @return [Fixnum]
318
+ attr_accessor :code
319
+
320
+ # A list of messages that carry the error details. There will be a
321
+ # common set of message types for APIs to use.
322
+ # Corresponds to the JSON property `details`
323
+ # @return [Array<Hash<String,Object>>]
324
+ attr_accessor :details
325
+
326
+ # A developer-facing error message, which should be in English. Any
327
+ # user-facing error message should be localized and sent in the
328
+ # google.rpc.Status.details field, or localized by the client.
329
+ # Corresponds to the JSON property `message`
330
+ # @return [String]
331
+ attr_accessor :message
332
+
333
+ def initialize(**args)
334
+ update!(**args)
335
+ end
336
+
337
+ # Update properties of this object
338
+ def update!(**args)
339
+ @code = args[:code] if args.key?(:code)
340
+ @details = args[:details] if args.key?(:details)
341
+ @message = args[:message] if args.key?(:message)
342
+ end
343
+ end
344
+
345
+ # A face annotation contains the results of face detection.
346
+ class FaceAnnotation
347
+ include Google::Apis::Core::Hashable
348
+
349
+ # Pitch angle. Indicates the upwards/downwards angle that the face is
350
+ # pointing
351
+ # relative to the image's horizontal plane. Range [-180,180].
352
+ # Corresponds to the JSON property `tiltAngle`
353
+ # @return [Float]
354
+ attr_accessor :tilt_angle
355
+
356
+ # Under-exposed likelihood.
357
+ # Corresponds to the JSON property `underExposedLikelihood`
358
+ # @return [String]
359
+ attr_accessor :under_exposed_likelihood
360
+
361
+ # A bounding polygon for the detected image annotation.
362
+ # Corresponds to the JSON property `fdBoundingPoly`
363
+ # @return [Google::Apis::VisionV1::BoundingPoly]
364
+ attr_accessor :fd_bounding_poly
365
+
366
+ # Face landmarking confidence. Range [0, 1].
367
+ # Corresponds to the JSON property `landmarkingConfidence`
368
+ # @return [Float]
369
+ attr_accessor :landmarking_confidence
370
+
371
+ # Joy likelihood.
372
+ # Corresponds to the JSON property `joyLikelihood`
373
+ # @return [String]
374
+ attr_accessor :joy_likelihood
375
+
376
+ # Detection confidence. Range [0, 1].
377
+ # Corresponds to the JSON property `detectionConfidence`
378
+ # @return [Float]
379
+ attr_accessor :detection_confidence
380
+
381
+ # Surprise likelihood.
382
+ # Corresponds to the JSON property `surpriseLikelihood`
383
+ # @return [String]
384
+ attr_accessor :surprise_likelihood
385
+
386
+ # Anger likelihood.
387
+ # Corresponds to the JSON property `angerLikelihood`
388
+ # @return [String]
389
+ attr_accessor :anger_likelihood
390
+
391
+ # Headwear likelihood.
392
+ # Corresponds to the JSON property `headwearLikelihood`
393
+ # @return [String]
394
+ attr_accessor :headwear_likelihood
395
+
396
+ # A bounding polygon for the detected image annotation.
397
+ # Corresponds to the JSON property `boundingPoly`
398
+ # @return [Google::Apis::VisionV1::BoundingPoly]
399
+ attr_accessor :bounding_poly
400
+
401
+ # Yaw angle. Indicates the leftward/rightward angle that the face is
402
+ # pointing, relative to the vertical plane perpendicular to the image. Range
403
+ # [-180,180].
404
+ # Corresponds to the JSON property `panAngle`
405
+ # @return [Float]
406
+ attr_accessor :pan_angle
407
+
408
+ # Detected face landmarks.
409
+ # Corresponds to the JSON property `landmarks`
410
+ # @return [Array<Google::Apis::VisionV1::Landmark>]
411
+ attr_accessor :landmarks
412
+
413
+ # Blurred likelihood.
414
+ # Corresponds to the JSON property `blurredLikelihood`
415
+ # @return [String]
416
+ attr_accessor :blurred_likelihood
417
+
418
+ # Roll angle. Indicates the amount of clockwise/anti-clockwise rotation of
419
+ # the
420
+ # face relative to the image vertical, about the axis perpendicular to the
421
+ # face. Range [-180,180].
422
+ # Corresponds to the JSON property `rollAngle`
423
+ # @return [Float]
424
+ attr_accessor :roll_angle
425
+
426
+ # Sorrow likelihood.
427
+ # Corresponds to the JSON property `sorrowLikelihood`
428
+ # @return [String]
429
+ attr_accessor :sorrow_likelihood
430
+
431
+ def initialize(**args)
432
+ update!(**args)
433
+ end
434
+
435
+ # Update properties of this object
436
+ def update!(**args)
437
+ @tilt_angle = args[:tilt_angle] if args.key?(:tilt_angle)
438
+ @under_exposed_likelihood = args[:under_exposed_likelihood] if args.key?(:under_exposed_likelihood)
439
+ @fd_bounding_poly = args[:fd_bounding_poly] if args.key?(:fd_bounding_poly)
440
+ @landmarking_confidence = args[:landmarking_confidence] if args.key?(:landmarking_confidence)
441
+ @joy_likelihood = args[:joy_likelihood] if args.key?(:joy_likelihood)
442
+ @detection_confidence = args[:detection_confidence] if args.key?(:detection_confidence)
443
+ @surprise_likelihood = args[:surprise_likelihood] if args.key?(:surprise_likelihood)
444
+ @anger_likelihood = args[:anger_likelihood] if args.key?(:anger_likelihood)
445
+ @headwear_likelihood = args[:headwear_likelihood] if args.key?(:headwear_likelihood)
446
+ @bounding_poly = args[:bounding_poly] if args.key?(:bounding_poly)
447
+ @pan_angle = args[:pan_angle] if args.key?(:pan_angle)
448
+ @landmarks = args[:landmarks] if args.key?(:landmarks)
449
+ @blurred_likelihood = args[:blurred_likelihood] if args.key?(:blurred_likelihood)
450
+ @roll_angle = args[:roll_angle] if args.key?(:roll_angle)
451
+ @sorrow_likelihood = args[:sorrow_likelihood] if args.key?(:sorrow_likelihood)
452
+ end
453
+ end
454
+
455
+ # A vertex represents a 2D point in the image.
456
+ # NOTE: the vertex coordinates are in the same scale as the original image.
457
+ class Vertex
458
+ include Google::Apis::Core::Hashable
459
+
460
+ # Y coordinate.
461
+ # Corresponds to the JSON property `y`
462
+ # @return [Fixnum]
463
+ attr_accessor :y
464
+
465
+ # X coordinate.
466
+ # Corresponds to the JSON property `x`
467
+ # @return [Fixnum]
468
+ attr_accessor :x
469
+
470
+ def initialize(**args)
471
+ update!(**args)
472
+ end
473
+
474
+ # Update properties of this object
475
+ def update!(**args)
476
+ @y = args[:y] if args.key?(:y)
477
+ @x = args[:x] if args.key?(:x)
478
+ end
479
+ end
480
+
481
+ # Color information consists of RGB channels, score and fraction of
482
+ # image the color occupies in the image.
483
+ class ColorInfo
484
+ include Google::Apis::Core::Hashable
485
+
486
+ # Stores the fraction of pixels the color occupies in the image.
487
+ # Value in range [0, 1].
488
+ # Corresponds to the JSON property `pixelFraction`
489
+ # @return [Float]
490
+ attr_accessor :pixel_fraction
491
+
492
+ # Represents a color in the RGBA color space. This representation is designed
493
+ # for simplicity of conversion to/from color representations in various
494
+ # languages over compactness; for example, the fields of this representation
495
+ # can be trivially provided to the constructor of "java.awt.Color" in Java; it
496
+ # can also be trivially provided to UIColor's "+colorWithRed:green:blue:alpha"
497
+ # method in iOS; and, with just a little work, it can be easily formatted into
498
+ # a CSS "rgba()" string in JavaScript, as well. Here are some examples:
499
+ # Example (Java):
500
+ # import com.google.type.Color;
501
+ # // ...
502
+ # public static java.awt.Color fromProto(Color protocolor) `
503
+ # float alpha = protocolor.hasAlpha()
504
+ # ? protocolor.getAlpha().getValue()
505
+ # : 1.0;
506
+ # return new java.awt.Color(
507
+ # protocolor.getRed(),
508
+ # protocolor.getGreen(),
509
+ # protocolor.getBlue(),
510
+ # alpha);
511
+ # `
512
+ # public static Color toProto(java.awt.Color color) `
513
+ # float red = (float) color.getRed();
514
+ # float green = (float) color.getGreen();
515
+ # float blue = (float) color.getBlue();
516
+ # float denominator = 255.0;
517
+ # Color.Builder resultBuilder =
518
+ # Color
519
+ # .newBuilder()
520
+ # .setRed(red / denominator)
521
+ # .setGreen(green / denominator)
522
+ # .setBlue(blue / denominator);
523
+ # int alpha = color.getAlpha();
524
+ # if (alpha != 255) `
525
+ # result.setAlpha(
526
+ # FloatValue
527
+ # .newBuilder()
528
+ # .setValue(((float) alpha) / denominator)
529
+ # .build());
530
+ # `
531
+ # return resultBuilder.build();
532
+ # `
533
+ # // ...
534
+ # Example (iOS / Obj-C):
535
+ # // ...
536
+ # static UIColor* fromProto(Color* protocolor) `
537
+ # float red = [protocolor red];
538
+ # float green = [protocolor green];
539
+ # float blue = [protocolor blue];
540
+ # FloatValue* alpha_wrapper = [protocolor alpha];
541
+ # float alpha = 1.0;
542
+ # if (alpha_wrapper != nil) `
543
+ # alpha = [alpha_wrapper value];
544
+ # `
545
+ # return [UIColor colorWithRed:red green:green blue:blue alpha:alpha];
546
+ # `
547
+ # static Color* toProto(UIColor* color) `
548
+ # CGFloat red, green, blue, alpha;
549
+ # if (![color getRed:&red green:&green blue:&blue alpha:&alpha]) `
550
+ # return nil;
551
+ # `
552
+ # Color* result = [Color alloc] init];
553
+ # [result setRed:red];
554
+ # [result setGreen:green];
555
+ # [result setBlue:blue];
556
+ # if (alpha <= 0.9999) `
557
+ # [result setAlpha:floatWrapperWithValue(alpha)];
558
+ # `
559
+ # [result autorelease];
560
+ # return result;
561
+ # `
562
+ # // ...
563
+ # Example (JavaScript):
564
+ # // ...
565
+ # var protoToCssColor = function(rgb_color) `
566
+ # var redFrac = rgb_color.red || 0.0;
567
+ # var greenFrac = rgb_color.green || 0.0;
568
+ # var blueFrac = rgb_color.blue || 0.0;
569
+ # var red = Math.floor(redFrac * 255);
570
+ # var green = Math.floor(greenFrac * 255);
571
+ # var blue = Math.floor(blueFrac * 255);
572
+ # if (!('alpha' in rgb_color)) `
573
+ # return rgbToCssColor_(red, green, blue);
574
+ # `
575
+ # var alphaFrac = rgb_color.alpha.value || 0.0;
576
+ # var rgbParams = [red, green, blue].join(',');
577
+ # return ['rgba(', rgbParams, ',', alphaFrac, ')'].join('');
578
+ # `;
579
+ # var rgbToCssColor_ = function(red, green, blue) `
580
+ # var rgbNumber = new Number((red << 16) | (green << 8) | blue);
581
+ # var hexString = rgbNumber.toString(16);
582
+ # var missingZeros = 6 - hexString.length;
583
+ # var resultBuilder = ['#'];
584
+ # for (var i = 0; i < missingZeros; i++) `
585
+ # resultBuilder.push('0');
586
+ # `
587
+ # resultBuilder.push(hexString);
588
+ # return resultBuilder.join('');
589
+ # `;
590
+ # // ...
591
+ # Corresponds to the JSON property `color`
592
+ # @return [Google::Apis::VisionV1::Color]
593
+ attr_accessor :color
594
+
595
+ # Image-specific score for this color. Value in range [0, 1].
596
+ # Corresponds to the JSON property `score`
597
+ # @return [Float]
598
+ attr_accessor :score
599
+
600
+ def initialize(**args)
601
+ update!(**args)
602
+ end
603
+
604
+ # Update properties of this object
605
+ def update!(**args)
606
+ @pixel_fraction = args[:pixel_fraction] if args.key?(:pixel_fraction)
607
+ @color = args[:color] if args.key?(:color)
608
+ @score = args[:score] if args.key?(:score)
609
+ end
610
+ end
611
+
612
+ # A bounding polygon for the detected image annotation.
613
+ class BoundingPoly
614
+ include Google::Apis::Core::Hashable
615
+
616
+ # The bounding polygon vertices.
617
+ # Corresponds to the JSON property `vertices`
618
+ # @return [Array<Google::Apis::VisionV1::Vertex>]
619
+ attr_accessor :vertices
620
+
621
+ def initialize(**args)
622
+ update!(**args)
623
+ end
624
+
625
+ # Update properties of this object
626
+ def update!(**args)
627
+ @vertices = args[:vertices] if args.key?(:vertices)
628
+ end
629
+ end
630
+
631
+ # A face-specific landmark (for example, a face feature).
632
+ # Landmark positions may fall outside the bounds of the image
633
+ # when the face is near one or more edges of the image.
634
+ # Therefore it is NOT guaranteed that 0 <= x < width or 0 <= y < height.
635
+ class Landmark
636
+ include Google::Apis::Core::Hashable
637
+
638
+ # A 3D position in the image, used primarily for Face detection landmarks.
639
+ # A valid Position must have both x and y coordinates.
640
+ # The position coordinates are in the same scale as the original image.
641
+ # Corresponds to the JSON property `position`
642
+ # @return [Google::Apis::VisionV1::Position]
643
+ attr_accessor :position
644
+
645
+ # Face landmark type.
646
+ # Corresponds to the JSON property `type`
647
+ # @return [String]
648
+ attr_accessor :type
649
+
650
+ def initialize(**args)
651
+ update!(**args)
652
+ end
653
+
654
+ # Update properties of this object
655
+ def update!(**args)
656
+ @position = args[:position] if args.key?(:position)
657
+ @type = args[:type] if args.key?(:type)
658
+ end
659
+ end
660
+
661
+ # Image context.
662
+ class ImageContext
663
+ include Google::Apis::Core::Hashable
664
+
665
+ # List of languages to use for TEXT_DETECTION. In most cases, an empty value
666
+ # will yield the best results as it will allow text detection to
667
+ # automatically detect the text language. For languages based on the latin
668
+ # alphabet a hint is not needed. In rare cases, when the language of
669
+ # the text in the image is known in advance, setting this hint will help get
670
+ # better results (although it will hurt a great deal if the hint is wrong).
671
+ # Text detection will return an error if one or more of the languages
672
+ # specified here are not supported. The exact list of supported languages are
673
+ # specified here:
674
+ # https://cloud.google.com/translate/v2/using_rest#language-params
675
+ # Corresponds to the JSON property `languageHints`
676
+ # @return [Array<String>]
677
+ attr_accessor :language_hints
678
+
679
+ # Rectangle determined by min and max LatLng pairs.
680
+ # Corresponds to the JSON property `latLongRect`
681
+ # @return [Google::Apis::VisionV1::LatLongRect]
682
+ attr_accessor :lat_long_rect
683
+
684
+ def initialize(**args)
685
+ update!(**args)
686
+ end
687
+
688
+ # Update properties of this object
689
+ def update!(**args)
690
+ @language_hints = args[:language_hints] if args.key?(:language_hints)
691
+ @lat_long_rect = args[:lat_long_rect] if args.key?(:lat_long_rect)
692
+ end
693
+ end
694
+
695
+ # Multiple image annotation requests are batched into a single service call.
696
+ class BatchAnnotateImagesRequest
697
+ include Google::Apis::Core::Hashable
698
+
699
+ # Individual image annotation requests for this batch.
700
+ # Corresponds to the JSON property `requests`
701
+ # @return [Array<Google::Apis::VisionV1::AnnotateImageRequest>]
702
+ attr_accessor :requests
703
+
704
+ def initialize(**args)
705
+ update!(**args)
706
+ end
707
+
708
+ # Update properties of this object
709
+ def update!(**args)
710
+ @requests = args[:requests] if args.key?(:requests)
711
+ end
712
+ end
713
+
714
+ # Set of detected entity features.
715
+ class EntityAnnotation
716
+ include Google::Apis::Core::Hashable
717
+
718
+ # Knowledge Graph entity ID. Maps to a freebase entity ID.
719
+ # (for example, "Google" maps to: mid /m/045c7b).
720
+ # Corresponds to the JSON property `mid`
721
+ # @return [String]
722
+ attr_accessor :mid
723
+
724
+ # Entity textual description, expressed in its <code>locale</code> language.
725
+ # Corresponds to the JSON property `description`
726
+ # @return [String]
727
+ attr_accessor :description
728
+
729
+ # The relevancy of the ICA (Image Content Annotation) label to the
730
+ # image. For example, the relevancy of 'tower' to an image containing
731
+ # 'Eiffel Tower' is likely higher than an image containing a distant towering
732
+ # building, though the confidence that there is a tower may be the same.
733
+ # Range [0, 1].
734
+ # Corresponds to the JSON property `topicality`
735
+ # @return [Float]
736
+ attr_accessor :topicality
737
+
738
+ # The language code for the locale in which the entity textual
739
+ # <code>description</code> (next field) is expressed.
740
+ # Corresponds to the JSON property `locale`
741
+ # @return [String]
742
+ attr_accessor :locale
743
+
744
+ # Some entities can have additional optional <code>Property</code> fields.
745
+ # For example a different kind of score or string that qualifies the entity.
746
+ # Corresponds to the JSON property `properties`
747
+ # @return [Array<Google::Apis::VisionV1::Property>]
748
+ attr_accessor :properties
749
+
750
+ # Overall score of the result. Range [0, 1].
751
+ # Corresponds to the JSON property `score`
752
+ # @return [Float]
753
+ attr_accessor :score
754
+
755
+ # A bounding polygon for the detected image annotation.
756
+ # Corresponds to the JSON property `boundingPoly`
757
+ # @return [Google::Apis::VisionV1::BoundingPoly]
758
+ attr_accessor :bounding_poly
759
+
760
+ # The location information for the recognized entity. Multiple
761
+ # <code>LocationInfo</code> elements can be present since one location may
762
+ # indicate the location of the scene in the query image, and another the
763
+ # location of the place where the query image was taken. Location information
764
+ # is usually present for landmarks.
765
+ # Corresponds to the JSON property `locations`
766
+ # @return [Array<Google::Apis::VisionV1::LocationInfo>]
767
+ attr_accessor :locations
768
+
769
+ # The accuracy of the entity recognition in an image.
770
+ # For example, for an image containing 'Eiffel Tower,' this field represents
771
+ # the confidence that there is a tower in the query image. Range [0, 1].
772
+ # Corresponds to the JSON property `confidence`
773
+ # @return [Float]
774
+ attr_accessor :confidence
775
+
776
+ def initialize(**args)
777
+ update!(**args)
778
+ end
779
+
780
+ # Update properties of this object
781
+ def update!(**args)
782
+ @mid = args[:mid] if args.key?(:mid)
783
+ @description = args[:description] if args.key?(:description)
784
+ @topicality = args[:topicality] if args.key?(:topicality)
785
+ @locale = args[:locale] if args.key?(:locale)
786
+ @properties = args[:properties] if args.key?(:properties)
787
+ @score = args[:score] if args.key?(:score)
788
+ @bounding_poly = args[:bounding_poly] if args.key?(:bounding_poly)
789
+ @locations = args[:locations] if args.key?(:locations)
790
+ @confidence = args[:confidence] if args.key?(:confidence)
791
+ end
792
+ end
793
+
794
+ # Arbitrary name/value pair.
795
+ class Property
796
+ include Google::Apis::Core::Hashable
797
+
798
+ # Value of the property.
799
+ # Corresponds to the JSON property `value`
800
+ # @return [String]
801
+ attr_accessor :value
802
+
803
+ # Name of the property.
804
+ # Corresponds to the JSON property `name`
805
+ # @return [String]
806
+ attr_accessor :name
807
+
808
+ def initialize(**args)
809
+ update!(**args)
810
+ end
811
+
812
+ # Update properties of this object
813
+ def update!(**args)
814
+ @value = args[:value] if args.key?(:value)
815
+ @name = args[:name] if args.key?(:name)
816
+ end
817
+ end
818
+
819
+ # Represents a color in the RGBA color space. This representation is designed
820
+ # for simplicity of conversion to/from color representations in various
821
+ # languages over compactness; for example, the fields of this representation
822
+ # can be trivially provided to the constructor of "java.awt.Color" in Java; it
823
+ # can also be trivially provided to UIColor's "+colorWithRed:green:blue:alpha"
824
+ # method in iOS; and, with just a little work, it can be easily formatted into
825
+ # a CSS "rgba()" string in JavaScript, as well. Here are some examples:
826
+ # Example (Java):
827
+ # import com.google.type.Color;
828
+ # // ...
829
+ # public static java.awt.Color fromProto(Color protocolor) `
830
+ # float alpha = protocolor.hasAlpha()
831
+ # ? protocolor.getAlpha().getValue()
832
+ # : 1.0;
833
+ # return new java.awt.Color(
834
+ # protocolor.getRed(),
835
+ # protocolor.getGreen(),
836
+ # protocolor.getBlue(),
837
+ # alpha);
838
+ # `
839
+ # public static Color toProto(java.awt.Color color) `
840
+ # float red = (float) color.getRed();
841
+ # float green = (float) color.getGreen();
842
+ # float blue = (float) color.getBlue();
843
+ # float denominator = 255.0;
844
+ # Color.Builder resultBuilder =
845
+ # Color
846
+ # .newBuilder()
847
+ # .setRed(red / denominator)
848
+ # .setGreen(green / denominator)
849
+ # .setBlue(blue / denominator);
850
+ # int alpha = color.getAlpha();
851
+ # if (alpha != 255) `
852
+ # result.setAlpha(
853
+ # FloatValue
854
+ # .newBuilder()
855
+ # .setValue(((float) alpha) / denominator)
856
+ # .build());
857
+ # `
858
+ # return resultBuilder.build();
859
+ # `
860
+ # // ...
861
+ # Example (iOS / Obj-C):
862
+ # // ...
863
+ # static UIColor* fromProto(Color* protocolor) `
864
+ # float red = [protocolor red];
865
+ # float green = [protocolor green];
866
+ # float blue = [protocolor blue];
867
+ # FloatValue* alpha_wrapper = [protocolor alpha];
868
+ # float alpha = 1.0;
869
+ # if (alpha_wrapper != nil) `
870
+ # alpha = [alpha_wrapper value];
871
+ # `
872
+ # return [UIColor colorWithRed:red green:green blue:blue alpha:alpha];
873
+ # `
874
+ # static Color* toProto(UIColor* color) `
875
+ # CGFloat red, green, blue, alpha;
876
+ # if (![color getRed:&red green:&green blue:&blue alpha:&alpha]) `
877
+ # return nil;
878
+ # `
879
+ # Color* result = [Color alloc] init];
880
+ # [result setRed:red];
881
+ # [result setGreen:green];
882
+ # [result setBlue:blue];
883
+ # if (alpha <= 0.9999) `
884
+ # [result setAlpha:floatWrapperWithValue(alpha)];
885
+ # `
886
+ # [result autorelease];
887
+ # return result;
888
+ # `
889
+ # // ...
890
+ # Example (JavaScript):
891
+ # // ...
892
+ # var protoToCssColor = function(rgb_color) `
893
+ # var redFrac = rgb_color.red || 0.0;
894
+ # var greenFrac = rgb_color.green || 0.0;
895
+ # var blueFrac = rgb_color.blue || 0.0;
896
+ # var red = Math.floor(redFrac * 255);
897
+ # var green = Math.floor(greenFrac * 255);
898
+ # var blue = Math.floor(blueFrac * 255);
899
+ # if (!('alpha' in rgb_color)) `
900
+ # return rgbToCssColor_(red, green, blue);
901
+ # `
902
+ # var alphaFrac = rgb_color.alpha.value || 0.0;
903
+ # var rgbParams = [red, green, blue].join(',');
904
+ # return ['rgba(', rgbParams, ',', alphaFrac, ')'].join('');
905
+ # `;
906
+ # var rgbToCssColor_ = function(red, green, blue) `
907
+ # var rgbNumber = new Number((red << 16) | (green << 8) | blue);
908
+ # var hexString = rgbNumber.toString(16);
909
+ # var missingZeros = 6 - hexString.length;
910
+ # var resultBuilder = ['#'];
911
+ # for (var i = 0; i < missingZeros; i++) `
912
+ # resultBuilder.push('0');
913
+ # `
914
+ # resultBuilder.push(hexString);
915
+ # return resultBuilder.join('');
916
+ # `;
917
+ # // ...
918
+ class Color
919
+ include Google::Apis::Core::Hashable
920
+
921
+ # The amount of green in the color as a value in the interval [0, 1].
922
+ # Corresponds to the JSON property `green`
923
+ # @return [Float]
924
+ attr_accessor :green
925
+
926
+ # The amount of blue in the color as a value in the interval [0, 1].
927
+ # Corresponds to the JSON property `blue`
928
+ # @return [Float]
929
+ attr_accessor :blue
930
+
931
+ # The amount of red in the color as a value in the interval [0, 1].
932
+ # Corresponds to the JSON property `red`
933
+ # @return [Float]
934
+ attr_accessor :red
935
+
936
+ # The fraction of this color that should be applied to the pixel. That is,
937
+ # the final pixel color is defined by the equation:
938
+ # pixel color = alpha * (this color) + (1.0 - alpha) * (background color)
939
+ # This means that a value of 1.0 corresponds to a solid color, whereas
940
+ # a value of 0.0 corresponds to a completely transparent color. This
941
+ # uses a wrapper message rather than a simple float scalar so that it is
942
+ # possible to distinguish between a default value and the value being unset.
943
+ # If omitted, this color object is to be rendered as a solid color
944
+ # (as if the alpha value had been explicitly given with a value of 1.0).
945
+ # Corresponds to the JSON property `alpha`
946
+ # @return [Float]
947
+ attr_accessor :alpha
948
+
949
+ def initialize(**args)
950
+ update!(**args)
951
+ end
952
+
953
+ # Update properties of this object
954
+ def update!(**args)
955
+ @green = args[:green] if args.key?(:green)
956
+ @blue = args[:blue] if args.key?(:blue)
957
+ @red = args[:red] if args.key?(:red)
958
+ @alpha = args[:alpha] if args.key?(:alpha)
959
+ end
960
+ end
961
+
962
+ # Detected entity location information.
963
+ class LocationInfo
964
+ include Google::Apis::Core::Hashable
965
+
966
+ # An object representing a latitude/longitude pair. This is expressed as a pair
967
+ # of doubles representing degrees latitude and degrees longitude. Unless
968
+ # specified otherwise, this must conform to the
969
+ # <a href="http://www.unoosa.org/pdf/icg/2012/template/WGS_84.pdf">WGS84
970
+ # standard</a>. Values must be within normalized ranges.
971
+ # Example of normalization code in Python:
972
+ # def NormalizeLongitude(longitude):
973
+ # """Wraps decimal degrees longitude to [-180.0, 180.0]."""
974
+ # q, r = divmod(longitude, 360.0)
975
+ # if r > 180.0 or (r == 180.0 and q <= -1.0):
976
+ # return r - 360.0
977
+ # return r
978
+ # def NormalizeLatLng(latitude, longitude):
979
+ # """Wraps decimal degrees latitude and longitude to
980
+ # [-180.0, 180.0] and [-90.0, 90.0], respectively."""
981
+ # r = latitude % 360.0
982
+ # if r <= 90.0:
983
+ # return r, NormalizeLongitude(longitude)
984
+ # elif r >= 270.0:
985
+ # return r - 360, NormalizeLongitude(longitude)
986
+ # else:
987
+ # return 180 - r, NormalizeLongitude(longitude + 180.0)
988
+ # assert 180.0 == NormalizeLongitude(180.0)
989
+ # assert -180.0 == NormalizeLongitude(-180.0)
990
+ # assert -179.0 == NormalizeLongitude(181.0)
991
+ # assert (0.0, 0.0) == NormalizeLatLng(360.0, 0.0)
992
+ # assert (0.0, 0.0) == NormalizeLatLng(-360.0, 0.0)
993
+ # assert (85.0, 180.0) == NormalizeLatLng(95.0, 0.0)
994
+ # assert (-85.0, -170.0) == NormalizeLatLng(-95.0, 10.0)
995
+ # assert (90.0, 10.0) == NormalizeLatLng(90.0, 10.0)
996
+ # assert (-90.0, -10.0) == NormalizeLatLng(-90.0, -10.0)
997
+ # assert (0.0, -170.0) == NormalizeLatLng(-180.0, 10.0)
998
+ # assert (0.0, -170.0) == NormalizeLatLng(180.0, 10.0)
999
+ # assert (-90.0, 10.0) == NormalizeLatLng(270.0, 10.0)
1000
+ # assert (90.0, 10.0) == NormalizeLatLng(-270.0, 10.0)
1001
+ # Corresponds to the JSON property `latLng`
1002
+ # @return [Google::Apis::VisionV1::LatLng]
1003
+ attr_accessor :lat_lng
1004
+
1005
+ def initialize(**args)
1006
+ update!(**args)
1007
+ end
1008
+
1009
+ # Update properties of this object
1010
+ def update!(**args)
1011
+ @lat_lng = args[:lat_lng] if args.key?(:lat_lng)
1012
+ end
1013
+ end
1014
+
1015
+ # Set of features pertaining to the image, computed by various computer vision
1016
+ # methods over safe-search verticals (for example, adult, spoof, medical,
1017
+ # violence).
1018
+ class SafeSearchAnnotation
1019
+ include Google::Apis::Core::Hashable
1020
+
1021
+ # Likelihood this is a medical image.
1022
+ # Corresponds to the JSON property `medical`
1023
+ # @return [String]
1024
+ attr_accessor :medical
1025
+
1026
+ # Violence likelihood.
1027
+ # Corresponds to the JSON property `violence`
1028
+ # @return [String]
1029
+ attr_accessor :violence
1030
+
1031
+ # Spoof likelihood. The likelihood that an obvious modification
1032
+ # was made to the image's canonical version to make it appear
1033
+ # funny or offensive.
1034
+ # Corresponds to the JSON property `spoof`
1035
+ # @return [String]
1036
+ attr_accessor :spoof
1037
+
1038
+ # Represents the adult contents likelihood for the image.
1039
+ # Corresponds to the JSON property `adult`
1040
+ # @return [String]
1041
+ attr_accessor :adult
1042
+
1043
+ def initialize(**args)
1044
+ update!(**args)
1045
+ end
1046
+
1047
+ # Update properties of this object
1048
+ def update!(**args)
1049
+ @medical = args[:medical] if args.key?(:medical)
1050
+ @violence = args[:violence] if args.key?(:violence)
1051
+ @spoof = args[:spoof] if args.key?(:spoof)
1052
+ @adult = args[:adult] if args.key?(:adult)
1053
+ end
1054
+ end
1055
+
1056
+ # Client image to perform Vision tasks over.
1057
+ class Image
1058
+ include Google::Apis::Core::Hashable
1059
+
1060
+ # External image source (i.e. Google Cloud Storage image location).
1061
+ # Corresponds to the JSON property `source`
1062
+ # @return [Google::Apis::VisionV1::ImageSource]
1063
+ attr_accessor :source
1064
+
1065
+ # Image content, represented as a stream of bytes.
1066
+ # Corresponds to the JSON property `content`
1067
+ # @return [String]
1068
+ attr_accessor :content
1069
+
1070
+ def initialize(**args)
1071
+ update!(**args)
1072
+ end
1073
+
1074
+ # Update properties of this object
1075
+ def update!(**args)
1076
+ @source = args[:source] if args.key?(:source)
1077
+ @content = args[:content] if args.key?(:content)
1078
+ end
1079
+ end
1080
+
1081
+ # Set of dominant colors and their corresponding scores.
1082
+ class DominantColorsAnnotation
1083
+ include Google::Apis::Core::Hashable
1084
+
1085
+ # RGB color values, with their score and pixel fraction.
1086
+ # Corresponds to the JSON property `colors`
1087
+ # @return [Array<Google::Apis::VisionV1::ColorInfo>]
1088
+ attr_accessor :colors
1089
+
1090
+ def initialize(**args)
1091
+ update!(**args)
1092
+ end
1093
+
1094
+ # Update properties of this object
1095
+ def update!(**args)
1096
+ @colors = args[:colors] if args.key?(:colors)
1097
+ end
1098
+ end
1099
+
1100
+ # The <em>Feature</em> indicates what type of image detection task to perform.
1101
+ # Users describe the type of Vision tasks to perform over images by
1102
+ # using <em>Feature</em>s. Features encode the Vision vertical to operate on
1103
+ # and the number of top-scoring results to return.
1104
+ class Feature
1105
+ include Google::Apis::Core::Hashable
1106
+
1107
+ # Maximum number of results of this type.
1108
+ # Corresponds to the JSON property `maxResults`
1109
+ # @return [Fixnum]
1110
+ attr_accessor :max_results
1111
+
1112
+ # The feature type.
1113
+ # Corresponds to the JSON property `type`
1114
+ # @return [String]
1115
+ attr_accessor :type
1116
+
1117
+ def initialize(**args)
1118
+ update!(**args)
1119
+ end
1120
+
1121
+ # Update properties of this object
1122
+ def update!(**args)
1123
+ @max_results = args[:max_results] if args.key?(:max_results)
1124
+ @type = args[:type] if args.key?(:type)
1125
+ end
1126
+ end
1127
+
1128
+ # Response to a batch image annotation request.
1129
+ class BatchAnnotateImagesResponse
1130
+ include Google::Apis::Core::Hashable
1131
+
1132
+ # Individual responses to image annotation requests within the batch.
1133
+ # Corresponds to the JSON property `responses`
1134
+ # @return [Array<Google::Apis::VisionV1::AnnotateImageResponse>]
1135
+ attr_accessor :responses
1136
+
1137
+ def initialize(**args)
1138
+ update!(**args)
1139
+ end
1140
+
1141
+ # Update properties of this object
1142
+ def update!(**args)
1143
+ @responses = args[:responses] if args.key?(:responses)
1144
+ end
1145
+ end
1146
+
1147
+ # Stores image properties (e.g. dominant colors).
1148
+ class ImageProperties
1149
+ include Google::Apis::Core::Hashable
1150
+
1151
+ # Set of dominant colors and their corresponding scores.
1152
+ # Corresponds to the JSON property `dominantColors`
1153
+ # @return [Google::Apis::VisionV1::DominantColorsAnnotation]
1154
+ attr_accessor :dominant_colors
1155
+
1156
+ def initialize(**args)
1157
+ update!(**args)
1158
+ end
1159
+
1160
+ # Update properties of this object
1161
+ def update!(**args)
1162
+ @dominant_colors = args[:dominant_colors] if args.key?(:dominant_colors)
1163
+ end
1164
+ end
1165
+
1166
+ # A 3D position in the image, used primarily for Face detection landmarks.
1167
+ # A valid Position must have both x and y coordinates.
1168
+ # The position coordinates are in the same scale as the original image.
1169
+ class Position
1170
+ include Google::Apis::Core::Hashable
1171
+
1172
+ # Y coordinate.
1173
+ # Corresponds to the JSON property `y`
1174
+ # @return [Float]
1175
+ attr_accessor :y
1176
+
1177
+ # Z coordinate (or depth).
1178
+ # Corresponds to the JSON property `z`
1179
+ # @return [Float]
1180
+ attr_accessor :z
1181
+
1182
+ # X coordinate.
1183
+ # Corresponds to the JSON property `x`
1184
+ # @return [Float]
1185
+ attr_accessor :x
1186
+
1187
+ def initialize(**args)
1188
+ update!(**args)
1189
+ end
1190
+
1191
+ # Update properties of this object
1192
+ def update!(**args)
1193
+ @y = args[:y] if args.key?(:y)
1194
+ @z = args[:z] if args.key?(:z)
1195
+ @x = args[:x] if args.key?(:x)
1196
+ end
1197
+ end
1198
+
1199
+ # An object representing a latitude/longitude pair. This is expressed as a pair
1200
+ # of doubles representing degrees latitude and degrees longitude. Unless
1201
+ # specified otherwise, this must conform to the
1202
+ # <a href="http://www.unoosa.org/pdf/icg/2012/template/WGS_84.pdf">WGS84
1203
+ # standard</a>. Values must be within normalized ranges.
1204
+ # Example of normalization code in Python:
1205
+ # def NormalizeLongitude(longitude):
1206
+ # """Wraps decimal degrees longitude to [-180.0, 180.0]."""
1207
+ # q, r = divmod(longitude, 360.0)
1208
+ # if r > 180.0 or (r == 180.0 and q <= -1.0):
1209
+ # return r - 360.0
1210
+ # return r
1211
+ # def NormalizeLatLng(latitude, longitude):
1212
+ # """Wraps decimal degrees latitude and longitude to
1213
+ # [-180.0, 180.0] and [-90.0, 90.0], respectively."""
1214
+ # r = latitude % 360.0
1215
+ # if r <= 90.0:
1216
+ # return r, NormalizeLongitude(longitude)
1217
+ # elif r >= 270.0:
1218
+ # return r - 360, NormalizeLongitude(longitude)
1219
+ # else:
1220
+ # return 180 - r, NormalizeLongitude(longitude + 180.0)
1221
+ # assert 180.0 == NormalizeLongitude(180.0)
1222
+ # assert -180.0 == NormalizeLongitude(-180.0)
1223
+ # assert -179.0 == NormalizeLongitude(181.0)
1224
+ # assert (0.0, 0.0) == NormalizeLatLng(360.0, 0.0)
1225
+ # assert (0.0, 0.0) == NormalizeLatLng(-360.0, 0.0)
1226
+ # assert (85.0, 180.0) == NormalizeLatLng(95.0, 0.0)
1227
+ # assert (-85.0, -170.0) == NormalizeLatLng(-95.0, 10.0)
1228
+ # assert (90.0, 10.0) == NormalizeLatLng(90.0, 10.0)
1229
+ # assert (-90.0, -10.0) == NormalizeLatLng(-90.0, -10.0)
1230
+ # assert (0.0, -170.0) == NormalizeLatLng(-180.0, 10.0)
1231
+ # assert (0.0, -170.0) == NormalizeLatLng(180.0, 10.0)
1232
+ # assert (-90.0, 10.0) == NormalizeLatLng(270.0, 10.0)
1233
+ # assert (90.0, 10.0) == NormalizeLatLng(-270.0, 10.0)
1234
+ class LatLng
1235
+ include Google::Apis::Core::Hashable
1236
+
1237
+ # The longitude in degrees. It must be in the range [-180.0, +180.0].
1238
+ # Corresponds to the JSON property `longitude`
1239
+ # @return [Float]
1240
+ attr_accessor :longitude
1241
+
1242
+ # The latitude in degrees. It must be in the range [-90.0, +90.0].
1243
+ # Corresponds to the JSON property `latitude`
1244
+ # @return [Float]
1245
+ attr_accessor :latitude
1246
+
1247
+ def initialize(**args)
1248
+ update!(**args)
1249
+ end
1250
+
1251
+ # Update properties of this object
1252
+ def update!(**args)
1253
+ @longitude = args[:longitude] if args.key?(:longitude)
1254
+ @latitude = args[:latitude] if args.key?(:latitude)
1255
+ end
1256
+ end
1257
+ end
1258
+ end
1259
+ end