摄像头的使用
这份资料是嵌入式Linux多媒体开发的核心实战篇章,从输入子系统平滑过渡到了摄像头视频采集。内容非常扎实,涵盖了从驱动接口到图像算法,再到库移植的完整链路。
我来为你梳理一个去粗取精、直击要害的总结,帮你把这一长串内容内化为自己的知识体系。
一、核心主线:视频采集全流程(V4L2)
这是本次课的骨架,必须像背流程一样熟悉:
- 打开设备:
open("/dev/video0", O_RDWR) - 查询能力:
ioctl(VIDIOC_QUERYCAP)—— 确认支持“视频捕获”和“流式传输”。 - 设置格式:
ioctl(VIDIOC_S_FMT)—— 关键:设置V4L2_PIX_FMT_YUYV(YUV422)及分辨率。注意:驱动可能不支持你设的分辨率,务必用VIDIOC_G_FMT回读确认! - 申请缓冲区:
ioctl(VIDIOC_REQBUFS)—— 申请若干帧缓冲区(如4个),类型为MMAP。 - 内存映射:
mmap()—— 将内核空间的缓冲区映射到用户空间,实现零拷贝。 - 缓冲区入队:
ioctl(VIDIOC_QBUF)—— 将所有申请的缓冲区加入驱动队列,等待填充数据。 - 开启流:
ioctl(VIDIOC_STREAMON)—— 告诉驱动开始采集。 - 循环处理(核心):
select()监听fd是否可读(有数据了再读,避免忙等)。ioctl(VIDIOC_DQBUF)出队 —— 取出一个装满数据的缓冲区。- 处理数据 —— 对这个缓冲区里的YUV数据进行转换(见下文)。
ioctl(VIDIOC_QBUF)入队 —— 处理完后,把这个缓冲区放回队列,循环利用。
- 停止与清理:
ioctl(VIDIOC_STREAMOFF)->munmap()->close()。
💡 李明轩老师点拨:
select监听的是可读状态!摄像头是“写数据给我们”,我们等它“写完”(可读)再读。超时(返回0)说明设备可能出问题了。
二、核心难点:YUV(YUYV)转RGB
这是算法重点,也是面试常考点。
1. 理解YUYV(YUV422)存储格式
- 核心规则:两个Y分量(像素)共享一组U、V分量。
- 内存排列:
Y0 U0 Y1 V0|Y2 U2 Y3 V2... - 含义:
(Y0, U0, V0)构成第一个像素。(Y1, U0, V0)构成第二个像素。- 每4个字节存储2个像素。
2. 转换公式(必须掌握)
R = Y + 1.402 * (V - 128)
G = Y - 0.344 * (U - 128) - 0.714 * (V - 128)
B = Y + 1.772 * (U - 128)
注意:公式中的U就是Cb,V就是Cr。
3. 代码实现关键点(来自博客与讲解)
- 循环单位:每次循环处理4个字节(2个像素),地址索引
i += 4。 - 边界钳制:计算出的R/G/B是浮点数,且可能超出
[0, 255]范围。必须用if判断并钳制到0-255,否则颜色会炸裂。 - 效率:用整数运算或查表法可以优化速度,但初学先保证正确性。
- 常见坑:你的摄像头数据可能是BGR顺序,而非RGB,调试时要留意。
三、实战技巧与工程经验
1. 坐标/图像缩放
- 触摸屏:原始坐标(如1024x600)需通过等比例缩放映射到LCD分辨率(如800x480)。
- 摄像头:若摄像头输出分辨率(如176x144)与LCD不符,需进行缩放。博客中使用最邻近插值法(速度快,实现简单),比双线性插值更适合嵌入式场景。
2. 图像格式转换链
在完整项目中,数据流通常如下:
YUYV (Camera) -> RGB (Processing) -> RGB565 (LCD Display) -> JPEG (Storage/Network)
3. libjpeg库移植与使用(重磅)
这是实现网络传输和存储的关键。
- 移植三步:
configure(指定交叉编译工具链和--host=arm-linux)->make->make install。 - 内存压缩:新版libjpeg(如v8b)支持
jpeg_mem_dest()函数,可将RGB数据直接压缩到内存缓冲区,避免了耗时的文件I/O,完美契合网络发送(send())的需求。 - 编译命令:
arm-linux-gnueabihf-gcc your_app.c -ljpeg -I/path/to/include -L/path/to/lib
四、课后作业与进阶思考
- 状态机(State Machine):在复杂的UI或协议处理中,用
switch-case管理不同状态(如:空闲、采集、暂停、传输),是嵌入式必备设计模式。 - V4L2文档:重点查阅
ioctl请求码(如VIDIOC_*)和v4l2_buffer结构体。官方文档是最好的参考书。 - 性能优化:思考如何用多线程分离“采集”、“转换”、“显示/发送”任务,避免一帧处理慢导致丢帧。
一句话总结本课
打通了摄像头(V4L2采集YUYV)→ 算法(YUYV转RGB)→ 处理(缩放/压缩)→ 输出(LCD显示/网络发送)的全栈数据通路,是嵌入式Linux多媒体应用的基石。

浙公网安备 33010602011771号