Pic-a-daily: Google की नेटिव Java क्लाइंट लाइब्रेरी की मदद से, तस्वीरों को स्टोर करें और उनका विश्लेषण करें

1. खास जानकारी

पहली कोड लैब में, आपको एक बकेट में तस्वीरें स्टोर करनी होंगी. इससे फ़ाइल बनाने का इवेंट जनरेट होगा, जिसे Cloud Run में डिप्लॉय की गई सेवा मैनेज करेगी. सेवा, इमेज का विश्लेषण करने और नतीजों को डेटास्टोर में सेव करने के लिए, Vision API को कॉल करेगी.

427de3100de3a61e.png

आपको क्या सीखने को मिलेगा

  • Cloud Storage
  • Cloud Run
  • क्लाउड विज़न एपीआई
  • Cloud Firestore

2. सेटअप और ज़रूरी शर्तें

अपने हिसाब से एनवायरमेंट सेटअप करना

  1. Google Cloud Console में साइन इन करें और नया प्रोजेक्ट बनाएं या किसी मौजूदा प्रोजेक्ट का फिर से इस्तेमाल करें. अगर आपके पास पहले से Gmail या Google Workspace खाता नहीं है, तो आपको नया खाता बनाना होगा.

b35bf95b8bf3d5d8.png

a99b7ace416376c4.png

bd84a6d3004737c5.png

  • प्रोजेक्ट का नाम, इस प्रोजेक्ट में हिस्सा लेने वाले लोगों का डिसप्ले नेम होता है. यह एक वर्ण स्ट्रिंग है, जिसका इस्तेमाल Google API नहीं करता. इसे कभी भी अपडेट किया जा सकता है.
  • प्रोजेक्ट आईडी, Google Cloud के सभी प्रोजेक्ट के लिए यूनीक होना चाहिए. साथ ही, आईडी को बदला नहीं जा सकता. सेट अप के बाद इसे बदला नहीं जा सकता. Cloud Console, एक यूनीक स्ट्रिंग अपने-आप जनरेट करता है; आम तौर पर, आपको उसके होने की कोई परवाह नहीं होती. ज़्यादातर कोडलैब में, आपको प्रोजेक्ट आईडी का रेफ़रंस देना होगा. आम तौर पर, इसे PROJECT_ID के तौर पर पहचाना जाता है. अगर आपको जनरेट किया गया आईडी पसंद नहीं है, तो आप कोई भी और रैंडम आईडी जनरेट कर सकते हैं. इसके अलावा, खुद भी आज़माया जा सकता है और देखें कि वह उपलब्ध है या नहीं. इस चरण के बाद इसे बदला नहीं जा सकता और प्रोजेक्ट के कुल समय तक बना रहेगा.
  • आपकी जानकारी के लिए, एक तीसरी वैल्यू यानी प्रोजेक्ट नंबर है. इसका इस्तेमाल कुछ एपीआई करते हैं. दस्तावेज़ में इन तीनों वैल्यू के बारे में ज़्यादा जानें.
  1. इसके बाद, आपको क्लाउड संसाधनों/एपीआई का इस्तेमाल करने के लिए, Cloud Console में बिलिंग चालू करनी होगी. इस कोडलैब का इस्तेमाल करने पर, आपको ज़्यादा पैसे नहीं चुकाने होंगे. इस ट्यूटोरियल के अलावा, संसाधनों को बंद करने के लिए कि आपको बिलिंग न करनी पड़े. इसके लिए, अपने बनाए गए संसाधनों को मिटाएं या पूरा प्रोजेक्ट मिटाएं. Google Cloud के नए उपयोगकर्ता, 300 डॉलर के मुफ़्त ट्रायल वाले प्रोग्राम में हिस्सा ले सकते हैं.

Cloud Shell शुरू करना

Google Cloud को आपके लैपटॉप से, कहीं से भी ऑपरेट किया जा सकता है. हालांकि, इस कोडलैब में Google Cloud Shell का इस्तेमाल किया जा रहा है. यह क्लाउड में चलने वाला कमांड लाइन एनवायरमेंट है.

Google Cloud Console में जाकर, सबसे ऊपर दाईं ओर मौजूद टूलबार पर क्लाउड शेल आइकॉन पर क्लिक करें:

55efc1aaa7a4d3ad.png

प्रावधान करने और एनवायरमेंट से कनेक्ट होने में कुछ ही समय लगेगा. उसके पूरा हो जाने पर, आपको कुछ ऐसा दिखाई देगा:

7ffe5cbb04455448.png

इस वर्चुअल मशीन में ऐसे सभी डेवलपमेंट टूल मौजूद हैं जिनकी आपको ज़रूरत पड़ेगी. यह पांच जीबी की स्थायी होम डायरेक्ट्री उपलब्ध कराता है और Google Cloud पर चलता है. यह नेटवर्क की परफ़ॉर्मेंस और पुष्टि करने की प्रक्रिया को बेहतर बनाता है. इस कोडलैब (कोड बनाना सीखना) में आपका सारा काम ब्राउज़र में किया जा सकता है. आपको कुछ भी इंस्टॉल करने की ज़रूरत नहीं है.

3. एपीआई चालू करें

इस लैब के लिए, आपको Cloud Functions और Vision API का इस्तेमाल करना होगा, लेकिन पहले उन्हें Cloud Console में या gcloud में चालू करना होगा.

Cloud Console में Vision API को चालू करने के लिए, खोज बार में Cloud Vision API खोजें:

cf48b1747ba6a6fb.png

आपको Cloud Vision API पेज पर ले जाया जाएगा:

ba4af419e6086fbb.png

ENABLE बटन पर क्लिक करें.

इसके अलावा, इसे Cloud Shell में चालू भी किया जा सकता है. इसके लिए, gcloud कमांड लाइन टूल इस्तेमाल करें.

Cloud Shell के अंदर, यह कमांड चलाएं:

gcloud services enable vision.googleapis.com

आपको कार्रवाई सफलतापूर्वक खत्म होने के लिए दिखाई देना चाहिए:

Operation "operations/acf.12dba18b-106f-4fd2-942d-fea80ecc5c1c" finished successfully.

Cloud Run और Cloud Build को भी चालू करें:

gcloud services enable cloudbuild.googleapis.com \
  run.googleapis.com

4. बकेट बनाना (कंसोल)

तस्वीरों के लिए स्टोरेज बकेट बनाएं. Google Cloud Platform कंसोल ( console.cloud.google.com) से या Cloud Shell से gsutil कमांड लाइन टूल या अपने लोकल डेवलपमेंट एनवायरमेंट की मदद से, ऐसा किया जा सकता है.

"हैमबर्गर" से (RECORD) मेन्यू, Storage पेज पर जाएं.

1930e055d138150a.png

अपने बकेट को नाम दें

CREATE BUCKET बटन पर क्लिक करें.

34147939358517f8.png

CONTINUE पर क्लिक करें.

जगह चुनें

197817f20be07678.png

अपनी पसंद के क्षेत्र में, एक से ज़्यादा इलाकों के लिए बकेट बनाएं (यहां Europe).

CONTINUE पर क्लिक करें.

डिफ़ॉल्ट स्टोरेज क्लास चुनना

53cd91441c8caf0e.png

अपने डेटा के लिए Standard स्टोरेज क्लास चुनें.

CONTINUE पर क्लिक करें.

ऐक्सेस कंट्रोल सेट करना

8c2b3b459d934a51.png

साथ ही, आपने सार्वजनिक तौर पर उपलब्ध इमेज पर काम किया है. इसलिए, इस बकेट में स्टोर की गई हमारी सभी तस्वीरों का ऐक्सेस कंट्रोल एक जैसा होना चाहिए.

Uniform ऐक्सेस कंट्रोल का विकल्प चुनें.

CONTINUE पर क्लिक करें.

सुरक्षा/एन्क्रिप्ट (सुरक्षित) करने का तरीका सेट करना

d931c24c3e705a68.png

डिफ़ॉल्ट (Google-managed key), क्योंकि आप अपनी एन्क्रिप्शन कुंजियों का इस्तेमाल नहीं करेंगे.) को डिफ़ॉल्ट रखें.

हमारी बकेट बनाने की प्रक्रिया को पूरा करने के लिए, CREATE पर क्लिक करें.

सभी उपयोगकर्ताओं को स्टोरेज व्यूअर के तौर पर जोड़ना

Permissions टैब पर जाएं:

d0ecfdcff730ea51.png

बकेट में allUsers सदस्य को, Storage > Storage Object Viewer की भूमिका के साथ जोड़ें, ऐसा करने का तरीका:

e9f25ec1ea0b6cc6.png

SAVE पर क्लिक करें.

5. बकेट बनाएं (gsutil)

बकेट बनाने के लिए, Cloud Shell में gsutil कमांड-लाइन टूल का इस्तेमाल भी किया जा सकता है.

Cloud Shell में, बकेट के यूनीक नाम के लिए एक वैरिएबल सेट करें. Cloud Shell में पहले से ही आपके यूनीक प्रोजेक्ट आईडी के लिए GOOGLE_CLOUD_PROJECT सेट है. आपके पास इसे बकेट के नाम में जोड़ने का विकल्प होता है.

उदाहरण के लिए:

export BUCKET_PICTURES=uploaded-pictures-${GOOGLE_CLOUD_PROJECT}

यूरोप में एक से ज़्यादा क्षेत्रों के लिए एक स्टैंडर्ड ज़ोन बनाएं:

gsutil mb -l EU gs://${BUCKET_PICTURES}

पक्का करें कि बकेट लेवल का ऐक्सेस एक जैसा हो:

gsutil uniformbucketlevelaccess set on gs://${BUCKET_PICTURES}

बकेट को सार्वजनिक बनाएं:

gsutil iam ch allUsers:objectViewer gs://${BUCKET_PICTURES}

कंसोल के Cloud Storage सेक्शन पर जाने पर, आपके पास एक सार्वजनिक uploaded-pictures बकेट होनी चाहिए:

a98ed4ba17873e40.png

परीक्षण करें कि आप बकेट में चित्र अपलोड कर सकते हैं और पिछले चरण में बताए गए अनुसार अपलोड किए गए चित्र सार्वजनिक रूप से उपलब्ध हैं.

6. बकेट के सार्वजनिक ऐक्सेस की जांच करना

स्टोरेज ब्राउज़र पर वापस जाने पर, आपको सूची में अपना बकेट "सार्वजनिक" के तौर पर दिखेगा ऐक्सेस देना होगा (इसमें चेतावनी का एक निशान शामिल है, जो आपको यह याद दिलाता है कि किसी के पास भी उस बकेट के कॉन्टेंट का ऐक्सेस है).

89e7a4d2c80a0319.png

आपकी बकेट अब चित्र प्राप्त करने के लिए तैयार है.

बकेट के नाम पर क्लिक करने पर, आपको बकेट की जानकारी दिखेगी.

131387f12d3eb2d3.png

यहां Upload files बटन का इस्तेमाल करके यह जांच की जा सकती है कि बकेट में कोई तस्वीर जोड़ी जा सकती है या नहीं. फ़ाइल चुनने वाला पॉप-अप आपसे एक फ़ाइल चुनने के लिए कहेगा. चुने जाने के बाद, इसे आपके बकेट में अपलोड कर दिया जाएगा. इसके बाद, आपको public का वह ऐक्सेस फिर से दिखेगा जो इस नई फ़ाइल के लिए अपने-आप एट्रिब्यूट हो गया है.

e87584471a6e9c6d.png

Public ऐक्सेस लेबल के साथ, आपको लिंक का एक छोटा आइकॉन भी दिखेगा. इस पर क्लिक करने पर, आपका ब्राउज़र उस इमेज के सार्वजनिक यूआरएल पर जाएगा, जो इस तरह का होगा:

https://storage.googleapis.com/BUCKET_NAME/PICTURE_FILE.png

जहां आपने अपने बकेट के लिए चुना है वह दुनिया भर में इस्तेमाल होने वाला यूनीक नाम है. इसके बाद, आपकी फ़ोटो का फ़ाइल नाम BUCKET_NAME है.

चित्र नाम के साथ चेक बॉक्स पर क्लिक करने से, DELETE बटन सक्षम हो जाएगा और आप इस पहली चित्र को हटा सकते हैं.

7. डेटाबेस तैयार करना

आपको Vision API से मिली तस्वीर की जानकारी को Cloud Firestore के डेटाबेस में सेव करना होगा. यह डेटाबेस, तेज़, पूरी तरह से मैनेज किया गया, सर्वरलेस, क्लाउड-नेटिव NoSQL दस्तावेज़ डेटाबेस है. Cloud Console के Firestore सेक्शन में जाकर अपना डेटाबेस तैयार करें:

9e4708d2257de058.png

दो विकल्प दिए जाते हैं: Native mode या Datastore mode. नेटिव मोड का इस्तेमाल करें. इसमें, ऑफ़लाइन सहायता और रीयल-टाइम सिंक करने जैसी अतिरिक्त सुविधाएं मिलती हैं.

SELECT NATIVE MODE पर क्लिक करें.

9449ace8cc84de43.png

एक से ज़्यादा क्षेत्र चुनें (यहां यूरोप में, लेकिन कम से कम वह क्षेत्र चुनें जो आपका फ़ंक्शन और स्टोरेज बकेट है).

CREATE DATABASE बटन पर क्लिक करें.

डेटाबेस बन जाने के बाद, आपको यह जानकारी दिखेगी:

56265949a124819e.png

+ START COLLECTION बटन पर क्लिक करके, नया कलेक्शन बनाएं.

नाम संग्रह pictures.

75806ee24c4e13a7.png

आपको कोई दस्तावेज़ बनाने की ज़रूरत नहीं है. नई तस्वीरें, Cloud Storage में सेव हो जाती हैं और Vision API इनका विश्लेषण कर सकता है. इसलिए, इन्हें प्रोग्राम के हिसाब से अपने-आप जोड़ा जा सकता है.

Save पर क्लिक करें.

Firestore, नए कलेक्शन में पहला डिफ़ॉल्ट दस्तावेज़ बनाता है. आपके पास उस दस्तावेज़ को सुरक्षित तरीके से मिटाने का विकल्प होता है, क्योंकि इसमें कोई काम की जानकारी नहीं होती:

5c2f1e17ea47f48f.png

हमारे कलेक्शन में, प्रोग्राम के हिसाब से अपने-आप बनने वाले दस्तावेज़ों में चार फ़ील्ड होंगे:

  • name (string): अपलोड की गई फ़ोटो की फ़ाइल का नाम, जो दस्तावेज़ की कुंजी भी है
  • लेबल (स्ट्रिंग की कैटगरी): Vision API की मदद से पहचाने गए आइटम के लेबल
  • color (string): मुख्य रंग का हेक्साडेसिमल रंग कोड (जैसे, #ab12ef)
  • बनाया गया (तारीख): इस इमेज के मेटाडेटा को सेव किए जाने के समय का टाइमस्टैंप
  • थंबनेल (बूलियन): एक वैकल्पिक फ़ील्ड, जो मौजूद होगी. अगर इस तस्वीर के लिए थंबनेल इमेज जनरेट की गई है, तो यह सही हो जाएगी

हम Firestore में ऐसी तस्वीरें ढूंढने के लिए Firestore में खोज करेंगे जिनमें थंबनेल उपलब्ध होंगे. साथ ही, हम उन्हें बनने की तारीख के हिसाब से क्रम में लगाने का काम करेंगे, इसलिए हमें एक सर्च इंडेक्स बनाना होगा.

Cloud Shell में, इस कमांड का इस्तेमाल करके इंडेक्स बनाया जा सकता है:

gcloud firestore indexes composite create \
  --collection-group=pictures \
  --field-config field-path=thumbnail,order=descending \
  --field-config field-path=created,order=descending

इसके अलावा, Cloud Console में भी ऐसा किया जा सकता है. ऐसा करने के लिए, बाईं ओर नेविगेशन कॉलम में Indexes पर क्लिक करें. इसके बाद, एक कंपोज़िट इंडेक्स बनाएं, जैसा कि यहां दिखाया गया है:

ecb8b95e3c791272.png

Create पर क्लिक करें. इंडेक्स बनाने में कुछ मिनट लग सकते हैं.

8. कोड का क्लोन बनाएं

अगर आपने पिछले कोड लैब में, पहले से कोई काम नहीं किया है, तो कोड का क्लोन बनाएं:

git clone https://github.com/GoogleCloudPlatform/serverless-photosharing-workshop

इसके बाद लैब बनाने के लिए, सेवा वाली डायरेक्ट्री पर जाएं:

cd serverless-photosharing-workshop/services/image-analysis/java

आपके पास सेवा के लिए यह फ़ाइल लेआउट होगा:

f79613aff479d8ad.png

9. सेवा कोड के बारे में ज़्यादा जानें

सबसे पहले यह देखा जाता है कि बीओएम का इस्तेमाल करके, pom.xml में Java क्लाइंट लाइब्रेरी कैसे चालू होती हैं:

सबसे पहले, pom.xml फ़ाइल में बदलाव करें, जो हमारे Java फ़ंक्शन की डिपेंडेंसी की सूची में शामिल है. Cloud Vision API Maven डिपेंडेंसी जोड़ने के लिए, कोड को अपडेट करें:

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
  <modelVersion>4.0.0</modelVersion>
  <groupId>cloudfunctions</groupId>
  <artifactId>gcs-function</artifactId>
  <version>1.0-SNAPSHOT</version>

  <properties>
    <maven.compiler.target>11</maven.compiler.target>
    <maven.compiler.source>11</maven.compiler.source>
  </properties>

  <dependencyManagement>
    <dependencies>
      <dependency>
        <groupId>com.google.cloud</groupId>
        <artifactId>libraries-bom</artifactId>
        <version>26.1.1</version>
        <type>pom</type>
        <scope>import</scope>
      </dependency>
    </dependencies>
  </dependencyManagement>

  <dependencies>
    <dependency>
      <groupId>com.google.cloud.functions</groupId>
      <artifactId>functions-framework-api</artifactId>
      <version>1.0.4</version>
      <type>jar</type>
    </dependency>
    <dependency>
      <groupId>com.google.cloud</groupId>
      <artifactId>google-cloud-firestore</artifactId>
    </dependency>
    <dependency>
      <groupId>com.google.cloud</groupId>
      <artifactId>google-cloud-vision</artifactId>
    </dependency>
    <dependency>
      <groupId>com.google.cloud</groupId>
      <artifactId>google-cloud-storage</artifactId>
    </dependency>
  </dependencies>

इस सुविधा को EventController क्लास में लागू किया गया है. बकेट में हर बार नई इमेज अपलोड किए जाने पर, सेवा को प्रोसेस करने के लिए एक सूचना मिलेगी:

@RestController
public class EventController {
  private static final Logger logger = Logger.getLogger(EventController.class.getName());
    
  private static final List<String> requiredFields = Arrays.asList("ce-id", "ce-source", "ce-type", "ce-specversion");

  @RequestMapping(value = "/", method = RequestMethod.POST)
  public ResponseEntity<String> receiveMessage(
    @RequestBody Map<String, Object> body, @RequestHeader Map<String, String> headers) throws IOException, InterruptedException, ExecutionException {
...
}

कोड, Cloud Events हेडर की पुष्टि करने के लिए काम करेगा:

System.out.println("Header elements");
for (String field : requiredFields) {
    if (headers.get(field) == null) {
    String msg = String.format("Missing expected header: %s.", field);
    System.out.println(msg);
    return new ResponseEntity<String>(msg, HttpStatus.BAD_REQUEST);
    } else {
    System.out.println(field + " : " + headers.get(field));
    }
}

System.out.println("Body elements");
for (String bodyField : body.keySet()) {
    System.out.println(bodyField + " : " + body.get(bodyField));
}

if (headers.get("ce-subject") == null) {
    String msg = "Missing expected header: ce-subject.";
    System.out.println(msg);
    return new ResponseEntity<String>(msg, HttpStatus.BAD_REQUEST);
} 

अब एक अनुरोध बनाया जा सकता है और कोड इसी तरह के एक अनुरोध को Vision API पर भेजने के लिए तैयार करेगा:

try (ImageAnnotatorClient vision = ImageAnnotatorClient.create()) {
    List<AnnotateImageRequest> requests = new ArrayList<>();
    
    ImageSource imageSource = ImageSource.newBuilder()
        .setGcsImageUri("gs://" + bucketName + "/" + fileName)
        .build();

    Image image = Image.newBuilder()
        .setSource(imageSource)
        .build();

    Feature featureLabel = Feature.newBuilder()
        .setType(Type.LABEL_DETECTION)
        .build();
    Feature featureImageProps = Feature.newBuilder()
        .setType(Type.IMAGE_PROPERTIES)
        .build();
    Feature featureSafeSearch = Feature.newBuilder()
        .setType(Type.SAFE_SEARCH_DETECTION)
        .build();
        
    AnnotateImageRequest request = AnnotateImageRequest.newBuilder()
        .addFeatures(featureLabel)
        .addFeatures(featureImageProps)
        .addFeatures(featureSafeSearch)
        .setImage(image)
        .build();
    
    requests.add(request);

हम Vision API की तीन मुख्य सुविधाएं मांग रहे हैं:

  • लेबल की पहचान: इससे पता चलता है कि उन तस्वीरों में क्या है
  • इमेज की प्रॉपर्टी: इससे फ़ोटो के दिलचस्प एट्रिब्यूट दिखाए जा सकते हैं (हम इमेज के मुख्य रंग में दिलचस्पी रखते हैं)
  • सुरक्षित खोज: जानें कि इमेज दिखाने के लिए सुरक्षित है या नहीं (इसमें वयस्क / चिकित्सा / वयस्क / हिंसक सामग्री नहीं होनी चाहिए)

अब हम Vision API को कॉल कर सकते हैं:

...
logger.info("Calling the Vision API...");
BatchAnnotateImagesResponse result = vision.batchAnnotateImages(requests);
List<AnnotateImageResponse> responses = result.getResponsesList();
...

रेफ़रंस के लिए, Vision API से मिलने वाले रिस्पॉन्स इस तरह दिखते हैं:

{
  "faceAnnotations": [],
  "landmarkAnnotations": [],
  "logoAnnotations": [],
  "labelAnnotations": [
    {
      "locations": [],
      "properties": [],
      "mid": "/m/01yrx",
      "locale": "",
      "description": "Cat",
      "score": 0.9959855675697327,
      "confidence": 0,
      "topicality": 0.9959855675697327,
      "boundingPoly": null
    },
    ✄ - - - ✄
  ],
  "textAnnotations": [],
  "localizedObjectAnnotations": [],
  "safeSearchAnnotation": {
    "adult": "VERY_UNLIKELY",
    "spoof": "UNLIKELY",
    "medical": "VERY_UNLIKELY",
    "violence": "VERY_UNLIKELY",
    "racy": "VERY_UNLIKELY",
    "adultConfidence": 0,
    "spoofConfidence": 0,
    "medicalConfidence": 0,
    "violenceConfidence": 0,
    "racyConfidence": 0,
    "nsfwConfidence": 0
  },
  "imagePropertiesAnnotation": {
    "dominantColors": {
      "colors": [
        {
          "color": {
            "red": 203,
            "green": 201,
            "blue": 201,
            "alpha": null
          },
          "score": 0.4175916016101837,
          "pixelFraction": 0.44456374645233154
        },
        ✄ - - - ✄
      ]
    }
  },
  "error": null,
  "cropHintsAnnotation": {
    "cropHints": [
      {
        "boundingPoly": {
          "vertices": [
            { "x": 0, "y": 118 },
            { "x": 1177, "y": 118 },
            { "x": 1177, "y": 783 },
            { "x": 0, "y": 783 }
          ],
          "normalizedVertices": []
        },
        "confidence": 0.41695669293403625,
        "importanceFraction": 1
      }
    ]
  },
  "fullTextAnnotation": null,
  "webDetection": null,
  "productSearchResults": null,
  "context": null
}

अगर कोई गड़बड़ी नहीं मिलती है, तो हम आगे की कार्रवाई कर सकते हैं. इसलिए, अगर ब्लॉक है, तो हमारे पास ऐसा क्यों है:

if (responses.size() == 0) {
    logger.info("No response received from Vision API.");
    return new ResponseEntity<String>(msg, HttpStatus.BAD_REQUEST);
}

AnnotateImageResponse response = responses.get(0);
if (response.hasError()) {
    logger.info("Error: " + response.getError().getMessage());
    return new ResponseEntity<String>(msg, HttpStatus.BAD_REQUEST);
}

हम इमेज में दिखाई गई चीज़ों, कैटगरी या थीम के लेबल बनाएंगे:

List<String> labels = response.getLabelAnnotationsList().stream()
    .map(annotation -> annotation.getDescription())
    .collect(Collectors.toList());
logger.info("Annotations found:");
for (String label: labels) {
    logger.info("- " + label);
}

हम चित्र के मुख्य रंग को जानने में दिलचस्पी रखते हैं:

String mainColor = "#FFFFFF";
ImageProperties imgProps = response.getImagePropertiesAnnotation();
if (imgProps.hasDominantColors()) {
    DominantColorsAnnotation colorsAnn = imgProps.getDominantColors();
    ColorInfo colorInfo = colorsAnn.getColors(0);

    mainColor = rgbHex(
        colorInfo.getColor().getRed(), 
        colorInfo.getColor().getGreen(), 
        colorInfo.getColor().getBlue());

    logger.info("Color: " + mainColor);
}

आइए, देखते हैं कि तस्वीर सुरक्षित है या नहीं:

boolean isSafe = false;
if (response.hasSafeSearchAnnotation()) {
    SafeSearchAnnotation safeSearch = response.getSafeSearchAnnotation();

    isSafe = Stream.of(
        safeSearch.getAdult(), safeSearch.getMedical(), safeSearch.getRacy(),
        safeSearch.getSpoof(), safeSearch.getViolence())
    .allMatch( likelihood -> 
        likelihood != Likelihood.LIKELY && likelihood != Likelihood.VERY_LIKELY
    );

    logger.info("Safe? " + isSafe);
}

हम वयस्क / स्पूफ़ / मेडिकल / हिंसा / वयस्क लोगों से जुड़ी विशेषताओं की जांच कर रहे हैं, ताकि यह पता लगाया जा सके कि ऐसे कॉन्टेंट की संभावना ज़्यादा है या इससे ज़्यादा नहीं.

अगर सुरक्षित खोज का नतीजा मिलता है, तो हम Firestore में मेटाडेटा सेव कर सकते हैं:

// Saving result to Firestore
if (isSafe) {
    FirestoreOptions firestoreOptions = FirestoreOptions.getDefaultInstance();
    Firestore pictureStore = firestoreOptions.getService();

    DocumentReference doc = pictureStore.collection("pictures").document(fileName);

    Map<String, Object> data = new HashMap<>();
    data.put("labels", labels);
    data.put("color", mainColor);
    data.put("created", new Date());

    ApiFuture<WriteResult> writeResult = doc.set(data, SetOptions.merge());

    logger.info("Picture metadata saved in Firestore at " + writeResult.get().getUpdateTime());
}

10. GraalVM की मदद से ऐप्लिकेशन की इमेज बनाएं (ज़रूरी नहीं)

इस वैकल्पिक चरण में, आप GraalVM का इस्तेमाल करके JIT(JVM) based app image और फिर AOT(Native) Java app image बनाएंगे.

बिल्ड चलाने के लिए, आपको यह पक्का करना होगा कि आपके पास सही JDK और नेटिव-इमेज बिल्डर इंस्टॉल और कॉन्फ़िगर किया गया है. यहां कई विकल्प मौजूद हैं.

To start, GraalVM 22.2.x कम्यूनिटी वर्शन डाउनलोड करें और GraalVM इंस्टॉलेशन पेज पर दिए गए निर्देशों का पालन करें.

इस प्रक्रिया को SDKMAN! की मदद से बहुत ज़्यादा आसान बनाया जा सकता है!

SDKman के साथ सही JDK डिस्ट्रिब्यूशन को इंस्टॉल करने के लिए, इंस्टॉल करने का निर्देश देकर शुरुआत करें:

sdk install java 22.2.r17-grl

SDKमैन को JIT और AOT, दोनों बिल्ड के लिए यह वर्शन इस्तेमाल करने का निर्देश दें:

sdk use java 22.2.0.r17-grl

GraalVM के लिए native-image utility इंस्टॉल करें:

gu install native-image

अपनी सुविधा के लिए, Cloudshell में इन आसान निर्देशों का इस्तेमाल करके, GraalVM और local-image उपयोगिता को इंस्टॉल किया जा सकता है:

# install GraalVM in your home directory
cd ~

# download GraalVM
wget https://github.com/graalvm/graalvm-ce-builds/releases/download/vm-22.2.0/graalvm-ce-java17-linux-amd64-22.2.0.tar.gz
ls
tar -xzvf graalvm-ce-java17-linux-amd64-22.2.0.tar.gz

# configure Java 17 and GraalVM 22.2
echo Existing JVM: $JAVA_HOME
cd graalvm-ce-java17-22.2.0
export JAVA_HOME=$PWD
cd bin
export PATH=$PWD:$PATH

echo JAVA HOME: $JAVA_HOME
echo PATH: $PATH

# install the native image utility
java -version
gu install native-image

cd ../..

सबसे पहले, GCP प्रोजेक्ट के एनवायरमेंट वैरिएबल सेट करें:

export GOOGLE_CLOUD_PROJECT=$(gcloud config get-value project)

इसके बाद लैब बनाने के लिए, सेवा वाली डायरेक्ट्री पर जाएं:

cd serverless-photosharing-workshop/services/image-analysis/java

JIT(JVM) ऐप्लिकेशन की इमेज बनाएं:

./mvnw package -Pjvm

टर्मिनल में बिल्ड लॉग देखें:

...
[INFO] --- spring-boot-maven-plugin:2.7.3:repackage (repackage) @ image-analysis ---
[INFO] Replacing main artifact with repackaged archive
[INFO] ------------------------------------------------------------------------
[INFO] BUILD SUCCESS
[INFO] ------------------------------------------------------------------------
[INFO] Total time:  24.009 s
[INFO] Finished at: 2022-09-26T22:17:32-04:00
[INFO] ------------------------------------------------------------------------

एओटी(नेटिव) इमेज बनाएं:.

./mvnw package -Pnative -DskipTests

नेटिव इमेज बिल्ड लॉग के साथ-साथ टर्मिनल में बिल्ड लॉग को देखें:

ध्यान दें कि बिल्ड में काफ़ी ज़्यादा समय लगता है. यह इस बात पर निर्भर करता है कि किस मशीन पर टेस्ट किया जा रहा है.

...
[2/7] Performing analysis...  [**********]                                                              (95.4s @ 3.57GB)
  23,346 (94.42%) of 24,725 classes reachable
  44,625 (68.71%) of 64,945 fields reachable
 163,759 (70.79%) of 231,322 methods reachable
     989 classes, 1,402 fields, and 11,032 methods registered for reflection
      63 classes,    69 fields, and    55 methods registered for JNI access
       5 native libraries: -framework CoreServices, -framework Foundation, dl, pthread, z
[3/7] Building universe...                                                                              (10.0s @ 5.35GB)
[4/7] Parsing methods...      [***]                                                                      (9.7s @ 3.13GB)
[5/7] Inlining methods...     [***]                                                                      (4.5s @ 3.29GB)
[6/7] Compiling methods...    [[6/7] Compiling methods...    [********]                                                                (67.6s @ 5.72GB)
[7/7] Creating image...                                                                                  (8.7s @ 4.59GB)
  62.21MB (54.80%) for code area:   100,371 compilation units
  50.98MB (44.91%) for image heap:  465,035 objects and 365 resources
 337.09KB ( 0.29%) for other data
 113.52MB in total
------------------------------------------------------------------------------------------------------------------------
Top 10 packages in code area:                               Top 10 object types in image heap:
   2.36MB com.google.protobuf                                 12.70MB byte[] for code metadata
   1.90MB i.g.xds.shaded.io.envoyproxy.envoy.config.core.v3    6.66MB java.lang.Class
   1.73MB i.g.x.shaded.io.envoyproxy.envoy.config.route.v3     6.47MB byte[] for embedded resources
   1.67MB sun.security.ssl                                     4.61MB byte[] for java.lang.String
   1.54MB com.google.cloud.vision.v1                           4.37MB java.lang.String
   1.46MB com.google.firestore.v1                              3.38MB byte[] for general heap data
   1.37MB io.grpc.xds.shaded.io.envoyproxy.envoy.api.v2.core   1.96MB com.oracle.svm.core.hub.DynamicHubCompanion
   1.32MB i.g.xds.shaded.io.envoyproxy.envoy.api.v2.route      1.80MB byte[] for reflection metadata
   1.09MB java.util                                          911.80KB java.lang.String[]
   1.08MB com.google.re2j                                    826.48KB c.o.svm.core.hub.DynamicHub$ReflectionMetadata
  45.91MB for 772 more packages                                6.45MB for 3913 more object types
------------------------------------------------------------------------------------------------------------------------
                        15.1s (6.8% of total time) in 56 GCs | Peak RSS: 7.72GB | CPU load: 4.37
------------------------------------------------------------------------------------------------------------------------
Produced artifacts:
 /Users/ddobrin/work/dan/serverless-photosharing-workshop/services/image-analysis/java/target/image-analysis (executable)
 /Users/ddobrin/work/dan/serverless-photosharing-workshop/services/image-analysis/java/target/image-analysis.build_artifacts.txt (txt)
========================================================================================================================
Finished generating 'image-analysis' in 3m 41s.
[INFO] ------------------------------------------------------------------------
[INFO] BUILD SUCCESS
[INFO] ------------------------------------------------------------------------
[INFO] Total time:  03:56 min
[INFO] Finished at: 2022-09-26T22:22:29-04:00
[INFO] ------------------------------------------------------------------------

11. कंटेनर की इमेज बनाएं और पब्लिश करें

चलिए, दो अलग-अलग वर्शन में कंटेनर इमेज बनाते हैं: एक JIT(JVM) image के तौर पर और दूसरी AOT(Native) Java image के तौर पर.

सबसे पहले, GCP प्रोजेक्ट के एनवायरमेंट वैरिएबल सेट करें:

export GOOGLE_CLOUD_PROJECT=$(gcloud config get-value project)

JIT(JVM) इमेज बनाएं:.

./mvnw package -Pjvm-image

टर्मिनल में बिल्ड लॉग देखें:

[INFO]     [creator]     Adding layer 'process-types'
[INFO]     [creator]     Adding label 'io.buildpacks.lifecycle.metadata'
[INFO]     [creator]     Adding label 'io.buildpacks.build.metadata'
[INFO]     [creator]     Adding label 'io.buildpacks.project.metadata'
[INFO]     [creator]     Adding label 'org.opencontainers.image.title'
[INFO]     [creator]     Adding label 'org.opencontainers.image.version'
[INFO]     [creator]     Adding label 'org.springframework.boot.version'
[INFO]     [creator]     Setting default process type 'web'
[INFO]     [creator]     Saving docker.io/library/image-analysis-jvm:r17...
[INFO]     [creator]     *** Images (03a44112456e):
[INFO]     [creator]           docker.io/library/image-analysis-jvm:r17
[INFO]     [creator]     Adding cache layer 'paketo-buildpacks/syft:syft'
[INFO]     [creator]     Adding cache layer 'cache.sbom'
[INFO] 
[INFO] Successfully built image 'docker.io/library/image-analysis-jvm:r17'
[INFO] 
[INFO] ------------------------------------------------------------------------
[INFO] BUILD SUCCESS
[INFO] ------------------------------------------------------------------------
[INFO] Total time:  02:11 min
[INFO] Finished at: 2022-09-26T13:09:34-04:00
[INFO] ------------------------------------------------------------------------

एओटी(नेटिव) इमेज बनाएं:.

./mvnw package -Pnative-image

टर्मिनल में बिल्ड लॉग को देखें. इसमें UPX का इस्तेमाल करके, नेटिव इमेज बिल्ड लॉग और इमेज को कंप्रेस करने की सुविधा भी शामिल है.

ध्यान दें कि बिल्ड में काफ़ी ज़्यादा समय लगता है. यह इस बात पर निर्भर करता है कि किस मशीन पर टेस्ट किया जा रहा है

...
[INFO]     [creator]     [2/7] Performing analysis...  [***********]                    (147.6s @ 3.10GB)
[INFO]     [creator]       23,362 (94.34%) of 24,763 classes reachable
[INFO]     [creator]       44,657 (68.67%) of 65,029 fields reachable
[INFO]     [creator]      163,926 (70.76%) of 231,656 methods reachable
[INFO]     [creator]          981 classes, 1,402 fields, and 11,026 methods registered for reflection
[INFO]     [creator]           63 classes,    68 fields, and    55 methods registered for JNI access
[INFO]     [creator]            4 native libraries: dl, pthread, rt, z
[INFO]     [creator]     [3/7] Building universe...                                      (21.1s @ 2.66GB)
[INFO]     [creator]     [4/7] Parsing methods...      [****]                            (13.7s @ 4.16GB)
[INFO]     [creator]     [5/7] Inlining methods...     [***]                              (9.6s @ 4.20GB)
[INFO]     [creator]     [6/7] Compiling methods...    [**********]                     (107.6s @ 3.36GB)
[INFO]     [creator]     [7/7] Creating image...                                         (14.7s @ 4.87GB)
[INFO]     [creator]       62.24MB (51.35%) for code area:   100,499 compilation units
[INFO]     [creator]       51.99MB (42.89%) for image heap:  473,948 objects and 473 resources
[INFO]     [creator]        6.98MB ( 5.76%) for other data
[INFO]     [creator]      121.21MB in total
[INFO]     [creator]     --------------------------------------------------------------------------------
[INFO]     [creator]     Top 10 packages in code area:           Top 10 object types in image heap:
[INFO]     [creator]        2.36MB com.google.protobuf             12.71MB byte[] for code metadata
[INFO]     [creator]        1.90MB i.g.x.s.i.e.e.config.core.v3     7.59MB byte[] for embedded resources
[INFO]     [creator]        1.73MB i.g.x.s.i.e.e.config.route.v3    6.66MB java.lang.Class
[INFO]     [creator]        1.67MB sun.security.ssl                 4.62MB byte[] for java.lang.String
[INFO]     [creator]        1.54MB com.google.cloud.vision.v1       4.39MB java.lang.String
[INFO]     [creator]        1.46MB com.google.firestore.v1          3.66MB byte[] for general heap data
[INFO]     [creator]        1.37MB i.g.x.s.i.e.envoy.api.v2.core    1.96MB c.o.s.c.h.DynamicHubCompanion
[INFO]     [creator]        1.32MB i.g.x.s.i.e.e.api.v2.route       1.80MB byte[] for reflection metadata
[INFO]     [creator]        1.09MB java.util                      910.41KB java.lang.String[]
[INFO]     [creator]        1.08MB com.google.re2j                826.95KB c.o.s.c.h.DynamicHu~onMetadata
[INFO]     [creator]       45.94MB for 776 more packages            6.69MB for 3916 more object types
[INFO]     [creator]     --------------------------------------------------------------------------------
[INFO]     [creator]         20.4s (5.6% of total time) in 81 GCs | Peak RSS: 6.75GB | CPU load: 4.53
[INFO]     [creator]     --------------------------------------------------------------------------------
[INFO]     [creator]     Produced artifacts:
[INFO]     [creator]      /layers/paketo-buildpacks_native-image/native-image/services.ImageAnalysisApplication (executable)
[INFO]     [creator]      /layers/paketo-buildpacks_native-image/native-image/services.ImageAnalysisApplication.build_artifacts.txt (txt)
[INFO]     [creator]     ================================================================================
[INFO]     [creator]     Finished generating '/layers/paketo-buildpacks_native-image/native-image/services.ImageAnalysisApplication' in 5m 59s.
[INFO]     [creator]         Executing upx to compress native image
[INFO]     [creator]                            Ultimate Packer for eXecutables
[INFO]     [creator]                               Copyright (C) 1996 - 2020
[INFO]     [creator]     UPX 3.96        Markus Oberhumer, Laszlo Molnar & John Reiser   Jan 23rd 2020
[INFO]     [creator]     
[INFO]     [creator]             File size         Ratio      Format      Name
[INFO]     [creator]        --------------------   ------   -----------   -----------
 127099880 ->  32416676   25.50%   linux/amd64   services.ImageAnalysisApplication
...
[INFO]     [creator]     ===> EXPORTING
...
[INFO]     [creator]     Adding cache layer 'paketo-buildpacks/native-image:native-image'
[INFO]     [creator]     Adding cache layer 'cache.sbom'
[INFO] 
[INFO] Successfully built image 'docker.io/library/image-analysis-native:r17'
------------------------------------------------------------------------
[INFO] BUILD SUCCESS
[INFO] ------------------------------------------------------------------------
[INFO] Total time:  05:28 min
[INFO] Finished at: 2022-09-26T13:19:53-04:00
[INFO] ------------------------------------------------------------------------

पुष्टि करें कि इमेज बन गई हैं:

docker images | grep image-analysis

दोनों इमेज को GCR में टैग करें और पुश करें:

# JIT(JVM) image
docker tag image-analysis-jvm:r17 gcr.io/${GOOGLE_CLOUD_PROJECT}/image-analysis-jvm:r17
docker push gcr.io/${GOOGLE_CLOUD_PROJECT}/image-analysis-jvm:r17

# AOT(Native) image
docker tag image-analysis-native:r17 gcr.io/${GOOGLE_CLOUD_PROJECT}/image-analysis-native:r17
docker push  gcr.io/${GOOGLE_CLOUD_PROJECT}/image-analysis-native:r17

12. Cloud Run पर डिप्लॉय करें

सेवा को लागू करने का समय.

आपको दो बार सेवा डिप्लॉय करनी होगी. पहली बार, जेआईटी(जेवीएम) इमेज का इस्तेमाल करके और दूसरी बार एओटी(नेटिव) इमेज का इस्तेमाल करके. तुलना के मकसद से, दोनों सर्विस डिप्लॉयमेंट में बकेट से एक ही इमेज को साथ-साथ प्रोसेस करेंगे.

सबसे पहले, GCP प्रोजेक्ट के एनवायरमेंट वैरिएबल सेट करें:

export GOOGLE_CLOUD_PROJECT=$(gcloud config get-value project)
gcloud config set project ${GOOGLE_CLOUD_PROJECT}
gcloud config set run/region 
gcloud config set run/platform managed
gcloud config set eventarc/location europe-west1

JIT(JVM) इमेज को डिप्लॉय करें और कंसोल में डिप्लॉयमेंट लॉग देखें:

gcloud run deploy image-analysis-jvm \
     --image gcr.io/${GOOGLE_CLOUD_PROJECT}/image-analysis-jvm:r17 \
     --region europe-west1 \
     --memory 2Gi --allow-unauthenticated

...
Deploying container to Cloud Run service [image-analysis-jvm] in project [...] region [europe-west1]
✓ Deploying... Done.                                                                                                                                                               
  ✓ Creating Revision...                                                                                                                                                           
  ✓ Routing traffic...                                                                                                                                                             
  ✓ Setting IAM Policy...                                                                                                                                                          
Done.                                                                                                                                                                              
Service [image-analysis-jvm] revision [image-analysis-jvm-00009-huc] has been deployed and is serving 100 percent of traffic.
Service URL: https://image-analysis-jvm-...-ew.a.run.app

एओटी(नेटिव) इमेज डिप्लॉय करें और कंसोल में डिप्लॉयमेंट लॉग देखें:

gcloud run deploy image-analysis-native \
     --image gcr.io/${GOOGLE_CLOUD_PROJECT}/image-analysis-native:r17 \
     --region europe-west1 \
     --memory 2Gi --allow-unauthenticated 
...
Deploying container to Cloud Run service [image-analysis-native] in project [...] region [europe-west1]
✓ Deploying... Done.                                                                                                                                                               
  ✓ Creating Revision...                                                                                                                                                           
  ✓ Routing traffic...                                                                                                                                                             
  ✓ Setting IAM Policy...                                                                                                                                                          
Done.                                                                                                                                                                              
Service [image-analysis-native] revision [image-analysis-native-00005-ben] has been deployed and is serving 100 percent of traffic.
Service URL: https://image-analysis-native-...-ew.a.run.app

13. Eventarc ट्रिगर सेट अप करें

Eventarc अलग-अलग माइक्रोसेवाओं के बीच, राज्य में होने वाले बदलावों को मैनेज करने के लिए एक स्टैंडर्ड सलूशन उपलब्ध कराता है. इस प्रोसेस को इवेंट कहा जाता है. ट्रिगर किए जाने पर, Eventarc इन इवेंट को Pub/Sub सदस्यताओं के ज़रिए अलग-अलग डेस्टिनेशन (इस दस्तावेज़ में, इवेंट डेस्टिनेशन देखें) पर रूट करता है. साथ ही, यह आपके लिए डिलीवरी, सुरक्षा, अनुमति, निगरानी करने की सुविधा, और गड़बड़ियों को मैनेज करता है.

आप Eventarc ट्रिगर बना सकते हैं, ताकि आपकी Cloud Run सेवा को किसी खास इवेंट या इवेंट के सेट की सूचनाएं मिलें. ट्रिगर के लिए फ़िल्टर तय करके, इवेंट की रूटिंग को कॉन्फ़िगर किया जा सकता है. इसमें इवेंट का सोर्स और टारगेट Cloud Run सेवा भी शामिल है.

सबसे पहले, GCP प्रोजेक्ट के एनवायरमेंट वैरिएबल सेट करें:

export GOOGLE_CLOUD_PROJECT=$(gcloud config get-value project)
gcloud config set project ${GOOGLE_CLOUD_PROJECT}
gcloud config set run/region 
gcloud config set run/platform managed
gcloud config set eventarc/location europe-west1

Cloud Storage सेवा खाते को pubsub.publisher दें:

SERVICE_ACCOUNT="$(gsutil kms serviceaccount -p ${GOOGLE_CLOUD_PROJECT})"

gcloud projects add-iam-policy-binding ${GOOGLE_CLOUD_PROJECT} \
    --member="serviceAccount:${SERVICE_ACCOUNT}" \
    --role='roles/pubsub.publisher'

इमेज प्रोसेस करने के लिए, JVM(JIT) और एओटी(नेटिव) सेवा की इमेज, दोनों के लिए Eventarc ट्रिगर सेट अप करें:

gcloud eventarc triggers list --location=eu

gcloud eventarc triggers create image-analysis-jvm-trigger \
     --destination-run-service=image-analysis-jvm \
     --destination-run-region=europe-west1 \
     --location=eu \
     --event-filters="type=google.cloud.storage.object.v1.finalized" \
     --event-filters="bucket=uploaded-pictures-${GOOGLE_CLOUD_PROJECT}" \
     --service-account=${PROJECT_NUMBER}-compute@developer.gserviceaccount.com

gcloud eventarc triggers create image-analysis-native-trigger \
     --destination-run-service=image-analysis-native \
     --destination-run-region=europe-west1 \
     --location=eu \
     --event-filters="type=google.cloud.storage.object.v1.finalized" \
     --event-filters="bucket=uploaded-pictures-${GOOGLE_CLOUD_PROJECT}" \
     --service-account=${PROJECT_NUMBER}-compute@developer.gserviceaccount.com    

देखें कि दोनों ट्रिगर बनाए गए हैं:

gcloud eventarc triggers list --location=eu

14. परीक्षण सेवा वर्शन

सेवा के डिप्लॉयमेंट की प्रोसेस पूरी होने के बाद, आपको Cloud Storage में एक तस्वीर पोस्ट करनी होगी. साथ ही, आपको यह पता करना होगा कि हमारी सेवाएं चालू हुई हैं या नहीं, Vision API ने क्या दिखाया है, और क्या डेटा Firestore में सेव हो गया है.

Cloud Storage पर वापस जाएं और उस बकेट पर क्लिक करें जो हमने लैब की शुरुआत में बनाई थी:

ff8a6567afc76235.png

बकेट की ज़्यादा जानकारी वाले पेज पर जाने के बाद, तस्वीर अपलोड करने के लिए Upload files बटन पर क्लिक करें.

उदाहरण के लिए, /services/image-analysis/java के तहत आपके कोड बेस के साथ एक GeekHour.jpeg इमेज दी जाती है. कोई इमेज चुनें और Open button दबाएं:

347b76e8b775f2f5.png

अब आपके पास सेवा के लागू होने की जांच करने का विकल्प है. इसकी शुरुआत image-analysis-jvm से होती है और इसके बाद image-analysis-native आती है.

"हैमबर्गर" से (भरोसेमंद) मेन्यू, Cloud Run > image-analysis-jvm सेवा पर जाएं.

लॉग पर क्लिक करें और आउटपुट देखें:

810a8684414ceafa.png

लॉग की सूची में देखा जा सकता है कि JIT(JVM) सेवा image-analysis-jvm को शुरू किया गया था.

लॉग, सेवा के चलने और उसके खत्म होने के बारे में बताते हैं. साथ ही, इनके बीच में हम लॉग स्टेटमेंट के साथ उन लॉग को देख सकते हैं जिन्हें हमने फ़ंक्शन में शामिल किया है. यह जानकारी, INFO के स्तर पर देखी जा सकती है. हम देखते हैं:

  • हमारे फ़ंक्शन को ट्रिगर करने वाले इवेंट का ब्यौरा,
  • Vision API कॉल से मिले रॉ नतीजे,
  • हमारी अपलोड की गई तस्वीर में मिले लेबल,
  • रंगों की मुख्य जानकारी,
  • क्या तस्वीर सुरक्षित है या नहीं,
  • आखिर में, तस्वीर से जुड़ा वह मेटाडेटा Firestore में सेव कर दिया जाता है.

image-analysis-native सेवा के लिए यह प्रोसेस दोहराई जाएगी.

"हैमबर्गर" से (भरोसेमंद) मेन्यू, Cloud Run > image-analysis-native सेवा पर जाएं.

लॉग पर क्लिक करें और आउटपुट देखें:

b80308c7d0f55a3.png

अब आपको यह देखना होगा कि इमेज का मेटाडेटा, Fiorestore में स्टोर हुआ है या नहीं.

"हैमबर्गर" से फिर से (RECORD) मेन्यू, Firestore सेक्शन पर जाएं. Data सब-सेक्शन (डिफ़ॉल्ट रूप से दिखाया जाता है) में, आपको pictures कलेक्शन दिखेगा. इसमें एक नया दस्तावेज़ जोड़ा गया है. यह कलेक्शन, आपकी अपलोड की गई तस्वीर से जुड़ा होगा:

933a20a9709cb006.png

15. स्टोरेज खाली करें (ज़रूरी नहीं)

अगर आपको सीरीज़ में मौजूद अन्य लैब का इस्तेमाल जारी नहीं रखना है, तो संसाधनों को इकट्ठा करके खर्च बचाया जा सकता है और क्लाउड पर अच्छा नागरिक बनाया जा सकता है. यहां बताए गए तरीके से, अलग-अलग संसाधनों को खाली किया जा सकता है.

बकेट मिटाना:

gsutil rb gs://${BUCKET_PICTURES}

फ़ंक्शन मिटाएं:

gcloud functions delete picture-uploaded --region europe-west1 -q

कलेक्शन से कलेक्शन मिटाएं को चुनकर, Firestore कलेक्शन मिटाएं:

410b551c3264f70a.png

इसके अलावा, पूरा प्रोजेक्ट मिटाया जा सकता है:

gcloud projects delete ${GOOGLE_CLOUD_PROJECT} 

16. बधाई हो!

बधाई हो! आपने इस प्रोजेक्ट की पहली कुंजी मैनेज करने वाली सेवा को लागू कर दिया है!

इसमें हमने इन विषयों के बारे में बताया

  • Cloud Storage
  • Cloud Run
  • क्लाउड विज़न एपीआई
  • Cloud Firestore
  • स्थानीय Java इमेज

अगले चरण