Utiliser l'API Video Intelligence avec Python

1. Présentation

cfaa6ffa7bc5ca70.png

L'API Video Intelligence vous permet d'utiliser la technologie d'analyse vidéo de Google dans vos applications.

Dans cet atelier, vous allez apprendre à utiliser l'API Video Intelligence avec Python.

Points abordés

  • Configurer votre environnement
  • Configurer Python
  • Détecter les changements de plans
  • Détecter des étiquettes
  • Détecter du contenu explicite
  • Transcrire la voix
  • Détecter du texte et en effectuer le suivi
  • Détecter et suivre des objets
  • Détecter et suivre les logos

Prérequis

  • Un projet Google Cloud
  • Un navigateur tel que Chrome ou Firefox
  • Connaissances de base sur Python

Enquête

Comment allez-vous utiliser ce tutoriel ?

Je vais le lire uniquement Je vais le lire et effectuer les exercices

Quel est votre niveau d'expérience avec Python ?

Débutant Intermédiaire Expert

Comment évalueriez-vous votre expérience des services Google Cloud ?

<ph type="x-smartling-placeholder"></ph> Débutant Intermédiaire Expert
.

2. Préparation

Configuration de l'environnement au rythme de chacun

  1. Connectez-vous à la console Google Cloud, puis créez un projet ou réutilisez un projet existant. (Si vous ne possédez pas encore de compte Gmail ou Google Workspace, vous devez en créer un.)

b35bf95b8bf3d5d8.png

a99b7ace416376c4.png

bd84a6d3004737c5.png

  • Le nom du projet est le nom à afficher pour les participants au projet. Il s'agit d'une chaîne de caractères non utilisée par les API Google. Vous pourrez toujours le modifier.
  • L'ID du projet est unique parmi tous les projets Google Cloud et non modifiable une fois défini. La console Cloud génère automatiquement une chaîne unique (en général, vous n'y accordez d'importance particulière). Dans la plupart des ateliers de programmation, vous devrez indiquer l'ID de votre projet (généralement identifié par PROJECT_ID). Si l'ID généré ne vous convient pas, vous pouvez en générer un autre de manière aléatoire. Vous pouvez également en spécifier un et voir s'il est disponible. Après cette étape, l'ID n'est plus modifiable et restera donc le même pour toute la durée du projet.
  • Pour information, il existe une troisième valeur (le numéro de projet) que certaines API utilisent. Pour en savoir plus sur ces trois valeurs, consultez la documentation.
  1. Vous devez ensuite activer la facturation dans la console Cloud pour utiliser les ressources/API Cloud. L'exécution de cet atelier de programmation est très peu coûteuse, voire sans frais. Pour désactiver les ressources et éviter ainsi que des frais ne vous soient facturés après ce tutoriel, vous pouvez supprimer le projet ou les ressources que vous avez créées. Les nouveaux utilisateurs de Google Cloud peuvent participer au programme d'essai sans frais pour bénéficier d'un crédit de 300 $.

Démarrer Cloud Shell

Bien que Google Cloud puisse être utilisé à distance depuis votre ordinateur portable, vous allez utiliser Cloud Shell dans cet atelier de programmation, un environnement de ligne de commande exécuté dans le cloud.

Activer Cloud Shell

  1. Dans Cloud Console, cliquez sur Activer Cloud Shell 853e55310c205094.png.

55efc1aaa7a4d3ad.png

Si vous démarrez Cloud Shell pour la première fois, un écran intermédiaire vous explique de quoi il s'agit. Si un écran intermédiaire s'est affiché, cliquez sur Continuer.

9c92662c6a846a5c.png

Le provisionnement et la connexion à Cloud Shell ne devraient pas prendre plus de quelques minutes.

9f0e51b578fecce5.png

Cette machine virtuelle contient tous les outils de développement nécessaires. Elle comprend un répertoire d'accueil persistant de 5 Go et s'exécute dans Google Cloud, ce qui améliore considérablement les performances du réseau et l'authentification. Une grande partie, voire la totalité, de votre travail dans cet atelier de programmation peut être effectué dans un navigateur.

Une fois connecté à Cloud Shell, vous êtes authentifié et le projet est défini sur votre ID de projet.

  1. Exécutez la commande suivante dans Cloud Shell pour vérifier que vous êtes authentifié :
gcloud auth list

Résultat de la commande

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

To set the active account, run:
    $ gcloud config set account `ACCOUNT`
  1. Exécutez la commande suivante dans Cloud Shell pour vérifier que la commande gcloud connaît votre projet:
gcloud config list project

Résultat de la commande

[core]
project = <PROJECT_ID>

Si vous obtenez un résultat différent, exécutez cette commande :

gcloud config set project <PROJECT_ID>

Résultat de la commande

Updated property [core/project].

3. Cofiguration de l'environnement

Avant de pouvoir utiliser l'API Video Intelligence, vous devez l'activer en exécutant la commande suivante dans Cloud Shell:

gcloud services enable videointelligence.googleapis.com

L'écran qui s'affiche devrait ressembler à ce qui suit :

Operation "operations/..." finished successfully.

Vous pouvez maintenant utiliser l'API Video Intelligence.

Accédez à votre répertoire d'accueil:

cd ~

Créez un environnement virtuel Python pour isoler les dépendances:

virtualenv venv-videointel

Activez l'environnement virtuel :

source venv-videointel/bin/activate

Installez IPython et la bibliothèque cliente de l'API Video Intelligence:

pip install ipython google-cloud-videointelligence

L'écran qui s'affiche devrait ressembler à ce qui suit :

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

Vous êtes maintenant prêt à utiliser la bibliothèque cliente de l'API Video Intelligence.

Dans les étapes suivantes, vous allez utiliser un interpréteur Python interactif appelé IPython, que vous avez installé à l'étape précédente. Démarrez une session en exécutant ipython dans Cloud Shell:

ipython

L'écran qui s'affiche devrait ressembler à ce qui suit :

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. Exemple de vidéo

Vous pouvez utiliser l'API Video Intelligence pour annoter des vidéos stockées dans Cloud Storage ou fournies sous forme d'octets de données.

Dans les étapes suivantes, vous allez utiliser un exemple de vidéo stocké dans Cloud Storage. Vous pouvez la regarder dans votre navigateur.

afe058b29c480d42.png

À vos marques, prêts, partez !

5. Détecter les changements de plan

Vous pouvez utiliser l'API Video Intelligence pour détecter les changements de plans dans une vidéo. Un plan est un segment de la vidéo, une série d'images offrant une continuité visuelle.

Copiez le code suivant dans votre session 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
    

Prenez quelques instants pour étudier le code et découvrez comment il utilise la méthode de la bibliothèque cliente annotate_video avec le paramètre SHOT_CHANGE_DETECTION pour analyser une vidéo et détecter les changements de plans.

Appelez la fonction pour analyser la vidéo:

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

results = detect_shot_changes(video_uri)

Attendez que la vidéo soit traitée:

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

Ajoutez cette fonction pour imprimer les plans de la vidéo:

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}")
        

Appelez la fonction :

print_video_shots(results)

L'écran qui s'affiche devrait ressembler à ce qui suit :

----------- 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

Si vous extrayez l'image du milieu de chaque plan et que vous les disposez sur un mur de plans, vous pouvez générer un résumé visuel de la vidéo:

25bbffa59f7ed71d.png

Résumé

Au cours de cette étape, vous avez pu procéder à la détection de changements de plans sur une vidéo à l'aide de l'API Video Intelligence. Pour en savoir plus, consultez l'article sur la détection des changements de plans.

6. Détecter des libellés

Vous pouvez utiliser l'API Video Intelligence pour détecter des étiquettes dans une vidéo. Les libellés décrivent la vidéo en fonction de son contenu visuel.

Copiez le code suivant dans votre session 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
    

Prenez quelques instants pour étudier le code et découvrez comment il utilise la méthode de la bibliothèque cliente annotate_video avec le paramètre LABEL_DETECTION pour analyser une vidéo et détecter des étiquettes.

Appelez la fonction pour analyser les 37 premières secondes de la vidéo:

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])

Attendez que la vidéo soit traitée:

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

Ajoutez cette fonction pour imprimer les étiquettes au niveau de la vidéo:

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})"
    

Appelez la fonction :

print_video_labels(results)

L'écran qui s'affiche devrait ressembler à ce qui suit :

------------------------------- 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)

Ces libellés au niveau de la vidéo vous permettent de comprendre que le début de la vidéo est principalement axé sur la nature et la végétation.

Ajoutez cette fonction pour imprimer les étiquettes au niveau des plans:

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)
    

Appelez la fonction :

print_shot_labels(results)

L'écran qui s'affiche devrait ressembler à ce qui suit :

------------------------------- 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
...

Ces étiquettes vous permettent de comprendre que la vidéo commence par un plan d'une planète (probablement la Terre), qu'il y a un papillon dans le plan 34.760-36.960s,...

Résumé

Au cours de cette étape, vous avez pu détecter des thèmes sur une vidéo à l'aide de l'API Video Intelligence. Pour en savoir plus sur la détection des libellés, consultez cette page.

7. Détecter des contenus explicites

Vous pouvez utiliser l'API Video Intelligence pour détecter le contenu explicite d'une vidéo. Le contenu explicite est un contenu réservé aux adultes, généralement inadapté aux personnes de moins de 18 ans. Cela inclut, sans s'y limiter, la nudité, les activités sexuelles et la pornographie. La détection est effectuée en fonction des signaux visuels par image uniquement (le son n'est pas utilisé). La réponse inclut des valeurs de probabilité allant de VERY_UNLIKELY à VERY_LIKELY.

Copiez le code suivant dans votre session 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
    

Prenez quelques instants pour étudier le code et découvrez comment il utilise la méthode de la bibliothèque cliente annotate_video avec le paramètre EXPLICIT_CONTENT_DETECTION pour analyser une vidéo et détecter le contenu explicite.

Appelez la fonction pour analyser les 10 premières secondes de la vidéo:

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])

Attendez que la vidéo soit traitée:

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

Ajoutez cette fonction pour imprimer les différents nombres de probabilités:

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}")
        

Appelez la fonction :

print_explicit_content(results)

L'écran qui s'affiche devrait ressembler à ce qui suit :

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

Ajoutez cette fonction pour imprimer les détails du cadre:

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)
        

Appelez la fonction :

print_frames(results, vi.Likelihood.VERY_UNLIKELY)

L'écran qui s'affiche devrait ressembler à ce qui suit :

------- 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

Résumé

Au cours de cette étape, vous avez pu détecter le contenu explicite d'une vidéo à l'aide de l'API Video Intelligence. Pour en savoir plus sur la détection de contenu explicite, consultez cet article.

8. Transcrire la voix

Vous pouvez utiliser l'API Video Intelligence pour transcrire des vidéos vocales en texte.

Copiez le code suivant dans votre session 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
    

Prenez quelques instants pour étudier le code et découvrez comment il utilise la méthode de la bibliothèque cliente annotate_video avec le paramètre SPEECH_TRANSCRIPTION pour analyser une vidéo et transcrire les paroles.

Appelez la fonction pour analyser la vidéo de 55 à 80 secondes:

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])

Attendez que la vidéo soit traitée:

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

Ajoutez la fonction suivante pour afficher une transcription de voix:

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()}")
        

Appelez la fonction :

print_video_speech(results)

L'écran qui s'affiche devrait ressembler à ce qui suit :

--------------------------- 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.

Ajoutez cette fonction pour afficher la liste des mots détectés et leurs codes temporels:

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}")
            

Appelez la fonction :

print_word_timestamps(results)

L'écran qui s'affiche devrait ressembler à ce qui suit :

------------------------------- 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.

Résumé

Au cours de cette étape, vous avez pu transcrire une vidéo à l'aide de l'API Video Intelligence. Découvrez comment transcrire des fichiers audio.

9. Détecter et suivre du texte

Vous pouvez utiliser l'API Video Intelligence pour détecter et suivre le texte dans une vidéo.

Copiez le code suivant dans votre session 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
    

Prenez quelques instants pour étudier le code et découvrez comment il utilise la méthode de la bibliothèque cliente annotate_video avec le paramètre TEXT_DETECTION pour analyser une vidéo et détecter du texte.

Appelez la fonction pour analyser la vidéo des secondes 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])

Attendez que la vidéo soit traitée:

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

Ajoutez cette fonction pour imprimer le texte détecté:

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
    

Appelez la fonction :

print_video_text(results)

L'écran qui s'affiche devrait ressembler à ce qui suit :

-------------------------------- 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.

Ajoutez cette fonction pour imprimer la liste des cadres de texte et des cadres de délimitation détectés:

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=" | ",
                )
                

Appelez la fonction pour vérifier quelles images affichent le nom du narrateur:

contained_text = "Goodall"
print_text_frames(results, contained_text)

L'écran qui s'affiche devrait ressembler à ce qui suit :

--------------------------------- 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)

Si vous tracez les cadres de délimitation au-dessus des cadres correspondants, vous obtiendrez ceci:

7e530d3d25f2f40e.gif

Résumé

Au cours de cette étape, vous avez pu effectuer la détection de texte et le suivi d'une vidéo à l'aide de l'API Video Intelligence. En savoir plus sur la détection et le suivi de texte

10. Détecter et suivre les objets

Vous pouvez utiliser l'API Video Intelligence pour détecter et suivre les objets dans une vidéo.

Copiez le code suivant dans votre session 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
    

Prenez quelques instants pour étudier le code et découvrez comment il utilise la méthode de la bibliothèque cliente annotate_video avec le paramètre OBJECT_TRACKING pour analyser une vidéo et détecter des objets.

Appelez la fonction pour analyser la vidéo de 98 à 112 secondes:

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])

Attendez que la vidéo soit traitée:

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

Ajoutez cette fonction pour afficher la liste des objets détectés:

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=" | ",
        )
        

Appelez la fonction :

print_detected_objects(results)

L'écran qui s'affiche devrait ressembler à ce qui suit :

------------------- 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.

Ajoutez cette fonction pour afficher la liste des cadres d'objets et des cadres de délimitation détectés:

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=" | ",
            )
            

Appelez la fonction avec l'ID d'entité pour les insectes:

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

L'écran qui s'affiche devrait ressembler à ce qui suit :

--------------------- 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)

Si vous tracez les cadres de délimitation au-dessus des cadres correspondants, vous obtiendrez ceci:

8f5796f6e73d1a46.gif

c195a2dca4573f95.gif

Résumé

Au cours de cette étape, vous avez pu effectuer la détection d'objets et le suivi d'une vidéo à l'aide de l'API Video Intelligence. En savoir plus sur la détection et le suivi des objets

11. Détecter et suivre les logos

Vous pouvez utiliser l'API Video Intelligence pour détecter et suivre les logos dans une vidéo. Plus de 100 000 marques et logos peuvent être détectés.

Copiez le code suivant dans votre session 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
    

Prenez quelques instants pour étudier le code et découvrez comment il utilise la méthode de la bibliothèque cliente annotate_video avec le paramètre LOGO_RECOGNITION pour analyser une vidéo et détecter les logos.

Appelez la fonction pour analyser l'avant-dernière séquence de la vidéo:

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])

Attendez que la vidéo soit traitée:

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

Ajoutez cette fonction pour imprimer la liste des logos détectés:

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=" | ",
            )
            

Appelez la fonction :

print_detected_logos(results)

L'écran qui s'affiche devrait ressembler à ce qui suit :

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

Ajoutez cette fonction pour imprimer la liste des cadres de logo et des cadres de délimitation détectés:

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=" | ",
                )
                

Appelez la fonction avec l'ID d'entité du logo Google Maps:

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

L'écran qui s'affiche devrait ressembler à ce qui suit :

------------------- 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)

Si vous tracez les cadres de délimitation au-dessus des cadres correspondants, vous obtiendrez ceci:

554743aff6d8824c.gif

Résumé

Au cours de cette étape, vous avez pu détecter les logos et effectuer le suivi d'une vidéo à l'aide de l'API Video Intelligence. En savoir plus sur la détection et le suivi des logos

12. Détecter plusieurs caractéristiques

Voici le type de requête que vous pouvez envoyer pour obtenir tous les insights en même temps:

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. Félicitations !

cfaa6ffa7bc5ca70.png

Vous avez appris à utiliser l'API Video Intelligence avec Python.

Effectuer un nettoyage

Pour nettoyer votre environnement de développement à partir de Cloud Shell:

  • Si vous êtes toujours dans votre session IPython, revenez au shell: exit
  • Cessez d'utiliser l'environnement virtuel Python: deactivate
  • Supprimez le dossier d'environnement virtuel: cd ~ ; rm -rf ./venv-videointel.

Pour supprimer votre projet Google Cloud à partir de Cloud Shell, procédez comme suit:

  • Récupérez l'ID de votre projet actuel: PROJECT_ID=$(gcloud config get-value core/project)
  • Assurez-vous qu'il s'agit bien du projet que vous souhaitez supprimer: echo $PROJECT_ID
  • Supprimez le projet: gcloud projects delete $PROJECT_ID

En savoir plus

Licence

Ce document est publié sous une licence Creative Commons Attribution 2.0 Generic.