cv::VideoCapture の使い方【OpenCV/C++】〜カメラ映像を取り込む〜

OpenCV for C++
📌 準備: OpenCV の環境構築がまだの方はこちら → C++ 環境構築ガイド / C#(OpenCvSharp)セットアップ

cv::VideoCapture の使い方【OpenCV/C++】〜カメラ映像を取り込む〜

cv::VideoCapture を使うと、PCに接続されたカメラからフレームをリアルタイムに取得できます。デバイスインデックスを渡して開くだけで、あとはループで read() を呼ぶだけです。

cv::VideoCapture cap(0);   // デバイス 0 を開く
cv::Mat frame;
cap.read(frame);            // 1フレーム取得

動作環境

  • OpenCV 4.x
  • コンパイル: g++ -std=c++17 main.cpp $(pkg-config --cflags --libs opencv4) -o main

環境構築がまだの方は環境構築ガイドを先にどうぞ。


基本の使い方

#include <iostream>
#include <opencv2/opencv.hpp>

int main() {
    // デバイス 0(通常は内蔵カメラ)を開く
    cv::VideoCapture cap(0);
    if (!cap.isOpened()) {
        std::cerr << "カメラを開けませんでした" << std::endl;
        return -1;
    }

    cv::Mat frame;
    while (true) {
        // 1フレーム取得
        if (!cap.read(frame)) {
            std::cerr << "フレームの取得に失敗しました" << std::endl;
            break;
        }

        cv::imshow("Camera", frame);

        // 'q' キーで終了
        if (cv::waitKey(1) == 'q') {
            break;
        }
    }

    // リソース解放(デストラクタでも呼ばれるが明示する)
    cap.release();
    cv::destroyAllWindows();
    return 0;
}

実行結果:

カメラ映像がウィンドウ "Camera" にリアルタイム表示されます。
'q' キーを押すと終了します。
カメラが見つからない場合は以下が標準エラーに出力されます:
  カメラを開けませんでした

コード解説:

行 説明
cv::VideoCapture cap(0) デバイス 0 を開く。複数カメラがある場合は 1, 2 … と変える
cap.isOpened() デバイスが正常に開かれたか確認。必ず入れる
cap.read(frame) 1フレームをデコードして frame に書き込む。失敗時は false を返す
cv::waitKey(1) 1ms 待機しつつキー入力を処理。0 にするとキー入力があるまで停止する
cap.release() カメラデバイスを明示的に解放する

引数と戻り値

コンストラクタ・open()

引数 型 説明
index int カメラのデバイスインデックス(0 が最初のカメラ)
apiPreference int キャプチャバックエンドの指定(省略時は自動選択)。cv::CAP_ANY, cv::CAP_V4L2, cv::CAP_DSHOW など
cv::VideoCapture cap(0, cv::CAP_V4L2);  // Linux で V4L2 を明示指定

read()

bool cap.read(cv::Mat& image);
  • 戻り値 true: フレーム取得成功
  • 戻り値 false: デバイスエラーまたはストリーム終端

get() / set() — 主要プロパティ

プロパティ定数 意味
cv::CAP_PROP_FRAME_WIDTH フレーム幅 (px)
cv::CAP_PROP_FRAME_HEIGHT フレーム高さ (px)
cv::CAP_PROP_FPS フレームレート
cv::CAP_PROP_FOURCC コーデック識別子
cap.set(cv::CAP_PROP_FRAME_WIDTH,  1280);
cap.set(cv::CAP_PROP_FRAME_HEIGHT, 720);
double fps = cap.get(cv::CAP_PROP_FPS);

⚠️ set() はリクエストであり、ハードウェアが対応していない値は無視されることがあります。設定後に get() で実際の値を確認してください。


実践例

解像度を取得してフレームを水平反転しながら表示する

カメラ映像をミラー表示にしたい場合(会議システムやセルフプレビューでよくある要件)。

#include <iostream>
#include <opencv2/opencv.hpp>

int main() {
    cv::VideoCapture cap(0);
    if (!cap.isOpened()) {
        std::cerr << "カメラを開けませんでした" << std::endl;
        return -1;
    }

    // 解像度を確認
    const double width  = cap.get(cv::CAP_PROP_FRAME_WIDTH);
    const double height = cap.get(cv::CAP_PROP_FRAME_HEIGHT);
    const double fps    = cap.get(cv::CAP_PROP_FPS);
    std::cout << "解像度: " << width << "x" << height
              << "  FPS: " << fps << std::endl;

    cv::Mat frame, mirrored;
    while (true) {
        if (!cap.read(frame)) break;

        // 水平反転(1 = 左右反転)
        cv::flip(frame, mirrored, 1);
        cv::imshow("Mirror", mirrored);

        if (cv::waitKey(1) == 'q') break;
    }

    cap.release();
    cv::destroyAllWindows();
    return 0;
}
解像度: 1280x720  FPS: 30
ミラー表示されたカメラ映像がウィンドウに表示されます。

cv::flip の使い方はcv::flip / cv::rotate の使い方【OpenCV/C++】〜画像の反転・90度回転〜で詳しく解説しています。


一定フレームごとにキャプチャした画像を横に並べて確認する

#include <iostream>
#include <opencv2/opencv.hpp>

int main() {
    cv::VideoCapture cap(0);
    if (!cap.isOpened()) {
        std::cerr << "カメラを開けませんでした" << std::endl;
        return -1;
    }

    cv::Mat frame;
    std::vector<cv::Mat> snapshots;
    int frameCount = 0;

    while (snapshots.size() < 3) {
        if (!cap.read(frame)) break;
        // 30フレームごとにスナップショットを保存
        if (frameCount % 30 == 0) {
            snapshots.push_back(frame.clone());
            std::cout << "スナップショット " << snapshots.size() << " 枚取得" << std::endl;
        }
        ++frameCount;
        cv::imshow("Live", frame);
        if (cv::waitKey(1) == 'q') break;
    }

    if (snapshots.size() == 3) {
        // 3枚を横に連結して表示
        cv::Mat row;
        cv::hconcat(snapshots, row);
        cv::imshow("Snapshots", row);
        cv::waitKey(0);
    }

    cap.release();
    cv::destroyAllWindows();
    return 0;
}

cv::hconcat の詳細はcv::hconcat / vconcat の使い方【OpenCV/C++】〜画像を連結する〜を参照してください。


つまずきポイント

✅ isOpened() を確認しないと後続処理でクラッシュする

cv::VideoCapture cap(0) はカメラが存在しなくてもコンストラクタ自体は例外を投げません。isOpened() が false のまま read() を呼ぶと空の Mat が返り、後続の処理で assertion エラーになります。必ず確認してください。

⚠️ デバイスインデックスが環境によって変わる

USB カメラを複数接続していると、抜き差しのたびにインデックスがずれることがあります。Linux では /dev/video0, /dev/video1 … を直接指定することで固定できます。

cv::VideoCapture cap("/dev/video2");

Windows では DirectShow バックエンドを明示すると安定することがあります。

cv::VideoCapture cap(0, cv::CAP_DSHOW);

⚠️ set() で解像度変更が反映されないことがある

cap.set(cv::CAP_PROP_FRAME_WIDTH, 1920) を呼んでも、カメラが対応していない場合はそのまま無視されます。set() 後に必ず get() で実際の値を確認する習慣をつけてください。また、open() の後に set() を呼ぶ必要があります(open 前は無効)。


関連する関数


まとめ

cv::VideoCapture は open() → read() のループ → release() の3ステップで使えます。isOpened() と read() の戻り値チェックを忘れずに入れることが安定動作の基本です。get() / set() で解像度や FPS を制御する際は、設定後に実際の値を確認する習慣をつけておくと現場でのトラブルを防げます。

🛠 画像処理のプロが開発するSDK/API

本ブログを運営するスワローインキュベートは、OpenCV ベースのなりすまし判定SDK/API(C++製・OpenCV 4.10)を開発しています。顔認証システムへの組み込み実績多数。

→ 顔認証のなりすまし対策 設計チェックリスト(当ブログ)
→ なりすまし判定SDK/APIの詳細を見る
→ API仕様書・サンプルコード

タイトルとURLをコピーしました