4. 数据采集
任务目标
本案例实现车载摄像头视频流采集,完成从摄像头设备读取帧数据、解码并保存为图像文件的全过程。采集结果将作为后续AI模型推理的数据来源,因此需要保证帧率稳定且图像格式统一。
环境与依赖
- 硬件:USB摄像头或CSI接口摄像头(本案例以V4L2接口为例)
- 操作系统:Linux(Ubuntu 20.04+)
- 依赖库:OpenCV(≥4.2)、V4L2内核驱动
- 安装命令:
sudo apt install libopencv-dev v4l-utils
核心实现
以下代码实现从摄像头采集视频流,逐帧读取并保存为JPEG图像。代码包含设备初始化、帧采集循环、异常退出处理和资源释放,可直接编译运行。
#include <opencv2/opencv.hpp>
#include <iostream>
#include <ctime>
#include <sys/stat.h>
int main() {
// 打开摄像头设备(0为默认摄像头,可改为/dev/video1等)
cv::VideoCapture cap(0);
if (!cap.isOpened()) {
std::cerr << "错误:无法打开摄像头设备" << std::endl;
return -1;
}
// 设置采集参数:分辨率1280x720,帧率30fps
cap.set(cv::CAP_PROP_FRAME_WIDTH, 1280);
cap.set(cv::CAP_PROP_FRAME_HEIGHT, 720);
cap.set(cv::CAP_PROP_FPS, 30);
// 创建保存目录
mkdir("captured_frames", 0777);
cv::Mat frame;
int frame_count = 0;
const int MAX_FRAMES = 100; // 采集100帧后自动停止
std::cout << "开始采集,共采集 " << MAX_FRAMES << " 帧..." << std::endl;
while (frame_count < MAX_FRAMES) {
// 读取一帧
cap >> frame;
if (frame.empty()) {
std::cerr << "警告:读取空帧,跳过" << std::endl;
continue;
}
// 生成带时间戳的文件名
char filename[128];
time_t now = time(nullptr);
struct tm *tm_info = localtime(&now);
strftime(filename, sizeof(filename),
"captured_frames/frame_%Y%m%d_%H%M%S_%03d.jpg", tm_info, frame_count);
// 保存为JPEG(质量95)
std::vector<int> params = {cv::IMWRITE_JPEG_QUALITY, 95};
bool saved = cv::imwrite(filename, frame, params);
if (!saved) {
std::cerr << "错误:保存图像失败 " << filename << std::endl;
break;
}
frame_count++;
if (frame_count % 10 == 0) {
std::cout << "已采集 " << frame_count << " 帧" << std::endl;
}
}
cap.release();
std::cout << "采集完成,共保存 " << frame_count << " 帧图像到 captured_frames/ 目录" << std::endl;
return 0;
}
编译与运行
# 编译
g++ -o frame_capture frame_capture.cpp $(pkg-config --cflags --libs opencv4)
# 运行(需要摄像头权限)
./frame_capture
验证方法
- 运行程序后,终端输出“开始采集”提示,每10帧打印一次进度;
- 程序结束后,检查当前目录下是否生成
captured_frames/文件夹; - 进入文件夹执行
ls | wc -l,确认文件数量为100; - 随机打开一张图片(如
eog frame_*.jpg),确认图像内容清晰、无花屏或绿屏; - 使用
file frame_*.jpg | head -1检查文件格式,应显示JPEG image data。
常见问题
- 摄像头无法打开:检查设备节点
ls /dev/video*,若权限不足执行sudo usermod -a -G video $USER后重新登录; - 图像全黑或花屏:尝试降低分辨率至640x480,或检查摄像头是否被其他进程占用(
sudo fuser /dev/video0); - 帧率不稳定:USB摄像头受带宽限制,可关闭自动曝光(
v4l2-ctl -c exposure_auto=1)提升稳定性。