1. 개요
Video Intelligence API를 사용하면 Google 동영상 분석 기술을 애플리케이션의 일부로 사용할 수 있습니다.
이 실습에서는 Python과 함께 Video Intelligence API를 사용하는 방법을 중점적으로 살펴봅니다.
학습할 내용
- 환경을 설정하는 방법
- Python 설정 방법
- 장면 변화를 감지하는 방법
- 라벨 감지 방법
- 선정적인 콘텐츠를 감지하는 방법
- 음성 스크립트 작성 방법
- 텍스트 감지 및 추적 방법
- 객체 감지 및 추적 방법
- 로고 감지 및 추적 방법
필요한 항목
설문조사
이 튜토리얼을 어떻게 사용하실 계획인가요?
귀하의 Python 사용 경험이 어떤지 평가해 주세요.
귀하의 Google Cloud 서비스 경험을 평가해 주세요.
<ph type="x-smartling-placeholder">2. 설정 및 요건
자습형 환경 설정
- Google Cloud Console에 로그인하여 새 프로젝트를 만들거나 기존 프로젝트를 재사용합니다. 아직 Gmail이나 Google Workspace 계정이 없는 경우 계정을 만들어야 합니다.
- 프로젝트 이름은 이 프로젝트 참가자의 표시 이름입니다. 이는 Google API에서 사용하지 않는 문자열이며 언제든지 업데이트할 수 있습니다.
- 프로젝트 ID는 모든 Google Cloud 프로젝트에서 고유하며, 변경할 수 없습니다(설정된 후에는 변경할 수 없음). Cloud 콘솔은 고유한 문자열을 자동으로 생성합니다. 일반적으로는 신경 쓰지 않아도 됩니다. 대부분의 Codelab에서는 프로젝트 ID (일반적으로
PROJECT_ID
로 식별됨)를 참조해야 합니다. 생성된 ID가 마음에 들지 않으면 다른 임의 ID를 생성할 수 있습니다. 또는 직접 시도해 보고 사용 가능한지 확인할 수도 있습니다. 이 단계 이후에는 변경할 수 없으며 프로젝트 기간 동안 유지됩니다. - 참고로 세 번째 값은 일부 API에서 사용하는 프로젝트 번호입니다. 이 세 가지 값에 대한 자세한 내용은 문서를 참고하세요.
- 다음으로 Cloud 리소스/API를 사용하려면 Cloud 콘솔에서 결제를 사용 설정해야 합니다. 이 Codelab 실행에는 많은 비용이 들지 않습니다. 이 튜토리얼이 끝난 후에 요금이 청구되지 않도록 리소스를 종료하려면 만든 리소스 또는 프로젝트를 삭제하면 됩니다. Google Cloud 신규 사용자는 300달러(USD) 상당의 무료 체험판 프로그램에 참여할 수 있습니다.
Cloud Shell 시작
Google Cloud를 노트북에서 원격으로 실행할 수도 있지만 이 Codelab에서는 Cloud에서 실행되는 명령줄 환경인 Cloud Shell을 사용합니다.
Cloud Shell 활성화
- Cloud Console에서 Cloud Shell 활성화를 클릭합니다.
Cloud Shell을 처음 시작하는 경우에는 무엇이 있는지 설명하는 중간 화면이 표시됩니다. 중간 화면이 표시되면 계속을 클릭합니다.
Cloud Shell을 프로비저닝하고 연결하는 데 몇 분 정도만 걸립니다.
가상 머신에는 필요한 개발 도구가 모두 들어 있습니다. 영구적인 5GB 홈 디렉터리를 제공하고 Google Cloud에서 실행되므로 네트워크 성능과 인증이 크게 개선됩니다. 이 Codelab에서 대부분의 작업은 브라우저를 사용하여 수행할 수 있습니다.
Cloud Shell에 연결되면 인증이 완료되었고 프로젝트가 자신의 프로젝트 ID로 설정된 것을 확인할 수 있습니다.
- Cloud Shell에서 다음 명령어를 실행하여 인증되었는지 확인합니다.
gcloud auth list
명령어 결과
Credentialed Accounts ACTIVE ACCOUNT * <my_account>@<my_domain.com> To set the active account, run: $ gcloud config set account `ACCOUNT`
- Cloud Shell에서 다음 명령어를 실행하여 gcloud 명령어가 프로젝트를 알고 있는지 확인합니다.
gcloud config list project
명령어 결과
[core] project = <PROJECT_ID>
또는 다음 명령어로 설정할 수 있습니다.
gcloud config set project <PROJECT_ID>
명령어 결과
Updated property [core/project].
3. 환경 설정
Video Intelligence API를 사용하려면 먼저 Cloud Shell에서 다음 명령어를 실행하여 API를 사용 설정합니다.
gcloud services enable videointelligence.googleapis.com
다음과 같은 결과를 확인할 수 있습니다.
Operation "operations/..." finished successfully.
이제 Video Intelligence API를 사용할 수 있습니다.
홈 디렉터리로 이동합니다.
cd ~
Python 가상 환경을 만들어 종속 항목을 격리합니다.
virtualenv venv-videointel
가상 환경을 활성화합니다.
source venv-videointel/bin/activate
IPython 및 Video Intelligence API 클라이언트 라이브러리를 설치합니다.
pip install ipython google-cloud-videointelligence
다음과 같은 결과를 확인할 수 있습니다.
... Installing collected packages: ..., ipython, google-cloud-videointelligence Successfully installed ... google-cloud-videointelligence-2.11.0 ...
이제 Video Intelligence API 클라이언트 라이브러리를 사용할 준비가 되었습니다.
다음 단계에서는 이전 단계에서 설치한 대화형 Python 인터프리터인 IPython을 사용합니다. Cloud Shell에서 ipython
를 실행하여 세션을 시작합니다.
ipython
다음과 같은 결과를 확인할 수 있습니다.
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 Intelligence API를 사용하여 Cloud Storage에 저장되었거나 데이터 바이트로 제공되는 동영상에 주석을 달 수 있습니다.
다음 단계에서는 Cloud Storage에 저장된 샘플 동영상을 사용합니다. 브라우저에서 동영상을 시청할 수 있습니다.
준비, 땅!
5. 장면 변화 감지
Video Intelligence API를 사용하여 동영상의 장면 변화를 감지할 수 있습니다. 샷이란 시각적 연속성을 지닌 일련의 프레임으로 구성된 동영상의 한 부분입니다.
다음 코드를 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
잠시 코드를 살펴보고 SHOT_CHANGE_DETECTION
매개변수와 함께 annotate_video
클라이언트 라이브러리 메서드를 사용하여 동영상을 분석하고 장면 변화를 감지하는 방법을 살펴보세요.
동영상을 분석하는 함수를 호출합니다.
video_uri = "gs://cloud-samples-data/video/JaneGoodall.mp4"
results = detect_shot_changes(video_uri)
동영상이 처리될 때까지 기다립니다.
Processing video: "gs://cloud-samples-data/video/JaneGoodall.mp4"...
이 함수를 추가하여 동영상 장면을 출력합니다.
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}")
함수 호출
print_video_shots(results)
다음과 같은 결과를 확인할 수 있습니다.
----------- 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
각 장면의 중간 프레임을 추출하여 프레임이 있는 벽에 배치하면 동영상에 대한 시각적 요약을 생성할 수 있습니다.
요약
이 단계에서는 Video Intelligence API를 사용하여 동영상에서 장면 변화 감지를 수행할 수 있었습니다. 장면 변화 감지에 대해 자세히 알아보세요.
6. 라벨 감지
Video Intelligence API를 사용하여 동영상의 라벨을 감지할 수 있습니다. 라벨은 시각적 콘텐츠를 기반으로 동영상을 설명합니다.
다음 코드를 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
잠시 코드를 살펴보고 LABEL_DETECTION
매개변수와 함께 annotate_video
클라이언트 라이브러리 메서드를 사용하여 동영상을 분석하고 라벨을 감지하는 방법을 알아보세요.
동영상의 처음 37초를 분석하는 함수를 호출합니다.
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])
동영상이 처리될 때까지 기다립니다.
Processing video: "gs://cloud-samples-data/video/JaneGoodall.mp4"...
이 함수를 추가하여 동영상 수준에서 라벨을 출력합니다.
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})"
함수 호출
print_video_labels(results)
다음과 같은 결과를 확인할 수 있습니다.
------------------------------- 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)
이러한 동영상 수준의 라벨 덕분에 동영상의 시작 부분이 주로 자연과 초목으로 이루어진다는 것을 알 수 있습니다.
이 함수를 추가하여 샷 수준에서 라벨을 출력합니다.
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)
함수 호출
print_shot_labels(results)
다음과 같은 결과를 확인할 수 있습니다.
------------------------------- 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 ...
이러한 장면 수준의 라벨 덕분에 동영상이 지구와 같은 행성의 장면으로 시작하며 34.760-36.960s
장면에 나비가 있다는 것을 알 수 있습니다.
요약
이 단계에서는 Video Intelligence API를 사용하여 동영상에 대한 라벨 인식을 수행할 수 있었습니다. 라벨 감지에 대해 자세히 알아보세요.
7. 유해성 콘텐츠 감지
Video Intelligence API를 사용하여 동영상의 유해성 콘텐츠를 감지할 수 있습니다. 음란물이란 일반적으로 18세 미만의 청소년에게 부적절한 성인용 콘텐츠로서 과도한 노출, 성행위, 포르노 등을 포함하되 이에 국한되지 않습니다. 감지는 프레임별 시각적 신호만을 기준으로 수행됩니다 (오디오는 사용되지 않음). 응답에는 VERY_UNLIKELY
~VERY_LIKELY
범위의 가능성 값이 포함됩니다.
다음 코드를 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
잠시 코드를 살펴보고 EXPLICIT_CONTENT_DETECTION
매개변수와 함께 annotate_video
클라이언트 라이브러리 메서드를 사용하여 동영상을 분석하고 선정적인 콘텐츠를 감지하는 방법을 살펴보세요.
동영상의 처음 10초를 분석하는 함수를 호출합니다.
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])
동영상이 처리될 때까지 기다립니다.
Processing video: "gs://cloud-samples-data/video/JaneGoodall.mp4"...
이 함수를 추가하여 다양한 가능성 수를 출력합니다.
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}")
함수 호출
print_explicit_content(results)
다음과 같은 결과를 확인할 수 있습니다.
----- Explicit content frames: 10 ------ LIKELIHOOD_UNSPECIFIED: 0 VERY_UNLIKELY : 10 UNLIKELY : 0 POSSIBLE : 0 LIKELY : 0 VERY_LIKELY : 0
이 함수를 추가하여 프레임 세부정보를 출력합니다.
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)
함수 호출
print_frames(results, vi.Likelihood.VERY_UNLIKELY)
다음과 같은 결과를 확인할 수 있습니다.
------- 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
요약
이 단계에서는 Video Intelligence API를 사용하여 동영상에서 유해성 콘텐츠 감지를 수행할 수 있었습니다. 선정적인 콘텐츠 감지에 대해 자세히 알아보세요.
8. 음성 스크립트 작성
Video Intelligence API를 사용하여 동영상 음성을 텍스트로 변환할 수 있습니다.
다음 코드를 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
잠시 코드를 살펴보고 annotate_video
클라이언트 라이브러리 메서드와 SPEECH_TRANSCRIPTION
매개변수를 사용하여 동영상을 분석하고 음성을 텍스트로 변환하는 방법을 알아보세요.
55~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])
동영상이 처리될 때까지 기다립니다.
Processing video: "gs://cloud-samples-data/video/JaneGoodall.mp4"...
이 함수를 추가하여 스크립트가 작성된 음성을 출력합니다.
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()}")
함수 호출
print_video_speech(results)
다음과 같은 결과를 확인할 수 있습니다.
--------------------------- 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.
이 함수를 추가하여 감지된 단어와 타임스탬프의 목록을 출력합니다.
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}")
함수 호출
print_word_timestamps(results)
다음과 같은 결과를 확인할 수 있습니다.
------------------------------- 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.
요약
이 단계에서는 Video Intelligence API를 사용하여 동영상에서 음성 스크립트를 작성할 수 있었습니다. 오디오 스크립트 작성에 대해 자세히 알아보세요.
9. 텍스트 감지 및 추적
Video Intelligence API를 사용하여 동영상의 텍스트를 감지하고 추적할 수 있습니다.
다음 코드를 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
잠시 코드를 살펴보고 TEXT_DETECTION
매개변수와 함께 annotate_video
클라이언트 라이브러리 메서드를 사용하여 동영상을 분석하고 텍스트를 감지하는 방법을 알아보세요.
13~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])
동영상이 처리될 때까지 기다립니다.
Processing video: "gs://cloud-samples-data/video/JaneGoodall.mp4"...
이 함수를 추가하여 감지된 텍스트를 출력합니다.
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
함수 호출
print_video_text(results)
다음과 같은 결과를 확인할 수 있습니다.
-------------------------------- 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.
이 함수를 추가하여 감지된 텍스트 프레임 및 경계 상자의 목록을 출력합니다.
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=" | ",
)
함수를 호출하여 내레이터 이름을 표시하는 프레임을 확인합니다.
contained_text = "Goodall"
print_text_frames(results, contained_text)
다음과 같은 결과를 확인할 수 있습니다.
--------------------------------- 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)
상응하는 프레임 위에 경계 상자를 그리면 다음과 같은 결과가 나타납니다.
요약
이 단계에서는 Video Intelligence API를 사용하여 동영상에서 텍스트 감지 및 추적을 수행할 수 있었습니다. 텍스트 감지 및 추적에 대해 자세히 알아보세요.
10. 객체 감지 및 추적
Video Intelligence API를 사용하여 동영상의 객체를 감지하고 추적할 수 있습니다.
다음 코드를 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
잠시 코드를 살펴보고 annotate_video
클라이언트 라이브러리 메서드와 OBJECT_TRACKING
매개변수를 사용하여 동영상을 분석하고 객체를 감지하는 방법을 알아보세요.
98~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])
동영상이 처리될 때까지 기다립니다.
Processing video: "gs://cloud-samples-data/video/JaneGoodall.mp4"...
이 함수를 추가하여 감지된 객체의 목록을 출력합니다.
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=" | ",
)
함수 호출
print_detected_objects(results)
다음과 같은 결과를 확인할 수 있습니다.
------------------- 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.
이 함수를 추가하여 감지된 객체 프레임 및 경계 상자의 목록을 출력합니다.
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=" | ",
)
곤충의 항목 ID로 함수를 호출합니다.
insect_entity_id = "/m/03vt0"
print_object_frames(results, insect_entity_id)
다음과 같은 결과를 확인할 수 있습니다.
--------------------- 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)
상응하는 프레임 위에 경계 상자를 그리면 다음과 같은 결과가 나타납니다.
요약
이 단계에서는 Video Intelligence API를 사용하여 동영상에서 객체 감지 및 추적을 수행할 수 있었습니다. 객체 감지 및 추적에 대해 자세히 알아보세요.
11. 로고 감지 및 추적
Video Intelligence API를 사용하여 동영상의 로고를 감지하고 추적할 수 있습니다. 100,000개가 넘는 브랜드와 로고를 감지할 수 있습니다.
다음 코드를 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
잠시 코드를 살펴보고 annotate_video
클라이언트 라이브러리 메서드와 LOGO_RECOGNITION
매개변수를 사용하여 동영상을 분석하고 로고를 감지하는 방법을 살펴보세요.
동영상의 끝에서 마지막 시퀀스를 분석하는 함수를 호출합니다.
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])
동영상이 처리될 때까지 기다립니다.
Processing video: "gs://cloud-samples-data/video/JaneGoodall.mp4"...
이 함수를 추가하여 감지된 로고의 목록을 출력합니다.
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=" | ",
)
함수 호출
print_detected_logos(results)
다음과 같은 결과를 확인할 수 있습니다.
------------------------------ Detected logos: 1 ------------------------------- 92% | 150.680 | 155.720 | 43 fr. | /m/055t58 | Google Maps
이 함수를 추가하여 감지된 로고 프레임 및 경계 상자의 목록을 출력합니다.
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=" | ",
)
Google 지도 로고 항목 ID로 함수를 호출합니다.
maps_entity_id = "/m/055t58"
print_logo_frames(results, maps_entity_id)
다음과 같은 결과를 확인할 수 있습니다.
------------------- 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)
상응하는 프레임 위에 경계 상자를 그리면 다음과 같은 결과가 나타납니다.
요약
이 단계에서는 Video Intelligence API를 사용하여 동영상에서 로고 감지 및 추적을 수행할 수 있었습니다. 로고 감지 및 추적에 대해 자세히 알아보세요.
12. 여러 특성 감지
다음은 모든 통계를 한 번에 얻을 수 있는 요청의 유형입니다.
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. 축하합니다.
Python을 사용하여 Video Intelligence API를 사용하는 방법을 알아보았습니다.
삭제
Cloud Shell에서 개발 환경을 삭제하려면 다음 안내를 따르세요.
- 아직 IPython 세션에 있다면 셸로 돌아갑니다.
exit
- Python 가상 환경 사용 중지:
deactivate
- 가상 환경 폴더 삭제:
cd ~ ; rm -rf ./venv-videointel
Google Cloud 프로젝트를 삭제하려면 Cloud Shell에서 다음 안내를 따르세요.
- 현재 프로젝트 ID를 가져옵니다.
PROJECT_ID=$(gcloud config get-value core/project)
- 삭제하려는 프로젝트가 맞는지 확인합니다.
echo $PROJECT_ID
- 프로젝트 삭제:
gcloud projects delete $PROJECT_ID
자세히 알아보기
- 브라우저에서 데모 테스트: https://zackakil.github.io/video-intelligence-api-visualiser
- Video Intelligence 문서: https://cloud.google.com/video-intelligence/docs
- 베타 기능: https://cloud.google.com/video-intelligence/docs/beta
- Google Cloud 기반 Python: https://cloud.google.com/python
- Python용 Cloud 클라이언트 라이브러리: https://github.com/googleapis/google-cloud-python
라이선스
이 작업물은 Creative Commons Attribution 2.0 일반 라이선스에 따라 사용이 허가되었습니다.