You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 

171 lines
6.9 KiB

  1. // Copyright 2017, Google LLC
  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. package vision
  15. import (
  16. "context"
  17. gax "github.com/googleapis/gax-go/v2"
  18. pb "google.golang.org/genproto/googleapis/cloud/vision/v1"
  19. "google.golang.org/grpc/codes"
  20. "google.golang.org/grpc/status"
  21. )
  22. // AnnotateImage runs image detection and annotation for a single image.
  23. func (c *ImageAnnotatorClient) AnnotateImage(ctx context.Context, req *pb.AnnotateImageRequest, opts ...gax.CallOption) (*pb.AnnotateImageResponse, error) {
  24. res, err := c.BatchAnnotateImages(ctx, &pb.BatchAnnotateImagesRequest{
  25. Requests: []*pb.AnnotateImageRequest{req},
  26. }, opts...)
  27. if err != nil {
  28. return nil, err
  29. }
  30. return res.Responses[0], nil
  31. }
  32. // Called for a single image and a single feature.
  33. func (c *ImageAnnotatorClient) annotateOne(ctx context.Context, img *pb.Image, ictx *pb.ImageContext, ftype pb.Feature_Type, maxResults int, opts []gax.CallOption) (*pb.AnnotateImageResponse, error) {
  34. res, err := c.AnnotateImage(ctx, &pb.AnnotateImageRequest{
  35. Image: img,
  36. ImageContext: ictx,
  37. Features: []*pb.Feature{{Type: ftype, MaxResults: int32(maxResults)}},
  38. }, opts...)
  39. if err != nil {
  40. return nil, err
  41. }
  42. // When there is only one image and one feature, the response's Error field is
  43. // unambiguously about that one detection, so we "promote" it to the error return
  44. // value.
  45. // res.Error is a google.rpc.Status. Convert to a Go error. Use a gRPC
  46. // error because it preserves the code as a separate field.
  47. // TODO(jba): preserve the details field.
  48. if res.Error != nil {
  49. return nil, status.Errorf(codes.Code(res.Error.Code), "%s", res.Error.Message)
  50. }
  51. return res, nil
  52. }
  53. // DetectFaces performs face detection on the image.
  54. // At most maxResults results are returned.
  55. func (c *ImageAnnotatorClient) DetectFaces(ctx context.Context, img *pb.Image, ictx *pb.ImageContext, maxResults int, opts ...gax.CallOption) ([]*pb.FaceAnnotation, error) {
  56. res, err := c.annotateOne(ctx, img, ictx, pb.Feature_FACE_DETECTION, maxResults, opts)
  57. if err != nil {
  58. return nil, err
  59. }
  60. return res.FaceAnnotations, nil
  61. }
  62. // DetectLandmarks performs landmark detection on the image.
  63. // At most maxResults results are returned.
  64. func (c *ImageAnnotatorClient) DetectLandmarks(ctx context.Context, img *pb.Image, ictx *pb.ImageContext, maxResults int, opts ...gax.CallOption) ([]*pb.EntityAnnotation, error) {
  65. res, err := c.annotateOne(ctx, img, ictx, pb.Feature_LANDMARK_DETECTION, maxResults, opts)
  66. if err != nil {
  67. return nil, err
  68. }
  69. return res.LandmarkAnnotations, nil
  70. }
  71. // DetectLogos performs logo detection on the image.
  72. // At most maxResults results are returned.
  73. func (c *ImageAnnotatorClient) DetectLogos(ctx context.Context, img *pb.Image, ictx *pb.ImageContext, maxResults int, opts ...gax.CallOption) ([]*pb.EntityAnnotation, error) {
  74. res, err := c.annotateOne(ctx, img, ictx, pb.Feature_LOGO_DETECTION, maxResults, opts)
  75. if err != nil {
  76. return nil, err
  77. }
  78. return res.LogoAnnotations, nil
  79. }
  80. // DetectLabels performs label detection on the image.
  81. // At most maxResults results are returned.
  82. func (c *ImageAnnotatorClient) DetectLabels(ctx context.Context, img *pb.Image, ictx *pb.ImageContext, maxResults int, opts ...gax.CallOption) ([]*pb.EntityAnnotation, error) {
  83. res, err := c.annotateOne(ctx, img, ictx, pb.Feature_LABEL_DETECTION, maxResults, opts)
  84. if err != nil {
  85. return nil, err
  86. }
  87. return res.LabelAnnotations, nil
  88. }
  89. // DetectTexts performs text detection on the image.
  90. // At most maxResults results are returned.
  91. func (c *ImageAnnotatorClient) DetectTexts(ctx context.Context, img *pb.Image, ictx *pb.ImageContext, maxResults int, opts ...gax.CallOption) ([]*pb.EntityAnnotation, error) {
  92. res, err := c.annotateOne(ctx, img, ictx, pb.Feature_TEXT_DETECTION, maxResults, opts)
  93. if err != nil {
  94. return nil, err
  95. }
  96. return res.TextAnnotations, nil
  97. }
  98. // DetectDocumentText performs full text (OCR) detection on the image.
  99. func (c *ImageAnnotatorClient) DetectDocumentText(ctx context.Context, img *pb.Image, ictx *pb.ImageContext, opts ...gax.CallOption) (*pb.TextAnnotation, error) {
  100. res, err := c.annotateOne(ctx, img, ictx, pb.Feature_DOCUMENT_TEXT_DETECTION, 0, opts)
  101. if err != nil {
  102. return nil, err
  103. }
  104. return res.FullTextAnnotation, nil
  105. }
  106. // DetectSafeSearch performs safe-search detection on the image.
  107. func (c *ImageAnnotatorClient) DetectSafeSearch(ctx context.Context, img *pb.Image, ictx *pb.ImageContext, opts ...gax.CallOption) (*pb.SafeSearchAnnotation, error) {
  108. res, err := c.annotateOne(ctx, img, ictx, pb.Feature_SAFE_SEARCH_DETECTION, 0, opts)
  109. if err != nil {
  110. return nil, err
  111. }
  112. return res.SafeSearchAnnotation, nil
  113. }
  114. // DetectImageProperties computes properties of the image.
  115. func (c *ImageAnnotatorClient) DetectImageProperties(ctx context.Context, img *pb.Image, ictx *pb.ImageContext, opts ...gax.CallOption) (*pb.ImageProperties, error) {
  116. res, err := c.annotateOne(ctx, img, ictx, pb.Feature_IMAGE_PROPERTIES, 0, opts)
  117. if err != nil {
  118. return nil, err
  119. }
  120. return res.ImagePropertiesAnnotation, nil
  121. }
  122. // DetectWeb computes a web annotation on the image.
  123. func (c *ImageAnnotatorClient) DetectWeb(ctx context.Context, img *pb.Image, ictx *pb.ImageContext, opts ...gax.CallOption) (*pb.WebDetection, error) {
  124. res, err := c.annotateOne(ctx, img, ictx, pb.Feature_WEB_DETECTION, 0, opts)
  125. if err != nil {
  126. return nil, err
  127. }
  128. return res.WebDetection, nil
  129. }
  130. // CropHints computes crop hints for the image.
  131. func (c *ImageAnnotatorClient) CropHints(ctx context.Context, img *pb.Image, ictx *pb.ImageContext, opts ...gax.CallOption) (*pb.CropHintsAnnotation, error) {
  132. res, err := c.annotateOne(ctx, img, ictx, pb.Feature_CROP_HINTS, 0, opts)
  133. if err != nil {
  134. return nil, err
  135. }
  136. return res.CropHintsAnnotation, nil
  137. }
  138. // LocalizeObject runs the localizer for object detection.
  139. func (c *ImageAnnotatorClient) LocalizeObjects(ctx context.Context, img *pb.Image, ictx *pb.ImageContext, opts ...gax.CallOption) ([]*pb.LocalizedObjectAnnotation, error) {
  140. res, err := c.annotateOne(ctx, img, ictx, pb.Feature_OBJECT_LOCALIZATION, 0, opts)
  141. if err != nil {
  142. return nil, err
  143. }
  144. return res.LocalizedObjectAnnotations, nil
  145. }
  146. // ProductSearch searches the image for products.
  147. func (c *ImageAnnotatorClient) ProductSearch(ctx context.Context, img *pb.Image, ictx *pb.ImageContext, opts ...gax.CallOption) (*pb.ProductSearchResults, error) {
  148. res, err := c.annotateOne(ctx, img, ictx, pb.Feature_PRODUCT_SEARCH, 0, opts)
  149. if err != nil {
  150. return nil, err
  151. }
  152. return res.ProductSearchResults, nil
  153. }