Sử dụng Video Intelligence API với Python

1. Tổng quan

cfaa6ffa7bc5ca70.png

Video Intelligence API cho phép bạn sử dụng công nghệ phân tích video của Google trong các ứng dụng của mình.

Trong phòng thí nghiệm này, bạn sẽ tập trung vào việc sử dụng Video Intelligence API bằng Python.

Kiến thức bạn sẽ học được

  • Cách thiết lập môi trường
  • Cách thiết lập Python
  • Cách phát hiện các thay đổi về cảnh
  • Cách phát hiện nhãn
  • Cách phát hiện nội dung phản cảm
  • Cách chép lời nói
  • Cách phát hiện và theo dõi văn bản
  • Cách phát hiện và theo dõi đối tượng
  • Cách phát hiện và theo dõi biểu trưng

Bạn cần có

  • Một dự án trên Google Cloud
  • Một trình duyệt, chẳng hạn như Chrome hoặc Firefox
  • Làm quen với cách sử dụng Python

Bản khảo sát

Bạn sẽ sử dụng hướng dẫn này như thế nào?

Chỉ đọc Đọc và hoàn thành bài tập

Bạn đánh giá thế nào về trải nghiệm của mình với Python?

Người mới bắt đầu Trung cấp Thành thạo

Bạn đánh giá thế nào về trải nghiệm của mình khi sử dụng các dịch vụ của Google Cloud?

Người mới bắt đầu Trung cấp Thành thạo

2. Thiết lập và yêu cầu

Thiết lập môi trường theo tốc độ của riêng bạn

  1. Đăng nhập vào Google Cloud Console rồi tạo một dự án mới hoặc sử dụng lại một dự án hiện có. Nếu chưa có tài khoản Gmail hoặc Google Workspace, bạn phải tạo một tài khoản.

b35bf95b8bf3d5d8.png

a99b7ace416376c4.png

bd84a6d3004737c5.png

  • Tên dự án là tên hiển thị của những người tham gia dự án này. Đây là một chuỗi ký tự mà các API của Google không sử dụng. Bạn luôn có thể cập nhật thông tin này.
  • Mã dự án là mã duy nhất trên tất cả các dự án trên Google Cloud và không thể thay đổi (bạn không thể thay đổi mã này sau khi đã đặt). Cloud Console sẽ tự động tạo một chuỗi duy nhất; thường thì bạn không cần quan tâm đến chuỗi này. Trong hầu hết các lớp học lập trình, bạn sẽ cần tham chiếu đến Mã dự án (thường được xác định là PROJECT_ID). Nếu không thích mã nhận dạng được tạo, bạn có thể tạo một mã nhận dạng ngẫu nhiên khác. Hoặc bạn có thể thử tên người dùng của riêng mình để xem tên đó có được chấp nhận hay không. Bạn không thể thay đổi tên này sau bước này và tên này sẽ tồn tại trong suốt thời gian của dự án.
  • Để bạn nắm được thông tin, có một giá trị thứ ba là Số dự án mà một số API sử dụng. Tìm hiểu thêm về cả 3 giá trị này trong tài liệu.
  1. Tiếp theo, bạn cần bật tính năng thanh toán trong Cloud Console để sử dụng các tài nguyên/API trên đám mây. Việc thực hiện lớp học lập trình này sẽ không tốn nhiều chi phí, nếu có. Để tắt các tài nguyên nhằm tránh bị tính phí ngoài phạm vi hướng dẫn này, bạn có thể xoá các tài nguyên đã tạo hoặc xoá dự án. Người dùng mới của Google Cloud đủ điều kiện tham gia chương trình Dùng thử miễn phí trị giá 300 USD.

Khởi động Cloud Shell

Mặc dù có thể vận hành Google Cloud từ xa trên máy tính xách tay, nhưng trong lớp học lập trình này, bạn sẽ sử dụng Cloud Shell, một môi trường dòng lệnh chạy trên đám mây.

Kích hoạt Cloud Shell

  1. Trong Cloud Console, hãy nhấp vào Kích hoạt Cloud Shell 853e55310c205094.png.

55efc1aaa7a4d3ad.png

Nếu đây là lần đầu tiên bạn khởi động Cloud Shell, bạn sẽ thấy một màn hình trung gian mô tả về Cloud Shell. Nếu bạn thấy màn hình trung gian, hãy nhấp vào Tiếp tục.

9c92662c6a846a5c.png

Quá trình cung cấp và kết nối với Cloud Shell chỉ mất vài giây.

9f0e51b578fecce5.png

Máy ảo này được trang bị tất cả các công cụ phát triển cần thiết. Nền tảng này cung cấp một thư mục chính có dung lượng 5 GB và chạy trong Google Cloud, giúp tăng cường đáng kể hiệu suất mạng và hoạt động xác thực. Bạn có thể thực hiện hầu hết, nếu không muốn nói là tất cả, công việc của mình trong lớp học lập trình này bằng trình duyệt.

Sau khi kết nối với Cloud Shell, bạn sẽ thấy rằng mình đã được xác thực và dự án được đặt thành mã dự án của bạn.

  1. Chạy lệnh sau trong Cloud Shell để xác nhận rằng bạn đã được xác thực:
gcloud auth list

Đầu ra của lệnh

 Credentialed Accounts
ACTIVE  ACCOUNT
*       <my_account>@<my_domain.com>

To set the active account, run:
    $ gcloud config set account `ACCOUNT`
  1. Chạy lệnh sau trong Cloud Shell để xác nhận rằng lệnh gcloud biết về dự án của bạn:
gcloud config list project

Đầu ra của lệnh

[core]
project = <PROJECT_ID>

Nếu không, bạn có thể đặt nó bằng lệnh sau:

gcloud config set project <PROJECT_ID>

Đầu ra của lệnh

Updated property [core/project].

3. Thiết lập môi trường

Trước khi có thể bắt đầu sử dụng Video Intelligence API, hãy chạy lệnh sau trong Cloud Shell để bật API này:

gcloud services enable videointelligence.googleapis.com

Bạn sẽ thấy như sau:

Operation "operations/..." finished successfully.

Giờ đây, bạn có thể sử dụng Video Intelligence API!

Chuyển đến thư mục chính:

cd ~

Tạo một môi trường ảo Python để tách biệt các phần phụ thuộc:

virtualenv venv-videointel

Kích hoạt môi trường ảo:

source venv-videointel/bin/activate

Cài đặt IPython và thư viện ứng dụng Video Intelligence API:

pip install ipython google-cloud-videointelligence

Bạn sẽ thấy như sau:

...
Installing collected packages: ..., ipython, google-cloud-videointelligence
Successfully installed ... google-cloud-videointelligence-2.11.0 ...

Giờ đây, bạn đã sẵn sàng sử dụng thư viện ứng dụng Video Intelligence API!

Trong các bước tiếp theo, bạn sẽ sử dụng một trình thông dịch Python tương tác có tên là IPython mà bạn đã cài đặt ở bước trước. Bắt đầu một phiên bằng cách chạy ipython trong Cloud Shell:

ipython

Bạn sẽ thấy như sau:

Python 3.9.2 (default, Feb 28 2021, 17:03:44)
Type 'copyright', 'credits' or 'license' for more information
IPython 8.12.0 -- An enhanced Interactive Python. Type '?' for help.

In [1]:

4. Video mẫu

Bạn có thể sử dụng Video Intelligence API để chú thích các video được lưu trữ trong Cloud Storage hoặc được cung cấp dưới dạng byte dữ liệu.

Trong các bước tiếp theo, bạn sẽ sử dụng một video mẫu được lưu trữ trong Cloud Storage. Bạn có thể xem video trong trình duyệt.

afe058b29c480d42.png

Chuẩn bị, sẵn sàng, bắt đầu!

5. Phát hiện các thay đổi về cảnh

Bạn có thể sử dụng Video Intelligence API để phát hiện các thay đổi về cảnh trong video. Cảnh là một đoạn video, một chuỗi khung hình có tính liên tục về hình ảnh.

Sao chép mã sau vào phiên IPython:

from typing import cast

from google.cloud import videointelligence_v1 as vi


def detect_shot_changes(video_uri: str) -> vi.VideoAnnotationResults:
    video_client = vi.VideoIntelligenceServiceClient()
    features = [vi.Feature.SHOT_CHANGE_DETECTION]
    request = vi.AnnotateVideoRequest(input_uri=video_uri, features=features)

    print(f'Processing video: "{video_uri}"...')
    operation = video_client.annotate_video(request)

    # Wait for operation to complete
    response = cast(vi.AnnotateVideoResponse, operation.result())
    # A single video is processed
    results = response.annotation_results[0]

    return results
    

Hãy dành chút thời gian để nghiên cứu mã và xem cách mã này sử dụng phương thức thư viện ứng dụng annotate_video với tham số SHOT_CHANGE_DETECTION để phân tích video và phát hiện các thay đổi về cảnh.

Gọi hàm để phân tích video:

video_uri = "gs://cloud-samples-data/video/JaneGoodall.mp4"

results = detect_shot_changes(video_uri)

Chờ video được xử lý:

Processing video: "gs://cloud-samples-data/video/JaneGoodall.mp4"...

Thêm hàm này để in các cảnh trong video:

def print_video_shots(results: vi.VideoAnnotationResults):
    shots = results.shot_annotations
    print(f" Video shots: {len(shots)} ".center(40, "-"))
    for i, shot in enumerate(shots):
        t1 = shot.start_time_offset.total_seconds()
        t2 = shot.end_time_offset.total_seconds()
        print(f"{i+1:>3} | {t1:7.3f} | {t2:7.3f}")
        

Gọi hàm:

print_video_shots(results)

Bạn sẽ thấy như sau:

----------- Video shots: 34 ------------
  1 |   0.000 |  12.880
  2 |  12.920 |  21.680
  3 |  21.720 |  27.880
...
 32 | 135.160 | 138.320
 33 | 138.360 | 146.200
 34 | 146.240 | 162.520

Nếu trích xuất khung hình ở giữa của mỗi cảnh quay và sắp xếp chúng thành một bức tường khung hình, bạn có thể tạo bản tóm tắt trực quan về video:

25bbffa59f7ed71d.png

Tóm tắt

Trong bước này, bạn có thể thực hiện tính năng phát hiện cảnh thay đổi trên video bằng Video Intelligence API. Bạn có thể đọc thêm về cách phát hiện cảnh thay đổi.

6. Phát hiện nhãn

Bạn có thể sử dụng Video Intelligence API để phát hiện nhãn trong video. Nhãn mô tả video dựa trên nội dung hình ảnh.

Sao chép mã sau vào phiên IPython:

from datetime import timedelta
from typing import Optional, Sequence, cast

from google.cloud import videointelligence_v1 as vi


def detect_labels(
    video_uri: str,
    mode: vi.LabelDetectionMode,
    segments: Optional[Sequence[vi.VideoSegment]] = None,
) -> vi.VideoAnnotationResults:
    video_client = vi.VideoIntelligenceServiceClient()
    features = [vi.Feature.LABEL_DETECTION]
    config = vi.LabelDetectionConfig(label_detection_mode=mode)
    context = vi.VideoContext(segments=segments, label_detection_config=config)
    request = vi.AnnotateVideoRequest(
        input_uri=video_uri,
        features=features,
        video_context=context,
    )

    print(f'Processing video "{video_uri}"...')
    operation = video_client.annotate_video(request)

    # Wait for operation to complete
    response = cast(vi.AnnotateVideoResponse, operation.result())
    # A single video is processed
    results = response.annotation_results[0]

    return results
    

Dành chút thời gian nghiên cứu đoạn mã này và xem cách đoạn mã sử dụng phương thức thư viện ứng dụng annotate_video với tham số LABEL_DETECTION để phân tích một video và phát hiện nhãn.

Gọi hàm để phân tích 37 giây đầu tiên của video:

video_uri = "gs://cloud-samples-data/video/JaneGoodall.mp4"
mode = vi.LabelDetectionMode.SHOT_MODE
segment = vi.VideoSegment(
    start_time_offset=timedelta(seconds=0),
    end_time_offset=timedelta(seconds=37),
)

results = detect_labels(video_uri, mode, [segment])

Chờ video được xử lý:

Processing video: "gs://cloud-samples-data/video/JaneGoodall.mp4"...

Thêm hàm này để in nhãn ở cấp video:

def print_video_labels(results: vi.VideoAnnotationResults):
    labels = sorted_by_first_segment_confidence(results.segment_label_annotations)

    print(f" Video labels: {len(labels)} ".center(80, "-"))
    for label in labels:
        categories = category_entities_to_str(label.category_entities)
        for segment in label.segments:
            confidence = segment.confidence
            t1 = segment.segment.start_time_offset.total_seconds()
            t2 = segment.segment.end_time_offset.total_seconds()
            print(
                f"{confidence:4.0%}",
                f"{t1:7.3f}",
                f"{t2:7.3f}",
                f"{label.entity.description}{categories}",
                sep=" | ",
            )


def sorted_by_first_segment_confidence(
    labels: Sequence[vi.LabelAnnotation],
) -> Sequence[vi.LabelAnnotation]:
    def first_segment_confidence(label: vi.LabelAnnotation) -> float:
        return label.segments[0].confidence

    return sorted(labels, key=first_segment_confidence, reverse=True)


def category_entities_to_str(category_entities: Sequence[vi.Entity]) -> str:
    if not category_entities:
        return ""
    entities = ", ".join([e.description for e in category_entities])
    return f" ({entities})"
    

Gọi hàm:

print_video_labels(results)

Bạn sẽ thấy như sau:

------------------------------- Video labels: 10 -------------------------------
 96% |   0.000 |  36.960 | nature
 74% |   0.000 |  36.960 | vegetation
 59% |   0.000 |  36.960 | tree (plant)
 56% |   0.000 |  36.960 | forest (geographical feature)
 49% |   0.000 |  36.960 | leaf (plant)
 43% |   0.000 |  36.960 | flora (plant)
 38% |   0.000 |  36.960 | nature reserve (geographical feature)
 38% |   0.000 |  36.960 | woodland (forest)
 35% |   0.000 |  36.960 | water resources (water)
 32% |   0.000 |  36.960 | sunlight (light)

Nhờ những nhãn ở cấp video này, bạn có thể hiểu rằng phần đầu video chủ yếu nói về thiên nhiên và cây cối.

Thêm hàm này để in nhãn ở cấp cảnh:

def print_shot_labels(results: vi.VideoAnnotationResults):
    labels = sorted_by_first_segment_start_and_confidence(
        results.shot_label_annotations
    )

    print(f" Shot labels: {len(labels)} ".center(80, "-"))
    for label in labels:
        categories = category_entities_to_str(label.category_entities)
        print(f"{label.entity.description}{categories}")
        for segment in label.segments:
            confidence = segment.confidence
            t1 = segment.segment.start_time_offset.total_seconds()
            t2 = segment.segment.end_time_offset.total_seconds()
            print(f"{confidence:4.0%} | {t1:7.3f} | {t2:7.3f}")


def sorted_by_first_segment_start_and_confidence(
    labels: Sequence[vi.LabelAnnotation],
) -> Sequence[vi.LabelAnnotation]:
    def first_segment_start_and_confidence(label: vi.LabelAnnotation):
        first_segment = label.segments[0]
        ms = first_segment.segment.start_time_offset.total_seconds()
        return (ms, -first_segment.confidence)

    return sorted(labels, key=first_segment_start_and_confidence)
    

Gọi hàm:

print_shot_labels(results)

Bạn sẽ thấy như sau:

------------------------------- Shot labels: 29 --------------------------------
planet (astronomical object)
 83% |   0.000 |  12.880
earth (planet)
 53% |   0.000 |  12.880
water resources (water)
 43% |   0.000 |  12.880
aerial photography (photography)
 43% |   0.000 |  12.880
vegetation
 32% |   0.000 |  12.880
 92% |  12.920 |  21.680
 83% |  21.720 |  27.880
 77% |  27.920 |  31.800
 76% |  31.840 |  34.720
...
butterfly (insect, animal)
 84% |  34.760 |  36.960
...

Nhờ những nhãn ở cấp cảnh này, bạn có thể biết rằng video bắt đầu bằng cảnh quay một hành tinh (có thể là Trái Đất), có một con bướm trong cảnh quay 34.760-36.960s,...

Tóm tắt

Ở bước này, bạn có thể thực hiện việc phát hiện nhãn trên video bằng Video Intelligence API. Bạn có thể đọc thêm về phát hiện nhãn.

7. Phát hiện nội dung phản cảm

Bạn có thể sử dụng Video Intelligence API để phát hiện nội dung phản cảm trong video. Nội dung phản cảm là nội dung người lớn thường không phù hợp với người dưới 18 tuổi, bao gồm nhưng không giới hạn ở ảnh khoả thân, hoạt động tình dục và nội dung khiêu dâm. Tính năng phát hiện chỉ dựa trên tín hiệu hình ảnh theo từng khung hình (không sử dụng âm thanh). Phản hồi bao gồm các giá trị về khả năng dao động từ VERY_UNLIKELY đến VERY_LIKELY.

Sao chép mã sau vào phiên IPython:

from datetime import timedelta
from typing import Optional, Sequence, cast

from google.cloud import videointelligence_v1 as vi


def detect_explicit_content(
    video_uri: str,
    segments: Optional[Sequence[vi.VideoSegment]] = None,
) -> vi.VideoAnnotationResults:
    video_client = vi.VideoIntelligenceServiceClient()
    features = [vi.Feature.EXPLICIT_CONTENT_DETECTION]
    context = vi.VideoContext(segments=segments)
    request = vi.AnnotateVideoRequest(
        input_uri=video_uri,
        features=features,
        video_context=context,
    )

    print(f'Processing video "{video_uri}"...')
    operation = video_client.annotate_video(request)

    # Wait for operation to complete
    response = cast(vi.AnnotateVideoResponse, operation.result())
    # A single video is processed
    results = response.annotation_results[0]

    return results
    

Dành chút thời gian nghiên cứu đoạn mã và xem cách đoạn mã này sử dụng phương thức thư viện ứng dụng annotate_video với tham số EXPLICIT_CONTENT_DETECTION để phân tích video và phát hiện nội dung phản cảm.

Gọi hàm để phân tích 10 giây đầu tiên của video:

video_uri = "gs://cloud-samples-data/video/JaneGoodall.mp4"
segment = vi.VideoSegment(
    start_time_offset=timedelta(seconds=0),
    end_time_offset=timedelta(seconds=10),
)

results = detect_explicit_content(video_uri, [segment])

Chờ video được xử lý:

Processing video: "gs://cloud-samples-data/video/JaneGoodall.mp4"...

Thêm hàm này để in ra số lượng các khả năng khác nhau:

def print_explicit_content(results: vi.VideoAnnotationResults):
    from collections import Counter

    frames = results.explicit_annotation.frames
    likelihood_counts = Counter([f.pornography_likelihood for f in frames])

    print(f" Explicit content frames: {len(frames)} ".center(40, "-"))
    for likelihood in vi.Likelihood:
        print(f"{likelihood.name:<22}: {likelihood_counts[likelihood]:>3}")
        

Gọi hàm:

print_explicit_content(results)

Bạn sẽ thấy như sau:

----- Explicit content frames: 10 ------
LIKELIHOOD_UNSPECIFIED:   0
VERY_UNLIKELY         :  10
UNLIKELY              :   0
POSSIBLE              :   0
LIKELY                :   0
VERY_LIKELY           :   0

Thêm hàm này để in thông tin chi tiết về khung hình:

def print_frames(results: vi.VideoAnnotationResults, likelihood: vi.Likelihood):
    frames = results.explicit_annotation.frames
    frames = [f for f in frames if f.pornography_likelihood == likelihood]

    print(f" {likelihood.name} frames: {len(frames)} ".center(40, "-"))
    for frame in frames:
        print(frame.time_offset)
        

Gọi hàm:

print_frames(results, vi.Likelihood.VERY_UNLIKELY)

Bạn sẽ thấy như sau:

------- VERY_UNLIKELY frames: 10 -------
0:00:00.365992
0:00:01.279206
0:00:02.268336
0:00:03.289253
0:00:04.400163
0:00:05.291547
0:00:06.449558
0:00:07.452751
0:00:08.577405
0:00:09.554514

Tóm tắt

Ở bước này, bạn có thể thực hiện quy trình phát hiện nội dung phản cảm trên video bằng Video Intelligence API. Bạn có thể đọc thêm về cách phát hiện nội dung phản cảm.

8. Chép lời nói

Bạn có thể sử dụng Video Intelligence API để chuyển lời thoại trong video thành văn bản.

Sao chép mã sau vào phiên IPython:

from datetime import timedelta
from typing import Optional, Sequence, cast

from google.cloud import videointelligence_v1 as vi


def transcribe_speech(
    video_uri: str,
    language_code: str,
    segments: Optional[Sequence[vi.VideoSegment]] = None,
) -> vi.VideoAnnotationResults:
    video_client = vi.VideoIntelligenceServiceClient()
    features = [vi.Feature.SPEECH_TRANSCRIPTION]
    config = vi.SpeechTranscriptionConfig(
        language_code=language_code,
        enable_automatic_punctuation=True,
    )
    context = vi.VideoContext(
        segments=segments,
        speech_transcription_config=config,
    )
    request = vi.AnnotateVideoRequest(
        input_uri=video_uri,
        features=features,
        video_context=context,
    )

    print(f'Processing video "{video_uri}"...')
    operation = video_client.annotate_video(request)

    # Wait for operation to complete
    response = cast(vi.AnnotateVideoResponse, operation.result())
    # A single video is processed
    results = response.annotation_results[0]

    return results
    

Dành chút thời gian nghiên cứu đoạn mã này và xem cách đoạn mã sử dụng phương thức thư viện ứng dụng annotate_video với tham số SPEECH_TRANSCRIPTION để phân tích video và chép lời lời nói.

Gọi hàm để phân tích video từ giây thứ 55 đến giây thứ 80:

video_uri = "gs://cloud-samples-data/video/JaneGoodall.mp4"
language_code = "en-GB"
segment = vi.VideoSegment(
    start_time_offset=timedelta(seconds=55),
    end_time_offset=timedelta(seconds=80),
)

results = transcribe_speech(video_uri, language_code, [segment])

Chờ video được xử lý:

Processing video: "gs://cloud-samples-data/video/JaneGoodall.mp4"...

Thêm hàm này để in ra lời nói được chép lời:

def print_video_speech(results: vi.VideoAnnotationResults, min_confidence: float = 0.8):
    def keep_transcription(transcription: vi.SpeechTranscription) -> bool:
        return min_confidence <= transcription.alternatives[0].confidence

    transcriptions = results.speech_transcriptions
    transcriptions = [t for t in transcriptions if keep_transcription(t)]

    print(f" Speech transcriptions: {len(transcriptions)} ".center(80, "-"))
    for transcription in transcriptions:
        first_alternative = transcription.alternatives[0]
        confidence = first_alternative.confidence
        transcript = first_alternative.transcript
        print(f" {confidence:4.0%} | {transcript.strip()}")
        

Gọi hàm:

print_video_speech(results)

Bạn sẽ thấy như sau:

--------------------------- Speech transcriptions: 2 ---------------------------
  91% | I was keenly aware of secret movements in the trees.
  92% | I looked into his large and lustrous eyes. They seem somehow to express his entire personality.

Thêm hàm này để in danh sách các từ được phát hiện và dấu thời gian của các từ đó:

def print_word_timestamps(
    results: vi.VideoAnnotationResults,
    min_confidence: float = 0.8,
):
    def keep_transcription(transcription: vi.SpeechTranscription) -> bool:
        return min_confidence <= transcription.alternatives[0].confidence

    transcriptions = results.speech_transcriptions
    transcriptions = [t for t in transcriptions if keep_transcription(t)]

    print(" Word timestamps ".center(80, "-"))
    for transcription in transcriptions:
        first_alternative = transcription.alternatives[0]
        confidence = first_alternative.confidence
        for word in first_alternative.words:
            t1 = word.start_time.total_seconds()
            t2 = word.end_time.total_seconds()
            word = word.word
            print(f"{confidence:4.0%} | {t1:7.3f} | {t2:7.3f} | {word}")
            

Gọi hàm:

print_word_timestamps(results)

Bạn sẽ thấy như sau:

------------------------------- Word timestamps --------------------------------
 93% |  55.000 |  55.700 | I
 93% |  55.700 |  55.900 | was
 93% |  55.900 |  56.300 | keenly
 93% |  56.300 |  56.700 | aware
 93% |  56.700 |  56.900 | of
...
 94% |  76.900 |  77.400 | express
 94% |  77.400 |  77.600 | his
 94% |  77.600 |  78.200 | entire
 94% |  78.200 |  78.500 | personality.

Tóm tắt

Trong bước này, bạn có thể thực hiện việc chép lời cho một video bằng Video Intelligence API. Bạn có thể đọc thêm về cách chuyển âm thanh thành văn bản.

9. Phát hiện và theo dõi văn bản

Bạn có thể dùng Video Intelligence API để phát hiện và theo dõi văn bản trong video.

Sao chép mã sau vào phiên IPython:

from datetime import timedelta
from typing import Optional, Sequence, cast

from google.cloud import videointelligence_v1 as vi


def detect_text(
    video_uri: str,
    language_hints: Optional[Sequence[str]] = None,
    segments: Optional[Sequence[vi.VideoSegment]] = None,
) -> vi.VideoAnnotationResults:
    video_client = vi.VideoIntelligenceServiceClient()
    features = [vi.Feature.TEXT_DETECTION]
    config = vi.TextDetectionConfig(
        language_hints=language_hints,
    )
    context = vi.VideoContext(
        segments=segments,
        text_detection_config=config,
    )
    request = vi.AnnotateVideoRequest(
        input_uri=video_uri,
        features=features,
        video_context=context,
    )

    print(f'Processing video "{video_uri}"...')
    operation = video_client.annotate_video(request)

    # Wait for operation to complete
    response = cast(vi.AnnotateVideoResponse, operation.result())
    # A single video is processed
    results = response.annotation_results[0]

    return results
    

Hãy dành chút thời gian nghiên cứu mã và xem cách mã này sử dụng phương thức thư viện ứng dụng annotate_video với tham số TEXT_DETECTION để phân tích video và phát hiện văn bản.

Gọi hàm để phân tích video từ giây thứ 13 đến giây thứ 27:

video_uri = "gs://cloud-samples-data/video/JaneGoodall.mp4"
segment = vi.VideoSegment(
    start_time_offset=timedelta(seconds=13),
    end_time_offset=timedelta(seconds=27),
)

results = detect_text(video_uri, segments=[segment])

Chờ video được xử lý:

Processing video: "gs://cloud-samples-data/video/JaneGoodall.mp4"...

Thêm hàm này để in văn bản đã phát hiện:

def print_video_text(results: vi.VideoAnnotationResults, min_frames: int = 15):
    annotations = sorted_by_first_segment_end(results.text_annotations)

    print(" Detected text ".center(80, "-"))
    for annotation in annotations:
        for text_segment in annotation.segments:
            frames = len(text_segment.frames)
            if frames < min_frames:
                continue
            text = annotation.text
            confidence = text_segment.confidence
            start = text_segment.segment.start_time_offset
            seconds = segment_seconds(text_segment.segment)
            print(text)
            print(f"  {confidence:4.0%} | {start} + {seconds:.1f}s | {frames} fr.")


def sorted_by_first_segment_end(
    annotations: Sequence[vi.TextAnnotation],
) -> Sequence[vi.TextAnnotation]:
    def first_segment_end(annotation: vi.TextAnnotation) -> int:
        return annotation.segments[0].segment.end_time_offset.total_seconds()

    return sorted(annotations, key=first_segment_end)


def segment_seconds(segment: vi.VideoSegment) -> float:
    t1 = segment.start_time_offset.total_seconds()
    t2 = segment.end_time_offset.total_seconds()
    return t2 - t1
    

Gọi hàm:

print_video_text(results)

Bạn sẽ thấy như sau:

-------------------------------- Detected text ---------------------------------
GOMBE NATIONAL PARK
   99% | 0:00:15.760000 + 1.7s | 15 fr.
TANZANIA
  100% | 0:00:15.760000 + 4.8s | 39 fr.
With words and narration by
  100% | 0:00:23.200000 + 3.6s | 31 fr.
Jane Goodall
   99% | 0:00:23.080000 + 3.8s | 33 fr.

Thêm hàm này để in danh sách các khung văn bản và hộp giới hạn được phát hiện:

def print_text_frames(results: vi.VideoAnnotationResults, contained_text: str):
    # Vertex order: top-left, top-right, bottom-right, bottom-left
    def box_top_left(box: vi.NormalizedBoundingPoly) -> str:
        tl = box.vertices[0]
        return f"({tl.x:.5f}, {tl.y:.5f})"

    def box_bottom_right(box: vi.NormalizedBoundingPoly) -> str:
        br = box.vertices[2]
        return f"({br.x:.5f}, {br.y:.5f})"

    annotations = results.text_annotations
    annotations = [a for a in annotations if contained_text in a.text]
    for annotation in annotations:
        print(f" {annotation.text} ".center(80, "-"))
        for text_segment in annotation.segments:
            for frame in text_segment.frames:
                frame_ms = frame.time_offset.total_seconds()
                box = frame.rotated_bounding_box
                print(
                    f"{frame_ms:>7.3f}",
                    box_top_left(box),
                    box_bottom_right(box),
                    sep=" | ",
                )
                

Gọi hàm để kiểm tra xem khung hình nào cho thấy tên của người dẫn chuyện:

contained_text = "Goodall"
print_text_frames(results, contained_text)

Bạn sẽ thấy như sau:

--------------------------------- Jane Goodall ---------------------------------
 23.080 | (0.39922, 0.49861) | (0.62752, 0.55888)
 23.200 | (0.38750, 0.49028) | (0.62692, 0.56306)
...
 26.800 | (0.36016, 0.49583) | (0.61094, 0.56048)
 26.920 | (0.45859, 0.49583) | (0.60365, 0.56174)

Nếu vẽ các khung hình chữ nhật trên các khung hình tương ứng, bạn sẽ nhận được kết quả như sau:

7e530d3d25f2f40e.gif

Tóm tắt

Trong bước này, bạn có thể thực hiện việc phát hiện và theo dõi văn bản trên video bằng Video Intelligence API. Bạn có thể đọc thêm về cách phát hiện và theo dõi văn bản.

10. Phát hiện và theo dõi vật thể

Bạn có thể sử dụng Video Intelligence API để phát hiện và theo dõi các đối tượng trong video.

Sao chép mã sau vào phiên IPython:

from datetime import timedelta
from typing import Optional, Sequence, cast

from google.cloud import videointelligence_v1 as vi


def track_objects(
    video_uri: str, segments: Optional[Sequence[vi.VideoSegment]] = None
) -> vi.VideoAnnotationResults:
    video_client = vi.VideoIntelligenceServiceClient()
    features = [vi.Feature.OBJECT_TRACKING]
    context = vi.VideoContext(segments=segments)
    request = vi.AnnotateVideoRequest(
        input_uri=video_uri,
        features=features,
        video_context=context,
    )

    print(f'Processing video "{video_uri}"...')
    operation = video_client.annotate_video(request)

    # Wait for operation to complete
    response = cast(vi.AnnotateVideoResponse, operation.result())
    # A single video is processed
    results = response.annotation_results[0]

    return results
    

Dành chút thời gian để nghiên cứu mã và xem cách mã này sử dụng phương thức thư viện ứng dụng annotate_video với tham số OBJECT_TRACKING để phân tích video và phát hiện các đối tượng.

Gọi hàm để phân tích video từ giây thứ 98 đến giây thứ 112:

video_uri = "gs://cloud-samples-data/video/JaneGoodall.mp4"
segment = vi.VideoSegment(
    start_time_offset=timedelta(seconds=98),
    end_time_offset=timedelta(seconds=112),
)

results = track_objects(video_uri, [segment])

Chờ video được xử lý:

Processing video: "gs://cloud-samples-data/video/JaneGoodall.mp4"...

Thêm hàm này để in danh sách các đối tượng được phát hiện:

def print_detected_objects(
    results: vi.VideoAnnotationResults,
    min_confidence: float = 0.7,
):
    annotations = results.object_annotations
    annotations = [a for a in annotations if min_confidence <= a.confidence]

    print(
        f" Detected objects: {len(annotations)}"
        f" ({min_confidence:.0%} <= confidence) ".center(80, "-")
    )
    for annotation in annotations:
        entity = annotation.entity
        description = entity.description
        entity_id = entity.entity_id
        confidence = annotation.confidence
        t1 = annotation.segment.start_time_offset.total_seconds()
        t2 = annotation.segment.end_time_offset.total_seconds()
        frames = len(annotation.frames)
        print(
            f"{description:<22}",
            f"{entity_id:<10}",
            f"{confidence:4.0%}",
            f"{t1:>7.3f}",
            f"{t2:>7.3f}",
            f"{frames:>2} fr.",
            sep=" | ",
        )
        

Gọi hàm:

print_detected_objects(results)

Bạn sẽ thấy như sau:

------------------- Detected objects: 3 (70% <= confidence) --------------------
insect                 | /m/03vt0   |  87% |  98.840 | 101.720 | 25 fr.
insect                 | /m/03vt0   |  71% | 108.440 | 111.080 | 23 fr.
butterfly              | /m/0cyf8   |  91% | 111.200 | 111.920 |  7 fr.

Thêm hàm này để in danh sách các khung đối tượng và hộp giới hạn đã phát hiện:

def print_object_frames(
    results: vi.VideoAnnotationResults,
    entity_id: str,
    min_confidence: float = 0.7,
):
    def keep_annotation(annotation: vi.ObjectTrackingAnnotation) -> bool:
        return (
            annotation.entity.entity_id == entity_id
            and min_confidence <= annotation.confidence
        )

    annotations = results.object_annotations
    annotations = [a for a in annotations if keep_annotation(a)]
    for annotation in annotations:
        description = annotation.entity.description
        confidence = annotation.confidence
        print(
            f" {description},"
            f" confidence: {confidence:.0%},"
            f" frames: {len(annotation.frames)} ".center(80, "-")
        )
        for frame in annotation.frames:
            t = frame.time_offset.total_seconds()
            box = frame.normalized_bounding_box
            print(
                f"{t:>7.3f}",
                f"({box.left:.5f}, {box.top:.5f})",
                f"({box.right:.5f}, {box.bottom:.5f})",
                sep=" | ",
            )
            

Gọi hàm bằng mã nhận dạng thực thể cho côn trùng:

insect_entity_id = "/m/03vt0"
print_object_frames(results, insect_entity_id)

Bạn sẽ thấy như sau:

--------------------- insect, confidence: 87%, frames: 25 ----------------------
 98.840 | (0.49327, 0.19617) | (0.69905, 0.69633)
 98.960 | (0.49559, 0.19308) | (0.70631, 0.69671)
...
101.600 | (0.46668, 0.19776) | (0.76619, 0.69371)
101.720 | (0.46805, 0.20053) | (0.76447, 0.68703)
--------------------- insect, confidence: 71%, frames: 23 ----------------------
108.440 | (0.47343, 0.10694) | (0.63821, 0.98332)
108.560 | (0.46960, 0.10206) | (0.63033, 0.98285)
...
110.960 | (0.49466, 0.05102) | (0.65941, 0.99357)
111.080 | (0.49572, 0.04728) | (0.65762, 0.99868)

Nếu vẽ các khung hình chữ nhật trên các khung hình tương ứng, bạn sẽ nhận được kết quả như sau:

8f5796f6e73d1a46.gif

c195a2dca4573f95.gif

Tóm tắt

Ở bước này, bạn có thể thực hiện việc phát hiện và theo dõi đối tượng trên video bằng Video Intelligence API. Bạn có thể đọc thêm về cách phát hiện và theo dõi đối tượng.

11. Phát hiện và theo dõi biểu trưng

Bạn có thể sử dụng Video Intelligence API để phát hiện và theo dõi các biểu trưng trong video. Bạn có thể phát hiện hơn 100.000 thương hiệu và biểu trưng.

Sao chép mã sau vào phiên IPython:

from datetime import timedelta
from typing import Optional, Sequence, cast

from google.cloud import videointelligence_v1 as vi


def detect_logos(
    video_uri: str, segments: Optional[Sequence[vi.VideoSegment]] = None
) -> vi.VideoAnnotationResults:
    video_client = vi.VideoIntelligenceServiceClient()
    features = [vi.Feature.LOGO_RECOGNITION]
    context = vi.VideoContext(segments=segments)
    request = vi.AnnotateVideoRequest(
        input_uri=video_uri,
        features=features,
        video_context=context,
    )

    print(f'Processing video "{video_uri}"...')
    operation = video_client.annotate_video(request)

    # Wait for operation to complete
    response = cast(vi.AnnotateVideoResponse, operation.result())
    # A single video is processed
    results = response.annotation_results[0]

    return results
    

Hãy dành chút thời gian nghiên cứu đoạn mã này và xem cách đoạn mã sử dụng phương thức thư viện ứng dụng annotate_video với tham số LOGO_RECOGNITION để phân tích một video và phát hiện các biểu trưng.

Gọi hàm để phân tích chuỗi gần cuối của video:

video_uri = "gs://cloud-samples-data/video/JaneGoodall.mp4"
segment = vi.VideoSegment(
    start_time_offset=timedelta(seconds=146),
    end_time_offset=timedelta(seconds=156),
)

results = detect_logos(video_uri, [segment])

Chờ video được xử lý:

Processing video: "gs://cloud-samples-data/video/JaneGoodall.mp4"...

Thêm hàm này để in danh sách biểu trưng được phát hiện:

def print_detected_logos(results: vi.VideoAnnotationResults):
    annotations = results.logo_recognition_annotations

    print(f" Detected logos: {len(annotations)} ".center(80, "-"))
    for annotation in annotations:
        entity = annotation.entity
        entity_id = entity.entity_id
        description = entity.description
        for track in annotation.tracks:
            confidence = track.confidence
            t1 = track.segment.start_time_offset.total_seconds()
            t2 = track.segment.end_time_offset.total_seconds()
            logo_frames = len(track.timestamped_objects)
            print(
                f"{confidence:4.0%}",
                f"{t1:>7.3f}",
                f"{t2:>7.3f}",
                f"{logo_frames:>3} fr.",
                f"{entity_id:<15}",
                f"{description}",
                sep=" | ",
            )
            

Gọi hàm:

print_detected_logos(results)

Bạn sẽ thấy như sau:

------------------------------ Detected logos: 1 -------------------------------
 92% | 150.680 | 155.720 |  43 fr. | /m/055t58       | Google Maps

Thêm hàm này để in danh sách các khung hình biểu trưng và hộp giới hạn đã phát hiện:

def print_logo_frames(results: vi.VideoAnnotationResults, entity_id: str):
    def keep_annotation(annotation: vi.LogoRecognitionAnnotation) -> bool:
        return annotation.entity.entity_id == entity_id

    annotations = results.logo_recognition_annotations
    annotations = [a for a in annotations if keep_annotation(a)]
    for annotation in annotations:
        description = annotation.entity.description
        for track in annotation.tracks:
            confidence = track.confidence
            print(
                f" {description},"
                f" confidence: {confidence:.0%},"
                f" frames: {len(track.timestamped_objects)} ".center(80, "-")
            )
            for timestamped_object in track.timestamped_objects:
                t = timestamped_object.time_offset.total_seconds()
                box = timestamped_object.normalized_bounding_box
                print(
                    f"{t:>7.3f}",
                    f"({box.left:.5f}, {box.top:.5f})",
                    f"({box.right:.5f}, {box.bottom:.5f})",
                    sep=" | ",
                )
                

Gọi hàm bằng mã nhận dạng thực thể biểu trưng Google Maps:

maps_entity_id = "/m/055t58"
print_logo_frames(results, maps_entity_id)

Bạn sẽ thấy như sau:

------------------- Google Maps, confidence: 92%, frames: 43 -------------------
150.680 | (0.42024, 0.28633) | (0.58192, 0.64220)
150.800 | (0.41713, 0.27822) | (0.58318, 0.63556)
...
155.600 | (0.41775, 0.27701) | (0.58372, 0.63986)
155.720 | (0.41688, 0.28005) | (0.58335, 0.63954)

Nếu vẽ các khung hình chữ nhật trên các khung hình tương ứng, bạn sẽ nhận được kết quả như sau:

554743aff6d8824c.gif

Tóm tắt

Ở bước này, bạn có thể thực hiện việc phát hiện và theo dõi biểu trưng trên video bằng Video Intelligence API. Bạn có thể đọc thêm về cách phát hiện và theo dõi biểu trưng.

12. Phát hiện nhiều đối tượng

Sau đây là loại yêu cầu bạn có thể đưa ra để nhận tất cả thông tin chi tiết cùng một lúc:

from google.cloud import videointelligence_v1 as vi

video_client = vi.VideoIntelligenceServiceClient()
video_uri = "gs://..."
features = [
    vi.Feature.SHOT_CHANGE_DETECTION,
    vi.Feature.LABEL_DETECTION,
    vi.Feature.EXPLICIT_CONTENT_DETECTION,
    vi.Feature.SPEECH_TRANSCRIPTION,
    vi.Feature.TEXT_DETECTION,
    vi.Feature.OBJECT_TRACKING,
    vi.Feature.LOGO_RECOGNITION,
    vi.Feature.FACE_DETECTION,  # NEW
    vi.Feature.PERSON_DETECTION,  # NEW
]
context = vi.VideoContext(
    segments=...,
    shot_change_detection_config=...,
    label_detection_config=...,
    explicit_content_detection_config=...,
    speech_transcription_config=...,
    text_detection_config=...,
    object_tracking_config=...,
    face_detection_config=...,  # NEW
    person_detection_config=...,  # NEW
)
request = vi.AnnotateVideoRequest(
    input_uri=video_uri,
    features=features,
    video_context=context,
)

# video_client.annotate_video(request)

13. Xin chúc mừng!

cfaa6ffa7bc5ca70.png

Bạn đã tìm hiểu cách sử dụng Video Intelligence API bằng Python!

Dọn dẹp

Để dọn dẹp môi trường phát triển, hãy làm như sau trong Cloud Shell:

  • Nếu bạn vẫn đang trong phiên IPython, hãy quay lại shell: exit
  • Ngừng sử dụng môi trường ảo Python: deactivate
  • Xoá thư mục môi trường ảo: cd ~ ; rm -rf ./venv-videointel

Để xoá dự án trên đám mây của bạn, hãy làm như sau trong Cloud Shell:

  • Lấy mã dự án hiện tại: PROJECT_ID=$(gcloud config get-value core/project)
  • Hãy đảm bảo rằng đây là dự án bạn muốn xoá: echo $PROJECT_ID
  • Xoá dự án: gcloud projects delete $PROJECT_ID

Tìm hiểu thêm

Giấy phép

Tác phẩm này được cấp phép theo giấy phép Ghi công theo Creative Commons 2.0 Chung.