تطبيق كشف قائمة انتظار Vertex AI Vision

1. الأهداف

نظرة عامة

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

  • احتسِب عدد الأشخاص الذين يقفون في طابور الانتظار.
  • احسب عدد الأشخاص الذين يتلقون الخدمة في مكتب الخدمة.

المعلومات التي ستطّلع عليها

  • كيفية إنشاء تطبيق في Vertex AI Vision ونشره
  • كيفية إعداد بث لبروتوكول RTSP باستخدام ملف فيديو ونقل البث إلى Vertex AI Vision باستخدام برنامج vaictl من كمبيوتر Jupyter Notebook
  • كيفية استخدام نموذج "إحصاءات الإشغال" وميزاته المختلفة
  • كيفية البحث عن الفيديوهات في مساحة التخزين Media Warehouse في Vertex AI Vision
  • كيفية ربط الناتج بأداة BigQuery، وكتابة طلب بحث SQL لاستخراج الإحصاءات من نتائج json للنموذج واستخدام النتائج لتصنيف الفيديو الأصلي وإضافة تعليقات توضيحية إليه

التكلفة:

تبلغ التكلفة الإجمالية لتنفيذ هذا البرنامج التدريبي على Google Cloud حوالي دولارين أمريكيين.

2. قبل البدء

أنشئ مشروعًا وفعِّل واجهات برمجة التطبيقات:

  1. في وحدة تحكّم Google Cloud، في صفحة أداة اختيار المشاريع، اختَر إنشاء مشروع على Google Cloud أو أنشِئ مشروعًا. ملاحظة: إذا كنت لا تخطّط للاحتفاظ بالموارد التي تنشئها في هذه العملية، أنشئ مشروعًا بدلاً من اختيار مشروع حالي. بعد الانتهاء من هذه الخطوات، يمكنك حذف المشروع، ما يؤدي إلى إزالة جميع الموارد المرتبطة به. الانتقال إلى أداة اختيار المشروع
  2. تأكَّد من تفعيل الفوترة لمشروعك على السحابة الإلكترونية. تعرَّف على كيفية التحقّق مما إذا كانت الفوترة مفعَّلة في مشروع.
  3. فعِّل Compute Engine وVertex API وNotebook API وVision AI API. تفعيل واجهات برمجة التطبيقات

إنشاء حساب خدمة:

  1. في Google Cloud Console، انتقِل إلى صفحة إنشاء حساب خدمة. الانتقال إلى "إنشاء حساب خدمة"
  2. اختَر مشروعك.
  3. في حقل اسم حساب الخدمة، أدخِل اسمًا. تملأ وحدة تحكّم Google Cloud حقل معرّف حساب الخدمة استنادًا إلى هذا الاسم. في حقل وصف حساب الخدمة، أدخِل وصفًا. على سبيل المثال، حساب الخدمة للبدء السريع.
  4. انقر على إنشاء ومتابعة.
  5. لمنح إذن الوصول إلى مشروعك، امنح حساب الخدمة الأدوار التالية:
  • الذكاء الاصطناعي للصور > محرِّر الذكاء الاصطناعي للصور
  • Compute Engine > Compute Instance Admin (إصدار تجريبي)
  • BigQuery > مشرف BigQuery

في قائمة اختيار دور، اختَر دورًا. للحصول على أدوار إضافية، انقر على إضافة دور آخر وأضِف كل دور إضافي.

  1. انقر على متابعة.
  2. انقر على تم لإنهاء إنشاء حساب الخدمة. لا تغلِق نافذة المتصفّح. ستحتاج إليه في الخطوة التالية.

3- إعداد Jupyter Notebook

قبل إنشاء تطبيق في "إحصاءات الإشغال"، يجب تسجيل مصدر بيانات يمكن للتطبيق استخدامه لاحقًا.

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

  1. تشغيل خادم rtsp كعملية في الخلفية
  2. تشغيل الأمر vaictl كعملية في الخلفية
  3. تنفيذ طلبات البحث ومعالجة الرمز البرمجي لتحليل نتائج إحصاءات الإشغال

إنشاء دفتر جوبيتر

الخطوة الأولى لإرسال فيديو من مثيل Jupyter Notebook هي إنشاء دفتر البيانات باستخدام حساب الخدمة الذي تم إنشاؤه في الخطوة السابقة.

  1. في وحدة التحكّم، انتقِل إلى صفحة Vertex AI. الانتقال إلى Vertex AI Workbench
  2. انقر على "دفاتر الملاحظات التي يديرها المستخدم".

65b7112822858dce.png

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

dc156f20b14651d7.png

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

b4dbc5fddc37e8d9.png

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

ec0b9ef00f0ef470.png

  1. بعد إنشاء المثيل، انقر على فتح JUPYTERLAB.

4. إعداد دفتر ملاحظات لبث الفيديو

قبل إنشاء تطبيق في "إحصاءات الإشغال"، يجب تسجيل مصدر بيانات يمكن للتطبيق استخدامه لاحقًا.

في هذا الدليل التعليمي، سنستخدم نسخة Jupyter Notebook لاستضافة فيديو، وسيتم إرسال بيانات الفيديوهات التي يتم بثّها من محطة Notebook الطرفية.

تنزيل أداة سطر الأوامر vaictl

  1. في مثيل Jupyterlab المفتوح، افتح مفكرة من مشغّل التطبيقات.

a6d182923ae4ada3.png

  1. نزِّل أداة سطر أوامر 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 لبث بيانات الفيديو إلى تطبيق إحصاءات الإشغال.

تسجيل بث جديد

  1. انقر على علامة التبويب "الأحداث" في اللوحة اليمنى من Vertex AI Vision.
  2. انقر على زر التسجيل في أعلى الصفحة eba418e723916514.png.
  3. في اسم ساحة المشاركات، أدخِل 'queue-stream'
  4. في حقل "المنطقة"، اختَر المنطقة نفسها التي تم اختيارها أثناء إنشاء "دفتر ملاحظات" في الخطوة السابقة.
  5. انقر على تسجيل.

نسخ عيّنة فيديو إلى جهازك الافتراضي

  1. في دفتر ملاحظاتك، انسخ نموذج فيديو باستخدام الأمر wget التالي.
!wget -q https://github.com/vagrantism/interesting-datasets/raw/main/video/collective_activity/seq25_h264.mp4

بث الفيديو من جهاز افتراضي ونقل البيانات إلى البث

  1. لإرسال ملف الفيديو هذا على الجهاز إلى بث إدخال التطبيق، استخدِم الأمر التالي في خلية دفتر الملاحظات. يجب إجراء عمليات الاستبدال للمتغيّرات التالية:
  • 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'
  1. بدء خادم rtsp-simple حيث نبث ملف الفيديو باستخدام بروتوكول 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)
  1. استخدام أداة سطر الأوامر 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)
  1. استخدِم أداة سطر الأوامر vaictl لبث الفيديو من معرّف الموارد المنتظم لخادم rtsp إلى بث "queue-stream" في Vertex AI Vision الذي تم إنشاؤه في الخطوة السابقة.
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 من خلال اختيار بث "البث من خلال الانتظار في قائمة المحتوى التالي".

الانتقال إلى علامة التبويب "الأحداث المباشرة"

1b7aac7d36552f29.png

6- إنشاء طلب

الخطوة الأولى هي إنشاء تطبيق يعالج بياناتك. يمكن اعتبار التطبيق مسارًا آليًا يربط ما يلي:

  • نقل البيانات: يتم نقل خلاصة فيديو إلى مصدر بيانات.
  • تحليل البيانات: يمكن إضافة نموذج الذكاء الاصطناعي(الرؤية الحاسوبية) بعد نقل البيانات.
  • تخزين البيانات: يمكن تخزين نسختَي خلاصة الفيديو (البث الأصلي والبث الذي تمت معالجته بواسطة نموذج الذكاء الاصطناعي) في مستودع وسائط.

في وحدة تحكّم Google Cloud، يتم تمثيل التطبيق في شكل رسم بياني.

إنشاء تطبيق فارغ

قبل أن تتمكّن من تعبئة الرسم البياني للتطبيق، عليك أولاً إنشاء تطبيق فارغ.

أنشئ تطبيقًا في "وحدة تحكّم Google Cloud".

  1. انتقِل إلى وحدة التحكم في Google Cloud.
  2. افتح علامة التبويب التطبيقات في لوحة بيانات Vertex AI Vision. الانتقال إلى علامة التبويب "التطبيقات"
  3. انقر على الزر إنشاء. 21ecba7a23e9979e.png
  4. أدخِل queue-app كاسم التطبيق واختَر منطقتك.
  5. انقر على إنشاء.

إضافة عقد مكوّنات التطبيق

بعد إنشاء التطبيق الفارغ، يمكنك إضافة العُقد الثلاثة إلى الرسم البياني للتطبيق:

  1. وحدة نقل البيانات: مورد البث الذي ينقل البيانات المُرسَلة من خادم فيديو rtsp أنشأته في دفتر البيانات
  2. وحدة المعالجة: نموذج إحصاءات الإشغال الذي يعالج البيانات المستورَدة.
  3. وحدة التخزين: مستودع الوسائط الذي يخزِّن الفيديوهات التي تمت معالجتها، ويعمل كمستودع للبيانات الوصفية. تتضمّن أماكن تخزين البيانات الوصفية معلومات تحليلية عن بيانات الفيديو التي تم نقلها ومعلومات استنتجتها نماذج الذكاء الاصطناعي.

أضِف عقد المكوّنات إلى تطبيقك في وحدة التحكّم.

  1. افتح علامة التبويب التطبيقات في لوحة بيانات Vertex AI Vision. الانتقال إلى علامة التبويب "التطبيقات"

سينقلك هذا إلى الرسم البياني المرئي لقناة المعالجة.

إضافة عقدة نقل بيانات

  1. لإضافة عقدة مصدر إدخال، حدِّد الخيار ساحات المشاركات في قسم الموصلات في القائمة الجانبية.
  2. في قسم المصدر من قائمة البث التي تفتح، انقر على إضافة مصادر بيانات.
  3. في قائمة إضافة أحداث البث، اختَر بثّ من "قائمة المحتوى التالي".
  4. لإضافة البث إلى الرسم البياني للتطبيق، انقر على إضافة أحداث البث.

إضافة عقدة معالجة بيانات

  1. لإضافة عقدة نموذج عدد النزلاء، اختَر خيار إحصاءات الإشغال في قسم النماذج المخصّصة من القائمة الجانبية.
  2. اترك الخيارات التلقائية الأشخاص. أزِل العلامة من المربّع بجانب مركبات إذا كان محدّدًا.

618b0c9dc671bae3.png

  1. في قسم "الخيارات المتقدّمة"، انقر على إنشاء مناطق/خطوط نشطة 5b2f31235603e05d.png.
  2. ارسم المناطق النشطة باستخدام أداة المضلّع (Polygon) لاحتساب عدد الأشخاص في تلك المنطقة. تصنيف المنطقة وفقًا لذلك

50281a723650491f.png

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

2bf0ff4d029d29eb.png

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

c067fa256ca5bb96.png

إضافة عقدة لتخزين البيانات

  1. لإضافة عقدة وجهة الإخراج (التخزين)، اختَر مستودع الذكاء الاصطناعي بالاستناد إلى الرؤية في قسم الموصّلات في القائمة الجانبية.
  2. انقر على موصِّل Vertex AI Warehouse لفتح قائمته، ثم انقر على ربط المستودع.
  3. في قائمة ربط المستودع، اختَر إنشاء مستودع جديد. أدخِل اسم "مستودع الطلبات في الانتظار"‏ (queue-warehouse)، واترك مدة مدة البقاء (TTL) على 14 يومًا.
  4. انقر على الزر إنشاء لإضافة المستودع.

7- ربط الإخراج بجدول BigQuery

عند إضافة موصِّل BigQuery إلى تطبيق Vertex AI Vision، سيتم نقل جميع نواتج نماذج التطبيقات المرتبطة إلى الجدول المستهدَف.

يمكنك إنشاء جدول BigQuery الخاص بك وتحديد هذا الجدول عند إضافة أداة ربط BigQuery إلى التطبيق، أو السماح لمنصّة تطبيق Vertex AI Vision بإنشاء الجدول تلقائيًا.

إنشاء الجداول تلقائيًا

إذا سمحت لمنصّة تطبيقات Vertex AI Vision بإنشاء الجدول تلقائيًا، يمكنك تحديد هذا الخيار عند إضافة عقدة رابط BigQuery.

تنطبق شروط الجدول ومجموعة البيانات التالية إذا كنت تريد استخدام إنشاء الجداول تلقائيًا:

  • مجموعة البيانات: اسم مجموعة البيانات التي تم إنشاؤها تلقائيًا هو visionai_dataset.
  • الجدول: اسم الجدول الذي تم إنشاؤه تلقائيًا هو visionai_dataset.APPLICATION_ID.
  • حدث خطأ أثناء المعالجة:
  • في حال توفُّر جدول يحمل الاسم نفسه ضمن مجموعة البيانات نفسها، لا يتم إنشاء الجدول تلقائيًا.
  1. افتح علامة التبويب التطبيقات في لوحة بيانات Vertex AI Vision. الانتقال إلى علامة التبويب "التطبيقات"
  2. اختَر عرض التطبيق بجانب اسم تطبيقك من القائمة.
  3. في صفحة "أداة إنشاء التطبيقات"، اختَر BigQuery من قسم الموصّلات.
  4. اترك حقل مسار BigQuery فارغًا.

ee0b67d4ab2263d.png

  1. في تخزين البيانات الوصفية من: اختَر "إحصاءات الإشغال" فقط وأزِل العلامة من المربّع بجانب مصادر البيانات.

من المفترض أن يظهر الرسم البياني النهائي للتطبيق على النحو التالي:

da0a1a049843572f.png

8. نشر تطبيقك لاستخدامه

بعد إنشاء تطبيقك الشامل الذي يتضمّن جميع المكوّنات اللازمة، تكون الخطوة الأخيرة لاستخدام التطبيق هي نشره.

  1. افتح علامة التبويب التطبيقات في لوحة بيانات Vertex AI Vision. الانتقال إلى علامة التبويب "التطبيقات"
  2. اختَر عرض التطبيق بجانب التطبيق قائمة المحتوى التالي في القائمة.
  3. من صفحة استوديو YouTube، انقر على الزر نشر.
  4. في مربّع حوار التأكيد التالي، انقر على نشر. قد تستغرق عملية النشر عدّة دقائق. بعد انتهاء عملية النشر، تظهر علامات اختيار خضراء بجانب العقد. dc514d9b9f35099d.png

9. البحث عن محتوى الفيديو في مستودع التخزين

بعد نقل بيانات الفيديو إلى تطبيق المعالجة، يمكنك عرض بيانات الفيديو التي تم تحليلها والبحث في البيانات استنادًا إلى معلومات إحصاءات الإشغال.

  1. افتح علامة التبويب المستودعات في لوحة بيانات Vertex AI Vision. الانتقال إلى علامة التبويب "المستودعات"
  2. ابحث عن مستودع "قائمة الانتظار" في القائمة، ثم انقر على عرض مواد العرض.
  3. في قسم عدد الأشخاص، اضبط القيمة الحد الأدنى على 1، والقيمة الحد الأقصى على 5.
  4. لفلترة بيانات الفيديوهات التي تمت معالجتها والمخزّنة في "مستودع الوسائط" في Vertex AI Vision، انقر على بحث.

a0e5766262443d6c.png

عرض لبيانات الفيديو المخزّنة التي تتطابق مع معايير البحث في وحدة تحكّم Google Cloud

10. إضافة تعليقات توضيحية وتحليل النتائج باستخدام جدول BigQuery

  1. في دفتر الملاحظات، قم بتهيئة المتغيرات التالية في الخلية.
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'
  1. سنلتقط الآن اللقطات من بث 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')
  1. سحب الطابع الزمني للبيانات ومعلومات التعليق التوضيحي من جدول 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)
  1. أضِف تعليقات توضيحية إلى اللقطات باستخدام الرمز البرمجي التالي:
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>&nbsp;</p>
        '''))
except KeyboardInterrupt:
  print('Stopping Live Monitoring')

9426ffe2376f0a7d.png

  1. يمكنك إيقاف مهمة التعليق التوضيحي باستخدام الزر إيقاف في شريط قائمة المفكرة.

6c19cb00dcb28894.png

  1. يمكنك إعادة زيارة اللقطات الفردية باستخدام الرمز التالي:
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%')))

78b63b546a4c883b.png

11. تهانينا

تهانينا، لقد أكملت الدرس التطبيقي.

التنظيف

لتجنُّب تحصيل رسوم من حسابك على Google Cloud مقابل الموارد المستخدَمة في هذا الدليل التعليمي، يمكنك إما حذف المشروع الذي يحتوي على الموارد أو الاحتفاظ بالمشروع وحذف الموارد الفردية.

حذف المشروع

حذف موارد فردية

المراجع

https://cloud.google.com/vision-ai/docs/overview

https://cloud.google.com/vision-ai/docs/occupancy-count-tutorial

الترخيص

استطلاع

كيف استخدمت هذا الدليل التعليمي؟

قرأت المقالة بالكامل فقط قرأت المقالة وأكملت التمارين

ما مدى فائدة هذا الدرس التطبيقي حول الترميز؟

مفيدة جدًا مفيدة نوعًا ما غير مفيدة

ما مدى سهولة اتباع هذا الدرس التطبيقي حول الترميز؟

سهل متوسط صعب