1. الأهداف
نظرة عامة
سيركّز هذا الدرس التطبيقي حول الترميز على إنشاء تطبيق Vertex AI Vision متكامل لمراقبة حجم قائمة الانتظار باستخدام لقطات فيديو للبيع بالتجزئة. سنستخدم ميزات إحصاءات الإشغال المضمّنة في "النموذج المتخصّص" المُدرَّب مسبقًا لتسجيل ما يلي:
- احسب عدد الأشخاص الواقفين في الصف.
- احتساب عدد الأشخاص الذين يتم خدمتهم عند المنضدة
ما ستتعلمه
- كيفية إنشاء تطبيق في Vertex AI Vision وتفعيله
- كيفية إعداد بث RTSP باستخدام ملف فيديو واستيعاب البث في Vertex AI Vision باستخدام vaictl من دفتر ملاحظات Jupyter
- كيفية استخدام نموذج "إحصاءات الإشغال" وميزاته المختلفة
- كيفية البحث عن فيديوهات في مستودع الوسائط في Vertex AI Vision
- كيفية ربط الإخراج بـ BigQuery وكتابة طلب SQL لاستخراج الإحصاءات من إخراج json للنموذج واستخدام الإخراج لتصنيف الفيديو الأصلي والتعليق عليه
التكلفة:
تبلغ التكلفة الإجمالية لتشغيل هذا الدرس التطبيقي على Google Cloud حوالي 2 دولار أمريكي.
2. قبل البدء
إنشاء مشروع وتفعيل واجهات برمجة التطبيقات:
- في وحدة تحكّم Google Cloud، في صفحة اختيار المشروع، اختَر مشروع Google Cloud أو أنشِئ مشروعًا. ملاحظة: إذا كنت لا تخطّط للاحتفاظ بالموارد التي تنشئها في هذا الإجراء، أنشئ مشروعًا بدلاً من اختيار مشروع حالي. بعد الانتهاء من هذه الخطوات، يمكنك حذف المشروع وإزالة جميع الموارد المرتبطة به. الانتقال إلى أداة اختيار المشاريع
- تأكَّد من تفعيل الفوترة لمشروعك على السحابة الإلكترونية. تعرَّف على كيفية التحقّق مما إذا كانت الفوترة مفعَّلة في مشروع.
- فعِّل Compute Engine وVertex API وNotebook API وVision AI API. تفعيل واجهات برمجة التطبيقات
إنشاء حساب خدمة:
- في Google Cloud Console، انتقِل إلى صفحة إنشاء حساب خدمة. الانتقال إلى "إنشاء حساب خدمة"
- اختَر مشروعك.
- في حقل اسم حساب الخدمة، أدخِل اسمًا. تعبئ Google Cloud Console الحقل معرّف حساب الخدمة استنادًا إلى هذا الاسم. في حقل وصف حساب الخدمة، أدخِل وصفًا. على سبيل المثال، حساب خدمة للبدء السريع.
- انقر على إنشاء ومتابعة.
- لمنح إذن الوصول إلى مشروعك، امنح حساب الخدمة الأدوار التالية:
- Vision AI > أداة تعديل Vision AI
- Compute Engine > إدارة مثيل Compute (إصدار تجريبي)
- BigQuery > مشرف BigQuery
في قائمة اختيار دور، اختَر دورًا. لإضافة أدوار أخرى، انقر على إضافة دور آخر وأضِف كل دور إضافي.
- انقر على متابعة.
- انقر على تم للانتهاء من إنشاء حساب الخدمة. لا تغلق نافذة المتصفح. ستستخدمه في الخطوة التالية.
3- إعداد Jupyter Notebook
قبل إنشاء تطبيق في "إحصاءات الإشغال"، يجب تسجيل مصدر بيانات يمكن للتطبيق استخدامه لاحقًا.
في هذا البرنامج التعليمي، ستنشئ مثيلاً من Jupyter Notebook يستضيف فيديو، وسترسل بيانات الفيديو المتدفقة من دفتر الملاحظات. نستخدم أداة جوبيتر نوتبوك لأنّها تتيح لنا المرونة في تنفيذ أوامر shell وتشغيل رموز برمجية مخصّصة للمعالجة المسبقة/اللاحقة في مكان واحد، ما يسهّل إجراء التجارب بسرعة. سنستخدم دفتر الملاحظات هذا للأغراض التالية:
- تشغيل خادم rtsp كعملية في الخلفية
- تنفيذ الأمر vaictl كعملية في الخلفية
- تنفيذ طلبات البحث ورموز المعالجة لتحليل نتائج إحصاءات الإشغال
إنشاء دفتر ملاحظات Jupyter
تتمثّل الخطوة الأولى في إرسال الفيديو من مثيل Jupyter Notebook في إنشاء دفتر باستخدام حساب الخدمة الذي أنشأناه في الخطوة السابقة.
- في وحدة التحكّم، انتقِل إلى صفحة Vertex AI. الانتقال إلى Vertex AI Workbench
- انقر على "دفاتر ملاحظات يديرها المستخدم"

- انقر على دفتر ملاحظات جديد > Tensorflow Enterprise 2.6 (مع LTS) > بدون وحدات معالجة الرسومات

- أدخِل اسم دفتر ملاحظات Jupyter. لمزيد من المعلومات، يُرجى الاطّلاع على اصطلاح تسمية الموارد.

- انقر على خيارات متقدمة.
- انتقِل للأسفل إلى أقسام الأذونات.
- أزِل العلامة من المربّع بجانب الخيار استخدام حساب الخدمة التلقائي في Compute Engine.
- أضِف عنوان البريد الإلكتروني لحساب الخدمة الذي تم إنشاؤه في الخطوة السابقة. انقر على إنشاء.

- بعد إنشاء المثيل، انقر على فتح JUPYTERLAB.
4. إعداد "دفتر ملاحظات" لبث الفيديو
قبل إنشاء تطبيق في "إحصاءات الإشغال"، يجب تسجيل مصدر بيانات يمكن للتطبيق استخدامه لاحقًا.
في هذا الدليل التعليمي، سنستخدم مثيل Jupyter Notebook لاستضافة فيديو، وسترسل بيانات بث الفيديو المباشر من نافذة Notebook الطرفية.
تنزيل أداة سطر الأوامر vaictl
- في مثيل Jupyterlab الذي تم فتحه، افتح دفتر ملاحظات من مشغّل التطبيقات.

- نزِّل أداة سطر الأوامر Vertex AI Vision (vaictl) وأداة سطر الأوامر لخادم rtsp وأداة open-cv باستخدام الأمر التالي في خلية دفتر الملاحظات:
!wget -q https://github.com/aler9/rtsp-simple-server/releases/download/v0.20.4/rtsp-simple-server_v0.20.4_linux_amd64.tar.gz
!wget -q https://github.com/google/visionai/releases/download/v0.0.4/visionai_0.0-4_amd64.deb
!tar -xf rtsp-simple-server_v0.20.4_linux_amd64.tar.gz
!pip install opencv-python --quiet
!sudo apt-get -qq remove -y visionai
!sudo apt-get -qq install -y ./visionai_0.0-4_amd64.deb
!sudo apt-get -qq install -y ffmpeg
5- نقل ملف فيديو للبث
بعد إعداد بيئة دفتر الملاحظات باستخدام أدوات سطر الأوامر المطلوبة، يمكنك نسخ ملف فيديو نموذجي ثم استخدام vaictl لبث بيانات الفيديو إلى تطبيق إحصاءات الإشغال.
تسجيل بث جديد
- انقر على علامة التبويب "مصادر البث" في اللوحة اليمنى من Vertex AI Vision.
- انقر على زر "تسجيل" في أعلى الصفحة

- في "اسم مجموعة البث" (Stream name)، أدخِل queue-stream.
- في "المنطقة"، اختَر المنطقة نفسها التي تم اختيارها أثناء إنشاء دفتر الملاحظات في الخطوة السابقة.
- انقر على تسجيل.
نسخ فيديو نموذجي إلى جهازك الافتراضي
- في دفتر الملاحظات، انسخ فيديو نموذجيًا باستخدام أمر wget التالي.
!wget -q https://github.com/vagrantism/interesting-datasets/raw/main/video/collective_activity/seq25_h264.mp4
بثّ الفيديو من الجهاز الافتراضي واستيعاب البيانات في البث
- لإرسال ملف الفيديو المحلي هذا إلى دفق إدخال التطبيق، استخدِم الأمر التالي في خلية دفتر الملاحظات. يجب استبدال المتغيرات التالية:
- PROJECT_ID: رقم تعريف مشروعك على Google Cloud
- LOCATION: معرّف موقعك الجغرافي على سبيل المثال، us-central1. لمزيد من المعلومات، يُرجى الاطّلاع على المواقع الجغرافية على السحابة الإلكترونية.
- LOCAL_FILE: اسم ملف فيديو محفوظ على الجهاز على سبيل المثال،
seq25_h264.mp4.
PROJECT_ID='<Your Google Cloud project ID>'
LOCATION='<Your stream location>'
LOCAL_FILE='seq25_h264.mp4'
STREAM_NAME='queue-stream'
- ابدأ خادم rtsp-simple-server حيث نبث ملف الفيديو باستخدام بروتوكول rtsp
import os
import time
import subprocess
subprocess.Popen(["nohup", "./rtsp-simple-server"], stdout=open('rtsp_out.log', 'a'), stderr=open('rtsp_err.log', 'a'), preexec_fn=os.setpgrp)
time.sleep(5)
- استخدام أداة سطر الأوامر ffmpeg لتكرار الفيديو في بث rtsp
subprocess.Popen(["nohup", "ffmpeg", "-re", "-stream_loop", "-1", "-i", LOCAL_FILE, "-c", "copy", "-f", "rtsp", f"rtsp://localhost:8554/{LOCAL_FILE.split('.')[0]}"], stdout=open('ffmpeg_out.log', 'a'), stderr=open('ffmpeg_err.log', 'a'), preexec_fn=os.setpgrp)
time.sleep(5)
- استخدِم أداة سطر الأوامر vaictl لبث الفيديو من معرّف الموارد المنتظم لخادم rtsp إلى بث Vertex AI Vision "queue-stream" الذي تم إنشاؤه في الخطوة السابقة.
subprocess.Popen(["nohup", "vaictl", "-p", PROJECT_ID, "-l", LOCATION, "-c", "application-cluster-0", "--service-endpoint", "visionai.googleapis.com", "send", "rtsp", "to", "streams", "queue-stream", "--rtsp-uri", f"rtsp://localhost:8554/{LOCAL_FILE.split('.')[0]}"], stdout=open('vaictl_out.log', 'a'), stderr=open('vaictl_err.log', 'a'), preexec_fn=os.setpgrp)
قد يستغرق الأمر حوالي 100 ثانية بين بدء عملية استيعاب vaictl وظهور الفيديو في لوحة البيانات.
بعد أن يصبح استيعاب البث متاحًا، يمكنك الاطّلاع على خلاصة الفيديو في علامة التبويب عمليات البث في لوحة بيانات Vertex AI Vision من خلال اختيار بث قائمة الانتظار.
الانتقال إلى علامة التبويب "البث المباشر"

6. إنشاء تطبيق
الخطوة الأولى هي إنشاء تطبيق يعالج بياناتك. يمكن اعتبار التطبيق مسارًا آليًا يربط بين ما يلي:
- نقل البيانات: يتم نقل خلاصة فيديو إلى مصدر بيانات.
- تحليل البيانات: يمكن إضافة نموذج الذكاء الاصطناعي(الرؤية الحاسوبية) بعد عملية الاستيعاب.
- تخزين البيانات: يمكن تخزين نسختَي خلاصة الفيديو (البث الأصلي والبث الذي يعالجه نموذج الذكاء الاصطناعي) في مستودع وسائط.
في Google Cloud Console، يتم تمثيل التطبيق كرسم بياني.
إنشاء تطبيق فارغ
قبل أن تتمكّن من ملء الرسم البياني للتطبيق، عليك أولاً إنشاء تطبيق فارغ.
أنشِئ تطبيقًا في Google Cloud Console.
- انتقِل إلى وحدة تحكّم Google Cloud.
- افتح علامة التبويب التطبيقات في لوحة بيانات Vertex AI Vision. الانتقال إلى علامة التبويب "التطبيقات"
- انقر على الزر إنشاء.

- أدخِل queue-app كاسم للتطبيق واختَر منطقتك.
- انقر على إنشاء.
إضافة عُقد لمكوّنات التطبيق
بعد إنشاء التطبيق الفارغ، يمكنك إضافة العُقد الثلاث إلى الرسم البياني للتطبيق:
- عقدة الاستيعاب: مورد البث الذي يستوعب البيانات المرسَلة من خادم فيديو rtsp أنشأته في دفتر الملاحظات.
- عقدة المعالجة: نموذج إحصاءات الإشغال الذي يعمل على البيانات التي تمّت إضافتها.
- عقدة التخزين: مستودع الوسائط الذي يخزِّن الفيديوهات المعالَجة ويعمل كمخزن للبيانات الوصفية. تتضمّن مستودعات البيانات الوصفية معلومات إحصائية حول بيانات الفيديو التي تمّت إضافتها، ومعلومات استنتجتها نماذج الذكاء الاصطناعي.
أضِف عُقد المكوّنات إلى تطبيقك في وحدة التحكّم.
- افتح علامة التبويب التطبيقات في لوحة بيانات Vertex AI Vision. الانتقال إلى علامة التبويب "التطبيقات"
سيتم نقلك إلى التمثيل المرئي للرسم البياني لخطوات المعالجة.
إضافة عقدة لنقل البيانات
- لإضافة عقدة لتدفق الإدخال، انقر على الخيار عمليات البث في قسم الموصلات من القائمة الجانبية.
- في قسم المصدر ضمن قائمة البث التي تفتح، انقر على إضافة قنوات بث.
- في قائمة إضافة أحداث البث، اختَر queue-stream.
- لإضافة البث إلى الرسم البياني للتطبيق، انقر على إضافة عمليات البث.
إضافة عقدة لمعالجة البيانات
- لإضافة عقدة نموذج عدد الأشخاص، انقر على خيار إحصاءات عدد الأشخاص في قسم النماذج المتخصّصة من القائمة الجانبية.
- اترك الخيارات التلقائية الأشخاص. أزِل العلامة من المربّع بجانب المركبات إذا كان محدّدًا.

- في قسم "الخيارات المتقدّمة"، انقر على إنشاء مناطق/خطوط نشطة
. - ارسم المناطق النشطة باستخدام أداة "المضلّع" لاحتساب عدد الأشخاص في تلك المنطقة. صنِّف المنطقة وفقًا لذلك

- انقر على سهم الرجوع في أعلى الصفحة.

- أضِف إعدادات لوقت البقاء لرصد الازدحام من خلال النقر على مربّع الاختيار.

إضافة عقدة لتخزين البيانات
- لإضافة عقدة وجهة الإخراج (التخزين)، اختَر الخيار VIsion AI Warehouse في قسم الموصلات (Connectors) من القائمة الجانبية.
- انقر على موصِّل Vertex AI Warehouse لفتح القائمة، ثم انقر على ربط مستودع البيانات.
- في قائمة ربط مستودع بيانات، اختَر إنشاء مستودع بيانات جديد. أطلِق على المستودع اسم queue-warehouse، واترك مدة البقاء (TTL) عند 14 يومًا.
- انقر على الزر إنشاء لإضافة المستودع.
7. ربط الناتج بجدول BigQuery
عند إضافة موصّل BigQuery إلى تطبيق Vertex AI Vision، سيتم استيعاب جميع نواتج نماذج التطبيقات المرتبطة في الجدول المستهدف.
يمكنك إما إنشاء جدول BigQuery الخاص بك وتحديد هذا الجدول عند إضافة أداة ربط BigQuery إلى التطبيق، أو السماح لمنصة تطبيق Vertex AI Vision بإنشاء الجدول تلقائيًا.
إنشاء الجداول تلقائيًا
إذا سمحت لمنصة تطبيقات Vertex AI Vision بإنشاء الجدول تلقائيًا، يمكنك تحديد هذا الخيار عند إضافة عقدة موصّل BigQuery.
تنطبق شروط مجموعة البيانات والجدول التالية إذا كنت تريد استخدام ميزة إنشاء الجداول تلقائيًا:
- مجموعة البيانات: اسم مجموعة البيانات التي يتم إنشاؤها تلقائيًا هو visionai_dataset.
- الجدول: اسم الجدول الذي يتم إنشاؤه تلقائيًا هو visionai_dataset.APPLICATION_ID.
- معالجة الأخطاء:
- إذا كان الجدول الذي يحمل الاسم نفسه ضِمن مجموعة البيانات نفسها متوفّرًا، لن يتم إنشاؤه تلقائيًا.
- افتح علامة التبويب التطبيقات في لوحة بيانات Vertex AI Vision. الانتقال إلى علامة التبويب "التطبيقات"
- انقر على عرض التطبيق بجانب اسم تطبيقك من القائمة.
- في صفحة "أداة إنشاء التطبيقات"، اختَر BigQuery من قسم الموصّلات.
- اترك حقل مسار BigQuery فارغًا.

- في تخزين البيانات الوصفية من:، اختَر "إحصاءات الإشغال" فقط وأزِل العلامة من مربّع الاختيار الخاص بمصادر البيانات.
من المفترض أن يظهر الرسم البياني النهائي للتطبيق على النحو التالي:

8. نشر تطبيقك لاستخدامه
بعد إنشاء تطبيقك المتكامل مع جميع المكوّنات اللازمة، تتمثّل الخطوة الأخيرة لاستخدام التطبيق في نشره.
- افتح علامة التبويب التطبيقات في لوحة بيانات Vertex AI Vision. الانتقال إلى علامة التبويب "التطبيقات"
- انقر على عرض التطبيق بجانب تطبيق queue-app في القائمة.
- من صفحة Studio، انقر على الزر نشر.
- في مربّع حوار التأكيد التالي، انقر على نشر. قد تستغرق عملية النشر عدة دقائق حتى تكتمل. بعد انتهاء عملية النشر، ستظهر علامات صح خضراء بجانب العُقد.

9- البحث عن محتوى الفيديو في مستودع التخزين
بعد نقل بيانات الفيديو إلى تطبيق المعالجة، يمكنك الاطّلاع على بيانات الفيديو التي تم تحليلها والبحث في البيانات استنادًا إلى معلومات إحصاءات الإشغال.
- افتح علامة التبويب المستودعات في لوحة بيانات Vertex AI Vision. الانتقال إلى علامة التبويب "المستودعات"
- ابحث عن مستودع queue-warehouse في القائمة، ثم انقر على عرض مواد العرض.
- في قسم عدد الأشخاص، اضبط قيمة الحدّ الأدنى على 1 وقيمة الحدّ الأقصى على 5.
- لفلترة بيانات الفيديو المعالَجة والمخزَّنة في "مستودع الوسائط" في Vertex AI Vision، انقر على بحث.

عرض لبيانات الفيديو المخزَّنة التي تتطابق مع معايير البحث في "وحدة تحكّم Google Cloud"
10. إضافة تعليقات توضيحية إلى النتائج وتحليلها باستخدام جدول BigQuery
- في "دفتر الملاحظات"، ابدأ المتغيرات التالية في الخلية.
DATASET_ID='vision_ai_dataset'
bq_table=f'{PROJECT_ID}.{DATASET_ID}.queue-app'
frame_buffer_size=10000
frame_buffer_error_milliseconds=5
dashboard_update_delay_seconds=3
rtsp_url='rtsp://localhost:8554/seq25_h264'
- الآن، سنلتقط اللقطات من بث rtsp باستخدام الرمز التالي:
import cv2
import threading
from collections import OrderedDict
from datetime import datetime, timezone
frame_buffer = OrderedDict()
frame_buffer_lock = threading.Lock()
stream = cv2.VideoCapture(rtsp_url)
def read_frames(stream):
global frames
while True:
ret, frame = stream.read()
frame_ts = datetime.now(timezone.utc).timestamp() * 1000
if ret:
with frame_buffer_lock:
while len(frame_buffer) >= frame_buffer_size:
_ = frame_buffer.popitem(last=False)
frame_buffer[frame_ts] = frame
frame_buffer_thread = threading.Thread(target=read_frames, args=(stream,))
frame_buffer_thread.start()
print('Waiting for stream initialization')
while not list(frame_buffer.keys()): pass
print('Stream Initialized')
- اسحب الطابع الزمني للبيانات ومعلومات التعليقات التوضيحية من جدول BigQuery وأنشئ دليلاً لتخزين صور اللقطات التي تم التقاطها:
from google.cloud import bigquery
import pandas as pd
client = bigquery.Client(project=PROJECT_ID)
query = f"""
SELECT MAX(ingestion_time) AS ts
FROM `{bq_table}`
"""
bq_max_ingest_ts_df = client.query(query).to_dataframe()
bq_max_ingest_epoch = str(int(bq_max_ingest_ts_df['ts'][0].timestamp()*1000000))
bq_max_ingest_ts = bq_max_ingest_ts_df['ts'][0]
print('Preparing to pull records with ingestion time >', bq_max_ingest_ts)
if not os.path.exists(bq_max_ingest_epoch):
os.makedirs(bq_max_ingest_epoch)
print('Saving output frames to', bq_max_ingest_epoch)
- أضِف تعليقات توضيحية إلى الإطارات باستخدام الرمز التالي:
import json
import base64
import numpy as np
from IPython.display import Image, display, HTML, clear_output
im_width = stream.get(cv2.CAP_PROP_FRAME_WIDTH)
im_height = stream.get(cv2.CAP_PROP_FRAME_HEIGHT)
dashdelta = datetime.now()
framedata = {}
cntext = lambda x: {y['entity']['labelString']: y['count'] for y in x}
try:
while True:
try:
annotations_df = client.query(f'''
SELECT ingestion_time, annotation
FROM `{bq_table}`
WHERE ingestion_time > TIMESTAMP("{bq_max_ingest_ts}")
''').to_dataframe()
except ValueError as e:
continue
bq_max_ingest_ts = annotations_df['ingestion_time'].max()
for _, row in annotations_df.iterrows():
with frame_buffer_lock:
frame_ts = np.asarray(list(frame_buffer.keys()))
delta_ts = np.abs(frame_ts - (row['ingestion_time'].timestamp() * 1000))
delta_tx_idx = delta_ts.argmin()
closest_ts_delta = delta_ts[delta_tx_idx]
closest_ts = frame_ts[delta_tx_idx]
if closest_ts_delta > frame_buffer_error_milliseconds: continue
image = frame_buffer[closest_ts]
annotations = json.loads(row['annotation'])
for box in annotations['identifiedBoxes']:
image = cv2.rectangle(
image,
(
int(box['normalizedBoundingBox']['xmin']*im_width),
int(box['normalizedBoundingBox']['ymin']*im_height)
),
(
int((box['normalizedBoundingBox']['xmin'] + box['normalizedBoundingBox']['width'])*im_width),
int((box['normalizedBoundingBox']['ymin'] + box['normalizedBoundingBox']['height'])*im_height)
),
(255, 0, 0), 2
)
img_filename = f"{bq_max_ingest_epoch}/{row['ingestion_time'].timestamp() * 1000}.png"
cv2.imwrite(img_filename, image)
binimg = base64.b64encode(cv2.imencode('.jpg', image)[1]).decode()
curr_framedata = {
'path': img_filename,
'timestamp_error': closest_ts_delta,
'counts': {
**{
k['annotation']['displayName'] : cntext(k['counts'])
for k in annotations['stats']["activeZoneCounts"]
},
'full-frame': cntext(annotations['stats']["fullFrameCount"])
}
}
framedata[img_filename] = curr_framedata
if (datetime.now() - dashdelta).total_seconds() > dashboard_update_delay_seconds:
dashdelta = datetime.now()
clear_output()
display(HTML(f'''
<h1>Queue Monitoring Application</h1>
<p>Live Feed of the queue camera:</p>
<p><img alt="" src="{img_filename}" style="float: left;"/></a></p>
<table border="1" cellpadding="1" cellspacing="1" style="width: 500px;">
<caption>Current Model Outputs</caption>
<thead>
<tr><th scope="row">Metric</th><th scope="col">Value</th></tr>
</thead>
<tbody>
<tr><th scope="row">Serving Area People Count</th><td>{curr_framedata['counts']['serving-zone']['Person']}</td></tr>
<tr><th scope="row">Queueing Area People Count</th><td>{curr_framedata['counts']['queue-zone']['Person']}</td></tr>
<tr><th scope="row">Total Area People Count</th><td>{curr_framedata['counts']['full-frame']['Person']}</td></tr>
<tr><th scope="row">Timestamp Error</th><td>{curr_framedata['timestamp_error']}</td></tr>
</tbody>
</table>
<p> </p>
'''))
except KeyboardInterrupt:
print('Stopping Live Monitoring')

- أوقِف مهمة التعليق التوضيحي باستخدام الزر إيقاف في شريط قائمة دفتر الملاحظات

- يمكنك إعادة زيارة إطارات فردية باستخدام الرمز التالي:
from IPython.html.widgets import Layout, interact, IntSlider
imgs = sorted(list(framedata.keys()))
def loadimg(frame):
display(framedata[imgs[frame]])
display(Image(open(framedata[imgs[frame]]['path'],'rb').read()))
interact(loadimg, frame=IntSlider(
description='Frame #:',
value=0,
min=0, max=len(imgs)-1, step=1,
layout=Layout(width='100%')))

11. تهانينا
تهانينا، لقد أكملت الدرس التطبيقي.
إخلاء مساحة
لتجنُّب تحمّل رسوم في حسابك على Google Cloud مقابل الموارد المستخدَمة في هذا البرنامج التعليمي، احذف المشروع الذي يحتوي على الموارد أو احتفظ بالمشروع واحذف الموارد الفردية.
حذف المشروع
حذف مراجع فردية
المراجع
https://cloud.google.com/vision-ai/docs/overview
https://cloud.google.com/vision-ai/docs/occupancy-count-tutorial