3. 3A统计信息解读
好,咱们进入第三章。这一章我打算聊聊3A统计信息——说白了,就是相机硬件给你报上来的那些“原始数据”。很多工程师调AE时,上来就改PID参数,结果越调越乱。我个人习惯是,先读懂统计信息,再动手。你想想看,连数据都看不懂,怎么调算法?
高通Spectra平台会把ISP处理完的统计信息,通过HAL层打包成特定的数据结构,送给3A算法库。这里面最重要的三样东西:3A统计数据格式、亮度直方图、分区亮度统计。咱们一个一个拆开讲。
3.1 HAL输出的3A统计数据格式
高通平台的3A统计信息,通常封装在 struct msm_isp_stats_data 或者类似的HAL结构体里。我接触过的几个平台,比如SM8250、SM8450,格式大同小异。核心字段包括:
| 字段名 | 类型 | 说明 |
|---|---|---|
stats_type |
uint32_t | 统计类型标识(如BG、BF、BH、BE) |
frame_id |
uint32_t | 帧序号,用于对齐时间戳 |
buf_addr |
void* | 统计数据的缓冲区指针 |
buf_len |
uint32_t | 缓冲区长度(字节) |
config_id |
uint32_t | 当前统计配置的ID,用于校验一致性 |
这里有个坑,我提醒一下。我曾经在调试一个项目时,发现AE收敛忽快忽慢,查了半天,结果是 frame_id 和实际图像帧没对齐。统计信息是上一帧的,但算法以为是最新帧。所以,一定要检查frame_id的连续性。
关键点:HAL输出的统计信息,默认是YUV域的数据。但有些场景下,你需要确认统计窗口是否与AEC的ROI对齐。不对齐的话,亮度统计就是错的。
3.2 亮度直方图的读取
亮度直方图,说白了就是一张“亮度分布图”。横轴是亮度等级(0~255),纵轴是像素个数。它能告诉你当前画面是偏暗、偏亮,还是反差太大。
高通平台输出的直方图,通常有256个bin,每个bin对应一个亮度级别的像素计数。读取方式很简单:
// 伪代码示例:读取直方图数据
uint32_t histogram[256];
memcpy(histogram, stats_buf->buf_addr, sizeof(histogram));
// 计算平均亮度
uint64_t total_pixels = 0;
uint64_t weighted_sum = 0;
for (int i = 0; i < 256; i++) {
weighted_sum += i * histogram[i];
total_pixels += histogram[i];
}
float avg_luminance = (float)weighted_sum / total_pixels;
嗯,这里要注意。直方图的数据格式,不同平台可能不一样。有的平台输出的是16位计数,有的是32位。我建议你拿到数据后,先打印几个bin的值,确认一下字节序和位宽。
我在项目中遇到过一个问题:直方图数据全是0。当时以为是硬件坏了,后来发现是HAL层没有使能直方图统计模块。所以,记得检查ISP的统计使能寄存器。
调试技巧:你可以把直方图数据导出来,用Python画个图。一眼就能看出画面是欠曝还是过曝。比看数值直观多了。
3.3 分区亮度统计的含义
分区亮度统计,英文叫Zone Stat。它不是对整个画面算一个平均亮度,而是把画面分成若干区域,每个区域单独统计。高通平台通常支持 5x5 或 15x15 的分区。
每个Zone Stat包含的信息:
- 平均亮度:该区域内所有像素的Y均值
- 亮度方差:反映该区域的纹理复杂度
- 有效像素计数:排除过暗或过亮像素后的有效统计数
为什么需要分区统计?我举个例子。你拍一张逆光人像,人脸在画面中央,背景很亮。如果只算全局平均亮度,算法会觉得画面挺亮的,于是降低曝光。结果人脸就黑了。但如果你用Zone Stat,算法可以只看人脸区域的亮度,忽略背景。这就是基于区域的AE。
高通平台的分区统计,通常以 struct msm_isp_stats_zone 的形式输出:
struct msm_isp_stats_zone {
uint16_t avg_luminance; // Q10格式,实际亮度 = avg_luminance / 1024
uint16_t variance; // 亮度方差
uint16_t pixel_count; // 有效像素数
uint8_t reserved[2]; // 对齐用
};
注意:分区统计的坐标原点,通常是从左上角开始。但有些平台会做镜像或旋转。如果你发现统计区域和实际画面位置对不上,检查一下ISP的裁剪和缩放配置。
3.4 知识结构总览
下面这张图,我把本章的核心逻辑画出来了。你可以对照着看,理解3A统计信息在整个AE调试中的位置。
3.5 实战中的注意事项
最后,我总结几个实战中容易踩的坑:
- 统计窗口与ROI不匹配:AEC的ROI和统计窗口必须一致。否则你对着人脸调曝光,统计的却是背景。
- 直方图数据饱和:如果画面中有大量纯白或纯黑区域,直方图两端会堆积。这时候平均亮度会失真,需要用中位数或加权平均。
- 分区统计的权重设置:不同区域对曝光的贡献不同。比如人脸区域权重高,天空区域权重低。权重设置不合理,AE会“犹豫不决”。
我的习惯:每次拿到新的平台,我都会先写一个小工具,把直方图和Zone Stat实时打印出来。对着不同场景看数据变化,很快就能摸清硬件的“脾气”。