OpenCV cv2.imwrite で発生する「_img.empty()」エラーと「動画安定化」による解決法

OpenCV cv2.imwrite で発生する「_img.empty()」エラーと「動画安定化」による解決法

こんにちは!

画像処理や動画解析の現場で広く利用されている OpenCV。

しかし実務で動画処理を行っていると、時折以下のようなエラーに遭遇することがあります。

cv2.error: OpenCV(4.11.0) /io/opencv/modules/imgcodecs/src/loadsave.cpp:929:
error: (-215:Assertion failed) !_img.empty() in function 'imwrite'

このエラーは、cv2.imwrite() に渡された画像が空(None またはサイズ0) の場合に発生します。 一見単純に見える問題ですが、背後には「入力動画の不安定さ」や「並列処理の競合」といった要因が潜んでいることが少なくありません。

本記事では、このエラーの発生原因を掘り下げ、実務で効果のある解決策として 「動画の安定化(正規化)」 を紹介します。

TL;DR

OpenCVの動画処理で頻発する !_img.empty() エラーは、入力動画(mp4)の不安定さが根本原因であることがけっこう多い

不安定な動画→安定化するためのffmpegコマンドは

ffmpeg で動画を安定化

ffmpeg -y -fflags +genpts -i INPUT.mp4 \
  -vf "fps=30,format=yuv420p" \
  -c:v libx264 -preset slow -crf 20 -g 90 -sc_threshold 0 \
  -movflags +faststart -an OUTPUT_stable.mp4

最終手段
それでもダメなら、 連番画像に展開してから処理

目次

  • なぜ「空画像」が紛れ込むのか?
  • エラーを防ぐ基本的な工夫
  • 動画を「安定化」してから処理する
  • さらに堅牢にするレシピ
  • 実務で役立つ環境上の注意点
  • デバッグ方法
  • まとめ

なぜ動画に「空画像」が紛れ込むのか?

1. 入力動画の不安定さ

  • 可変フレームレート(VFR) 一部のカメラやスマートフォンは VFR で撮影しており、処理パイプラインによっては「抜けフレーム」や「タイムスタンプ不整合」が発生します。
  • 特殊なピクセルフォーマット 10bit、4:2:2、4:4:4 など、標準的でないフォーマットはライブラリによって扱いが不安定。
  • GOP 構造の揺らぎ I/P/B フレームの参照構造が複雑な動画は、特定フレームだけ取り出しに失敗するケースがあります。

2. 中間処理での破損

  • 一時的に PNG などへ展開して並列処理を行うと、I/O が競合し libpng error: IDAT: CRC error が出ることがあります
  • たとえば、 Windows + WSL 環境で /mnt/c を経由すると、I/O レイテンシが大きく、破損の可能性が増したりします

3. アルゴリズム側の仕様

  • 顔検出やセグメンテーションなどの処理で「対象が見つからない場合に None を返す」実装になっていると、そのまま imwrite に渡されて落ちます。

4. 環境要因

  • ディスクの空き容量不足やメモリ不足による一時的なフレーム生成失敗。
  • 並列度が高すぎて一時ファイルの読み書きが衝突するケース。

エラーを防ぐ基本的な工夫

imwrite 前のチェック

まずは cv2.imwrite を呼ぶ前に、画像が空でないか確認するのが基本です。

if img is None or getattr(img, "size", 0) == 0:
    # 空の場合はスキップやフォールバック処理を行う
    continue
cv2.imwrite(path, img)

安全なラッパー関数の例

リトライやフォールバックコピーを組み合わせるとさらに堅牢になります。

import cv2, os, shutil, time

def safe_imwrite(path, img, retries=2, sleep=0.05):
    if img is None or getattr(img, "size", 0) == 0:
        return False
    for _ in range(retries + 1):
        try:
            if cv2.imwrite(path, img):
                return True
        except cv2.error:
            pass
        time.sleep(sleep)
    return False

def write_with_fallback(out_path, img, src_path_for_fallback=None):
    os.makedirs(os.path.dirname(out_path), exist_ok=True)
    if safe_imwrite(out_path, img):
        return True
    if src_path_for_fallback and os.path.exists(src_path_for_fallback):
        shutil.copy2(src_path_for_fallback, out_path)
        return True
    return False

動画を「安定化」してから処理する

根本的な解決策として有効なのが、

入力動画を事前に正規化(安定化)すること

です。

これがけっこう効きます

具体的には以下のような ffmpeg コマンドを利用します。

標準的な安定化(最初に試すべきレシピ)

ffmpeg -y -fflags +genpts -i INPUT.mp4 \
  -vf "fps=30,format=yuv420p" \
  -c:v libx264 -preset slow -crf 20 -g 90 -sc_threshold 0 \
  -movflags +faststart \
  -an \
  OUTPUT_stable.mp4

オプションの詳細説明

オプション 説明 効果
-fflags +genpts タイムスタンプ生成 欠損したPTSを補完
-vf fps=30 FPS固定 VFR→CFR変換で安定化
-vf format=yuv420p ピクセルフォーマット統一 最も互換性の高い8bit 4:2:0に
-g 90 GOPサイズ指定 30fpsなら3秒ごとにIフレーム
-sc_threshold 0 シーンチェンジ無効化 GOP構造の完全な安定化
-crf 20 品質設定 品質とファイルサイズのバランス
-movflags +faststart メタデータ配置最適化 ストリーミング再生の高速化
-an 音声除去 映像処理に特化

さらに堅牢にするレシピ

I フレームのみ(All-I)

ffmpeg -i INPUT.mp4 \
  -vf "fps=30,format=yuv420p" \
  -c:v libx264 -crf 18 -g 1 \
  -an \
  OUTPUT_allI.mp4

→ すべて I フレーム化するため、ランダムアクセス時の不具合が激減。ただしファイルサイズは増加。

ProRes 422HQ(中間コーデック)

ffmpeg -i INPUT.mp4 \
  -vf "fps=30,format=yuv422p10le" \
  -c:v prores_ks -profile:v 3 \
  -an \
  OUTPUT_prores422hq.mov

→ 編集用途でもよく使われる高品質・高安定コーデック。

MJPEG(軽量で堅牢)

ffmpeg -i INPUT.mp4 \
  -vf "fps=30,format=yuvj420p" \
  -c:v mjpeg -q:v 3 \
  -an \
  OUTPUT_mjpeg.avi

→ I フレームのみ、デコードも軽い。検証・実験用に便利。

画像連番に展開(最強の安定策)

mkdir -p frames
ffmpeg -i INPUT.mp4 -vf "fps=30" -qscale:v 2 frames/%06d.jpg

→ PNG より JPG の方が CRC エラーを避けやすく、大量並列処理に強い。


実務で役立つ環境上の注意点

  • WSL を使う場合 一時ファイルは /mnt/c ではなく /home/... 側(ext4)に置く方が安定。
  • ディスクの空き容量 df -h で確認し、余裕を持たせる。容量不足は破損の温床。
  • 並列度の調整 ワーカー数を減らすと I/O 衝突や PNG CRC エラーを減らせる。
  • "未検出=原画返し"の仕様に統一 処理関数が None を返さず、検出できなければ元のフレームを返す設計にする。

デバッグ方法

問題の切り分けには、どのフレームで失敗しているかを特定することが重要です。

フレーム読み込みの検証

def debug_frame_read(video_path):
    """どのフレームで読み込みに失敗しているか特定"""
    cap = cv2.VideoCapture(video_path)
    frame_count = 0
    failed_frames = []
    
    while True:
        ret, frame = cap.read()
        if not ret:
            break
        if frame is None or frame.size == 0:
            failed_frames.append(frame_count)
            print(f"Frame {frame_count}: Empty or corrupted")
        frame_count += 1
    
    cap.release()
    
    if failed_frames:
        print(f"\n問題のあるフレーム数: {len(failed_frames)}")
        print(f"最初の10個: {failed_frames[:10]}")
    else:
        print(f"全 {frame_count} フレーム正常に読み込み可能")
    
    return failed_frames

動画の整合性チェック

def verify_video_integrity(video_path):
    """動画ファイルの基本情報と整合性を確認"""
    cap = cv2.VideoCapture(video_path)
    
    if not cap.isOpened():
        print(f"エラー: {video_path} を開けません")
        return False
    
    fps = cap.get(cv2.CAP_PROP_FPS)
    frame_count = int(cap.get(cv2.CAP_PROP_FRAME_COUNT))
    width = int(cap.get(cv2.CAP_PROP_FRAME_WIDTH))
    height = int(cap.get(cv2.CAP_PROP_FRAME_HEIGHT))
    
    print(f"動画情報:")
    print(f"  FPS: {fps}")
    print(f"  フレーム数: {frame_count}")
    print(f"  解像度: {width}x{height}")
    
    # 実際に読み込めるフレーム数をカウント
    actual_count = 0
    while True:
        ret, _ = cap.read()
        if not ret:
            break
        actual_count += 1
    
    cap.release()
    
    if actual_count != frame_count:
        print(f"警告: メタデータのフレーム数({frame_count})と")
        print(f"      実際のフレーム数({actual_count})が一致しません")
        return False
    
    return True

まとめ

  • cv2.imwrite_img.empty() エラーは 空画像が渡された結果 であり、背景には 入力動画の不安定さや I/O の揺らぎ がある。
  • 解決にはの二段構えが効果的。
    1. ガード処理を入れる(空画像をスキップ or フォールバック)
    2. 動画を ffmpeg で安定化する(CFR化・ピクセルフォーマット統一・GOP安定化)
  • さらに堅牢化するなら、All-I / ProRes / MJPEG / 画像連番 といった手段も検討可能。
  • デバッグ時は、問題のあるフレームを特定することで原因の切り分けが容易になる。

こうした工夫により、実務の動画処理パイプラインはより堅牢で信頼性の高いものになります。

なにはともあれ、
まずは後段で泣かないために入力となる動画の品質をあげましょう!

それでは、お読みいただきありがとうございました!

Read more

Google GenAI SDK のストリーミングでマルチターン画像編集🍌が不安定になる問題と対処法

Google GenAI SDK のストリーミングでマルチターン画像編集🍌が不安定になる問題と対処法

こんにちは! Gemini 3 Pro Image (Nano banana Pro)を使ったマルチターン画像編集機能を実装していたところ、動いたり動かなかったりするという厄介な問題に遭遇しました。 本記事では、この問題の現象、原因調査の過程、そして解決策を共有します。 問題の現象 実行環境 Google GenAI SDKライブラリ(pip): google-genai 1.56.0 期待する動作 1. ユーザー: 「かわいい子猫の画像を生成して」 2. Gemini: 子猫の画像を生成 3. ユーザー: 「この子にメガネをかけて」 4. Gemini: 同じ子猫にメガネをかけた画像を生成 実際に起きた現象 1. ユーザー: 「かわいい子猫の画像を生成して」 2. Gemini: 茶色の子猫の画像を生成 3. ユーザー: 「この子にメガネをかけて」 4. Gemini: メガネをかけた女の子の画像を生成

By Qualiteg プロダクト開発部
【出展報告】TOKYO DIGICONX 2026

【出展報告】TOKYO DIGICONX 2026

こんにちは! 先日、「TOKYO DIGICONX 2026」に出展してまいりましたのでレポートさせていただきます! TOKYO DIGICONX 2026 TOKYO DIGICONX 2026は、2026年1月8日(木)~10日(土)に東京ビッグサイト 南3・4ホールで開催された、XR・メタバース・AI・Web3をテーマにした総合展示会です。 正式名称は「第3回 TOKYO XR・メタバース&コンテンツビジネスワールド」で、東京都、XRコンソーシアム、Metaverse Japan、東京商工会議所で構成されるXR・メタバース等産業展実行委員会が主催しています。 180社以上のスタートアップや企業が出展し、ビジネスデイ(8日・9日)とパブリックデイ(10日)の3日間にわたり、XR・メタバース・AI分野の最前線を体感できるイベントとなりました。 冬の東京ビッグサイト 新年明けて間もない1月の東京ビッグサイト。お正月気分もそこそこに、気合を入れて会場入りしました�

By Qualiteg ビジネス開発本部 | マーケティング部
コーディングエージェントの現状と未来への展望 【第2回】主要ツール比較と構造的課題

コーディングエージェントの現状と未来への展望 【第2回】主要ツール比較と構造的課題

こんにちは! 今回は、コーディングエージェントシリーズ第2回です! 前回の第1回では、2025年12月時点で百花繚乱状態にあるAIコーディングエージェントの全体像を俯瞰しました。 AIコーディングエージェント20選!現状と未来への展望 【第1回】全体像と基礎こんにちは! 今回は、20種類以上あるまさに百花繚乱なAIコーディングツールを一挙に紹介&解説していきたいとおもいます! AIをつかったコーディングはもはや常識となり、日々目まぐるしく新しいツールが登場しています。当社でも自社開発のAIコーディングツールをふくめ複数のツールを活用してソフトウェア開発をすすめていますが、次々とナイスなツールがでてきて興奮しつつも、正直キャッチアップが追いつかない…!という状況です。 「結局どれを使えばいいの?」「Claude CodeとCursorって何が違うの?」「オープンソースでも使えるやつあるの?」——そんな疑問を持っている方も多いのではないでしょうか。 そこで本シリーズでは、2025年12月時点でのAIコーディングツールを徹底的に整理してみました。商用サービスからオープンソースまで、20

By Qualiteg コンサルティング
LLM学習の現実:GPU選びから学習コストまで徹底解説

LLM学習の現実:GPU選びから学習コストまで徹底解説

こんにちは! なぜOpenAIやAnthropicは世界最高水準のLLMを作れるのに、それに肩を並べる日本発のLLMは存在しないのでしょうか? 技術力の差でしょうか。それとも人材の問題でしょうか。 答えはもっとシンプルです。GPUの枚数とお金です。 今日はそんな 「LLMの学習」にフォーカスをあて、そのリアルについて徹底解説いたします! 1. はじめに 「LLMを自分で学習させてみたい」 そう思ったとき、最初にぶつかる壁がGPUの問題です。 どのGPUを何枚使えばいいのか。クラウドで借りるべきか、オンプレで買うべきか。そもそも個人や小規模チームでLLM学習は現実的なのか。 本記事では、こうした疑問に対して、具体的な数字と事例を交えながら答えていきます。 たとえばLLaMA 2の学習にはA100が2,048枚使われました。DeepSeek-V3は約8億円かかりました。では、あなたの手元のGPUでは何ができるのか。そこを明らかにしていきたいと思います。 対象読者は、LLM学習に興味があるエンジニアや研究者です。PyTorchでモデルを書いたことがある程度の知識を前提とし

By Qualiteg プロダクト開発部, Qualiteg 研究部