最常用和最强大的库是 OpenCV,我们将以 OpenCV 为核心,从基础到进阶,为你提供一份完整的 C 语言视频捕获指南。

(图片来源网络,侵删)
核心工具:OpenCV
OpenCV (Open Source Computer Vision Library) 是一个跨平台的计算机视觉和机器学习软件库,它包含了超过 2500 个优化的算法,涵盖了视频捕获、图像处理、特征检测、物体识别等方方面面。
为什么选择 OpenCV?
- 功能强大:几乎你能想到的任何视频/图像处理功能,它都有。
- 易于上手:API 设计相对直观,对于 C/C++ 友好。
- 跨平台:支持 Windows, Linux, macOS, Android, iOS 等。
- 社区活跃:文档丰富,教程和示例代码非常多。
第一步:安装 OpenCV
在开始编码之前,你必须在你的系统上安装 OpenCV。
在 Linux (Ubuntu/Debian) 上
# 更新包列表
sudo apt update
# 安装必要的构建工具和依赖
sudo apt install build-essential cmake git libgtk2.0-dev pkg-config libavcodec-dev libavformat-dev libswscale-dev
# 克隆 OpenCV 源代码
git clone https://github.com/opencv/opencv.git
git clone https://github.com/opencv/opencv_contrib.git
# 创建一个构建目录
cd opencv
mkdir build && cd build
# 配置 CMake (指定安装路径和启用 contrib 模块)
cmake -D CMAKE_BUILD_TYPE=RELEASE \
-D CMAKE_INSTALL_PREFIX=/usr/local \
-D OPENCV_EXTRA_MODULES_PATH=../../opencv_contrib/modules \
-D WITH_GTK=ON \
-D WITH_OPENGL=ON \
-D BUILD_EXAMPLES=ON ..
# 编译 (这需要一些时间)
make -j4
# 安装
sudo make install
在 Windows 上
- 推荐使用预编译库:从 OpenCV 官网 下载预编译好的版本(
opencv-4.x.x-vc14_vc15.exe)。 - 安装:运行安装程序,它会解压文件到一个目录(
C:\opencv)。 - 配置环境变量:
- 将
C:\opencv\build\x64\vc15\bin(根据你的版本和编译器选择) 添加到系统的PATH环境变量中。
- 将
- 配置你的 IDE (如 Visual Studio):
- 创建一个新的 C++ 控制台项目。
- 右键点击项目 -> 属性。
- C/C++ -> 常规 -> 附加包含目录:添加
C:\opencv\build\include。 - 链接器 -> 常规 -> 附加库目录:添加
C:\opencv\build\x64\vc15\lib。 - 链接器 -> 输入 -> 附加依赖项:添加
opencv_world410d.lib(调试版) 或opencv_world410.lib(发布版),注意版本号410可能不同。
第二步:编写 C 代码进行视频捕获
OpenCV 的 C API 和 C++ API 有些许不同,这里我们重点介绍 C API,因为它更符合你的问题。

(图片来源网络,侵删)
从摄像头捕获实时视频
这是最常见的用法,程序会打开你的默认摄像头,并逐帧显示视频流,直到你按下某个键('q')退出。
核心概念:
CvCapture: 结构体,代表一个视频捕获设备(摄像头或视频文件)。cvCaptureFromCAM(): 打开摄像头并初始化CvCapture结构体。cvQueryFrame(): 从CvCapture中捕获并解码一帧图像,返回一个IplImage*指针。注意: 这个函数返回的是指向内部缓冲区的指针,不要手动释放它,下一次调用cvQueryFrame时,旧帧的内存会被自动释放。cvShowImage(): 在一个窗口中显示IplImage。cvWaitKey(): 等待用户按键,这是控制视频播放和退出的关键,参数是等待的毫秒数,如果为 0,则无限期等待。
示例代码 (capture_camera.c):
#include <stdio.h>
#include <opencv/cv.h>
#include <opencv/highgui.h>
int main() {
// 1. 初始化摄像头
// 参数 -1 表示使用默认摄像头
CvCapture* capture = cvCaptureFromCAM(-1);
if (!capture) {
fprintf(stderr, "无法打开摄像头!\n");
return -1;
}
// 2. 创建一个窗口来显示视频
cvNamedWindow("Camera Feed", CV_WINDOW_AUTOSIZE);
printf("摄像头已打开,按 'q' 键退出...\n");
// 3. 循环捕获并显示帧
while (1) {
// 捕获一帧
IplImage* frame = cvQueryFrame(capture);
// frame 为 NULL,说明视频结束或出错
if (!frame) {
printf("无法获取帧或视频已结束,\n");
break;
}
// 显示当前帧
cvShowImage("Camera Feed", frame);
// 检查按键
// cvWaitKey(1) 等待 1 毫秒,如果在这 1 毫秒内按下了 'q' 键,则返回 'q' 的 ASCII 码
char c = cvWaitKey(1);
if (c == 'q') {
printf("用户请求退出,\n");
break;
}
}
// 4. 释放资源
cvReleaseCapture(&capture);
cvDestroyWindow("Camera Feed");
return 0;
}
从视频文件捕获
从文件捕获和从摄像头捕获非常相似,只是初始化 CvCapture 的函数不同。

(图片来源网络,侵删)
核心概念:
cvCaptureFromFile(): 通过文件路径打开一个视频文件。
示例代码 (capture_file.c):
#include <stdio.h>
#include <opencv/cv.h>
#include <opencv/highgui.h>
int main() {
// 1. 打开视频文件
// 将 "my_video.mp4" 替换为你的视频文件路径
CvCapture* capture = cvCaptureFromFile("my_video.mp4");
if (!capture) {
fprintf(stderr, "无法打开视频文件!\n");
return -1;
}
// 2. 获取视频的帧率 (FPS)
int fps = cvGetCaptureProperty(capture, CV_CAP_PROP_FPS);
printf("视频帧率: %d FPS\n", fps);
// 3. 创建一个窗口
cvNamedWindow("Video Player", CV_WINDOW_AUTOSIZE);
printf("视频播放中,按 'q' 键退出...\n");
// 4. 循环捕获并显示帧
while (1) {
IplImage* frame = cvQueryFrame(capture);
if (!frame) {
printf("视频播放完毕,\n");
break;
}
cvShowImage("Video Player", frame);
// 使用视频的帧率来控制播放速度
// fps 为 0 (例如某些文件无法获取 fps),则使用默认延迟
int delay = (fps > 0) ? (1000 / fps) : 30;
char c = cvWaitKey(delay);
if (c == 'q') {
printf("用户请求退出,\n");
break;
}
}
// 5. 释放资源
cvReleaseCapture(&capture);
cvDestroyWindow("Video Player");
return 0;
}
第三步:编译和运行代码
在 Linux 上
你需要链接 OpenCV 的库。
# 假设你的源文件是 capture_camera.c gcc capture_camera.c -o capture_camera `pkg-config --cflags --libs opencv4` # 运行 ./capture_camera
注意:较新版本的 OpenCV (4.x) 可能使用 opencv4 而不是 opencv 作为 pkg-config 的名称,如果命令失败,请尝试 opencv。
在 Windows (Visual Studio) 上
- 将你的 C 代码(
capture_camera.c)添加到项目中。 - 确保项目属性中已经正确配置了 OpenCV 的包含目录和库目录(见安装步骤)。
- 链接器 -> 输入 -> 附加依赖项 中,确保有
opencv_world410d.lib(或对应版本)。 - 直接按
F5编译并运行。
重要提示:C API vs. C++ API
虽然我们使用了 C API,但请注意:
- C API 已被标记为过时:OpenCV 的开发重点已经完全转移到 C++ API 上,C API 主要是为了向后兼容。
- C++ API 更现代、更安全:
- 使用
cv::VideoCapture类代替CvCapture*,它更安全,资源管理更方便(RAII)。 - 使用
cv::Mat类代替IplImage*,cv::Mat是一个自动内存管理的图像类,避免了手动内存分配和释放的麻烦。
- 使用
- 新项目建议:除非你有特殊的理由必须使用 C,否则强烈建议你直接学习 OpenCV 的 C++ API,它的学习曲线更平滑,代码也更健壮。
C++ API 的一个简单对比示例:
// C++ API 示例
#include <opencv2/opencv.hpp>
int main() {
// cv::VideoCapture 是一个类,对象在离开作用域时会自动关闭
cv::VideoCapture cap(0); // 打开默认摄像头
if (!cap.isOpened()) {
std::cerr << "无法打开摄像头!" << std::endl;
return -1;
}
cv::namedWindow("C++ Feed", cv::WINDOW_AUTOSIZE);
cv::Mat frame; // cv::Mat 是一个智能矩阵/图像类
while (true) {
cap >> frame; // 操作符 >> 重载,更简洁
if (frame.empty()) {
break;
}
cv::imshow("C++ Feed", frame);
if (cv::waitKey(1) == 'q') {
break;
}
}
// cap 和 frame 会自动释放,无需手动操作
return 0;
}
| 任务 | C API 函数 | C++ API 类/方法 | 说明 |
|---|---|---|---|
| 打开摄像头 | cvCaptureFromCAM(-1) |
cv::VideoCapture cap(0); |
初始化捕获对象 |
| 打开文件 | cvCaptureFromFile("path.mp4") |
cv::VideoCapture cap("path.mp4"); |
初始化捕获对象 |
| 读取一帧 | IplImage* frame = cvQueryFrame(cap); |
cap >> frame; |
获取并解码下一帧 |
| 显示图像 | cvShowImage("Win", frame); |
cv::imshow("Win", frame); |
在窗口中显示图像 |
| 等待按键 | cvWaitKey(10); |
cv::waitKey(10); |
处理窗口事件和延时 |
| 释放资源 | cvReleaseCapture(&cap); |
cap.release(); |
对象析构时自动调用 |
希望这份详细的指南能帮助你开始在 C 语言中使用 OpenCV 进行视频捕获!祝你编程愉快!
