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 như một phần của ứng dụng.

Trong phòng thí nghiệm này, bạn sẽ tập trung vào việc sử dụng Video Intelligence API với 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 những thay đổi về cảnh quay
  • 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 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
  • Quen thuộc với Python

Khảo sát

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

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

Bạn đánh giá thế nào về trải nghiệm sử dụng Python?

Người mới tập Trung cấp Thành thạo

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

Người mới tập 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 tiến độ riêng

  1. Đăng nhập vào Google Cloud Console rồi tạo dự án mới hoặc sử dụng lại 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ự không được API của Google sử dụng. Bạn luôn có thể cập nhật ứng dụng.
  • Mã dự án là duy nhất trong tất cả các dự án Google Cloud và không thể thay đổi (không thể thay đổi sau khi đã đặt). Cloud Console sẽ tự động tạo một chuỗi duy nhất; thường bạn không quan tâm đến sản phẩm đó là gì. Trong hầu hết các lớp học lập trình, bạn sẽ cần tham khảo Mã dự án của mình (thường được xác định là PROJECT_ID). Nếu không thích mã đã tạo, bạn có thể tạo một mã nhận dạng ngẫu nhiên khác. Ngoài ra, bạn có thể thử cách riêng của mình để xem có thể sử dụng hay không. Bạn không thể thay đổi mã này sau bước này và mã vẫn giữ nguyên trong thời gian dự án.
  • Đối với thông tin của bạn, có giá trị thứ ba, Project Number (Số dự án), mà một số API sử dụng. Tìm hiểu thêm về cả ba giá trị này trong tài liệu này.
  1. Tiếp theo, bạn sẽ phải bật tính năng thanh toán trong Cloud Console để sử dụng API/tài nguyên trên đám mây. Việc chạy qua lớp học lập trình này sẽ không tốn nhiều chi phí. Để tắt các tài nguyên nhằm tránh phát sinh việc thanh toán ngoài hướng dẫn này, bạn có thể xoá các tài nguyên bạ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í 300 USD.

Khởi động Cloud Shell

Mặc dù bạn 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 trong Đá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.pngs.

55efc1aaa7a4d3ad.pngS

Nếu đây là lần đầu tiê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 nhìn thấy màn hình trung gian, hãy nhấp vào Tiếp tục.

9c92662c6a846a5c.pngS

Quá trình cấp phép và kết nối với Cloud Shell chỉ mất vài phút.

9f0e51b578fecce5.pngs

Máy ảo này được tải tất cả các công cụ phát triển cần thiết. Dịch vụ này cung cấp thư mục gốc có dung lượng ổn định 5 GB và chạy trên Google Cloud, giúp nâng cao đáng kể hiệu suất và khả năng xác thực của mạng. Nhiều (nếu không nói là) tất cả công việc của bạn trong lớp học lập trình này đều có thể thực hiện bằng trình duyệt.

Sau khi kết nối với Cloud Shell, bạn sẽ thấy mình đã được xác thực và dự án được đặt thành mã dự á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

Kết quả 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

Kết quả lệnh

[core]
project = <PROJECT_ID>

Nếu chưa, bạn có thể thiết lập chế độ này bằng lệnh sau:

gcloud config set project <PROJECT_ID>

Kết quả lệnh

Updated property [core/project].

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

Trước khi bạn có thể bắt đầu sử dụng API Video Intelligence, 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 API Video Intelligence!

Chuyển đến thư mục gốc:

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 API Video Intelligence:

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 API Video Intelligence!

Trong các bước tiếp theo, bạn sẽ sử dụng trình thông dịch Python tương tác có tên IPython mà bạn đã cài đặt trong 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 cho những video được lưu trữ trong Cloud Storage hoặc được cung cấp dưới dạng byte dữ liệu.

Ở 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 này trong trình duyệt của mình.

afe058b29c480d42.png

Đã sẵn sàng, vững vàng, bắt đầu thôi!

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

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

Sao chép mã sau vào phiên IPython của bạn:

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 đoạn mã này 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ố SHOT_CHANGE_DETECTION để phân tích một video và phát hiện những thay đổi về cảnh quay.

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ờ hệ thống xử lý video:

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

Thêm hàm này để in cảnh quay 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 bạn trích xuất khung hình giữa của mỗi cảnh quay và sắp xếp chúng vào một khung hình tường, thì bạn có thể tạo một bản tóm tắt bằng hình ảnh cho video:

25bbffa59f7ed71d.pngS

Tóm tắt

Ở bước này, bạn có thể dùng Video Intelligence API để phát hiện thay đổi cảnh quay trên một video. Bạn có thể đọc thêm về cách phát hiện những thay đổi đối với cảnh quay.

6. Phát hiện nhãn

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

Sao chép mã sau vào phiên IPython của bạn:

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
    

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

Gọi hàm này để 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ờ hệ thống xử lý video:

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ờ các nhãn ở cấp video này, bạn có thể hiểu rằng phần đầu của video chủ yếu nói về thiên nhiên và thực vật.

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

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ờ các nhãn ở cấp độ cảnh quay này, bạn có thể hiểu 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

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

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

Bạn có thể dùng API Video Intelligence để 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 những người dưới 18 tuổi và 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. Việc phát hiện chỉ được thực hiện dựa trên tín hiệu hình ảnh trên mỗi khung hình (không sử dụng âm thanh). Phản hồi bao gồm các giá trị khả năng xảy ra trong khoảng từ VERY_UNLIKELY đến VERY_LIKELY.

Sao chép mã sau vào phiên IPython của bạn:

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
    

Hãy dành chút thời gian nghiên cứu mã này 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ố EXPLICIT_CONTENT_DETECTION để phân tích video và phát hiện nội dung phản cảm.

Gọi hàm này để 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ờ hệ thống xử lý video:

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

Thêm hàm này để in ra số 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 chi tiết khung:

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ể phát hiện nội dung phản cảm trên một video bằng API Video Intelligence. 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 để chép lời lời nói trong video thành văn bản.

Sao chép mã sau vào phiên IPython của bạn:

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
    

Hãy dành chút thời gian nghiên cứu mã này 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ố SPEECH_TRANSCRIPTION để phân tích video và chép lời.

Gọi hàm này để phân tích video từ giây 55 đến 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ờ hệ thống xử lý video:

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

Thêm hàm này để in 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 để xuất danh sách các từ được phát hiện và dấu thời gian tương ứng:

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

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

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 của bạn:

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ã này 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 một video và phát hiện văn bản.

Gọi hàm này để phân tích video từ giây 13 đến 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ờ hệ thống xử lý video:

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

Thêm hàm này để in văn bản được 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 này để kiểm tra xem khung nào hiển thị tên của người đọc:

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 hộp giới hạn lên trên các khung tương ứng, bạn sẽ có kết quả như sau:

7e530d3d25f2f40e.gif

Tóm tắt

Ở bước này, bạn có thể phát hiện và theo dõi văn bản trên video bằng API Video Intelligence. 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 đối tượng

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 của bạn:

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
    

Hãy dành chút thời gian nghiên cứu mã này 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 đối tượng.

Gọi hàm này để phân tích video từ giây 98 đến 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ờ hệ thống xử lý video:

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

Thêm hàm này để in danh sách đối tượng đã 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 được 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 hộp giới hạn lên trên các khung tương ứng, bạn sẽ 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 hoạt động phát hiện và theo dõi đối tượng trên một video bằng cách sử dụ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ể dùng Video Intelligence API để phát hiện và theo dõi các biểu trưng trong một video. Hệ thống 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 của bạn:

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 mã này 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ố LOGO_RECOGNITION để phân tích một video và phát hiện biểu trưng.

Gọi hàm này để phân tích chuỗi áp chót 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ờ hệ thống xử lý video:

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 biểu trưng và hộp giới hạn được 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 của biểu trưng Google Map:

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 hộp giới hạn lên trên các khung tương ứng, bạn sẽ có kết quả như sau:

554743aff6d8824c.gif

Tóm tắt

Ở bước này, bạn có thể phát hiện và theo dõi biểu trưng trên video bằng API Video Intelligence. 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 tính năng

Đây là loại yêu cầu bạn có thể thực hiện để 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, từ 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 của bạn: cd ~ ; rm -rf ./venv-videointel

Cách xoá dự án của bạn trên Google Cloud khỏi Cloud Shell:

  • Truy xuất mã dự án hiện tại của bạn: PROJECT_ID=$(gcloud config get-value core/project)
  • Hãy đảm bảo đây là dự án mà 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 chung Ghi nhận tác giả Creative Commons 2.0.