1. Mục tiêu
Tổng quan
Lớp học lập trình này sẽ tập trung vào việc tạo một ứng dụng Vertex AI Vision từ đầu đến cuối để giám sát quy mô hàng đợi bằng cảnh quay video bán lẻ. Chúng ta sẽ sử dụng các tính năng tích hợp của mô hình Chuyên biệt được huấn luyện trước Phân tích mức độ sử dụng để ghi lại những điều sau:
- Đếm số người đang đứng trong hàng đợi.
- Đếm số người được phục vụ tại quầy.
Kiến thức bạn sẽ học được
- Cách tạo một ứng dụng trong Vertex AI Vision và triển khai ứng dụng đó
- Cách thiết lập luồng RTSP bằng tệp video và nhập luồng đó vào Vertex AI Vision bằng vaictl từ một Sổ tay Jupyter.
- Cách sử dụng mô hình Phân tích mức độ sử dụng và các tính năng khác nhau của mô hình này.
- Cách tìm kiếm video trong Kho lưu trữ đa phương tiện của Vertex AI Vision.
- Cách kết nối đầu ra với BigQuery, viết truy vấn SQL để trích xuất thông tin chi tiết từ đầu ra JSON của mô hình và sử dụng đầu ra đó để gắn nhãn và chú thích video gốc.
Chi phí:
Tổng chi phí để chạy bài tập thực hành này trên Google Cloud là khoảng 2 USD.
2. Trước khi bắt đầu
Tạo một dự án và bật các API:
- Trong bảng điều khiển Cloud, trên trang chọn dự án, hãy chọn hoặc tạo một dự án trên Google Cloud. Lưu ý: Nếu bạn không có ý định giữ lại các tài nguyên mà bạn tạo trong quy trình này, hãy tạo một dự án thay vì chọn một dự án hiện có. Sau khi hoàn tất các bước này, bạn có thể xoá dự án để loại bỏ tất cả tài nguyên liên kết với dự án đó. Chuyển đến bộ chọn dự án
- Đảm bảo rằng bạn đã bật tính năng thanh toán cho dự án trên Cloud. Tìm hiểu cách kiểm tra xem tính năng thanh toán có được bật trên một dự án hay không.
- Bật Compute Engine, Vertex API, Notebook API và Vision AI API. Bật các API
Tạo một tài khoản dịch vụ:
- Trong bảng điều khiển Google Cloud, hãy chuyển đến trang Tạo tài khoản dịch vụ. Chuyển đến phần Tạo tài khoản dịch vụ
- Chọn dự án của bạn.
- Trong trường Tên tài khoản dịch vụ, hãy nhập một tên. Bảng điều khiển Cloud sẽ điền trường Mã tài khoản dịch vụ dựa trên tên này. Trong trường Nội dung mô tả tài khoản dịch vụ, hãy nhập nội dung mô tả. Ví dụ: Tài khoản dịch vụ cho hướng dẫn bắt đầu nhanh.
- Nhấp vào Tạo và tiếp tục.
- Để cấp quyền truy cập vào dự án, hãy cấp(các) vai trò sau cho tài khoản dịch vụ của bạn:
- Vision AI > Vision AI Editor
- Compute Engine > Compute Instance Admin (beta)
- BigQuery > BigQuery Admin .
Trong danh sách Chọn vai trò, hãy chọn một vai trò. Đối với các vai trò khác, hãy nhấp vào Thêm vai trò khác rồi thêm từng vai trò khác.
- Nhấp vào Tiếp tục.
- Nhấp vào Xong để hoàn tất quá trình tạo tài khoản dịch vụ. Đừng đóng cửa sổ trình duyệt. Bạn sẽ sử dụng chỉ mục này trong bước tiếp theo.
3. Thiết lập Jupyter Notebook
Trước khi tạo một Ứng dụng trong Occupancy Analytics, bạn phải đăng ký một luồng mà Ứng dụng có thể sử dụng sau này.
Trong hướng dẫn này, bạn sẽ tạo một thực thể Jupyter Notebook lưu trữ video và gửi dữ liệu video truyền trực tuyến đó từ sổ tay. Chúng tôi đang sử dụng sổ tay jupyter vì nó mang lại cho chúng tôi sự linh hoạt để thực thi các lệnh shell cũng như chạy mã xử lý trước/sau tuỳ chỉnh ở một nơi duy nhất, rất phù hợp cho việc thử nghiệm nhanh. Chúng tôi sẽ sử dụng sổ tay này để:
- Chạy máy chủ rtsp dưới dạng một quy trình nền
- Chạy lệnh vaictl dưới dạng quy trình nền
- Chạy các truy vấn và mã xử lý để phân tích kết quả phân tích mức độ sử dụng
Tạo một sổ tay Jupyter
Bước đầu tiên để gửi video từ một phiên bản Jupyter Notebook là tạo sổ tay bằng tài khoản dịch vụ mà bạn đã tạo ở bước trước.
- Trong bảng điều khiển, hãy chuyển đến trang Vertex AI. Chuyển đến Vertex AI Workbench
- Nhấp vào Sổ tay do người dùng quản lý

- Nhấp vào New Notebook > Tensorflow Enterprise 2.6 (with LTS) > Without GPUs (Sổ tay mới > Tensorflow Enterprise 2.6 (có LTS) > Không có GPU)

- Nhập tên cho sổ tay jupyter. Để biết thêm thông tin, hãy xem Quy ước đặt tên tài nguyên.

- Nhấp vào TUỲ CHỌN NÂNG CAO
- Di chuyển xuống Phần Quyền
- Bỏ đánh dấu lựa chọn Sử dụng tài khoản dịch vụ mặc định của Compute Engine
- Thêm địa chỉ email Tài khoản dịch vụ đã tạo ở bước trước. Sau đó, nhấp vào Tạo.

- Sau khi tạo phiên bản, hãy nhấp vào OPEN JUPYTERLAB (MỞ JUPYTERLAB).
4. Thiết lập Notebook để phát trực tuyến video
Trước khi tạo một Ứng dụng trong Occupancy Analytics, bạn phải đăng ký một luồng mà Ứng dụng có thể sử dụng sau này.
Trong hướng dẫn này, chúng ta sẽ dùng thực thể sổ tay Jupyter để lưu trữ một video và bạn sẽ gửi dữ liệu video phát trực tuyến đó từ thiết bị đầu cuối của sổ tay.
Tải công cụ dòng lệnh vaictl xuống
- Trong phiên bản Jupyterlab đã mở, hãy mở một Notebook (Sổ tay) trong trình chạy.

- Tải công cụ dòng lệnh Vertex AI Vision (vaictl), công cụ dòng lệnh máy chủ rtsp, công cụ open-cv xuống bằng lệnh sau trong ô sổ tay:
!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. Truyền dẫn tệp video để truyền trực tuyến
Sau khi thiết lập môi trường sổ tay bằng các công cụ dòng lệnh bắt buộc, bạn có thể sao chép một tệp video mẫu rồi dùng vaictl để truyền trực tuyến dữ liệu video đến ứng dụng phân tích mức độ sử dụng.
Đăng ký một luồng mới
- Nhấp vào thẻ luồng trên bảng điều khiển bên trái của Vertex AI Vision.
- Nhấp vào nút Đăng ký ở trên cùng

- Trong phần Tên luồng, hãy nhập "queue-stream"
- Trong phần khu vực, hãy chọn cùng một khu vực mà bạn đã chọn trong quá trình tạo Sổ tay ở bước trước.
- Nhấp vào Đăng ký
Sao chép một video mẫu vào máy ảo
- Trong sổ tay, hãy sao chép một video mẫu bằng lệnh wget sau.
!wget -q https://github.com/vagrantism/interesting-datasets/raw/main/video/collective_activity/seq25_h264.mp4
Phát trực tiếp video từ máy ảo và truyền dữ liệu vào luồng phát trực tiếp
- Để gửi tệp video cục bộ này đến luồng đầu vào của ứng dụng, hãy sử dụng lệnh sau trong ô sổ tay của bạn. Bạn phải thay thế các biến sau:
- PROJECT_ID: Mã dự án trên Google Cloud.
- LOCATION: Mã vị trí của bạn. Ví dụ: us-central1. Để biết thêm thông tin, hãy xem bài viết Vị trí trên đám mây.
- LOCAL_FILE: Tên tệp của một tệp video cục bộ. Ví dụ:
seq25_h264.mp4.
PROJECT_ID='<Your Google Cloud project ID>'
LOCATION='<Your stream location>'
LOCAL_FILE='seq25_h264.mp4'
STREAM_NAME='queue-stream'
- Khởi động rtsp-simple-server để truyền trực tuyến tệp video bằng giao thức 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)
- Sử dụng công cụ dòng lệnh ffmpeg để lặp lại video trong luồng 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)
- Sử dụng công cụ dòng lệnh vaictl để truyền phát video từ uri máy chủ rtsp đến luồng Vertex AI Vision 'queue-stream' mà chúng ta đã tạo ở bước trước.
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)
Có thể mất khoảng 100 giây từ khi bạn bắt đầu thao tác truyền dẫn vaictl cho đến khi video xuất hiện trong trang tổng quan.
Sau khi có thể nhập luồng, bạn có thể xem nguồn cấp dữ liệu video trong thẻ Luồng của trang tổng quan Vertex AI Vision bằng cách chọn luồng hàng đợi.
Chuyển đến thẻ Sự kiện phát trực tiếp

6. Tạo ứng dụng
Bước đầu tiên là tạo một ứng dụng xử lý dữ liệu của bạn. Bạn có thể coi ứng dụng là một quy trình tự động kết nối các thành phần sau:
- Nhập dữ liệu: Nguồn cấp dữ liệu video được nhập vào một luồng.
- Phân tích dữ liệu: Bạn có thể thêm một mô hình AI(Thị giác máy tính) sau khi nhập.
- Lưu trữ dữ liệu: Hai phiên bản của nguồn cấp dữ liệu video (luồng ban đầu và luồng do mô hình AI xử lý) có thể được lưu trữ trong một kho lưu trữ nội dung nghe nhìn.
Trong bảng điều khiển Cloud, một ứng dụng được biểu thị dưới dạng một biểu đồ.
Tạo một ứng dụng trống
Trước khi điền vào biểu đồ ứng dụng, trước tiên bạn phải tạo một ứng dụng trống.
Tạo một ứng dụng trong bảng điều khiển Cloud của Google.
- Chuyển đến bảng điều khiển Google Cloud.
- Mở thẻ Ứng dụng trên trang tổng quan Vertex AI Vision. Chuyển đến thẻ Ứng dụng
- Nhấp vào nút Tạo.

- Nhập "queue-app" làm tên ứng dụng rồi chọn khu vực của bạn.
- Nhấp vào Tạo.
Thêm các nút thành phần ứng dụng
Sau khi tạo ứng dụng trống, bạn có thể thêm 3 nút vào biểu đồ ứng dụng:
- Nút tiếp nhận: Tài nguyên luồng tiếp nhận dữ liệu được gửi từ một máy chủ video rtsp mà bạn đã tạo trong sổ tay.
- Nút xử lý: Mô hình phân tích mức độ sử dụng hoạt động dựa trên dữ liệu đã được nhập.
- Nút lưu trữ: Kho lưu trữ nội dung nghe nhìn lưu trữ các video đã xử lý và đóng vai trò là kho lưu trữ siêu dữ liệu. Các kho siêu dữ liệu bao gồm thông tin phân tích về dữ liệu video đã nhập và thông tin do các mô hình AI suy luận.
Thêm các nút thành phần vào ứng dụng của bạn trong bảng điều khiển.
- Mở thẻ Ứng dụng của trang tổng quan Vertex AI Vision. Chuyển đến thẻ Ứng dụng
Thao tác này sẽ đưa bạn đến phần trực quan hoá biểu đồ của quy trình xử lý.
Thêm một nút nhập dữ liệu
- Để thêm một nút luồng đầu vào, hãy chọn mục Luồng trong phần Trình kết nối của trình đơn bên.
- Trong phần Nguồn của trình đơn Phát trực tiếp mở ra, hãy chọn Thêm luồng phát.
- Trong trình đơn Add streams (Thêm luồng), hãy chọn queue-stream.
- Để thêm luồng vào biểu đồ ứng dụng, hãy nhấp vào Thêm luồng.
Thêm nút xử lý dữ liệu
- Để thêm nút mô hình đếm số người, hãy chọn mục phân tích số người trong mục Mô hình chuyên biệt của trình đơn bên.
- Để nguyên lựa chọn mặc định là Mọi người. Bỏ chọn Xe nếu bạn đã chọn.

- Trong phần Tuỳ chọn nâng cao, hãy nhấp vào Tạo vùng/đường kích hoạt

- Vẽ các vùng hoạt động bằng công cụ Đa giác để đếm số người trong vùng đó. Gắn nhãn cho vùng tương ứng

- Nhấp vào biểu tượng Mũi tên quay lại ở trên cùng.

- Thêm chế độ cài đặt cho thời gian dừng để phát hiện tình trạng tắc nghẽn bằng cách nhấp vào Hộp đánh dấu.

Thêm một nút lưu trữ dữ liệu
- Để thêm nút đích đến đầu ra (lưu trữ), hãy chọn mục Kho AI Vision trong phần Trình kết nối của trình đơn bên.
- Nhấp vào Trình kết nối Vertex AI Warehouse để mở trình đơn của trình kết nối này, rồi nhấp vào Kết nối kho dữ liệu.
- Trong trình đơn Kết nối kho hàng, hãy chọn Tạo kho hàng mới. Đặt tên cho kho hàng là queue-warehouse và để nguyên thời lượng TTL là 14 ngày.
- Nhấp vào nút Tạo để thêm kho hàng.
7. Kết nối đầu ra với bảng BigQuery
Khi bạn thêm một trình kết nối BigQuery vào ứng dụng Vertex AI Vision, tất cả đầu ra của mô hình ứng dụng có thể kết nối sẽ được nhập vào bảng đích.
Bạn có thể tạo bảng BigQuery của riêng mình và chỉ định bảng đó khi thêm một trình kết nối BigQuery vào ứng dụng, hoặc để nền tảng ứng dụng Vertex AI Vision tự động tạo bảng.
Tự động tạo bảng
Nếu cho phép nền tảng ứng dụng Vertex AI Vision tự động tạo bảng, bạn có thể chỉ định lựa chọn này khi thêm nút trình kết nối BigQuery.
Các điều kiện sau đây về tập dữ liệu và bảng sẽ áp dụng nếu bạn muốn sử dụng tính năng tự động tạo bảng:
- Tập dữ liệu: Tên tập dữ liệu được tạo tự động là visionai_dataset.
- Bảng: Tên bảng được tạo tự động là visionai_dataset.APPLICATION_ID.
- Xử lý lỗi:
- Nếu có bảng cùng tên trong cùng một tập dữ liệu, thì hệ thống sẽ không tự động tạo bảng.
- Mở thẻ Ứng dụng của trang tổng quan Vertex AI Vision. Chuyển đến thẻ Ứng dụng
- Chọn Xem ứng dụng bên cạnh tên ứng dụng của bạn trong danh sách.
- Trên trang trình tạo ứng dụng, hãy chọn BigQuery trong mục Trình kết nối.
- Để trống trường Đường dẫn BigQuery.

- Trong phần store metadata from: (lưu trữ siêu dữ liệu từ), chỉ chọn "phân tích mức độ sử dụng" và bỏ chọn các luồng.
Biểu đồ ứng dụng cuối cùng sẽ có dạng như sau:

8. Triển khai ứng dụng để sử dụng
Sau khi bạn tạo ứng dụng toàn diện với tất cả các thành phần cần thiết, bước cuối cùng để sử dụng ứng dụng là triển khai ứng dụng đó.
- Mở thẻ Ứng dụng trên trang tổng quan Vertex AI Vision. Chuyển đến thẻ Ứng dụng
- Chọn Xem ứng dụng bên cạnh ứng dụng queue-app trong danh sách.
- Trên trang Studio, hãy nhấp vào nút Deploy (Triển khai).
- Trong hộp thoại xác nhận sau đây, hãy nhấp vào Triển khai. Thao tác triển khai có thể mất vài phút để hoàn tất. Sau khi quá trình triển khai hoàn tất, dấu kiểm màu xanh lục sẽ xuất hiện bên cạnh các nút.

9. Tìm kiếm nội dung video trong kho lưu trữ
Sau khi nhập dữ liệu video vào ứng dụng xử lý, bạn có thể xem dữ liệu video đã phân tích và tìm kiếm dữ liệu dựa trên thông tin phân tích về số người.
- Mở thẻ Kho hàng trên trang tổng quan Vertex AI Vision. Chuyển đến thẻ Kho hàng
- Tìm kho hàng queue-warehouse trong danh sách, rồi nhấp vào Xem tài sản.
- Trong phần Số người, hãy đặt giá trị Tối thiểu thành 1 và giá trị Tối đa thành 5.
- Để lọc dữ liệu video đã xử lý được lưu trữ trong Kho lưu trữ nội dung nghe nhìn của Vertex AI Vision, hãy nhấp vào Tìm kiếm.

Chế độ xem dữ liệu video được lưu trữ phù hợp với tiêu chí tìm kiếm trong bảng điều khiển Cloud của Google.
10. Chú thích và phân tích đầu ra bằng bảng BigQuery
- Trong Sổ tay, hãy khởi chạy các biến sau trong ô.
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'
- Giờ đây, chúng ta sẽ ghi lại các khung hình từ luồng rtsp bằng mã sau:
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')
- Lấy dấu thời gian dữ liệu và thông tin chú thích từ bảng bigquery, rồi tạo một thư mục để lưu trữ hình ảnh khung hình đã chụp:
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)
- Chú thích các khung hình bằng đoạn mã sau:
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')

- Dừng tác vụ chú thích bằng nút Dừng trong thanh trình đơn của sổ tay

- Bạn có thể truy cập lại từng khung hình bằng mã sau:
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. Xin chúc mừng
Xin chúc mừng, bạn đã hoàn thành bài thực hành!
Dọn dẹp
Để tránh bị tính phí vào tài khoản Google Cloud của bạn cho các tài nguyên được dùng trong hướng dẫn này, hãy xoá dự án chứa các tài nguyên đó hoặc giữ lại dự án rồi xoá từng tài nguyên.
Xoá dự án
Xoá từng tài nguyên
Tài nguyên
https://cloud.google.com/vision-ai/docs/overview
https://cloud.google.com/vision-ai/docs/occupancy-count-tutorial