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 ứng dụng Vertex AI Vision từ đầu đến cuối để theo dõi kích thước 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 sẵn 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 để thu thập những thông tin sau:
- Đếm số người đang xếp hàng.
- Đế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 và triển khai ứng dụng trong Vertex AI Vision
- 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ừ Sổ tay Jupyter.
- Cách sử dụng mô hình Phân tích mức sử dụng phòng và các tính năng của mô hình này.
- Cách tìm video trong kho lưu trữ 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ừ dữ liệu đầu ra json của mô hình, đồng thời sử dụng kết quả đó để gắn nhãn và chú thích cho video gốc.
Chi phí:
Tổng chi phí để chạy lớp học này trên Google Cloud là khoảng 2 USD.
2. Trước khi bắt đầu
Tạo dự án và bật API:
- Trong Google Cloud Console, trên trang bộ chọn dự án, hãy chọn hoặc tạo dự án Google Cloud. Lưu ý: Nếu bạn không đị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, xoá 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 Google 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 API
Tạo tài khoản dịch vụ:
- Trong Google Cloud Console, 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 tên. Bảng điều khiển Google Cloud sẽ điền vào trường Mã tài khoản dịch vụ dựa trên tên này. Trong trường 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ụ để 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 (Trí tuệ nhân tạo cho thị giác > Trình chỉnh sửa trí tuệ nhân tạo cho thị giác)
- Compute Engine > Compute Instance Admin (beta)
- BigQuery > BigQuery Admin (BigQuery > Quản trị viên BigQuery).
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 việc tạo tài khoản dịch vụ. Đừng đóng cửa sổ trình duyệt. Bạn sẽ sử dụng nó trong bước tiếp theo.
3. Thiết lập Jupyter Notebook
Trước khi tạo một Ứng dụng trong công cụ Phân tích về tỷ lệ kín phòng, bạn phải đăng ký một luồng để Ứ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ể Sổ tay Jupyter lưu trữ một video và gửi dữ liệu video truyền trực tuyến đó từ sổ tay. Chúng ta đang sử dụng sổ tay jupyter vì ứng dụng này cho phép chúng ta 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 để thử nghiệm nhanh. Chúng ta sẽ sử dụng sổ tay này để:
- Chạy máy chủ rtsp dưới dạng quy trình trong nền
- Chạy lệnh vaictl dưới dạng quy trình trong nền
- Chạy truy vấn và mã xử lý để phân tích kết quả phân tích số người lưu trú
Tạo sổ tay Jupyter
Bước đầu tiên để gửi video từ một thực thể Sổ tay Jupyter là tạo sổ tay bằng tài khoản dịch vụ mà chúng ta đã 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 (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 Các phần về quyền
- Bỏ đánh dấu lựa chọn Use Compute Engine mặc định cho tài khoản dịch vụ
- Thêm email Tài khoản dịch vụ đã tạo ở bước trước. Sau đó, hãy nhấp vào Tạo.
- Sau khi tạo thực thể, hãy nhấp vào MỞ JUPYTERLAB.
4. Thiết lập Sổ tay để phát trực tuyến video
Trước khi tạo một Ứng dụng trong công cụ Phân tích về tỷ lệ kín phòng, bạn phải đăng ký một luồng để Ứng dụng có thể sử dụng sau này.
Trong hướng dẫn này, chúng ta sẽ sử dụng phiên bản Jupyter Notebook để lưu trữ video và bạn gửi dữ liệu video phát trực tuyến đó từ cửa sổ dòng lệnh của Notebook.
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) từ 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 ô của 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 để phát trực tuyến
Sau khi thiết lập môi trường máy tính xách tay bằng các công cụ dòng lệnh bắt buộc, bạn có thể sao chép tệp video mẫu rồi sử dụng vaictl để truyền trực tuyến dữ liệu video đến ứng dụng phân tích tình trạng phòng.
Đăng ký một sự kiện phát trực tiếp 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ý ở đầu
- Trong mục Tên sự kiện phát trực tiếp, hãy nhập "queue-stream"
- Trong khu vực, hãy chọn cùng một khu vực đã chọn trong quá trình tạo Sổ tay ở bước trước.
- Nhấp vào Đăng ký
Sao chép 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 tuyến video từ máy ảo và nhập dữ liệu vào luồng
- Để gửi tệp video trên máy này tới luồng đầu vào của ứng dụng, hãy sử dụng lệnh sau trong ô sổ tay. Bạn phải thực hiện các thay thế biến sau:
- PROJECT_ID: Mã dự án của bạn trên Google Cloud.
- LOCATION (VỊ TRÍ): Mã nhận dạng 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í đám mây.
- LOCAL_FILE: Tên tệp của 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 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 trực tuyến video từ uri máy chủ rtsp đến luồng "queue-stream" của Vertex AI Vision 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ắt đầu thao tác nhập vaictl đến khi video xuất hiện trong trang tổng quan.
Sau khi quá trình truyền trực tuyến có sẵn, 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.
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. Ứng dụng có thể được coi là một quy trình tự động kết nối những thành phần sau:
- Quá trình 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ô hình AI (Trí tuệ nhân tạo) (Khoa học 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 kho phương tiện.
Trong Google Cloud Console, ứng dụng được biểu thị dưới dạng biểu đồ.
Tạo ứng dụng trống
Để có thể điền 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 Google Cloud.
- Chuyển đến bảng điều khiển của Google Cloud.
- Mở thẻ Applications (Ứ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 và chọn khu vực của bạn.
- Nhấp vào Tạo.
Thêm nút thành phần ứng dụng
Sau khi tạo ứng dụng trống, bạn có thể thêm ba nút vào biểu đồ ứng dụng:
- Điểm truyền dẫn: Tài nguyên luồng truyền dẫn dữ liệu được gửi 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 số người lưu trú hoạt động dựa trên dữ liệu được nhập.
- Nút bộ nhớ: Kho 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. 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 suy luận của các mô hình AI.
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ẻ Applications (Ứng dụng) trên trang tổng quan Vertex AI Vision. Chuyển đến thẻ Ứng dụng
Thao tác này sẽ đưa bạn đến hình ảnh biểu đồ của quy trình xử lý.
Thêm nút truyền dẫn dữ liệu
- Để thêm nút luồng đầu vào, hãy chọn tuỳ chọn Luồng trong phần Đầu nối của trình đơn bên.
- Trong phần Nguồn của trình đơn Luồng mở ra, hãy chọn Thêm luồng.
- Trong trình đơn Thêm luồng, hãy chọn luồng-hàng đợi.
- Để 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 về số người lưu trú, hãy chọn mục số liệu phân tích về số người lưu trú trong mục Mô hình chuyên biệt của trình đơn bên.
- Giữ nguyên lựa chọn mặc định Mọi người. Bỏ đánh dấu mục Xe nếu bạn đã chọn mục này.
- Trong phần Tuỳ chọn nâng cao, hãy nhấp vào Tạo vùng/đường hoạt động
- 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 vùng đó cho phù hợp
- Nhấp vào Mũi tên quay lại ở trên cùng.
- Thêm chế độ cài đặt thời gian lưu lại để 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 nút lưu trữ dữ liệu
- Để thêm nút đích đầu ra (bộ nhớ), hãy chọn tuỳ chọn VIsion AI Warehouse (Kho AI về hình ảnh) trong phần Connectors (Bộ 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, nhấp vào Connect warehouse (Kết nối kho).
- Trong trình đơn Kết nối kho, hãy chọn Tạo kho mới. Đặt tên kho là queue-warehouse và để thời lượng TTL là 14 ngày.
- Nhấp vào nút Tạo để thêm kho.
7. Kết nối đầu ra với bảng BigQuery
Khi bạn thêm trình kết nối BigQuery vào ứng dụng Vertex AI Vision của mình, thì tất cả dữ liệu đầu ra của mô hình ứng dụng đã 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 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 tuỳ chọn này khi thêm nút trình kết nối BigQuery.
Tập dữ liệu và các điều kiện sau đây của bảng sẽ được áp dụng nếu bạn muốn dùng tính năng tạo bảng tự độ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 bảng có cùng tên trong cùng một tập dữ liệu đã tồn tại, thì quá trình tạo tự động sẽ không diễn ra.
- Mở thẻ Applications (Ứ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 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 từ phần Trình kết nối.
- Để trống trường Đường dẫn BigQuery.
- Trong phần siêu dữ liệu của cửa hàng from: chỉ chọn "số liệu phân tích về tỷ lệ kín phòng" rồi bỏ đánh dấu các sự kiện phát trực tiếp.
Biểu đồ ứng dụng hoàn thiện 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ẻ Applications (Ứ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, hãy nhấp vào Deploy (Triển khai). Quá trình triển khai có thể mất vài phút để hoàn tất. Sau khi triển khai xong, 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 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 lưu trú.
- Mở thẻ Kho của trang tổng quan Vertex AI Vision. Chuyển đến thẻ Kho
- Tìm kho hàng trong hàng đợi 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 phương tiện của Vertex AI Vision, hãy nhấp vào Tìm kiếm.
Chế độ xem dữ liệu video đã lưu trữ khớp với tiêu chí tìm kiếm trong bảng điều khiển Google Cloud.
10. Chú thích và phân tích kết quả 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'
- Bây giờ, chúng ta sẽ chụp 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, đồng thờ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 bằng 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 Stop (Dừng) trong thanh trình đơn của sổ tay
- Bạn có thể xem 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 lớp học lập trình!
Dọn dẹp
Để tránh bị tính phí cho tài khoản Google Cloud của bạn đối với các tài nguyên được sử 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 và 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