functions/image-analysis/go/main.go (73 lines of code) (raw):

// Copyright 2021 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // https://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // Package p contains a Google Cloud Storage Cloud Function. package p import ( "context" "fmt" "log" "strings" "time" "cloud.google.com/go/firestore" vision "cloud.google.com/go/vision/apiv1" "github.com/pkg/errors" pb "google.golang.org/genproto/googleapis/cloud/vision/v1" ) // GCSEvent is the payload of a GCS event. Please refer to the docs for // additional information regarding GCS events. type GCSEvent struct { Bucket string `json:"bucket"` Name string `json:"name"` } // firestorePicture is the structure of a `pictures` document in Firestore type firestorePicture struct { Labels []string `firestore:"labels"` Color string `firestore:"color"` // Created value will be set with the time of creation on the server (firestore) side // see https://godoc.org/cloud.google.com/go/firestore#DocumentRef.Create Created time.Time `firestore:"created,serverTimestamp"` } /* VisionAnalysis creates a thumbnail when a file is changed in a Cloud Storage bucket. You can deploy this function to Cloud Function with the command: gcloud functions deploy image-analysis \ --region $YOUR_REGION \ --entry-point VisionAnalysis \ --trigger-bucket $YOUR_SOURCE_BUCKET \ --runtime go111 \ --no-allow-unauthenticated */ func VisionAnalysis(ctx context.Context, e GCSEvent) error { log.Printf("Event: %#v", e) filename := e.Name filebucket := e.Bucket log.Printf("New picture uploaded %s in %s", filename, filebucket) client, err := vision.NewImageAnnotatorClient(ctx) if err != nil { log.Printf("Failed to create client: %v", err) return errors.New("Failed to create CloudVision client") } defer client.Close() request := &pb.AnnotateImageRequest{ Image: &pb.Image{ Source: &pb.ImageSource{ ImageUri: fmt.Sprintf("gs://%s/%s", filebucket, filename), }, }, Features: []*pb.Feature{ {Type: pb.Feature_LABEL_DETECTION}, {Type: pb.Feature_IMAGE_PROPERTIES}, {Type: pb.Feature_SAFE_SEARCH_DETECTION}, }, } r, err := client.AnnotateImage(ctx, request) if err != nil { log.Printf("Failed annotate image: %v", err) return fmt.Errorf("Vision API error: code %d, message: '%s'", r.Error.Code, r.Error.Message) } resp := visionResponse{r} log.Printf("Raw vision output for: %s: %s", filename, resp.toJSON()) labels := resp.getLabels() log.Printf("Labels: %s", strings.Join(labels, ", ")) color := resp.getDominantColor() log.Printf("Color: %s", color) if !resp.isSafe() { return nil } // if the picture is safe to display, store it in Firestore pictureStore, err := firestore.NewClient(ctx, firestore.DetectProjectID) if err != nil { log.Printf("Failed to get 'pictures' firestore collection: %v", err) return errors.New("Failed to get 'pictures' firestore collection") } _, err = pictureStore.Doc("pictures/"+filename).Create(ctx, firestorePicture{ Labels: labels, Color: color, }) if err != nil { log.Printf("Failed to add picture in firestore: %v", err) return errors.New("Failed to add picture in firestore") } return nil }