技術関連

[cloud vision api]動画の中の字幕を抽出してみる

投稿日:

概要

作成したもの

  • GOOGLEのcloud vision apiを使って動画の中に特定の字幕が含まれるかどうかの判別アルゴリズムを作成

使用した技術・ライブラリ

  • OpenCV
  • Google Colud Vision API

動機

人が興奮しているときの動画を機械的に収集したくて、
「ヤバイ!」と言っているときが興奮している場面が多かったので、
字幕の中で特定のワードが含まれる動画を検知するアルゴリズムを書きました。

実装

Python3.6xを使って実装していきます。

実装方針

以下のフローで実装をしていきます。
1.一定間隔のフレームごとに動画から画像を抽出
2.画像にOCRをかけて字幕を取得
3.取得した字幕に特定のワードが含まれるかどうかを判別

①はOpenCVを使って動画から画像を抽出し、
②は日本語に対応しているGoogle Vision APIを使用してAPI経由で画像からテキストを取得していきます。

Google Vision APIの設定については、今回割愛し実装部分のみ載せていきたいと思います。

実装結果


GOOGLE_CLOUD_VISION_API_URL = 'https://vision.googleapis.com/v1/images:annotate?key='
API_KEY = '' # 取得したAPIキーを入力してください。
INPUT_DIR = './data/*/'
STEP_SEC = 1 # 何秒ごとに動画をキャプションするか
PIC_SIZE = 200
TMP_IMG = './tmp.jpg'
PICK_UP_WORD = ['やばい','ヤバイ','ヤバい']

STEP_SECでは何秒ごとにOCR処理をするかを指定
PIC_SIZEではAPIに送信するときのサイズを指定
PICK_UP_WORDでは検出するワードのリストを定義しています。


# APIを呼び、認識結果をjson型で返す
def request_cloud_vison_api(image_base64):
    api_url = GOOGLE_CLOUD_VISION_API_URL + API_KEY
    req_body = json.dumps({
        'requests': [{
            'image': {
                'content': image_base64.decode('utf-8') # jsonに変換するためにstring型に変換する
            },
            'features': [{
                'type': 'TEXT_DETECTION', # ここを変更することで分析内容を変更できる
                'maxResults': 10,
            }]
        }]
    })
    res = requests.post(api_url, data=req_body)
    return res.json()

APIに画像を送信する関数になります。画像はBASE64に変換してJsonでAPIに投げています。


# 画像読み込み
def img_to_base64(filepath):
    with open(filepath, 'rb') as img:
        img_byte = img.read()
    return base64.b64encode(img_byte)


画像をBASE64に変換するための関数を作成します。



# 入力動画読み込み
file_list = glob.glob(os.path.join(INPUT_DIR,'*.mp4'))

検査する動画ファイルリストを取得します。


result_list = []
for file in file_list:
    result = {}
    result['file_name'] = file
    result['res'] = []
    result['flag'] = False
    cap = cv2.VideoCapture(file)
    fps = cap.get(cv2.CAP_PROP_FPS)
    frame_count = cap.get(cv2.CAP_PROP_FRAME_COUNT)
    for n in range(0, int(frame_count), int(fps * STEP_SEC)):
        cap.set(cv2.CAP_PROP_POS_FRAMES, n)
        ret, frame = cap.read()
        # APIに送信
        frame = cv2.resize(frame, (PIC_SIZE,int(frame.shape[0]*PIC_SIZE/frame.shape[1])))
        tmp_img = cv2.imwrite(TMP_IMG, frame)
        img_base64 = img_to_base64(TMP_IMG)
        res = request_cloud_vison_api(img_base64)
        # 認識した文字のみを出力
        if "fullTextAnnotation" in res["responses"][0]:
            text = res["responses"][0]["fullTextAnnotation"]["text"]
            result['res'].append({'text':text,'sec':n/fps})
            for yabai in PICK_UP_WORD:
                if yabai in text:
                    result['flag'] = True
                    break
    result_list.append(result)
    print(result['flag'], ':',result['file_name'])

指定した秒数のフレームごとに画像を抽出して、APIに画像を投げていきます。
取得したテキストの中に特定のワードがあれば、フラグをTrueにして終了になります。

実行結果


[{'file_name': './data\\bad\\119821.mp4', 'res': [], 'flag': False},
{'file_name': './data\\bad\\209294.mp4', 'res': [], 'flag': False},
{'file_name': './data\\bad\\711710.mp4', 'res': [], 'flag': False},
{'file_name': './data\\bad\\731465.mp4', 'res': [], 'flag': False},
{'file_name': './data\\good\\112300.mp4',
'res': [{'text': '自分から誘ってまさかのドタキャン!!\n', 'sec': 0.0},
{'text': 'ついにキレた\n', 'sec': 0.9676343009676344}],
'flag': False},
{'file_name': './data\\good\\887107.mp4',
'res': [{'text': 'やばいっ\n', 'sec': 0.0},
{'text': 'やばいっ\n', 'sec': 1.0},
{'text': 'やばいっ\n', 'sec': 2.0},
{'text': 'ヤパイです\n', 'sec': 3.0},
{'text': 'ヤパイです\n', 'sec': 4.0},
{'text': 'ヤパイです\n', 'sec': 5.0}],
'flag': True}]

badに字幕なし、goodに字幕あり動画を格納しており、
goodのなかでyabai_1.mp4は「ヤバイ」テロップが含まれているのですが、きちんと検知できています。

結論・感想

cloud vision APIとOpenCVを使用して簡単に動画の中のテロップを検知するアルゴリズムを書くことができました。
次回はこのアルゴリズムとOpenPoseを使ってヤバいときの動きについて分析していきたいと思います。

-技術関連

Copyright© AIなんて気合いダッ! , 2019 All Rights Reserved Powered by AFFINGER5.