見出し画像

【ChatGPT】にPythonプログラム書いてもらった「動画からフレーム静止画を抽出」

今日は、やろうと思っていてなかなか手がつかなかったPythonプログラムをchatGPTにお願いして完成させてみました。

前回、「BingAI」にお願いしてPythonプログラムを作った記事をアップしましたが、その次のステップのプログラムを今日完成させようというものです。

実をいうと、前回はBingAIを使ったのですが、chatGPTの場合は履歴がきちんと残せるため管理上便利なのと、最近のchatGPTは、生成途中に文字数がいっぱいで途切れてしまっても「生成継続」できるようになり、コードが途切れてしまうということがなくなったので、今回はchatGPTにPythonプログラムを作ってもらったわけです。

全体の構想は下記のようなものです。

1.プログラムA:静止画を連続再生するスライドショープログラム

これが上記のnoteで紹介したプログラムです。

2.プログラムB:動画からフレーム静止画を抽出するプログラム

これを今日つくりました。

この二つのプログラムが完成すると、下記の手順で動画生成を行うことが出来ます。

<AI動画生成の手順>

1.プログラムBを使って、基準となる動画からフレーム単位で静止画を取得する。
2.Stable Diffusionのimg2imgのBatch機能を使って、フレーム単位の静止画を1枚ずつ自動で画像生成する。
 →PROMPTに書かれた内容を反映した静止画が生成される。
3.プログラムAを使って、静止画を動画に変換する。

結果として、元の動画の動きをトレースしながら顔が違う新しい動画が生成されます。

下記の動画が完成した動画です。(Denoising strength:0.25)
モデル:chilloutmix_NiPrunedFp32Fix

Stable Diffusionには、拡張機能で「SD-CN-Animation」というものがありますが、それを使うよりも、この方法の方が、修正がしやすく便利なのではないかと思ってつくってみました。

Stable Diffusionのimg2imgのBatch機能の操作方法は、別のnoteに整理して、後ほどアップします。

chatGPTにPythonでプログラムを書いてもらう

まずは、下記のような依頼をしました。

<依頼内容>

Mov2Movというフォルダを作成し、同じフォルダ内に置かれた動画ファイル(MP4)からフレーム単位で静止画を取得し、保存するプログラムをPythonで作成してください。詳細は以下の通りです。

1.1秒間に切り取るフレーム数を入力ボックスで入力できるようにする。デフォルトは24枚とする。
2.動画を選択して実行できるようにする。
3.動画のファイル名と同一の名前のフォルダを新たに作成し、生成した静止画像(pngファイル)はそのフォルダの中に入れる。

これに対してchatGPTは、あっという間にコードを書いてくれ、それを実行するとエラーが出たのですが、そのエラーを教えると、すぐに間違いを修正し、最終的に下記のコードが完成しました。

import cv2
import sys
import os
import tkinter as tk
from tkinter import filedialog

# フレームレートのデフォルト値
default_frame_rate = 24

# フレームレートの入力ボックスを表示する関数
def get_frame_rate():
    root = tk.Tk()
    root.withdraw()

    frame_rate = tk.simpledialog.askinteger("フレームレート", "1秒間に切り取るフレーム数を入力してください(デフォルト: 24):", initialvalue=default_frame_rate)

    if frame_rate is None:
        frame_rate = default_frame_rate

    return frame_rate

# 動画ファイルを選択する関数
def select_video_file():
    root = tk.Tk()
    root.withdraw()

    file_path = filedialog.askopenfilename(title="動画ファイルを選択してください", filetypes=[("動画ファイル", "*.mp4"), ("すべてのファイル", "*.*")])

    if not file_path:
        print("動画ファイルが選択されませんでした。")
        sys.exit()

    return file_path

# フレーム保存用のフォルダを作成する関数
def create_output_folder(video_path):
    folder_path = os.path.splitext(video_path)[0]

    if not os.path.exists(folder_path):
        os.makedirs(folder_path)

    return folder_path

# 動画からフレームを切り取る関数
def extract_frames(video_path, frame_rate):
    # 動画ファイル読み込み
    cap = cv2.VideoCapture(video_path)

    if not cap.isOpened():
        print("動画の読み込み失敗")
        sys.exit()

    digit = len(str(int(cap.get(cv2.CAP_PROP_FRAME_COUNT))))

    n = 0
    count = 0
    frame_interval = int(cap.get(cv2.CAP_PROP_FPS) / frame_rate)
    while True:
        # read()でフレーム画像が読み込めたかを示すbool、フレーム画像の配列ndarrayのタプル
        is_image, frame_img = cap.read()
        if is_image:
            if count % frame_interval == 0:
                # 画像を保存
                cv2.imwrite(folder_path + "/" + str(n).zfill(digit) + ".png", frame_img)
                n += 1
            count += 1
        else:
            # フレーム画像が読み込めなかったら終了
            break

    cap.release()

# フレームレートを取得
frame_rate = get_frame_rate()

# 動画ファイルを選択
video_path = select_video_file()

# 出力用のフォルダを作成
folder_path = create_output_folder(video_path)

# フレームの切り取りと保存
extract_frames(video_path, frame_rate)

僕は、プログラムの構造についての知識は少しはありますが、Pythonのコードを自力で書くことはできません。
それでも、この通り、あっという間にプログラムが完成するというのは驚きです。

この記事が気に入ったらサポートをしてみませんか?