১. সংক্ষিপ্ত বিবরণ
প্রথম কোড ল্যাবে, আপনি একটি বাকেটে ছবি সংরক্ষণ করবেন। এর ফলে একটি ফাইল তৈরির ইভেন্ট তৈরি হবে, যা ক্লাউড রানে ডেপ্লয় করা একটি সার্ভিস দ্বারা পরিচালিত হবে। সার্ভিসটি ইমেজ অ্যানালাইসিস করার জন্য ভিশন এপিআই-কে কল করবে এবং ফলাফল একটি ডেটাস্টোরে সংরক্ষণ করবে।

আপনি যা শিখবেন
- ক্লাউড স্টোরেজ
- ক্লাউড রান
- ক্লাউড ভিশন এপিআই
- ক্লাউড ফায়ারস্টোর
২. সেটআপ এবং প্রয়োজনীয়তা
স্ব-গতিতে পরিবেশ সেটআপ
- Google Cloud Console- এ সাইন-ইন করুন এবং একটি নতুন প্রজেক্ট তৈরি করুন অথবা বিদ্যমান কোনো প্রজেক্ট পুনরায় ব্যবহার করুন। যদি আপনার আগে থেকে Gmail বা Google Workspace অ্যাকাউন্ট না থাকে, তবে আপনাকে অবশ্যই একটি তৈরি করতে হবে।



- প্রজেক্টের নামটি হলো এই প্রজেক্টের অংশগ্রহণকারীদের প্রদর্শিত নাম। এটি একটি ক্যারেক্টার স্ট্রিং যা গুগল এপিআই ব্যবহার করে না। আপনি যেকোনো সময় এটি আপডেট করতে পারেন।
- প্রজেক্ট আইডি সমস্ত গুগল ক্লাউড প্রজেক্ট জুড়ে অনন্য এবং অপরিবর্তনীয় (একবার সেট করার পর এটি পরিবর্তন করা যায় না)। ক্লাউড কনসোল স্বয়ংক্রিয়ভাবে একটি অনন্য স্ট্রিং তৈরি করে; সাধারণত এটি কী তা নিয়ে আপনার মাথা ঘামানোর দরকার নেই। বেশিরভাগ কোডল্যাবে, আপনাকে আপনার প্রজেক্ট আইডি উল্লেখ করতে হবে (যা সাধারণত
PROJECT_IDহিসাবে চিহ্নিত করা হয়)। তৈরি করা আইডিটি আপনার পছন্দ না হলে, আপনি এলোমেলোভাবে আরেকটি তৈরি করতে পারেন। বিকল্পভাবে, আপনি আপনার নিজের আইডি দিয়ে চেষ্টা করে দেখতে পারেন যে সেটি উপলব্ধ আছে কিনা। এই ধাপের পরে এটি পরিবর্তন করা যাবে না এবং প্রজেক্টের পুরো সময়কাল জুড়ে এটি অপরিবর্তিত থাকবে। - আপনার অবগতির জন্য জানাচ্ছি যে, তৃতীয় একটি ভ্যালু রয়েছে, যা হলো প্রজেক্ট নম্বর , এবং কিছু এপিআই এটি ব্যবহার করে থাকে। ডকুমেন্টেশনে এই তিনটি ভ্যালু সম্পর্কে আরও বিস্তারিত জানুন।
- এরপর, ক্লাউড রিসোর্স/এপিআই ব্যবহার করার জন্য আপনাকে ক্লাউড কনসোলে বিলিং চালু করতে হবে। এই কোডল্যাবটি সম্পন্ন করতে খুব বেশি খরচ হবে না, এমনকি আদৌ কোনো খরচ নাও হতে পারে। এই টিউটোরিয়ালের পর বিলিং এড়াতে রিসোর্সগুলো বন্ধ করার জন্য, আপনি আপনার তৈরি করা রিসোর্সগুলো অথবা প্রজেক্টটি ডিলিট করে দিতে পারেন। নতুন গুগল ক্লাউড ব্যবহারকারীরা ৩০০ মার্কিন ডলারের ফ্রি ট্রায়াল প্রোগ্রামের জন্য যোগ্য।
ক্লাউড শেল শুরু করুন
যদিও গুগল ক্লাউড আপনার ল্যাপটপ থেকে দূরবর্তীভাবে পরিচালনা করা যায়, এই কোডল্যাবে আপনি গুগল ক্লাউড শেল ব্যবহার করবেন, যা ক্লাউডে চালিত একটি কমান্ড লাইন পরিবেশ।
গুগল ক্লাউড কনসোল থেকে, উপরের ডানদিকের টুলবারে থাকা ক্লাউড শেল আইকনটিতে ক্লিক করুন:

পরিবেশটি প্রস্তুত করতে এবং এর সাথে সংযোগ স্থাপন করতে মাত্র কয়েক মুহূর্ত সময় লাগবে। এটি শেষ হলে, আপনি এইরকম কিছু দেখতে পাবেন:

এই ভার্চুয়াল মেশিনটিতে আপনার প্রয়োজনীয় সমস্ত ডেভেলপমেন্ট টুলস লোড করা আছে। এটি একটি স্থায়ী ৫ জিবি হোম ডিরেক্টরি প্রদান করে এবং গুগল ক্লাউডে চলে, যা নেটওয়ার্ক পারফরম্যান্স ও অথেনটিকেশনকে ব্যাপকভাবে উন্নত করে। এই কোডল্যাবে আপনার সমস্ত কাজ একটি ব্রাউজারের মধ্যেই করা যাবে। আপনাকে কিছুই ইনস্টল করতে হবে না।
৩. এপিআই সক্রিয় করুন
এই ল্যাবের জন্য আপনারা ক্লাউড ফাংশন এবং ভিশন এপিআই ব্যবহার করবেন, কিন্তু তার আগে ক্লাউড কনসোল অথবা gcloud ব্যবহার করে এগুলোকে সক্রিয় করে নিতে হবে।
ক্লাউড কনসোলে ভিশন এপিআই সক্রিয় করতে, সার্চ বারে Cloud Vision API লিখে সার্চ করুন:

আপনি ক্লাউড ভিশন এপিআই পৃষ্ঠায় পৌঁছাবেন:

ENABLE বোতামটি ক্লিক করুন।
বিকল্পভাবে, আপনি gcloud কমান্ড লাইন টুল ব্যবহার করে ক্লাউড শেলেও এটি সক্রিয় করতে পারেন।
ক্লাউড শেলের ভিতরে, নিম্নলিখিত কমান্ডটি চালান:
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
৪. বাকেটটি তৈরি করুন (কনসোল)
ছবিগুলোর জন্য একটি স্টোরেজ বাকেট তৈরি করুন। আপনি এটি গুগল ক্লাউড প্ল্যাটফর্ম কনসোল ( console.cloud.google.com ) থেকে অথবা ক্লাউড শেল বা আপনার স্থানীয় ডেভেলপমেন্ট এনভায়রনমেন্ট থেকে gsutil কমান্ড লাইন টুল ব্যবহার করে করতে পারেন।
স্টোরেজে যান
'হ্যামবার্গার' (☰) মেনু থেকে Storage পৃষ্ঠায় যান।

আপনার বালতির নাম দিন
CREATE BUCKET বাটনটিতে ক্লিক করুন।

চালিয়ে CONTINUE ক্লিক করুন।
অবস্থান নির্বাচন করুন

আপনার পছন্দের অঞ্চলে (এখানে Europe ) একটি বহু-আঞ্চলিক বাকেট তৈরি করুন।
চালিয়ে CONTINUE ক্লিক করুন।
ডিফল্ট স্টোরেজ ক্লাস বেছে নিন

আপনার ডেটার জন্য Standard স্টোরেজ ক্লাস বেছে নিন।
চালিয়ে CONTINUE ক্লিক করুন।
অ্যাক্সেস নিয়ন্ত্রণ সেট করুন

যেহেতু আপনি সর্বজনীনভাবে প্রবেশযোগ্য ছবি নিয়ে কাজ করবেন, তাই আপনি চাইবেন যে এই বাকেটে সংরক্ষিত আমাদের সমস্ত ছবির জন্য একই রকম প্রবেশাধিকার নিয়ন্ত্রণ ব্যবস্থা থাকুক।
Uniform অ্যাক্সেস কন্ট্রোল বিকল্পটি বেছে নিন।
চালিয়ে CONTINUE ক্লিক করুন।
সুরক্ষা/এনক্রিপশন সেট করুন

ডিফল্ট ( Google-managed key) রাখুন, যেহেতু আপনি আপনার নিজের এনক্রিপশন কী ব্যবহার করবেন না।
আমাদের বাকেট তৈরি চূড়ান্ত করতে CREATE ক্লিক করুন।
সকল ব্যবহারকারীকে স্টোরেজ ভিউয়ার হিসেবে যুক্ত করুন
Permissions ট্যাবে যান:

নিম্নোক্তভাবে বাকেটটিতে allUsers গ্রুপের একজন সদস্যকে Storage > Storage Object Viewer রোলে যুক্ত করুন:

SAVE ক্লিক করুন।
৫. বাকেটটি তৈরি করুন (gsutil)
এছাড়াও আপনি ক্লাউড শেলে gsutil কমান্ড লাইন টুল ব্যবহার করে বাকেট তৈরি করতে পারেন।
ক্লাউড শেলে, অনন্য বাকেট নামের জন্য একটি ভেরিয়েবল সেট করুন। ক্লাউড শেলে ইতিমধ্যেই 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 বাকেট থাকার কথা:

পূর্ববর্তী ধাপে ব্যাখ্যা অনুযায়ী, পরীক্ষা করে দেখুন যে আপনি বাকেটে ছবি আপলোড করতে পারছেন এবং আপলোড করা ছবিগুলো সর্বজনীনভাবে উপলব্ধ আছে।
৬. বাকেটটিতে সর্বসাধারণের প্রবেশাধিকার পরীক্ষা করুন।
স্টোরেজ ব্রাউজারে ফিরে গেলে, আপনি তালিকায় আপনার বাকেটটি দেখতে পাবেন, যেটির অ্যাক্সেস "পাবলিক" হিসেবে সেট করা থাকবে (সাথে একটি সতর্কীকরণ চিহ্নও থাকবে, যা আপনাকে মনে করিয়ে দেবে যে যে কেউ ওই বাকেটের কন্টেন্ট অ্যাক্সেস করতে পারবে)।

আপনার বাকেটটি এখন ছবি গ্রহণের জন্য প্রস্তুত।
বাকেটের নামে ক্লিক করলে আপনি বাকেটের বিস্তারিত তথ্য দেখতে পাবেন।

সেখানে, আপনি বাকেটে একটি ছবি যোগ করতে পারেন কিনা তা পরীক্ষা করার জন্য Upload files বোতামটি ব্যবহার করে দেখতে পারেন। একটি ফাইল চুজারের পপআপ আপনাকে একটি ফাইল বেছে নিতে বলবে। একবার বেছে নেওয়া হলে, এটি আপনার বাকেটে আপলোড হয়ে যাবে এবং আপনি আবার সেই public অ্যাক্সেসটি দেখতে পাবেন যা এই নতুন ফাইলটিতে স্বয়ংক্রিয়ভাবে যুক্ত হয়ে গেছে।

Public অ্যাক্সেস’ লেবেলটির পাশে আপনি একটি ছোট লিঙ্ক আইকনও দেখতে পাবেন। সেটিতে ক্লিক করলে, আপনার ব্রাউজারটি সেই ছবিটির পাবলিক ইউআরএল-এ চলে যাবে, যা দেখতে এইরকম হবে:
https://storage.googleapis.com/BUCKET_NAME/PICTURE_FILE.png
এখানে BUCKET_NAME হলো আপনার বাকেটের জন্য বেছে নেওয়া বিশ্বব্যাপী অনন্য নাম, এবং তারপরে আপনার ছবির ফাইলের নাম।
ছবির নামের পাশে থাকা চেকবক্সে ক্লিক করলে DELETE বাটনটি সক্রিয় হবে এবং আপনি এই প্রথম ছবিটি মুছে ফেলতে পারবেন।
৭. ডাটাবেস প্রস্তুত করুন।
আপনি ভিশন এপিআই (Vision API) থেকে পাওয়া ছবির তথ্য ক্লাউড ফায়ারস্টোর (Cloud Firestore) ডেটাবেসে সংরক্ষণ করবেন, যা একটি দ্রুত, সম্পূর্ণভাবে পরিচালিত, সার্ভারবিহীন, ক্লাউড-নেটিভ নোএসকিউএল (NoSQL) ডকুমেন্ট ডেটাবেস। ক্লাউড কনসোলের (Cloud Console) Firestore ) বিভাগে গিয়ে আপনার ডেটাবেস প্রস্তুত করুন:

দুটি বিকল্প দেওয়া আছে: Native mode বা Datastore mode । নেটিভ মোড ব্যবহার করুন, যা অফলাইন সাপোর্ট এবং রিয়েল-টাইম সিনক্রোনাইজেশনের মতো অতিরিক্ত সুবিধা প্রদান করে।
SELECT NATIVE MODE এ ক্লিক করুন।

একটি বহু-অঞ্চলীয় বিকল্প বেছে নিন (এখানে ইউরোপে, তবে আদর্শগতভাবে অন্তত সেই একই অঞ্চল যেখানে আপনার ফাংশন এবং স্টোরেজ বাকেট রয়েছে)।
CREATE DATABASE বাটনটিতে ক্লিক করুন।
ডাটাবেস তৈরি হয়ে গেলে, আপনি নিম্নলিখিত বিষয়গুলো দেখতে পাবেন:

+ START COLLECTION বাটনে ক্লিক করে একটি নতুন কালেকশন তৈরি করুন।
নাম সংগ্রহের pictures ।

আপনার কোনো ডকুমেন্ট তৈরি করার প্রয়োজন নেই। ক্লাউড স্টোরেজে নতুন ছবি জমা হওয়ার সাথে সাথে এবং ভিশন এপিআই (Vision API) দ্বারা সেগুলো বিশ্লেষণ হওয়ার পর, আপনি প্রোগ্রাম্যাটিকভাবেই সেগুলো যুক্ত করে নেবেন।
Save এ ক্লিক করুন।
ফায়ারস্টোর নতুন তৈরি করা কালেকশনে একটি প্রথম ডিফল্ট ডকুমেন্ট তৈরি করে, আপনি নিরাপদে সেই ডকুমেন্টটি মুছে ফেলতে পারেন কারণ এতে কোনো দরকারি তথ্য থাকে না:

আমাদের সংগ্রহে প্রোগ্রামগতভাবে যে নথিগুলো তৈরি করা হবে, সেগুলোতে ৪টি ফিল্ড থাকবে:
- নাম (স্ট্রিং): আপলোড করা ছবির ফাইলের নাম, যা ডকুমেন্টটির কী-ও বটে।
- লেবেল (স্ট্রিং-এর অ্যারে): ভিশন এপিআই দ্বারা শনাক্তকৃত আইটেমগুলোর লেবেল।
- color (string): প্রধান রঙের হেক্সাডেসিমাল কোড (যেমন, #ab12ef)
- তৈরি হওয়ার তারিখ: এই ছবিটির মেটাডেটা সংরক্ষণের সময়কার টাইমস্ট্যাম্প।
- থাম্বনেইল (বুলিয়ান): একটি ঐচ্ছিক ক্ষেত্র যা তখনই উপস্থিত থাকবে এবং 'ট্রু' হবে, যদি এই ছবিটির জন্য একটি থাম্বনেইল ছবি তৈরি করা হয়ে থাকে।
যেহেতু আমরা ফায়ারস্টোরে থাম্বনেইলসহ ছবি খুঁজব এবং তৈরির তারিখ অনুসারে সাজাব, তাই আমাদের একটি সার্চ ইনডেক্স তৈরি করতে হবে।
আপনি ক্লাউড শেলে নিম্নলিখিত কমান্ডের মাধ্যমে ইনডেক্সটি তৈরি করতে পারেন:
gcloud firestore indexes composite create \
--collection-group=pictures \
--field-config field-path=thumbnail,order=descending \
--field-config field-path=created,order=descending
অথবা আপনি ক্লাউড কনসোল থেকেও এটি করতে পারেন। এর জন্য, বাম দিকের নেভিগেশন কলামে থাকা Indexes এ ক্লিক করে, নিচে দেখানো পদ্ধতি অনুযায়ী একটি কম্পোজিট ইনডেক্স তৈরি করুন:

Create এ ক্লিক করুন। ইনডেক্স তৈরি হতে কয়েক মিনিট সময় লাগতে পারে।
৮. কোডটি ক্লোন করুন
আগের কোড ল্যাবে যদি কোডটি ক্লোন না করে থাকেন, তবে এবার তা করুন:
git clone https://github.com/GoogleCloudPlatform/serverless-photosharing-workshop
এরপর আপনি ল্যাব তৈরি করা শুরু করতে সার্ভিসটি থাকা ডিরেক্টরিতে যেতে পারেন:
cd serverless-photosharing-workshop/services/image-analysis/java
পরিষেবাটির জন্য আপনার কাছে নিম্নলিখিত ফাইল বিন্যাস থাকবে:

৯. পরিষেবা কোডটি অন্বেষণ করুন
আপনি BOM ব্যবহার করে pom.xml এ জাভা ক্লায়েন্ট লাইব্রেরিগুলি কীভাবে সক্রিয় করা হয়েছে তা দেখে শুরু করবেন:
প্রথমে, pom.xml ফাইলটি খুলুন, যেখানে আমাদের জাভা অ্যাপের নির্ভরতাগুলোর তালিকা রয়েছে; এখানে ভিশন, ক্লাউড স্টোরেজ এবং ফায়ারস্টোর এপিআই-এর ব্যবহারের উপর মনোযোগ দিতে হবে।
<?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 https://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>3.2.0-M3</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
<groupId>services</groupId>
<artifactId>image-analysis</artifactId>
<version>0.0.1</version>
<name>image-analysis</name>
<description>Spring App for Image Analysis</description>
<properties>
<java.version>17</java.version>
<maven.compiler.target>17</maven.compiler.target>
<maven.compiler.source>17</maven.compiler.source>
<spring-cloud.version>2023.0.0-M2</spring-cloud.version>
<testcontainers.version>1.19.1</testcontainers.version>
</properties>
...
<dependencyManagement>
<dependencies>
<dependency>
<groupId>com.google.cloud</groupId>
<artifactId>libraries-bom</artifactId>
<version>26.24.0</version>
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement>
—
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-function-web</artifactId>
</dependency>
<dependency>
<groupId>com.google.cloud.functions</groupId>
<artifactId>functions-framework-api</artifactId>
<version>1.1.0</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>
এই কার্যকারিতাটি 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);
আমরা ভিশন এপিআই-এর তিনটি প্রধান সক্ষমতা জানতে চাইছি:
- লেবেল শনাক্তকরণ : ঐ ছবিগুলোতে কী আছে তা বোঝার জন্য
- ছবির বৈশিষ্ট্য : ছবির আকর্ষণীয় গুণাবলী তুলে ধরতে (আমরা ছবির প্রধান রঙটি জানতে আগ্রহী)
- নিরাপদ অনুসন্ধান : ছবিটি দেখানোর জন্য নিরাপদ কিনা তা জানতে (এতে প্রাপ্তবয়স্ক / চিকিৎসা সংক্রান্ত / উত্তেজক / হিংসাত্মক বিষয়বস্তু থাকা উচিত নয়)
এই পর্যায়ে, আমরা ভিশন এপিআই-কে কল করতে পারি:
...
logger.info("Calling the Vision API...");
BatchAnnotateImagesResponse result = vision.batchAnnotateImages(requests);
List<AnnotateImageResponse> responses = result.getResponsesList();
...
তথ্যসূত্র হিসেবে, ভিশন এপিআই থেকে প্রাপ্ত প্রতিক্রিয়াটি দেখতে এইরকম:
{
"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 ব্লকটি রয়েছে:
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);
}
আমরা প্রাপ্তবয়স্ক / ব্যঙ্গাত্মক / চিকিৎসা সংক্রান্ত / সহিংস / উত্তেজক বৈশিষ্ট্যগুলো যাচাই করে দেখছি যে সেগুলো অসম্ভাব্য নাকি অত্যন্ত সম্ভাব্য ।
নিরাপদ অনুসন্ধানের ফলাফল ঠিক থাকলে, আমরা ফায়ারস্টোরে মেটাডেটা সংরক্ষণ করতে পারি:
// Saving result to Firestore
if (isSafe) {
ApiFuture<WriteResult> writeResult =
eventService.storeImage(fileName, labels,
mainColor);
logger.info("Picture metadata saved in Firestore at " +
writeResult.get().getUpdateTime());
}
...
public ApiFuture<WriteResult> storeImage(String fileName,
List<String> labels,
String mainColor) {
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());
return doc.set(data, SetOptions.merge());
}
১০. GraalVM দিয়ে অ্যাপ ইমেজ তৈরি করুন
এই ঐচ্ছিক ধাপে, আপনি GraalVM ব্যবহার করে প্রথমে একটি JIT based app image এবং তারপর একটি Native Java app image তৈরি করবেন।
বিল্ডটি চালানোর জন্য, আপনাকে নিশ্চিত করতে হবে যে আপনার একটি উপযুক্ত JDK এবং নেটিভ-ইমেজ বিল্ডার ইনস্টল ও কনফিগার করা আছে। এর জন্য বেশ কয়েকটি বিকল্প উপলব্ধ রয়েছে।
To start , GraalVM 22.3.x কমিউনিটি এডিশনটি ডাউনলোড করুন এবং GraalVM ইনস্টলেশন পৃষ্ঠার নির্দেশাবলী অনুসরণ করুন।
SDKMAN-এর সাহায্যে এই প্রক্রিয়াটি অনেক সহজ করা যায়!
SDKman ব্যবহার করে উপযুক্ত JDK ডিস্ট্রিবিউশন ইনস্টল করতে, প্রথমে এই install কমান্ডটি ব্যবহার করুন:
sdk install java 17.0.8-graal
JIT এবং AOT উভয় বিল্ডের জন্য SDKman-কে এই সংস্করণটি ব্যবহার করার নির্দেশ দিন:
sdk use java 17.0.8-graal
আপনার সুবিধার জন্য, Cloudshell আপনি এই সহজ কমান্ডগুলো ব্যবহার করে GraalVM এবং নেটিভ-ইমেজ ইউটিলিটি ইনস্টল করতে পারেন:
# download GraalVM wget https://download.oracle.com/graalvm/17/latest/graalvm-jdk-17_linux-x64_bin.tar.gz tar -xzf graalvm-jdk-17_linux-x64_bin.tar.gz ls -lart # configure Java 17 and GraalVM for Java 17 # note the name of the latest GraalVM version, as unpacked by the tar command echo Existing JVM: $JAVA_HOME cd graalvm-jdk-17.0.8+9.1 export JAVA_HOME=$PWD cd bin export PATH=$PWD:$PATH echo JAVA HOME: $JAVA_HOME echo PATH: $PATH cd ../.. # validate the version with java -version # observe Java(TM) SE Runtime Environment Oracle GraalVM 17.0.8+9.1 (build 17.0.8+9-LTS-jvmci-23.0-b14) Java HotSpot(TM) 64-Bit Server VM Oracle GraalVM 17.0.8+9.1 (build 17.0.8+9-LTS-jvmci-23.0-b14, mixed mode, sharing)
প্রথমে, GCP প্রজেক্টের এনভায়রনমেন্ট ভেরিয়েবলগুলো সেট করুন:
export GOOGLE_CLOUD_PROJECT=$(gcloud config get-value project)
এরপর আপনি ল্যাব তৈরি করা শুরু করতে সার্ভিসটি থাকা ডিরেক্টরিতে যেতে পারেন:
cd serverless-photosharing-workshop/services/image-analysis/java
JIT অ্যাপ্লিকেশন ইমেজটি তৈরি করুন:
./mvnw package
টার্মিনালে বিল্ড লগটি পর্যবেক্ষণ করুন:
... [INFO] Results: [INFO] [INFO] Tests run: 6, Failures: 0, Errors: 0, Skipped: 0 [INFO] [INFO] [INFO] --- maven-jar-plugin:3.3.0:jar (default-jar) @ image-analysis --- [INFO] Building jar: /home/user/serverless-photosharing-workshop/services/image-analysis/java/target/image-analysis-0.0.1.jar [INFO] [INFO] --- spring-boot-maven-plugin:3.2.0-M3:repackage (repackage) @ image-analysis --- [INFO] Replacing main artifact /home/user/serverless-photosharing-workshop/services/image-analysis/java/target/image-analysis-0.0.1.jar with repackaged archive, adding nested dependencies in BOOT-INF/. [INFO] The original artifact has been renamed to /home/user/serverless-photosharing-workshop/services/image-analysis/java/target/image-analysis-0.0.1.jar.original [INFO] ------------------------------------------------------------------------ [INFO] BUILD SUCCESS [INFO] ------------------------------------------------------------------------ [INFO] Total time: 15.335 s [INFO] Finished at: 2023-10-10T19:33:25Z [INFO] ------------------------------------------------------------------------
নেটিভ (AOT ব্যবহার করে) ইমেজটি বিল্ড করুন:
./mvnw native:compile -Pnative
টার্মিনালে বিল্ড লগটি পর্যবেক্ষণ করুন, যার মধ্যে নেটিভ ইমেজ বিল্ড লগও অন্তর্ভুক্ত রয়েছে:
মনে রাখবেন যে, আপনি কোন মেশিনে পরীক্ষা করছেন তার উপর নির্ভর করে বিল্ড হতে বেশ কিছুটা বেশি সময় লাগে।
...
[2/7] Performing analysis... [*********] (124.5s @ 4.53GB)
29,732 (93.19%) of 31,905 classes reachable
60,161 (70.30%) of 85,577 fields reachable
261,973 (67.29%) of 389,319 methods reachable
2,940 classes, 2,297 fields, and 97,421 methods registered for reflection
81 classes, 90 fields, and 62 methods registered for JNI access
4 native libraries: dl, pthread, rt, z
[3/7] Building universe... (11.7s @ 4.67GB)
[4/7] Parsing methods... [***] (6.1s @ 5.91GB)
[5/7] Inlining methods... [****] (4.5s @ 4.39GB)
[6/7] Compiling methods... [******] (35.3s @ 4.60GB)
[7/7] Creating image... (12.9s @ 4.61GB)
80.08MB (47.43%) for code area: 190,483 compilation units
73.81MB (43.72%) for image heap: 660,125 objects and 189 resources
14.95MB ( 8.86%) for other data
168.84MB in total
------------------------------------------------------------------------------------------------------------------------
Top 10 packages in code area: Top 10 object types in image heap:
2.66MB com.google.cloud.vision.v1p4beta1 18.51MB byte[] for code metadata
2.60MB com.google.cloud.vision.v1 9.27MB java.lang.Class
2.49MB com.google.protobuf 7.34MB byte[] for reflection metadata
2.40MB com.google.cloud.vision.v1p3beta1 6.35MB byte[] for java.lang.String
2.17MB com.google.storage.v2 5.72MB java.lang.String
2.12MB com.google.firestore.v1 4.46MB byte[] for embedded resources
1.64MB sun.security.ssl 4.30MB c.oracle.svm.core.reflect.SubstrateMethodAccessor
1.51MB i.g.xds.shaded.io.envoyproxy.envoy.config.core.v3 4.27MB byte[] for general heap data
1.47MB com.google.cloud.vision.v1p2beta1 2.50MB com.oracle.svm.core.hub.DynamicHubCompanion
1.34MB i.g.x.shaded.io.envoyproxy.envoy.config.route.v3 1.17MB java.lang.Object[]
58.34MB for 977 more packages 9.19MB for 4667 more object types
------------------------------------------------------------------------------------------------------------------------
13.5s (5.7% of total time) in 75 GCs | Peak RSS: 9.44GB | CPU load: 6.13
------------------------------------------------------------------------------------------------------------------------
Produced artifacts:
/home/user/serverless-photosharing-workshop/services/image-analysis/java/target/image-analysis (executable)
/home/user/serverless-photosharing-workshop/services/image-analysis/java/target/image-analysis.build_artifacts.txt (txt)
========================================================================================================================
Finished generating '/home/user/serverless-photosharing-workshop/services/image-analysis/java/target/image-analysis' in 3m 57s.
[INFO] ------------------------------------------------------------------------
[INFO] BUILD SUCCESS
[INFO] ------------------------------------------------------------------------
[INFO] Total time: 04:28 min
[INFO] Finished at: 2023-10-10T19:53:30Z
[INFO] ------------------------------------------------------------------------
১১. কন্টেইনার ইমেজ তৈরি এবং প্রকাশ করুন
চলুন দুটি ভিন্ন সংস্করণে একটি কন্টেইনার ইমেজ তৈরি করি: একটি JIT image হিসেবে এবং অন্যটি Native Java image হিসেবে।
প্রথমে, GCP প্রজেক্টের এনভায়রনমেন্ট ভেরিয়েবলগুলো সেট করুন:
export GOOGLE_CLOUD_PROJECT=$(gcloud config get-value project)
JIT ইমেজটি তৈরি করুন:
./mvnw spring-boot:build-image -Pji
টার্মিনালে বিল্ড লগটি পর্যবেক্ষণ করুন:
[INFO] [creator] Timer: Saving docker.io/library/image-analysis-maven-jit:latest... started at 2023-10-10T20:00:31Z [INFO] [creator] *** Images (4c84122a1826): [INFO] [creator] docker.io/library/image-analysis-maven-jit:latest [INFO] [creator] Timer: Saving docker.io/library/image-analysis-maven-jit:latest... ran for 6.975913605s and ended at 2023-10-10T20:00:38Z [INFO] [creator] Timer: Exporter ran for 8.068588001s and ended at 2023-10-10T20:00:38Z [INFO] [creator] Timer: Cache started at 2023-10-10T20:00:38Z [INFO] [creator] Reusing cache layer 'paketo-buildpacks/syft:syft' [INFO] [creator] Adding cache layer 'buildpacksio/lifecycle:cache.sbom' [INFO] [creator] Timer: Cache ran for 200.449002ms and ended at 2023-10-10T20:00:38Z [INFO] [INFO] Successfully built image 'docker.io/library/image-analysis-maven-jit:latest' [INFO] [INFO] ------------------------------------------------------------------------ [INFO] BUILD SUCCESS [INFO] ------------------------------------------------------------------------ [INFO] Total time: 43.887 s [INFO] Finished at: 2023-10-10T20:00:39Z [INFO] ------------------------------------------------------------------------
AOT(নেটিভ) ইমেজটি তৈরি করুন:
./mvnw spring-boot:build-image -Pnative
টার্মিনালে বিল্ড লগটি পর্যবেক্ষণ করুন, যার মধ্যে নেটিভ ইমেজ বিল্ড লগও অন্তর্ভুক্ত রয়েছে।
দ্রষ্টব্য:
- আপনি কোন মেশিনে পরীক্ষা করছেন তার উপর নির্ভর করে, বিল্ড হতে বেশ কিছুটা বেশি সময় লাগে।
- ছবিগুলোকে UPX দিয়ে আরও সংকুচিত করা যায়, তবে তা স্টার্ট-আপ পারফরম্যান্সে সামান্য নেতিবাচক প্রভাব ফেলে, তাই এই বিল্ডে UPX ব্যবহার করা হয়নি — এটি সবসময়ই একটি সামান্য আপস।
... [INFO] [creator] Saving docker.io/library/image-analysis-maven-native:latest... [INFO] [creator] *** Images (13167702674e): [INFO] [creator] docker.io/library/image-analysis-maven-native:latest [INFO] [creator] Adding cache layer 'paketo-buildpacks/bellsoft-liberica:native-image-svm' [INFO] [creator] Adding cache layer 'paketo-buildpacks/syft:syft' [INFO] [creator] Adding cache layer 'paketo-buildpacks/native-image:native-image' [INFO] [creator] Adding cache layer 'buildpacksio/lifecycle:cache.sbom' [INFO] [INFO] Successfully built image 'docker.io/library/image-analysis-maven-native:latest' [INFO] [INFO] ------------------------------------------------------------------------ [INFO] BUILD SUCCESS [INFO] ------------------------------------------------------------------------ [INFO] Total time: 03:37 min [INFO] Finished at: 2023-10-10T20:05:16Z [INFO] ------------------------------------------------------------------------
ইমেজগুলো বিল্ড হয়েছে কিনা তা যাচাই করুন:
docker images | grep image-analysis
ছবি দুটি ট্যাগ করে GCR-এ পাঠান:
# JIT image
docker tag image-analysis-maven-jit gcr.io/${GOOGLE_CLOUD_PROJECT}/image-analysis-maven-jit
docker push gcr.io/${GOOGLE_CLOUD_PROJECT}/image-analysis-maven-jit
# Native(AOT) image
docker tag image-analysis-maven-native gcr.io/${GOOGLE_CLOUD_PROJECT}/image-analysis-maven-native
docker push gcr.io/${GOOGLE_CLOUD_PROJECT}/image-analysis-maven-native
১২. ক্লাউড রানে স্থাপন করুন
সার্ভিসটি ডেপ্লয় করার সময় হয়েছে।
আপনি সার্ভিসটি দুইবার ডেপ্লয় করবেন, একবার JIT ইমেজ ব্যবহার করে এবং দ্বিতীয়বার AOT (নেটিভ) ইমেজ ব্যবহার করে। তুলনার উদ্দেশ্যে, উভয় সার্ভিস ডেপ্লয়মেন্টই বাকেট থেকে একই ইমেজ সমান্তরালভাবে প্রসেস করবে।
প্রথমে, 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 ইমেজটি ডিপ্লয় করুন এবং কনসোলে ডিপ্লয়মেন্ট লগটি পর্যবেক্ষণ করুন:
gcloud run deploy image-analysis-jit \
--image gcr.io/${GOOGLE_CLOUD_PROJECT}/image-analysis-maven-jit \
--region europe-west1 \
--memory 2Gi --allow-unauthenticated
...
Deploying container to Cloud Run service [image-analysis-jit] in project [...] region [europe-west1]
✓ Deploying... Done.
✓ Creating Revision...
✓ Routing traffic...
✓ Setting IAM Policy...
Done.
Service [image-analysis-jit] revision [image-analysis-jvm-00009-huc] has been deployed and is serving 100 percent of traffic.
Service URL: https://image-analysis-jit-...-ew.a.run.app
নেটিভ ইমেজটি ডিপ্লয় করুন এবং কনসোলে ডিপ্লয়মেন্ট লগটি পর্যবেক্ষণ করুন:
gcloud run deploy image-analysis-native \
--image gcr.io/${GOOGLE_CLOUD_PROJECT}/image-analysis-maven-native \
--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
১৩. ইভেন্টআর্ক ট্রিগার সেটআপ করুন
ইভেন্টআর্ক বিচ্ছিন্ন মাইক্রোসার্ভিসগুলোর মধ্যে স্টেট পরিবর্তনের প্রবাহ, যা ইভেন্ট নামে পরিচিত, পরিচালনা করার জন্য একটি প্রমিত সমাধান প্রদান করে। ট্রিগার হলে, ইভেন্টআর্ক এই ইভেন্টগুলোকে পাব/সাব সাবস্ক্রিপশনের মাধ্যমে বিভিন্ন গন্তব্যে (এই ডকুমেন্টে, ‘ইভেন্ট গন্তব্য’ দেখুন) পাঠিয়ে দেয় এবং একই সাথে আপনার জন্য ডেলিভারি, নিরাপত্তা, অনুমোদন, পর্যবেক্ষণযোগ্যতা এবং ত্রুটি-পরিচালনা পরিচালনা করে।
আপনি একটি ইভেন্টআর্ক ট্রিগার তৈরি করতে পারেন, যাতে আপনার ক্লাউড রান পরিষেবা একটি নির্দিষ্ট ইভেন্ট বা একাধিক ইভেন্টের নোটিফিকেশন পায়। ট্রিগারের জন্য ফিল্টার নির্দিষ্ট করে, আপনি ইভেন্টের রাউটিং কনফিগার করতে পারেন, যার মধ্যে ইভেন্টের উৎস এবং লক্ষ্য ক্লাউড রান পরিষেবা অন্তর্ভুক্ত থাকে।
প্রথমে, 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
ক্লাউড স্টোরেজ পরিষেবা অ্যাকাউন্টে 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'
ইমেজটি প্রসেস করার জন্য JIT এবং Native সার্ভিস ইমেজ উভয়ের জন্যই Eventarc ট্রিগার সেট আপ করুন:
gcloud eventarc triggers list --location=eu
gcloud eventarc triggers create image-analysis-jit-trigger \
--destination-run-service=image-analysis-jit \
--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
১৪. পরীক্ষার পরিষেবা সংস্করণ
সার্ভিস ডেপ্লয়মেন্ট সফল হলে, আপনি ক্লাউড স্টোরেজে একটি ছবি পোস্ট করবেন, দেখবেন আমাদের সার্ভিসগুলো চালু হয়েছে কিনা, ভিশন এপিআই কী রিটার্ন করছে, এবং ফায়ারস্টোরে মেটাডেটা সংরক্ষিত হয়েছে কিনা।
Cloud Storage ফিরে যান এবং ল্যাবের শুরুতে আমরা যে বাকেটটি তৈরি করেছিলাম সেটিতে ক্লিক করুন:

বাকেট ডিটেইলস পেজে প্রবেশ করার পর, একটি ছবি আপলোড করার জন্য Upload files বাটনে ক্লিক করুন।
উদাহরণস্বরূপ, আপনার কোডবেসের সাথে /services/image-analysis/java ফোল্ডারে একটি GeekHour.jpeg ইমেজ দেওয়া আছে। একটি ইমেজ সিলেক্ট করুন এবং Open button চাপুন:

আপনি এখন সার্ভিসটির কার্যকারিতা পরীক্ষা করতে পারেন, প্রথমে image-analysis-jit এবং তারপরে image-analysis-native ।
'হ্যামবার্গার' (☰) মেনু থেকে Cloud Run > image-analysis-jit সার্ভিসটিতে যান।
লগ-এ ক্লিক করুন এবং আউটপুটটি পর্যবেক্ষণ করুন:

এবং প্রকৃতপক্ষে, লগগুলির তালিকায় আমি দেখতে পাচ্ছি যে image-analysis-jit JIT পরিষেবাটি চালু করা হয়েছিল।
লগগুলো সার্ভিসটির কার্য সম্পাদনের শুরু এবং শেষ নির্দেশ করে। এবং এর মাঝে, আমরা আমাদের ফাংশনে INFO লেভেলের লগ স্টেটমেন্ট দিয়ে রাখা লগগুলো দেখতে পারি। আমরা দেখতে পাই:
- যে ঘটনাটি আমাদের ফাংশনটিকে সক্রিয় করে তার বিবরণ,
- ভিশন এপিআই কল থেকে প্রাপ্ত কাঁচা ফলাফল,
- আমরা যে ছবিটি আপলোড করেছিলাম, তাতে যে লেবেলগুলো পাওয়া গিয়েছিল,
- প্রভাবশালী রঙের তথ্য,
- ছবিটি দেখানো নিরাপদ কিনা,
- এবং অবশেষে ছবিটির মেটাডেটা ফায়ারস্টোরে সংরক্ষণ করা হয়েছে।
আপনি image-analysis-native সার্ভিসটির জন্য প্রক্রিয়াটি পুনরাবৃত্তি করবেন।
'হ্যামবার্গার' (☰) মেনু থেকে Cloud Run > image-analysis-native সার্ভিসটিতে যান।
লগ-এ ক্লিক করুন এবং আউটপুটটি পর্যবেক্ষণ করুন:

এখন আপনাকে লক্ষ্য করতে হবে যে ছবির মেটাডেটা ফায়ারস্টোরে সংরক্ষিত হয়েছে কি না।
আবার 'হ্যামবার্গার' (☰) মেনু থেকে, Firestore বিভাগে যান। Data উপবিভাগে (যা ডিফল্টরূপে দেখানো হয়), আপনি pictures কালেকশনটি দেখতে পাবেন, যেখানে আপনার এইমাত্র আপলোড করা ছবিটির সাথে সম্পর্কিত একটি নতুন ডকুমেন্ট যুক্ত থাকবে:

১৫. পরিষ্কার করা (ঐচ্ছিক)
আপনি যদি এই সিরিজের অন্য ল্যাবগুলো চালিয়ে যেতে না চান, তাহলে খরচ বাঁচাতে এবং সার্বিকভাবে একজন ভালো ক্লাউড ব্যবহারকারী হতে রিসোর্সগুলো পরিষ্কার করতে পারেন। আপনি নিম্নলিখিত উপায়ে একে একে রিসোর্সগুলো পরিষ্কার করতে পারেন।
বাকেটটি মুছে ফেলুন:
gsutil rb gs://${BUCKET_PICTURES}
ফাংশনটি মুছে ফেলুন:
gcloud functions delete picture-uploaded --region europe-west1 -q
কালেকশন থেকে 'ডিলিট কালেকশন' নির্বাচন করে ফায়ারস্টোর কালেকশনটি মুছে ফেলুন:

বিকল্পভাবে, আপনি পুরো প্রজেক্টটি মুছে ফেলতে পারেন:
gcloud projects delete ${GOOGLE_CLOUD_PROJECT}
১৬. অভিনন্দন!
অভিনন্দন! আপনি প্রকল্পের প্রথম মূল পরিষেবাটি সফলভাবে বাস্তবায়ন করেছেন!
আমরা যা আলোচনা করেছি
- ক্লাউড স্টোরেজ
- ক্লাউড রান
- ক্লাউড ভিশন এপিআই
- ক্লাউড ফায়ারস্টোর
- নেটিভ জাভা ইমেজ