VideoCapture入門|基本から黒画面・FPS対策

AI用語

カメラ映像をリアルタイムで扱ったり、動画ファイルをフレーム単位で処理したりするとき、OpenCVの「VideoCapture」は欠かせない存在です。ただ、実際に使ってみると「画面が黒いまま」「FPSが思いどおりにならない」「動画ファイルの情報をどう取得すればいいのか分からない」など、初心者だけでなく実務でもつまずきが起きやすい部分でもあります。

この記事では、VideoCaptureの基本から、Webカメラ・動画ファイルの扱い方、プロパティ設定の注意点、よくあるエラーとチェックリスト、そしてAI・画像処理への応用まで整理します。読み終える頃には、VideoCaptureを使った入力処理を自信を持って構築できるようになるはずです。

📖この記事のポイント

  • VideoCaptureはWebカメラや動画ファイルを扱うOpenCVの基本クラスで、ret/frameの理解が重要!
  • カメラと動画読み込みは同じAPIで統一的に利用できるため、応用が効きやすい!
  • 解像度・FPSなどの設定はカメラ側制約が多く、set() と get() の確認が必須!
  • 黒画面・isOpened() False・frame None などは環境依存トラブルが多く、チェックリスト対応が有効!
  • 動画情報の取得やフレーム位置のジャンプなど実務で使う操作が揃っている!
  • 取得したフレームはAIモデルや画像処理にそのまま活用でき、リアルタイム処理設計が鍵になる!
  • たった2時間の無料セミナー会社に依存しない働き方&AIスキルを身につけられる!
  • 今すぐ申し込めば、すぐに月収10万円UPを目指すための超有料級の12大特典も無料でもらえる!

\ 累計受講者10万人突破 /

無料特典を今すぐ受け取る
監修者プロフィール
森下浩志
日本最大級のAI情報プラットフォーム「romptn ai」編集長。著書に「0からはじめるStable Diffusion」「0からはじめるStable Diffusion モデル・拡張機能集編」など、AmazonベストセラーのAI関連書籍を多数執筆。AIにおける情報の非対称性を解消するための社内研修や出張講義も行う。

VideoCaptureとは?OpenCVにおける役割と基本

VideoCaptureは、OpenCVでカメラ映像や動画ファイルなどの「映像ストリーム」を読み込むためのクラスです。Pythonでは cv2.VideoCapture()、C++では cv::VideoCapture として利用でき、どちらも「フレームを1枚ずつ取得する入口」という役割を担います。

VideoCaptureでできること

  • PCやノートPCに接続されたWebカメラの映像をリアルタイムに取得する
  • mp4 / avi などの動画ファイルを1フレームずつ読み込む
  • 連番画像(img_0001.jpg, img_0002.jpg, …)を“動画のように”扱う
  • 環境によっては、IPカメラやRTSPストリームを入力として扱う

いずれの場合も、「VideoCaptureからフレームを取り出す → 好きな処理をする → 次のフレームを読む」というループ構造になります。

コンストラクタの基本(カメラID・ファイルパス・API指定)

PythonでのVideoCaptureコンストラクタの代表的な例は次の3つです。

import cv2

# 1. デフォルトのWebカメラ(デバイスID 0)
cap = cv2.VideoCapture(0)

# 2. 動画ファイル
cap = cv2.VideoCapture("movie.mp4")

# 3. APIバックエンドを明示(Windowsで安定させたいときなど)
cap = cv2.VideoCapture(0, cv2.CAP_DSHOW)  # 例:DirectShow を指定

第1引数に「デバイス番号」または「ファイルパス」を渡し、必要に応じて第2引数で使用するAPIバックエンド(V4L2, DirectShow など)を指定できます。

read() が返す ret と frame の意味

read() を呼ぶと、次の2つが返されます。

  • ret:フレーム取得が成功したかどうか(True/False)
  • frame:取得した画像データ(NumPy配列)

動画の終端に到達したり、カメラからフレームが取得できない場合は ret が False になります。これを利用してループ終了を判断するのが定番のパターンです。

while cap.isOpened():
    ret, frame = cap.read()
    if not ret:
        # 動画終端 or エラー
        break

    # frame に対して処理を書く

Webカメラを表示する最小サンプルコード

まずはWebカメラを起動し、1フレームずつ取得してウィンドウに表示する最小構成を確認します。

Pythonでの基本コード

import cv2

cap = cv2.VideoCapture(0)

if not cap.isOpened():
    print("カメラが開けませんでした")
    exit()

while True:
    ret, frame = cap.read()
    if not ret:
        break

    cv2.imshow("Camera", frame)

    # 'q' キーで終了
    if cv2.waitKey(1) & 0xFF == ord('q'):
        break

cap.release()
cv2.destroyAllWindows()
  • cap.isOpened() で「そもそもカメラが開けているか」を確認する
  • waitKey(1) は1msだけキー入力を待ちつつ、ウィンドウを更新する役割も持つ

デバイス番号の仕組みと選び方

VideoCaptureの第1引数に渡す「0」「1」「2」などの数字は、OSが認識しているカメラのIDです。

  • ノートPCの内蔵カメラは多くの場合 0
  • USBカメラを追加すると 1, 2… と番号が増えていく
  • 「0では開かない」場合は 1, 2 と順に試す

どの番号がどのカメラに対応しているか分からないときは、OS標準のカメラアプリ(Windowsの「カメラ」アプリやmacOSのPhoto Boothなど)で接続状況を確認しつつ、番号を切り替えて試すと把握しやすくなります。

安全に終了するためのポイント

  • cap.release() を必ず実行して、カメラデバイスを解放する
  • cv2.destroyAllWindows() でOpenCVが開いたウィンドウをまとめて閉じる
  • 例外が起きても確実に解放したい場合は try/finally で囲む
cap = cv2.VideoCapture(0)

try:
    while True:
        ret, frame = cap.read()
        if not ret:
            break
        cv2.imshow("Camera", frame)
        if cv2.waitKey(1) & 0xFF == ord('q'):
            break
finally:
    cap.release()
    cv2.destroyAllWindows()

動画ファイル(mp4など)の読み込みと基本操作

動画ファイルも、VideoCaptureにファイルパスを渡すだけで読み込めます。Webカメラのコードから「引数が0かパスか」が変わるだけです。

動画ファイルを1フレームずつ読み込む例

import cv2

cap = cv2.VideoCapture("movie.mp4")

if not cap.isOpened():
    print("動画ファイルを開けませんでした")
    exit()

while True:
    ret, frame = cap.read()
    if not ret:
        # 終端に到達
        break

    cv2.imshow("Video", frame)

    # 再生速度を少しゆっくりにする例(20ms待機)
    if cv2.waitKey(20) & 0xFF == ord('q'):
        break

cap.release()
cv2.destroyAllWindows()

相対パスがうまく通らない場合は、一度絶対パスで試すと原因切り分けがしやすくなります。

FPSやフレーム数などの動画情報を取得する

動画ファイルの基本情報(メタデータ)は get() で取得できます。

取得したい情報CAP_PROP
総フレーム数CAP_PROP_FRAME_COUNT
FPSCAP_PROP_FPS
動画の幅CAP_PROP_FRAME_WIDTH
動画の高さCAP_PROP_FRAME_HEIGHT
fps = cap.get(cv2.CAP_PROP_FPS)
frame_count = cap.get(cv2.CAP_PROP_FRAME_COUNT)
width = cap.get(cv2.CAP_PROP_FRAME_WIDTH)
height = cap.get(cv2.CAP_PROP_FRAME_HEIGHT)

duration = frame_count / fps if fps > 0 else 0

print(f"FPS: {fps}")
print(f"フレーム数: {frame_count}")
print(f"解像度: {width} x {height}")
print(f"長さ: {duration:.2f} 秒")

特定のフレームや位置にジャンプする

動画の一部だけを処理したい場合は、フレーム位置を明示的に指定してから read() します。

# 100フレーム目から再生を開始
cap.set(cv2.CAP_PROP_POS_FRAMES, 100)

ret, frame = cap.read()
# ここで frame は 100フレーム目(0始まりなら101枚目)の画像

開始・終了フレームを決めてループを書くことで、「00:10〜00:20の区間だけ切り出す」といった処理も実現できます。

VideoCaptureのプロパティ設定(FPS・解像度・明るさ)を正しく扱う

VideoCaptureでは set() を使うことで、解像度やFPS、明るさなど各種プロパティを変更できます。ただし「指定した値がそのまま反映されるとは限らない」点に注意が必要です。多くの場合、カメラ側の仕様やドライバの制約が優先されます。

解像度とFPSを設定する例

cap = cv2.VideoCapture(0)

# 希望する解像度とFPSを指定
cap.set(cv2.CAP_PROP_FRAME_WIDTH, 1280)
cap.set(cv2.CAP_PROP_FRAME_HEIGHT, 720)
cap.set(cv2.CAP_PROP_FPS, 30)

# 実際に適用された値を確認
width = cap.get(cv2.CAP_PROP_FRAME_WIDTH)
height = cap.get(cv2.CAP_PROP_FRAME_HEIGHT)
fps = cap.get(cv2.CAP_PROP_FPS)

print(f"実際の解像度: {width}x{height}, FPS: {fps}")

このように、「set → get」で確認するのが基本です。希望値と実際の値が違うのは珍しくなく、カメラが対応している解像度・FPSの組み合わせの中から最も近いモードが自動的に選ばれていることが多いです。

設定が反映されない主な理由

  • カメラがその解像度・FPSの組み合わせに対応していない
  • USB2.0で1080p@60fpsなど、帯域的に厳しい条件になっている
  • ドライバやOS側で上限が決められている
  • 特定のバックエンド(API)が解像度変更に対応していない

Windowsでは cv2.CAP_DSHOW を指定すると挙動が安定するケースがあります。LinuxではV4L2関連のツール(v4l2-ctl など)で対応モードを確認しておくと、どの設定が通るのか予測しやすくなります。

露光や明るさなどのプロパティ

監視カメラや工場のライン検査などでは、露光時間や明るさを固定したいケースがあります。代表的なプロパティは次のようなものです。

  • cv2.CAP_PROP_EXPOSURE:露光時間
  • cv2.CAP_PROP_BRIGHTNESS:明るさ
  • cv2.CAP_PROP_CONTRAST:コントラスト
cap.set(cv2.CAP_PROP_EXPOSURE, -6)  # 値のスケールはカメラ依存
cap.set(cv2.CAP_PROP_BRIGHTNESS, 128)

これらも「カメラがサポートしていないと無視される」ことがあり、値のスケールも機種によって異なります。「設定したのに変わらない」ときは、カメラの仕様書や設定ツール側の値も確認してみてください。

VideoCaptureが動かないときのチェックリスト

VideoCapture周りのトラブルは、「原因がどこにあるのか」が分かりにくいのがつらいところです。最低限押さえておきたいチェックリストをまとめます。

1. isOpened() が False になるとき

  • カメラが他アプリ(Zoom, Teams, OBS など)に占有されていないか
  • デバイス番号が合っているか(0だけでなく1, 2も試す)
  • OS側でカメラがそもそも認識されているか(デバイスマネージャ・設定画面で確認)
  • USBハブ経由で電力不足や接続不良が起きていないか

2. 画面が黒い・frame が None になるとき

  • read() の戻り値を必ずチェックしているか(if not ret: break
  • 露光が極端に短い、または固定されていて暗くなりすぎていないか
  • 動画ファイルの終端に到達していないか
  • GPUエンコードされた一部のmp4など、環境によっては対応コーデックの問題がないか

特に「frameがNoneのまま処理を書いてしまい、後続の処理でエラーになる」ケースはよくあるので、retやframeのチェックを癖にしておくと安全です。

3. OSごとの注意点(macOS / Windows)

macOS では、初回実行時に「カメラへのアクセスが必要です」といったダイアログが表示される場合があります。システム設定の「プライバシーとセキュリティ」→「カメラ」で、Pythonや使用しているターミナルアプリに権限を付与してください。

Windows では、ZoomやTeams、OBSなどのアプリがカメラを占有しているとVideoCaptureが開けません。一度それらのアプリを終了するか、OS再起動で解放されるか確認してみてください。

AI・画像処理への応用と設計のコツ

VideoCaptureで取得したフレームは、そのままAIモデルや画像処理アルゴリズムの入力として使えます。物体検出(YOLO)、姿勢推定(MediaPipe)、顔認識など、多くのタスクの「入り口」がVideoCaptureです。

フレーム → AIモデルへの基本フロー

  • VideoCaptureでフレームを取得(BGR形式)
  • BGR → RGB に変換(多くのディープラーニング系ライブラリはRGB前提)
  • リサイズや正規化など前処理を行う
  • モデルに入力して推論を実行
  • 結果を元のフレームに描画して表示・保存
import cv2

# 例:YOLOv5/YOLOv8 などを読み込んだ model があるとする
cap = cv2.VideoCapture(0)

while True:
    ret, frame = cap.read()
    if not ret:
        break

    # BGR → RGB
    rgb = cv2.cvtColor(frame, cv2.COLOR_BGR2RGB)

    # モデルに渡して推論(ライブラリによって書き方は異なる)
    results = model(rgb)

    # 結果を描画して表示する処理を書く…

    cv2.imshow("Result", frame)
    if cv2.waitKey(1) & 0xFF == ord('q'):
        break

cap.release()
cv2.destroyAllWindows()

リアルタイム推論を安定させるための工夫

  • 推論時間に対してFPSが高すぎる場合は、入力解像度を下げる(720pや640×480など)
  • すべてのフレームを推論にかけず、「数フレームに1回だけ推論する」戦略も有効
  • VideoCaptureで取得するスレッドと推論スレッドを分けて、フレームをキューで受け渡す設計も考えられる

VideoCaptureは「どのくらいの速度でフレームが供給されるか」を決めるので、AI処理の時間と合わせて全体のスループットを設計することが重要です。

FAQ

カメラ映像が左右反転している

ノートPCの内蔵カメラなどでは、ミラー表示になっていることがあります。OpenCV側で補正したい場合は、次のように cv2.flip() を使います。

flipped = cv2.flip(frame, 1)  # 1 は左右反転

動画の一部分だけ切り出したい

開始フレームと終了フレームを決めて、その範囲だけループを回します。

start = int(10 * fps)  # 10秒目
end = int(20 * fps)    # 20秒目

cap.set(cv2.CAP_PROP_POS_FRAMES, start)

while True:
    current = cap.get(cv2.CAP_PROP_POS_FRAMES)
    if current >= end:
        break
    ret, frame = cap.read()
    if not ret:
        break
    # この区間のフレームだけ処理する

スマホをWebカメラとしてVideoCaptureで扱える?

「DroidCam」「Iriun」などのアプリを使うと、スマホをPC側の“仮想Webカメラ”として認識させることができます。その状態でVideoCaptureのデバイス番号(0, 1, 2…)を切り替えれば、通常のWebカメラと同じように扱えます。

AI用途で最適な解像度は?

用途やモデルにもよりますが、リアルタイム性を重視する場合は720p(1280×720)前後など、やや低めの解像度から試すのが一般的です。精度を上げたいときは、解像度を上げるだけでなく、検出対象のサイズやモデルの入力サイズ(例:640×640)とのバランスも考える必要があります。

CAP_PROP_FPSで設定した値と実際のFPSが違う

カメラやドライバがサポートしているモードの中から、近い値に自動的に丸められている可能性があります。まずは get(CAP_PROP_FPS) で実際の値を確認し、その値を前提にアプリ側の設計を調整するのが現実的です。

まとめ

  • VideoCaptureはカメラ・動画入力の中心となるクラスで、retとframeの意味を理解すると扱いやすくなる
  • Webカメラと動画ファイルは、コンストラクタの引数が「デバイスIDかファイルパスか」の違いだけで同じAPIで統一的に扱える
  • 解像度やFPS、明るさなどのプロパティ設定はカメラ側の仕様に依存し、set() した値がそのまま反映されないことも多い
  • isOpened() や read() の戻り値をチェックし、OSごとの権限・占有問題を押さえておくとトラブルシュートがぐっと楽になる
  • 取得したフレームはAIモデルや画像処理の入力としてそのまま活用でき、解像度やフレームレート設計がリアルタイム処理の鍵になる

VideoCaptureはシンプルなAPIでありながら、カメラの仕様やOSの制約など環境依存の要素が多い機能です。この記事で紹介した基本の使い方とチェックポイントを押さえておけば、「動かない」「重い」といった問題にも落ち着いて対処できるようになります。ここを土台に、用途に合わせた画像処理やAIモデルの実装へ発展させてみてください。

romptn ai厳選のおすすめ無料AIセミナーでは、AIの勉強法に不安を感じている方に向けた内容でオンラインセミナーを開催しています。

AIを使った副業の始め方や、収入を得るまでのロードマップについて解説しているほか、受講者の方には、ここでしか手に入らないおすすめのプロンプト集などの特典もプレゼント中です。

AIについて効率的に学ぶ方法や、業務での活用に関心がある方は、ぜひご参加ください。

\累計受講者10万人突破/