हर दिन फ़ोटो लेना: Lab 1—तस्वीरों को स्टोर करें और उनका विश्लेषण करें

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

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

d650ca5386ea71ad.png

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

  • Cloud Storage
  • Cloud Functions
  • क्लाउड विज़न एपीआई
  • 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 Functions भी चालू करें:

gcloud services enable cloudfunctions.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. फ़ंक्शन बनाएं

इस चरण में, एक ऐसा फ़ंक्शन बनाया जाता है जो फ़ोटो के अपलोड किए गए इवेंट पर प्रतिक्रिया देता है.

Google Cloud Console के Cloud Functions सेक्शन पर जाएं. इस पेज पर जाने पर, Cloud Functions सेवा अपने-आप चालू हो जाएगी.

9d29e8c026a7a53f.png

Create function पर क्लिक करें.

कोई नाम चुनें (जैसे, picture-uploaded) और इलाका (बकेट के लिए क्षेत्र के विकल्प को ध्यान में रखें):

4bb222633e6f278.png

फ़ंक्शन दो तरह के होते हैं:

  • ऐसे एचटीटीपी फ़ंक्शन जिन्हें यूआरएल (जैसे, वेब एपीआई) के ज़रिए शुरू किया जा सकता है.
  • बैकग्राउंड फ़ंक्शन, जो किसी इवेंट से ट्रिगर हो सकते हैं.

आपको ऐसा बैकग्राउंड फ़ंक्शन बनाना है जो हमारे Cloud Storage बकेट में किसी नई फ़ाइल के अपलोड होने पर ट्रिगर होता है:

d9a12fcf58f4813c.png

आपको Finalize/Create इवेंट टाइप में दिलचस्पी है. यह इवेंट तब ट्रिगर होता है, जब बकेट में कोई फ़ाइल बनाई जाती है या अपडेट की जाती है:

b30c8859b07dc4cb.png

किसी फ़ाइल के बनाए जाने या अपडेट किए जाने पर Cloud Functions को सूचना देने के लिए, पहले बनाया गया बकेट चुनें:

cb15a1f4c7a1ca5f.png

पहले बनाया गया बकेट चुनने के लिए, Select पर क्लिक करें. इसके बाद, Save पर क्लिक करें

c1933777fac32c6a.png

'आगे बढ़ें' पर क्लिक करने से पहले, रनटाइम, बिल्ड, कनेक्शन, और सुरक्षा सेटिंग में जाकर, डिफ़ॉल्ट स्टोरेज (256 एमबी) को बड़ा करके उसमें बदलाव किया जा सकता है. साथ ही, उसे 1 जीबी पर अपडेट किया जा सकता है.

83d757e6c38e10.png

Next पर क्लिक करने के बाद, रनटाइम, सोर्स कोड, और एंट्री पॉइंट को ट्यून किया जा सकता है.

इस फ़ंक्शन के लिए Inline editor को बनाए रखें:

7dccb5a3fa66363d.png

Node.js के रनटाइम में से कोई एक चुनें:

21defc3b0accd5b4.png

सोर्स कोड में एक index.js JavaScript फ़ाइल होती है. साथ ही, एक package.json फ़ाइल होती है, जो कई तरह का मेटाडेटा और डिपेंडेंसी उपलब्ध कराती है.

कोड का डिफ़ॉल्ट स्निपेट छोड़ें: यह अपलोड की गई फ़ोटो का फ़ाइल नाम लॉग करता है:

465aca96eb8ca5f9.png

फ़िलहाल, टेस्टिंग के लिए, फ़ंक्शन के नाम को helloGCS में एक्ज़ीक्यूट करें.

फ़ंक्शन बनाने और डिप्लॉय करने के लिए, Deploy पर क्लिक करें. डिप्लॉयमेंट पूरा हो जाने के बाद, आपको फ़ंक्शन की सूची में हरे रंग के सर्कल वाला सही का निशान दिखेगा:

e9d78025d16651aa.png

8. फ़ंक्शन की जांच करें

इस चरण में, देखें कि फ़ंक्शन, स्टोरेज इवेंट का जवाब देता है या नहीं.

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

इमेज अपलोड करने के लिए, इमेज बकेट पर क्लिक करें. इसके बाद, Upload files पर क्लिक करें.

21767ec3cb8b18de.png

Logging > Logs Explorer पेज पर जाने के लिए, Cloud Console में फिर से नेविगेट करें.

Log Fields सिलेक्टर में, अपने फ़ंक्शन के लिए खास तौर पर बनाए गए लॉग देखने के लिए Cloud Function चुनें. लॉग फ़ील्ड में नीचे की ओर स्क्रोल करें. इसके बाद, किसी फ़ंक्शन को चुनकर, फ़ंक्शन से जुड़े लॉग को बारीकी से देखें. picture-uploaded फ़ंक्शन चुनें.

आपको लॉग आइटम दिखेंगे. इनमें फ़ंक्शन के बनने की जानकारी, फ़ंक्शन के शुरू और खत्म होने का समय, और हमारा असल लॉग स्टेटमेंट दिखना चाहिए:

e8ba7d39c36df36c.png

हमारे लॉग स्टेटमेंट में यह बताया गया है: Processing file: pic-a-daily-architecture-events.png. इसका मतलब है कि इस फ़ोटो को बनाए जाने और सेव करने से जुड़ा इवेंट, उम्मीद के मुताबिक ट्रिगर हुआ है.

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

आपको 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 पर क्लिक करें. इंडेक्स बनाने में कुछ मिनट लग सकते हैं.

10. फ़ंक्शन को अपडेट करें

फ़ंक्शन को अपडेट करने के लिए, Functions पेज पर वापस जाएं, ताकि हमारी तस्वीरों का विश्लेषण करने के लिए Vision API को शुरू किया जा सके. साथ ही, Firestore में मेटाडेटा स्टोर किया जा सके.

"हैमबर्गर" से (IAB) मेन्यू में जाकर, Cloud Functions सेक्शन पर जाएं. इसके बाद, फ़ंक्शन के नाम पर क्लिक करें और Source टैब चुनें. इसके बाद, EDIT बटन पर क्लिक करें.

सबसे पहले, package.json फ़ाइल में बदलाव करें. इसमें हमारे Node.JS फ़ंक्शन की डिपेंडेंसी की सूची बनाएं. Cloud Vision API NPM डिपेंडेंसी जोड़ने के लिए कोड अपडेट करें:

{
  "name": "picture-analysis-function",
  "version": "0.0.1",
  "dependencies": {
    "@google-cloud/storage": "^1.6.0",
    "@google-cloud/vision": "^1.8.0",
    "@google-cloud/firestore": "^3.4.1"
  }
}

डिपेंडेंसी अप-टू-डेट है, इसलिए index.js फ़ाइल को अपडेट करके, हमारे फ़ंक्शन के कोड पर काम किया जा रहा है.

index.js में मौजूद कोड को नीचे दिए गए कोड से बदलें. इसके बारे में अगले चरण में बताया जाएगा.

const vision = require('@google-cloud/vision');
const Storage = require('@google-cloud/storage');
const Firestore = require('@google-cloud/firestore');

const client = new vision.ImageAnnotatorClient();

exports.vision_analysis = async (event, context) => {
    console.log(`Event: ${JSON.stringify(event)}`);

    const filename = event.name;
    const filebucket = event.bucket;

    console.log(`New picture uploaded ${filename} in ${filebucket}`);

    const request = {
        image: { source: { imageUri: `gs://${filebucket}/${filename}` } },
        features: [
            { type: 'LABEL_DETECTION' },
            { type: 'IMAGE_PROPERTIES' },
            { type: 'SAFE_SEARCH_DETECTION' }
        ]
    };

    // invoking the Vision API
    const [response] = await client.annotateImage(request);
    console.log(`Raw vision output for: ${filename}: ${JSON.stringify(response)}`);

    if (response.error === null) {
        // listing the labels found in the picture
        const labels = response.labelAnnotations
            .sort((ann1, ann2) => ann2.score - ann1.score)
            .map(ann => ann.description)
        console.log(`Labels: ${labels.join(', ')}`);

        // retrieving the dominant color of the picture
        const color = response.imagePropertiesAnnotation.dominantColors.colors
            .sort((c1, c2) => c2.score - c1.score)[0].color;
        const colorHex = decColorToHex(color.red, color.green, color.blue);
        console.log(`Colors: ${colorHex}`);

        // determining if the picture is safe to show
        const safeSearch = response.safeSearchAnnotation;
        const isSafe = ["adult", "spoof", "medical", "violence", "racy"].every(k => 
            !['LIKELY', 'VERY_LIKELY'].includes(safeSearch[k]));
        console.log(`Safe? ${isSafe}`);

        // if the picture is safe to display, store it in Firestore
        if (isSafe) {
            const pictureStore = new Firestore().collection('pictures');
            
            const doc = pictureStore.doc(filename);
            await doc.set({
                labels: labels,
                color: colorHex,
                created: Firestore.Timestamp.now()
            }, {merge: true});

            console.log("Stored metadata in Firestore");
        }
    } else {
        throw new Error(`Vision API error: code ${response.error.code}, message: "${response.error.message}"`);
    }
};

function decColorToHex(r, g, b) {
    return '#' + Number(r).toString(16).padStart(2, '0') + 
                 Number(g).toString(16).padStart(2, '0') + 
                 Number(b).toString(16).padStart(2, '0');
}

11. फ़ंक्शन को एक्सप्लोर करें

आइए, इन दिलचस्प हिस्सों के बारे में गहराई से जानते हैं.

सबसे पहले, हमें विज़न, स्टोरेज, और Firestore के लिए ज़रूरी मॉड्यूल ज़रूरी हैं:

const vision = require('@google-cloud/vision');
const Storage = require('@google-cloud/storage');
const Firestore = require('@google-cloud/firestore');

इसके बाद, हम Vision API के लिए क्लाइंट तैयार करते हैं:

const client = new vision.ImageAnnotatorClient();

अब हमारे काम के स्ट्रक्चर की बात करते हैं. हम इसे एक एसिंक्रोनस फ़ंक्शन बनाते हैं, क्योंकि हम Node.js 8 में शुरू की गई async / Await क्षमताओं का इस्तेमाल कर रहे हैं:

exports.vision_analysis = async (event, context) => {
    ...
    const filename = event.name;
    const filebucket = event.bucket;
    ...
}

हस्ताक्षर पर ध्यान दें. साथ ही, यह भी देखें कि हम Cloud फ़ंक्शन को ट्रिगर करने वाली फ़ाइल और बकेट का नाम कैसे पता करते हैं.

यहां बताया गया है कि इवेंट पेलोड कैसा दिखता है:

{
  "bucket":"uploaded-pictures",
  "contentType":"image/png",
  "crc32c":"efhgyA==",
  "etag":"CKqB956MmucCEAE=",
  "generation":"1579795336773802",
  "id":"uploaded-pictures/Screenshot.png/1579795336773802",
  "kind":"storage#object",
  "md5Hash":"PN8Hukfrt6C7IyhZ8d3gfQ==",
  "mediaLink":"https://www.googleapis.com/download/storage/v1/b/uploaded-pictures/o/Screenshot.png?generation=1579795336773802&alt=media",
  "metageneration":"1",
  "name":"Screenshot.png",
  "selfLink":"https://www.googleapis.com/storage/v1/b/uploaded-pictures/o/Screenshot.png",
  "size":"173557",
  "storageClass":"STANDARD",
  "timeCreated":"2020-01-23T16:02:16.773Z",
  "timeStorageClassUpdated":"2020-01-23T16:02:16.773Z",
  "updated":"2020-01-23T16:02:16.773Z"
}

हम Vision क्लाइंट के ज़रिए ईमेल भेजने के लिए एक अनुरोध तैयार करते हैं:

const request = {
    image: { source: { imageUri: `gs://${filebucket}/${filename}` } },
    features: [
        { type: 'LABEL_DETECTION' },
        { type: 'IMAGE_PROPERTIES' },
        { type: 'SAFE_SEARCH_DETECTION' }
    ]
};

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

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

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

const [response] = await client.annotateImage(request);

रेफ़रंस के लिए, 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 (response.error === null) {
    ...
} else {
    throw new Error(`Vision API error: code ${response.error.code},  
                     message: "${response.error.message}"`);
}

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

const labels = response.labelAnnotations
    .sort((ann1, ann2) => ann2.score - ann1.score)
    .map(ann => ann.description)

हम लेबल को सबसे ज़्यादा स्कोर के हिसाब से क्रम में लगा रहे हैं.

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

const color = response.imagePropertiesAnnotation.dominantColors.colors
    .sort((c1, c2) => c2.score - c1.score)[0].color;
const colorHex = decColorToHex(color.red, color.green, color.blue);

हम फिर से स्कोर के हिसाब से कलर क्रम में लगाने की कोशिश कर रहे हैं. पहला, स्कोर के हिसाब से.

हम लाल / हरे / नीले मानों को हेक्साडेसिमल कलर कोड में बदलने के लिए एक यूटिलिटी फ़ंक्शन का इस्तेमाल कर रहे हैं जिसका इस्तेमाल हम सीएसएस स्टाइलशीट में कर सकते हैं.

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

const safeSearch = response.safeSearchAnnotation;
const isSafe = ["adult", "spoof", "medical", "violence", "racy"]
    .every(k => !['LIKELY', 'VERY_LIKELY'].includes(safeSearch[k]));

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

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

if (isSafe) {
    const pictureStore = new Firestore().collection('pictures');
            
    const doc = pictureStore.doc(filename);
    await doc.set({
        labels: labels,
        color: colorHex,
        created: Firestore.Timestamp.now()
    }, {merge: true});
}

12. फ़ंक्शन को डिप्लॉय करें

फ़ंक्शन को डिप्लॉय करने का समय.

274c1e2fca6c0bd9.png

DEPLOY बटन दबाएं और नया वर्शन डिप्लॉय हो जाएगा. प्रोग्रेस देखी जा सकती है:

4e0ac812a9124e7c.png

13. फ़ंक्शन को फिर से टेस्ट करें

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

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

d44c1584122311c7.png

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

26bb31d35fb6aa3d.png

"हैमबर्गर" से (RECORD) मेन्यू, Logging > Logs एक्सप्लोरर पर जाएं.

Log Fields सिलेक्टर में, अपने फ़ंक्शन के लिए खास तौर पर बनाए गए लॉग देखने के लिए Cloud Function चुनें. लॉग फ़ील्ड में नीचे की ओर स्क्रोल करें. इसके बाद, किसी फ़ंक्शन को चुनकर, फ़ंक्शन से जुड़े लॉग को बारीकी से देखें. picture-uploaded फ़ंक्शन चुनें.

b651dca7e25d5b11.png

लॉग की सूची में, यह देखा जा सकता है कि हमारे फ़ंक्शन को शुरू किया गया था:

d22a7f24954e4f63.png

लॉग, फ़ंक्शन के चलने के शुरू और खत्म होने के बारे में बताते हैं. साथ ही, इन दोनों के बीच में हम console.log() स्टेटमेंट की मदद से अपने फ़ंक्शन में डाले गए लॉग देख सकते हैं. हम देखते हैं:

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

9ff7956a215c15da.png

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

a6137ab9687da370.png

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

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

बकेट मिटाना:

gsutil rb gs://${BUCKET_PICTURES}

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

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

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

410b551c3264f70a.png

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

gcloud projects delete ${GOOGLE_CLOUD_PROJECT} 

15. बधाई हो!

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

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

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

अगले चरण