מדריך לזיהוי תוויות

קהל

המדריך הזה נועד לעזור לכם להתחיל לחקור ולפתח אפליקציות באמצעות Video Intelligence API. הוא מיועד לאנשים שיש להם היכרות בסיסית עם Python. בנוסף, לא נדרש ידע רב בתכנות כדי להבין את התוכן. אחרי שתעברו על המדריך הזה, תוכלו להשתמש במסמכי העיון כדי ליצור אפליקציות בסיסיות משלכם.

במדריך הזה נסביר איך ליצור אפליקציה ל-Video Intelligence API באמצעות קוד Python. המטרה כאן היא לא להסביר על ספריות הלקוח של Python, אלא להסביר איך לבצע קריאות ל-Video Intelligence API באמצעות התכונה של זיהוי תוויות בסרטון. אפליקציות ב-Java וב-Node.js דומות במהותן.

אם אתם מחפשים דוגמה של קוד בלבד או דוגמה בשפה אחרת, כדאי לעיין במדריך המפורט.

דרישות מוקדמות

כדי לבצע את המדריך הזה, אתם צריכים:

הוספת הערות לסרטון באמצעות זיהוי תוויות

במדריך הזה נסביר איך ליצור אפליקציה בסיסית ל-Video API באמצעות בקשת LABEL_DETECTION. LABEL_DETECTION בקשה מוסיפה לסרטון הערות עם תוויות (או 'תגים') שנבחרות על סמך תוכן התמונה. לדוגמה, סרטון של רכבת במעבר חצייה עשוי להניב תוויות כמו 'רכבת', 'תחבורה', 'מעבר חצייה'.

בהמשך מופיע הקוד המלא שנדרש למדריך הזה. הסרנו את רוב ההערות מהקוד הזה כדי להדגיש כמה הוא קצר. במקום זאת, נספק הערות בהמשך כשתעברו על הקוד.

import argparse

from google.cloud import videointelligence



def analyze_labels(path):
    """Detects labels given a GCS path."""
    video_client = videointelligence.VideoIntelligenceServiceClient()
    features = [videointelligence.Feature.LABEL_DETECTION]
    operation = video_client.annotate_video(
        request={"features": features, "input_uri": path}
    )
    print("\nProcessing video for label annotations:")

    result = operation.result(timeout=90)
    print("\nFinished processing.")

    segment_labels = result.annotation_results[0].segment_label_annotations
    for i, segment_label in enumerate(segment_labels):
        print("Video label description: {}".format(segment_label.entity.description))
        for category_entity in segment_label.category_entities:
            print(
                "\tLabel category description: {}".format(category_entity.description)
            )

        for i, segment in enumerate(segment_label.segments):
            start_time = (
                segment.segment.start_time_offset.seconds
                + segment.segment.start_time_offset.microseconds / 1e6
            )
            end_time = (
                segment.segment.end_time_offset.seconds
                + segment.segment.end_time_offset.microseconds / 1e6
            )
            positions = "{}s to {}s".format(start_time, end_time)
            confidence = segment.confidence
            print("\tSegment {}: {}".format(i, positions))
            print("\tConfidence: {}".format(confidence))
        print("\n")


if __name__ == "__main__":
    parser = argparse.ArgumentParser(
        description=__doc__, formatter_class=argparse.RawDescriptionHelpFormatter
    )
    parser.add_argument("path", help="GCS file path for label detection.")
    args = parser.parse_args()

    analyze_labels(args.path)

האפליקציה הפשוטה הזו מבצעת את המשימות הבאות:

  1. מייבא את הספריות שנדרשות להפעלת האפליקציה.
  2. מקבלת קובץ וידאו שמאוחסן ב-URI של Cloud Storage כארגומנט ומעבירה אותו לפונקציה main().
  3. מקבל פרטי כניסה להפעלת השירות Video Intelligence API.
  4. יוצר בקשה להערה בסרטון כדי לשלוח אותה לשירות הווידאו.
  5. הבקשה נשלחת ומוחזרת פעולה ממושכת.
  6. הפונקציה חוזרת על הפעולה ארוכת הטווח עד שהסרטון יעובד ויוחזרו ערכים זמינים.
  7. מנתח את התגובה של השירות ומציג את התגובה למשתמש.

ייבוא ספריות

import argparse

from google.cloud import videointelligence

מייבאים כמה ספריות סטנדרטיות: argparse כדי לאפשר לאפליקציה לקבל שמות של קובצי קלט כארגומנטים, ו-sys כדי לעצב את הפלט בזמן ההמתנה לתגובות מ-API. החבילה time מיובאת כדי להפעיל כמה לולאות המתנה פשוטות.

כשמשתמשים ב-Video Intelligence API, צריך גם לייבא את google.cloud.videointelligence_v1 ואת מחלקת הספירה שלו, שמכילה את הספרייה של הקריאות ל-API שלנו.

הפעלת האפליקציה

parser = argparse.ArgumentParser(
    description=__doc__, formatter_class=argparse.RawDescriptionHelpFormatter
)
parser.add_argument("path", help="GCS file path for label detection.")
args = parser.parse_args()

analyze_labels(args.path)

במקרה הזה, הארגומנט שמועבר מנותח כדי לקבל את ה-URI של Cloud Storage של שם קובץ הווידאו, ומועבר לפונקציה main().

אימות ל-API

לפני שמתקשרים עם שירות Video Intelligence API, צריך לאמת את השירות באמצעות פרטי כניסה שהושגו בעבר. הדרך הכי פשוטה לקבל פרטי כניסה באפליקציה היא באמצעות Application Default Credentials‏ (ADC). כברירת מחדל, ADC מנסה לקבל פרטי כניסה מקובץ הסביבה GOOGLE_APPLICATION_CREDENTIALS, שצריך להיות מוגדר כך שיצביע על קובץ מפתח ה-JSON של חשבון השירות. (הגדרתם את חשבון השירות והסביבה שלכם לשימוש ב-ADC במדריך לתחילת העבודה.

הרכבת הבקשה

video_client = videointelligence.VideoIntelligenceServiceClient()
features = [videointelligence.Feature.LABEL_DETECTION]
operation = video_client.annotate_video(
    request={"features": features, "input_uri": path}
)

עכשיו ששירות Video Intelligence API מוכן, אפשר ליצור בקשה לשירות הזה. הבקשות ל-Video Intelligence API מסופקות כאובייקטים של JSON. מידע מלא על המבנה הספציפי של בקשה כזו מופיע בהפניית Video Intelligence API.

קטע הקוד הזה מבצע את המשימות הבאות:

  1. יוצר את ה-JSON לבקשת POST ל-method‏ annotate_video().
  2. הפונקציה מחדירה את המיקום של קובץ הווידאו ב-Cloud Storage אל הבקשה.
  3. מציין ששיטת annotate צריכה לבצע LABEL_DETECTION.

בדיקת הפעולה

result = operation.result(timeout=90)
print("\nFinished processing.")

באמצעות בקשת הפעולה הקיימת עבור הפעולה הקיימת, נוצרת לולאת while כדי לבדוק מעת לעת את מצב הפעולה. אחרי שהפעולה מציינת שהיא done, התגובה מנותחת.

ניתוח התשובה

segment_labels = result.annotation_results[0].segment_label_annotations
for i, segment_label in enumerate(segment_labels):
    print("Video label description: {}".format(segment_label.entity.description))
    for category_entity in segment_label.category_entities:
        print(
            "\tLabel category description: {}".format(category_entity.description)
        )

    for i, segment in enumerate(segment_label.segments):
        start_time = (
            segment.segment.start_time_offset.seconds
            + segment.segment.start_time_offset.microseconds / 1e6
        )
        end_time = (
            segment.segment.end_time_offset.seconds
            + segment.segment.end_time_offset.microseconds / 1e6
        )
        positions = "{}s to {}s".format(start_time, end_time)
        confidence = segment.confidence
        print("\tSegment {}: {}".format(i, positions))
        print("\tConfidence: {}".format(confidence))
    print("\n")

אחרי שהפעולה תושלם, התשובה תכיל את התוצאה בתוך AnnotateVideoResponse, שמורכבת מרשימה של annotationResults, אחת לכל סרטון שנשלח בבקשה. מכיוון שבבקשה נשלח רק סרטון אחד, נלקחת התוצאה הראשונה segmentLabelAnnotations, וכל התוויות ב-segmentLabelAnnotations עוברות בלולאה. אם משתמשים רק ב-segmentLabelAnnotations, במדריך הזה מוצגות רק הערות ברמת הסרטון. כל segment_label כולל תיאור (segment_label.description), רשימה של קטגוריות ישויות (segment_label.category_entities) ורשימה של קטעים שמציינים את שעת ההתחלה ושעת הסיום של המקרים שבהם התווית מופיעה בסרטון (צריך להיות קטע אחד שמתפרש על פני הסרטון כולו או קטע וידאו במקרה של segment_label_annotations).

{
   "name":"us-west1.12089999971048628582",
   "metadata":{
      "@type":"type.googleapis.com/google.cloud.videointelligence.v1.AnnotateVideoProgress",
      "annotationProgress":[
         {
            "inputUri":"gs://YOUR_BUCKET/YOUR_OBJECT",
            "updateTime":"2020-01-31T01:49:52.498015Z",
            "startTime":"2020-01-31T01:49:43.056481Z"
         }
      ]
   },
   "done": true,
   "response":{
      "@type":"type.googleapis.com/google.cloud.videointelligence.v1.AnnotateVideoResponse",
      "annotationResults":[
         {
            "inputUri":"gs://YOUR_BUCKET/YOUR_OBJECT",
            "segmentLabelAnnotations": [
              {
                "entity": {
                  "entityId": "/m/01yrx",
                  "languageCode": "en-US"
                },
                "segments": [
                  {
                    "segment": {
                      "startTimeOffset": "0s",
                      "endTimeOffset": "14.833664s"
                    },
                    "confidence": 0.98509187
                  }
                ]
              },
               ...
            ]
         }
      ]
   }
}

מכיוון שבבקשה נשלח רק סרטון אחד, המערכת מדפיסה את description הראשון של התוצאה הראשונה.

הפעלת האפליקציה

כדי להפעיל את האפליקציה, פשוט מעבירים לה את ה-URI של Cloud Storage של סרטון:

$ python labels.py gs://YOUR_BUCKET/YOUR_OBJECT
Operation us-west1.4757250774497581229 started: 2020-01-30T01:46:30.158989Z
Operation processing ...
The video has been successfully processed.

Video label description: urban area
        Label category description: city
        Segment 0: 0.0s to 38.752016s
        Confidence: 0.946980476379


Video label description: traffic
        Segment 0: 0.0s to 38.752016s
        Confidence: 0.94105899334


Video label description: vehicle
        Segment 0: 0.0s to 38.752016s
        Confidence: 0.919958174229
...
 

תשובה

בהמשך מופיעה דוגמה לפלט אפשרי.

Processing video for label annotations:

Finished processing. Video label description: crowd Label category description: people Segment 0: 0.0s to 60.24s Confidence: 0.527720749378

Video label description: official Label category description: person Segment 0: 0.0s to 60.24s Confidence: 0.372822880745

Video label description: audience Label category description: people Segment 0: 0.0s to 60.24s Confidence: 0.501719772816

Video label description: news Segment 0: 0.0s to 60.24s Confidence: 0.867252230644

Video label description: people Label category description: person Segment 0: 0.0s to 60.24s Confidence: 0.46747264266

Video label description: politics Segment 0: 0.0s to 60.24s Confidence: 0.319397002459

כל הכבוד! ביצעתם משימת הערות באמצעות Video Intelligence API.