3、3A统计信息解读:HAL输出的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调试中的位置。

3A统计信息知识结构 HAL输出3A统计数据 统计数据格式 亮度直方图 分区亮度统计 关键字段 stats_type / frame_id buf_addr / buf_len 256个bin 每个bin对应亮度等级 用于计算平均亮度 5x5 / 15x15分区 avg_luminance / variance 支持基于区域的AE AE算法收敛性调试

3.5 实战中的注意事项

最后,我总结几个实战中容易踩的坑:

  1. 统计窗口与ROI不匹配:AEC的ROI和统计窗口必须一致。否则你对着人脸调曝光,统计的却是背景。
  2. 直方图数据饱和:如果画面中有大量纯白或纯黑区域,直方图两端会堆积。这时候平均亮度会失真,需要用中位数或加权平均。
  3. 分区统计的权重设置:不同区域对曝光的贡献不同。比如人脸区域权重高,天空区域权重低。权重设置不合理,AE会“犹豫不决”。

我的习惯:每次拿到新的平台,我都会先写一个小工具,把直方图和Zone Stat实时打印出来。对着不同场景看数据变化,很快就能摸清硬件的“脾气”。