曝光、快门(全局、卷帘)、CMOS 与 CCD、相机软件调试

概述

拍照的总体流程,在数码相机或影像传感器(如CMOS、CCD)中,拍摄图像的过程可以分为以下几个核心阶段:

  • 光线进入镜头 → 打在感光元件上(图像传感器)
  • 感光元件将光信号转换为电信号(电压信号)
  • 电信号经过采样、放大、模数转换(ADC)成为数字信号
  • 数字信号经图像处理(白平衡、降噪、锐化)→ 输出图像文件

曝光

  • 曝光(Exposure)指的是传感器接收到的总光量,它决定了图像的明暗程度。曝光由以下三个要素共同决定:
  • 快门时间(Shutter Speed):光照射在传感器上的时间长度。
  • 光圈大小(Aperture):光线进入镜头的通光孔径。
  • 感光度(ISO):传感器对光信号的放大倍数。

快门

  • 快门的作用:控制光照时间窗口
  • 快门是控制光照射时间的"门"。它决定了传感器在多长时间内"接受"光信号
  • 机械快门:通过物理遮光板打开/关闭。
  • 电子快门:通过控制传感器读出电路的开关时间实现。
  • 在快门打开的时间内,光子打到传感器的每个像素上,产生电子积累。快门关闭后,传感器开始读取这些电子信号。
  • 快门时间:从传感器开始接收光信号到停止接收光信号之间的时间。在这段时间内,每个像素的光电二极管都在"积分"入射光能量,即不断累积电子。当快门关闭后,积分结束,电荷量固定下来,随后才进入读出阶段。

电信号采集

电压信号采集过程:从光子到电压

  • 当光照射到图像传感器(以CMOS为例)时:
  • 光电转换:光子打在像素点的光电二极管上,释放电子,形成电荷累积。
  • 电荷-电压转换:在快门关闭后,像素的电荷通过电容转化为电压信号。
  • 读出放大与采样保持(Sample & Hold):每个像素的电压信号被读取、放大,并暂存。
  • 模数转换(ADC):模拟电压信号转换为数字信号,供图像处理使用。
bash 复制代码
时间轴:   |--- 快门开启 --->--- 快门关闭 ---> 读出/采样 ---> ADC转换 ---> 数字信号输出 |
信号变化: | 光子积累(电荷增加) | 电荷保持 | 电压采样 | 电压转数字 | 图像信号生成 |

全局快门(Global Shutter)和卷帘快门(Rolling Shutter):

CMOS 传感器**"理论上"每个像素都能独立采样**,但"**实际上"电路和物理架构根本无法让所有像素同时采样**:

  • 回顾拍照流程:光进入感光元器件、快门打开、开始曝光、曝光结束、快门关闭、电压采样。
  • 因为无法所有像素同时采样,所以发明了一些方法:
  • 卷帘快门:逐行曝光 + 逐行采样。(果冻效应,但是电荷转移少,噪点少)
  • 全局快门:整体曝光 + 电容保持电荷 + 逐行挨个采样。(电容保持电荷存在噪点,但是没有果冻效应)

其余的折中方案:

方案 思想 优缺点
卷帘快门 行扫描,逐行曝光+读出 简单、便宜、有果冻效应
全局快门 所有像素同时曝光+采样 无畸变、结构复杂、成本高
准全局快门(Near-Global) 多行同步曝光、快速读出 畸变极小,成本可控
存储层分离架构(stacked sensor) 在像素层下增加独立读出层 紧凑、性能提升,但制造贵(Sony 近年采用)

卷帘快门带来的果冻效应:因为卷帘快门是一行一行曝光、一行一行采样,所以会产生"果冻效应",也就是运动模糊。


那一款相机既支持全局快门也支持卷帘快门,你之前说的缺点"光敏面积变小"、"电路复杂度上升",是不是就不存在了,因为他已经做好了全局快门?此时卷帘快门的唯一优势就是功耗低?

  • 确实一款相机如果同时支持全局快门与卷帘快门,那么它的底层硬件都已经固定,全局快门带来了的"光敏面积变小"、"电路复杂度上升"的问题,卷帘快门模式下也仍然存在。
  • 但是卷帘快门也有它的优势:噪声更低一点。
  • 在卷帘快门(Rolling Shutter)模式下,每个像素确实不需要额外的存储电容(Sample & Hold Capacitor),而是在曝光结束后,直接把像素节点的电荷转换为电压并立刻读取。卷帘快门像素的"电荷→电压→数字化"过程是同步发生的
  • 全局快门模式下,电荷需要从光电二极管转移两次(PD → Csh → 放大节点),每次转移都会带来信号失真与噪声

CCD 与 CMOS 的区别

CCD与CMOS图像传感器光电转换的原理相同,他们最主要的差别在于信号的读出过程不同;

  • 光电转化:光子打到感光单元(像素) → 电子被激发 → 形成电荷信号。
  • 由于CCD仅有一个(或少数几个)输出节点统一读出,其信号输出的一致性非常好; 而CMOS芯片中,每个像素都有各自的信号放大器,各自进行电荷-电压的转换,其信号输出的一致性较差。

软件调试与验证

V4L2-ctrl 介绍

V4L 是 Video for Linux 的缩写,2 代表是第二个版本,v4l2-ctl 支持绝大多数 USB 摄像头的关键原因在于它依赖的 V4L2 通用标准层 与 UVC 驱动

通用的 UVC 标准驱动,绝大多数 USB 摄像头都遵循 USB Video Class (UVC) 标准,因此,v4l2-ctl 能通过标准的 V4L2 控制接口访问这些控件。

  • Linux 内核中自带的 uvcvideo 驱动支持 UVC 1.0/1.1/1.5 协议。
  • uvcvideo 驱动在注册 /dev/videoX 设备时,自动将摄像头的功能映射为 V4L2 控件(controls),例如
    • V4L2_CID_BRIGHTNESS
    • V4L2_CID_CONTRAST
    • V4L2_CID_EXPOSURE_AUTO
    • V4L2_CID_FOCUS_ABSOLUTE

厂商扩展控制的兼容机制

  • 即使部分摄像头有厂商私有控制项(如 Logitech 的人脸跟踪、红外切换),它们通常仍通过 V4L2_CID_PRIVATE_BASE 向上注册。
  • v4l2-ctl --list-ctrls 会列出所有这些自定义控制。
  • 只要驱动正确注册,v4l2-ctl 就能访问。

UVC 驱动与 V4L2 子系统高度统一

  • 内核中 uvcvideo 驱动直接实现了 V4L2 子系统的所有关键接口(包括视频采集、流控制、控制项查询)。
  • 因此,v4l2-ctl 几乎不需要针对不同品牌做额外适配。

V4L2-ctrl 指令

安装相关工具:

bash 复制代码
sudo apt update
sudo apt install v4l-utils
v4l2-ctl --version

查看当前的 USB 相机列表

bash 复制代码
# w300: 摄像头的逻辑名称(由设备固件或驱动提供)
# (usb-0000:00:14.0-6):摄像头连接的 USB 总线信息(物理连接位置)
# /dev/video0:摄像头的主视频流接口(通常是图像采集节点)
# /dev/video1:附属视频接口(可能是元数据流、红外流或麦克风接口)
# /dev/media0:Media Controller 节点,用于高级设备拓扑管理(连接传感器、ISP、编码器等子设备)
w300: w300 (usb-0000:00:14.0-6):
	/dev/video0
	/dev/video1
	/dev/media0

查看某个具体视频流的配置:

bash 复制代码
v4l2-ctl --device=/dev/video1 --all

# 查看用户可以修改的配置信息:
v4l2-ctl --device=/dev/video0 --list-ctrls
bash 复制代码
# v4l2-ctl --device=/dev/video1 --all, 关于视频流的输出信息
Format Video Capture:
	Width/Height      : 1920/1080
	Pixel Format      : 'MJPG' (Motion-JPEG)
	Field             : None
	Bytes per Line    : 0
	Size Image        : 4147789
	Colorspace        : sRGB
	Transfer Function : Default (maps to sRGB)
	YCbCr/HSV Encoding: Default (maps to ITU-R 601)
	Quantization      : Default (maps to Full Range)

Format Video Capture 中的 Width/Height : 1920/1080,它表示当前输出视频流的分辨率,但不一定等于感光元件(sensor)的物理像素数量。

# 现代摄像头在传感器与输出之间还有许多中间环节
传感器原始像素 → ISP(图像信号处理)→ 编码/压缩 → USB 传输 → 输出帧

# 常见的几种情况:
1. 输出分辨率 = 传感器原生分辨率
	最理想情况。
	比如传感器物理像素是 1920×1080,驱动输出 1920×1080;
	图像清晰,细节完整。
2. 输出分辨率 < 传感器分辨率(下采样)
	常见于高分辨率传感器降级输出。
	比如传感器 2592×1944(5MP),输出 1280×720;
	驱动或 ISP 做了下采样(average/binning);
	图像细节减少,但噪声更低。
3. 输出分辨率 > 传感器分辨率(插值放大)
	廉价 USB 摄像头常见。
	实际传感器也许只有 640×480(VGA),但驱动报告 1920×1080;驱动内部做了数字插值(软件放大),
	结果"像素多了,但细节没变",画面看起来虚假清晰。

在 Linux 下通过 v4l2-ctl 或其他用户态命令行工具,你看不到摄像头传感器(MOS/CMOS Sensor)真正的物理像素数量,只能看到驱动报告出来的视频输出格式(分辨率、帧率、像素格式)

  • v4l2-ctl、ffmpeg、media-ctl 等命令访问的是 /dev/videoX 设备。这条链路最终的输出是"视频流".
  • 驱动层通常不公开底层传感器信息:
  • 对于 USB 摄像头(UVC 协议):内核只看到一个标准化的接口(UVC descriptors),不知道里面是什么传感器芯片(例如 OV5640、GC2145、IMX219 等)。它只知道设备"支持哪些分辨率"和"支持哪些像素格式"。
  • 对于 MIPI/CSI 摄像头(嵌入式平台):驱动可能确实知道底层 sensor 信息,但只有在 media-ctl、libcamera 层才可能看到。
  • 获取真实像素数的正确途径:先确认摄像头的 USB Vendor ID / Product ID ---> 然后上网搜索对应的芯片,一般能查到使用的 CMOS 芯片型号(如 OV2640、GC0308 等),---> 再查该 sensor 的 datasheet,就能看到其原生像素。

查看当前视频流支持的所有分辨率、帧率、图像格式:

bash 复制代码
v4l2-ctl --list-formats-ext

设置当前视频流的分辨率、帧率、图像格式:

  • 修改分辨率只影响当前会话;设备重新插拔后通常会恢复默认。
  • 若有多个摄像头,务必带上 --device=/dev/videoX。
  • 如果用 ffplay、ffmpeg 等工具采流,它们可能在打开时会覆盖 v4l2-ctl 设置(因为它们会重新请求特定分辨率/格式)。
bash 复制代码
v4l2-ctl --device=/dev/video0 --set-fmt-video=width=<宽度>,height=<高度>,pixelformat=<格式>

# 把摄像头设置为 1280×720,MJPEG 格式
v4l2-ctl --device=/dev/video0 --set-fmt-video=width=1280,height=720,pixelformat=MJPG

v4l2-ctl --set-fmt-video=width=1920,height=1080,pixelformat=MJPG --set-parm=30

设置当前视频流的曝光信息。

先查看当前的曝光信息:

  • auto_exposure: min=0 max=3 default=3 value=3 (Aperture Priority Mode),设置为1 的时候,才是手动模式,这时候才可以设置曝光时间。
  • exposure_time_absolute: min=1 max=5000 step=1 default=157 value=157 flags=inactive
bash 复制代码
v4l2-ctl --list-ctrls

User Controls

                     brightness 0x00980900 (int)    : min=-64 max=64 step=1 default=0 value=0
                       contrast 0x00980901 (int)    : min=0 max=64 step=1 default=32 value=32
                     saturation 0x00980902 (int)    : min=0 max=128 step=1 default=64 value=64
                            hue 0x00980903 (int)    : min=-40 max=40 step=1 default=0 value=0
        white_balance_automatic 0x0098090c (bool)   : default=1 value=1
                          gamma 0x00980910 (int)    : min=72 max=500 step=1 default=100 value=100
                           gain 0x00980913 (int)    : min=0 max=100 step=1 default=0 value=0
           power_line_frequency 0x00980918 (menu)   : min=0 max=2 default=1 value=1 (50 Hz)
      white_balance_temperature 0x0098091a (int)    : min=2800 max=6500 step=1 default=4600 value=4600 flags=inactive
                      sharpness 0x0098091b (int)    : min=0 max=6 step=1 default=4 value=4
         backlight_compensation 0x0098091c (int)    : min=0 max=160 step=1 default=80 value=80

Camera Controls
                  auto_exposure 0x009a0901 (menu)   : min=0 max=3 default=3 value=3 (Aperture Priority Mode)
         exposure_time_absolute 0x009a0902 (int)    : min=1 max=5000 step=1 default=157 value=157 flags=inactive
     exposure_dynamic_framerate 0x009a0903 (bool)   : default=0 value=1

设置不同的曝光率:受限需要关闭自动曝光,设置为手动曝光模式

bash 复制代码
# 设置为手动曝光模式:
v4l2-ctl -c auto_exposure=1

# 设置曝光时间:
v4l2-ctl -c exposure_time_absolute=80

验证效果:使用 ffplay 来抓取视频流,此时曝光时间越短,画面应该越暗,曝光时间越长,画面应该越亮。

bash 复制代码
ffplay /dev/video0

Opencv

opencv 安装

https://www.cnblogs.com/booturbo/p/17399215.html

opencv 架构

OpenCV(Open Source Computer Vision Library)是一个跨平台的计算机视觉库,

用 C/C++ 实现,底层封装了各种 图像采集、处理、显示与硬件接口。它可以运行在 Windows、Linux、macOS、Android、iOS、嵌入式板卡 等多平台。

OpenCV 的总体架构,可以概括为一个 "多层抽象模型":

bash 复制代码
┌────────────────────────────┐
│ 应用层(Python / C++ / Java APIs)│
├────────────────────────────┤
│ 模块层(imgproc, videoio, dnn, calib3d, etc.)│
├────────────────────────────┤
│ 平台适配层(HAL: Hardware Abstraction Layer)│
├────────────────────────────┤
│ 底层系统接口(OS / 驱动 / SDK) │
└────────────────────────────┘
层级 功能
应用层 用户调用的接口,比如 cv::imread(), cv::VideoCapture(), cv::imshow()
模块层 图像处理算法模块(滤波、边缘检测、人脸识别、深度学习等)
HAL 层(Hardware Abstraction Layer) 抽象硬件加速接口,屏蔽不同平台的差异(CPU / CUDA / OpenCL)
底层接口 不同操作系统提供的驱动接口(V4L2、DirectShow、AVFoundation 等)

OpenCV 访问摄像头/视频设备时的底层驱动差异:

OpenCV 的 cv::VideoCapture 模块负责与操作系统的视频接口交互,在不同系统下,它自动选择对应的驱动或后端:

平台 使用的底层驱动或 API 说明
Linux 🎥 V4L2 (Video4Linux2) 直接调用 /dev/videoX 设备(USB 摄像头、CSI 摄像头等)
Windows 🎬 DirectShowMedia Foundation 用 Windows 自带的视频捕获框架访问 USB 摄像头
macOS 🍎 AVFoundation Apple 的原生多媒体框架
Android 📱 NDK Camera API / OpenMAX / MediaNDK 调用安卓底层相机接口
iOS 📷 AVFoundation (iOS SDK) 同样通过苹果的多媒体接口
GStreamer(可选) 🧩 可跨平台的多媒体框架 OpenCV 可编译时启用 GStreamer 支持,用于视频流/网络推流
FFmpeg(可选) 🧠 通用视频解码库 主要用于读取文件(MP4、AVI 等),也能采流

所以,当你在不同系统上调用:cv::VideoCapture cap(0);

OpenCV 会自动:

  • 在 Linux 下走 /dev/video0 → V4L2;
  • 在 Windows 下走 DirectShow;
  • 在 macOS 下走 AVFoundation;
  • 用户完全无需关心底层实现。
相关推荐
人月神话-Lee18 小时前
WWDC26 深度解析:如何在 iOS 27 中打造“秒开”的相机体验
ios·swift·相机·wwdc·用户体验
yym1611512 天前
专业的饲料颗粒机
相机
开开心心就好3 天前
清理重复文件释放C盘空间的工具
安全·智能手机·pdf·gitlab·音视频·intellij idea·1024程序员节
yym1611514 天前
饲料颗粒机销售厂家哪家可靠
相机
yym1611515 天前
饲料颗粒机工厂有哪些
相机
埃科光电5 天前
打通全场景检测痛点UB系列相机赋能多元智造场景
图像处理·数码相机·计算机视觉·制造·相机
颗粒机Cathy7 天前
饲料颗粒机企业有哪些
相机
数据皮皮侠AI7 天前
中国土地利用驱动因子数据集(9种驱动因子/裁剪到省市/Tif)
大数据·人工智能·笔记·能源·1024程序员节
yym1611519 天前
饲料颗粒机生产厂家
相机
颗粒机Cathy9 天前
饲料颗粒机工厂哪个好
相机