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::read — 本記事で解説したフレーム取得メソッド
- cv::VideoWriter — フレームを動画ファイルに書き出す際に使用
- cv::imshow / cv::waitKey — 取得したフレームをウィンドウ表示する基本セット
- cv::flip / cv::rotate の使い方【OpenCV/C++】〜画像の反転・90度回転〜 — カメラ映像のミラー表示に頻用
- cv::hconcat / vconcat の使い方【OpenCV/C++】〜画像を連結する〜 — 複数フレームをまとめて表示する
まとめ
cv::VideoCapture は open() → read() のループ → release() の3ステップで使えます。isOpened() と read() の戻り値チェックを忘れずに入れることが安定動作の基本です。get() / set() で解像度や FPS を制御する際は、設定後に実際の値を確認する習慣をつけておくと現場でのトラブルを防げます。
🛠 画像処理のプロが開発するSDK/API
本ブログを運営するスワローインキュベートは、OpenCV ベースのなりすまし判定SDK/API(C++製・OpenCV 4.10)を開発しています。顔認証システムへの組み込み実績多数。
→ 顔認証のなりすまし対策 設計チェックリスト(当ブログ)
→ なりすまし判定SDK/APIの詳細を見る
→ API仕様書・サンプルコード

