1
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

OpenCVで静止画から動画を作成する方法

Posted at

はじめに

image.png

複数の静止画から動画を作成したいケースは多いと思います。この記事では、OpenCVを使用して静止画から動画を作成する方法を解説します。シンプルで高速な処理が可能なため、大量の画像を扱う場合に特に有効です。

環境準備

必要なライブラリをインストールします:

pip install opencv-python
pip install tqdm  # 進捗表示用(オプション)

基本的な実装

image.png

1. シンプルな動画作成

import cv2
import glob
import os

def create_video(image_folder, output_path, fps=30):
    # 画像ファイルの取得(.jpg, .png対応)
    images = []
    for ext in ('*.jpg', '*.png'):
        images.extend(glob.glob(os.path.join(image_folder, ext)))
    images = sorted(images)
    
    if not images:
        print("画像が見つかりません")
        return
    
    # 最初の画像から動画サイズを取得
    frame = cv2.imread(images[0])
    height, width, layers = frame.shape
    
    # 動画ファイルの設定
    fourcc = cv2.VideoWriter_fourcc(*'mp4v')
    video = cv2.VideoWriter(output_path, fourcc, fps, (width, height))
    
    # 各画像を動画に追加
    for image in images:
        frame = cv2.imread(image)
        video.write(frame)
    
    video.release()
    print(f"動画を保存しました: {output_path}")

2. 進捗表示付きの実装

from tqdm import tqdm

def create_video_with_progress(image_folder, output_path, fps=30):
    images = sorted(glob.glob(os.path.join(image_folder, '*.jpg')))
    
    if not images:
        print("画像が見つかりません")
        return
    
    frame = cv2.imread(images[0])
    height, width, layers = frame.shape
    
    fourcc = cv2.VideoWriter_fourcc(*'mp4v')
    video = cv2.VideoWriter(output_path, fourcc, fps, (width, height))
    
    for image in tqdm(images, desc="動画作成中"):
        frame = cv2.imread(image)
        video.write(frame)
    
    video.release()

3. リサイズ機能付きの実装

import numpy as np

def resize_frame(frame, target_size=(1920, 1080)):
    """アスペクト比を保持しながらリサイズ"""
    h, w = frame.shape[:2]
    aspect = w / h
    
    if aspect > target_size[0] / target_size[1]:
        # 幅に合わせてリサイズ
        new_w = target_size[0]
        new_h = int(new_w / aspect)
    else:
        # 高さに合わせてリサイズ
        new_h = target_size[1]
        new_w = int(new_h * aspect)
    
    resized = cv2.resize(frame, (new_w, new_h))
    
    # 黒背景に中央配置
    result = np.zeros((target_size[1], target_size[0], 3), dtype=np.uint8)
    y_offset = (target_size[1] - new_h) // 2
    x_offset = (target_size[0] - new_w) // 2
    result[y_offset:y_offset+new_h, x_offset:x_offset+new_w] = resized
    
    return result

def create_video_with_resize(image_folder, output_path, target_size=(1920, 1080), fps=30):
    images = sorted(glob.glob(os.path.join(image_folder, '*.jpg')))
    
    if not images:
        print("画像が見つかりません")
        return
    
    fourcc = cv2.VideoWriter_fourcc(*'mp4v')
    video = cv2.VideoWriter(output_path, fourcc, fps, target_size)
    
    for image in tqdm(images, desc="動画作成中"):
        frame = cv2.imread(image)
        if frame is None:
            print(f"警告: {image} を読み込めませんでした")
            continue
        
        resized_frame = resize_frame(frame, target_size)
        video.write(resized_frame)
    
    video.release()
    print(f"動画を保存しました: {output_path}")

使用例

# 基本的な使用方法
create_video("images", "output.mp4")

# リサイズ機能付きで使用(フルHD)
create_video_with_resize("images", "output_hd.mp4", target_size=(1920, 1080))

# 進捗表示付きで使用
create_video_with_progress("images", "output_with_progress.mp4")

トラブルシューティング

1. 生成された動画が再生できない場合

コーデックを変更することで解決できる場合があります:

# H264コーデックを使用
fourcc = cv2.VideoWriter_fourcc(*'avc1')  # または 'H264'

2. メモリエラーが発生する場合

バッチ処理を導入してメモリ使用量を抑えることができます:

def create_video_memory_efficient(image_folder, output_path, batch_size=10):
    images = sorted(glob.glob(os.path.join(image_folder, '*.jpg')))
    
    frame = cv2.imread(images[0])
    height, width, layers = frame.shape
    
    fourcc = cv2.VideoWriter_fourcc(*'mp4v')
    video = cv2.VideoWriter(output_path, fourcc, 30, (width, height))
    
    # バッチ処理でメモリ使用量を抑える
    for i in range(0, len(images), batch_size):
        batch = images[i:i+batch_size]
        for image in batch:
            frame = cv2.imread(image)
            video.write(frame)
    
    video.release()

3. よくある問題と解決策

  1. 画像の読み込みエラー

    • 画像パスに日本語が含まれていないか確認
    • ファイルのパーミッションを確認
    • 対応していない画像形式でないか確認
  2. 出力動画のサイズが大きすぎる

    • fpsを調整(30→24など)
    • リサイズ機能を使用して解像度を下げる
    • 圧縮率の高いコーデックを使用
  3. 処理が遅い場合

    • バッチサイズを調整
    • 画像を事前にリサイズ
    • マルチプロセス処理の導入を検討

まとめ

image.png

OpenCVを使用することで、以下のような利点があります:

  • シンプルなコードで動画作成が可能
  • 処理が高速
  • メモリ効率が良い
  • カスタマイズ性が高い

参考リンク

参考: 静止画像を生成するプログラム

import numpy as np
import matplotlib.pyplot as plt
import matplotlib.patches as patches
from PIL import Image

# 画像サイズ
width, height = 300, 200
num_frames = 50  # フレーム数

# 猫の移動範囲(横方向)
x_positions = np.linspace(20, width - 80, num_frames)

# 画像を保存するリスト
image_files = []

# 画像を生成
for i in range(num_frames):
    fig, ax = plt.subplots(figsize=(width / 50, height / 50), dpi=50)
    ax.set_xlim(0, width)
    ax.set_ylim(0, height)
    ax.set_xticks([])
    ax.set_yticks([])
    ax.axis("off")

    # 背景色
    ax.set_facecolor("lightblue")

    # 猫の胴体
    body = patches.Ellipse((x_positions[i], 100), 60, 30, color="black")
    ax.add_patch(body)

    # 頭
    head = patches.Circle((x_positions[i] + 35, 110), 15, color="black")
    ax.add_patch(head)

    # 足(交互に動かす)
    leg1_y = 85 if i % 2 == 0 else 75
    leg2_y = 75 if i % 2 == 0 else 85
    ax.plot([x_positions[i] - 20, x_positions[i] - 15], [leg1_y, 60], color="black", linewidth=3)
    ax.plot([x_positions[i] + 20, x_positions[i] + 15], [leg2_y, 60], color="black", linewidth=3)

    # 尾
    tail = patches.Arc((x_positions[i] - 30, 110), 30, 30, angle=0, theta1=30, theta2=150, color="black", linewidth=3)
    ax.add_patch(tail)

    # 画像を保存
    filename = f"image{i+1:03d}.png"
    plt.savefig(filename, bbox_inches='tight', pad_inches=0.1)
    plt.close(fig)
    image_files.append(filename)

# 生成した画像を確認
image_files[:5]  # 最初の5枚を表示

image.png

1
1
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?