1. 相機與視頻操作
1.1 打開視頻/相機
OpenCV 中 imread()
只能讀取靜態圖像,若要讀取視頻文件或攝像頭流,需要使用 VideoCapture
類:
// 構造函數
cv::VideoCapture::VideoCapture();
cv::VideoCapture::VideoCapture(const std::string& filename, int apiPreference = cv::CAP_ANY); // 打開視頻文件,apiPreference為設置屬性
cv::VideoCapture::VideoCapture(int index, int apiPreference = cv::CAP_ANY); // 打開攝像頭,index 為設備 ID// 或者先默認構造,再調用 open()
VideoCapture cap;
cap.open("example.avi");
cap.open(0);
1.2 讀取并播放視頻
VideoCapture video("example.avi");
if (!video.isOpened()) {std::cerr << "Error: 無法打開視頻文件!" << std::endl;return -1;
}double fps = video.get(cv::CAP_PROP_FPS); // 讀取幀率
int delay = static_cast<int>(1000.0 / fps); // 每幀顯示時長(毫秒)while (true) {cv::Mat frame;video >> frame; // 讀取下一幀到 frameif (frame.empty()) break; // 視頻結束或讀取失敗則退出cv::imshow("Video Playback", frame);if (cv::waitKey(delay) == 'q') break;
}
video.release();
cv::destroyAllWindows();
2. 視頻屬性查詢
使用 VideoCapture::get(propId)
可以獲取視頻或攝像頭流的各種參數:
Property | 參數 ID |
---|---|
當前播放位置(毫秒) | CAP_PROP_POS_MSEC (0) |
視頻寬度 | CAP_PROP_FRAME_WIDTH (3) |
視頻高度 | CAP_PROP_FRAME_HEIGHT (4) |
幀率 | CAP_PROP_FPS (5) |
編解碼器 | CAP_PROP_FOURCC (6) |
總幀數 | CAP_PROP_FRAME_COUNT (7) |
返回圖像格式 | CAP_PROP_FORMAT (8) |
攝像頭專屬屬性 | |
亮度 | CAP_PROP_BRIGHTNESS (10) |
對比度 | CAP_PROP_CONTRAST (11) |
飽和度 | CAP_PROP_SATURATION (12) |
色調 | CAP_PROP_HUE (13) |
增益 | CAP_PROP_GAIN (14) |
示例:
double width = video.get(cv::CAP_PROP_FRAME_WIDTH);
double height = video.get(cv::CAP_PROP_FRAME_HEIGHT);
3. 視頻寫入與保存
3.1 VideoWriter
類
// 構造函數
cv::VideoWriter::VideoWriter();
cv::VideoWriter::VideoWriter(const std::string& filename,int fourcc, double fps, cv::Size frameSize, bool isColor = true);
filename:輸出文件路徑及名稱(帶后綴)
fourcc:編碼格式,使用 VideoWriter::fourcc('M','J','P','G')
等,-1為自動采用合適的編解碼器
fps:輸出幀率
frameSize:視頻分辨率(寬, 高)
isColor:是否彩色(true
/false
)
3.2 保存攝像頭視頻
#include <opencv2/opencv.hpp>
#include <iostream>using namespace std;
using namespace cv;int main() {VideoCapture cap(0);if (!cap.isOpened()) {cerr << "Error: 無法打開攝像頭!" << endl;return -1;}// 讀取第一幀以獲取格式Mat frame;cap.read(frame);bool isColor = (frame.type() == CV_8UC3);// 配置 VideoWriterint codec = VideoWriter::fourcc('M','J','P','G');double fps = 30.0;Size size(640, 480);VideoWriter writer("output.avi", codec, fps, size, isColor);if (!writer.isOpened()) {cerr << "Error: 無法創建視頻寫入器!" << endl;return -1;}// 循環讀取并寫入while (1) {if (!cap.read(frame) || frame.empty()) {cerr << "Error: 無法讀取幀或幀為空!" << endl;break;}writer.write(frame);imshow("Capture & Save", frame);if (waitKey(30) == 'q') {cout << "退出程序" << endl;break;}}cap.release();writer.release();destroyAllWindows();return 0;
}
4. 窗口交互與滑動條
4.1 創建滑動條
createTrackbar(trackbarName, windowName, &value, maxCount, callback, userdata=0);
trackbarName:滑動條名稱
windowName:所屬窗口名稱
value:滑動條的當前值(整型指針)
maxCount:滑動條最大值
callback:回調函數,每次滑動時調用
userdata:用戶自定義數據指針(可選)
4.2 示例:圖像閾值調整
#include <opencv2/opencv.hpp>
#include <iostream>using namespace std;
using namespace cv;int maxValue = 127;
Mat gray, binary;void callback(int, void*) {adaptiveThreshold(gray, binary, maxValue,ADAPTIVE_THRESH_MEAN_C,THRESH_BINARY, 11, 2);imshow("Thresh", binary);
}int main() {string inputPath = "/home/user/test.jpg";string outputPath = "/home/user/outputs.jpg";gray = imread(inputPath, IMREAD_GRAYSCALE);if (gray.empty()) {cerr << "Error: 無法讀取輸入圖像!" << endl;return -1;}namedWindow("Thresh");createTrackbar("MaxValue", "Thresh", &maxValue, 255, onTrackbar);// 初始顯示onTrackbar(0, nullptr);while (true) {char key = (char)waitKey(10);if (key == 'q') {imwrite(outputPath, binary);cout << "結果已保存到: " << outputPath << endl;break;}}destroyAllWindows();return 0;
}
回調函數簽名:void callback(int pos, void* userdata);
每次滑動時,pos
為當前滑動位置,可用全局變量或 getTrackbarPos()
獲取最新值。
5. 相機圖像處理示例
上述代碼中實現了利用滑動條調整二值化圖像中的閾值,核心在于callback函數對圖像的更新。
#include <opencv2/opencv.hpp>
#include <iostream>using namespace std;
using namespace cv;int maxValue = 127;
Mat gray, binary;void callback(int, void*) {adaptiveThreshold(gray, binary, maxValue,ADAPTIVE_THRESH_MEAN_C,THRESH_BINARY, 11, 2);imshow("Binary", binary);
}int main() {VideoCapture cap(0);if (!cap.isOpened()) {cerr << "Error: 無法打開攝像頭!" << endl;return -1;}namedWindow("Binary");createTrackbar("Threshold", "Binary", &maxValue, 255, onTrackbar);while (1) {Mat frame;cap >> frame;if (frame.empty()) {cerr << "Error: 捕獲幀為空!" << endl;break;}// 轉灰度并二值化cvtColor(frame, gray, COLOR_BGR2GRAY);onTrackbar(0, nullptr); // 初始更新一次imshow("Binary", binary);if (waitKey(30) == 'q') {destroyWindow("Binary");break;}}cap.release();return 0;
}