めもちょー

メモ帳代わりに使っています。

動画から特定範囲をトリミング

必要なものをインスコ

pip install ffmpeg-python
import ffmpeg
import cv2
import os.path
import numpy as np

def video_trimming(video_path, x, y, w, h):
    """
    video_path # ファイルの絶対パス
    start_x = 850  # 切り取りたい区画のx座標(px)
    start_y = 500  # 切り取りたい区画のy座標(px)
    width = 700  # 切り取りたい区画の幅(px)
    height = 580  # 切り取りたい区画の高さ(px)
    """

    # トリミングファイル・パラメータ指定
    stream = ffmpeg.input(video_path)
    stream = ffmpeg.crop(stream, x, x, w, h)

    # 出力ファイル名生成
    output_file_str = video_path.split(".")
    output_file_name = output_file_str[0] + "_trimed." + output_file_str[1]
    stream = ffmpeg.output(stream, output_file_name)

    # 実行(ファイルがあると上書き)
    ffmpeg.run(stream, overwrite_output=True)


def output_one_img(video_path, frame_no=0):
    cap_file: cv2.VideoCapture = cv2.VideoCapture(video_path)
    
    width = cap_file.get(cv2.CAP_PROP_FRAME_WIDTH) # 192.0
    height = cap_file.get(cv2.CAP_PROP_FRAME_HEIGHT) # 1080.0
    frame_count = cap_file.get(cv2.CAP_PROP_FRAME_COUNT) # 774: [0: 773]の整数値が使える
    print("width:", width)
    print("height:", height)
    print("総frame数:", frame_count)


    if frame_no != 0:
        cap_file.set(cv2.CAP_PROP_POS_FRAMES, frame_no-1)
    ret, frame = cap_file.read()
    print(type(frame)) # numpy.ndarray
    print(frame.shape) # (1080, 1920, 3)
    return frame


def output_img(output_path, nd_array):
    cv2.imwrite(output_path, nd_array)
    

def put_rect_on_img(nd_array, x, y, w, h):
    img = cv2.rectangle(nd_array, (x, y), (x+w, y+h), (255, 255, 0), 3)
    return img


if __name__ == '__main__':
    video_path = 'sample.mp4'
    
    # 対象範囲を調べるための操作
    # output one frame
    frame = output_one_img(video_path, frame_no=500)
    video_name, ext = os.path.splitext(video_path)
    output_path = video_name + "_one_frame" + ".png"
    output_img(output_path, frame)

    # 画像の対象範囲をマーキング
    x, y = 1100, 700
    w, h = 820, 300
    marked_img = put_rect_on_img(frame, x, y, w, h)
    output_path = video_name + "_one_fram_marked" + ".png"
    output_img(output_path, frame)

    # 上の2つで調整が出来たらx,y,w,hを使ってクロッピング
    video_trimming(video_path, x, y, w, h)

上2つの関数で任意のフレーム数と長方形の枠で切り取りたい部分を調整できる(本当はGUI作りたいところだったけど面倒なので画像を開きながらプログラムを実行し続ける)
f:id:gesoges0:20220306005432p:plain
f:id:gesoges0:20220306005444p:plain

video_trimming()関数を実行すると元のmp4の指定した部分の動画を得ることができる
f:id:gesoges0:20220306010037g:plain

この動画に対してpyocrを使用すれば(フレーム番号(≒時刻)、ラベル)のリストが得られそう