2. AE目标亮度设定
任务说明
本案例实现AE(自动曝光)中目标亮度(Target Luma)的设定逻辑:根据场景模式(自动、夜景、背光)选择不同的目标亮度基准值,并支持根据实时帧亮度统计动态调整目标值,使画面亮度逐步收敛到期望水平。
核心实现
// ae_target_luma.h
#ifndef AE_TARGET_LUMA_H
#define AE_TARGET_LUMA_H
#include <stdint.h>
typedef enum {
SCENE_AUTO = 0,
SCENE_NIGHT,
SCENE_BACKLIT,
SCENE_MAX
} scene_mode_t;
typedef struct {
uint8_t target_luma; // 当前目标亮度 0-255
uint8_t min_luma; // 目标亮度下限
uint8_t max_luma; // 目标亮度上限
uint8_t adjust_step; // 每帧最大调整步长
scene_mode_t scene;
} ae_target_ctx_t;
// 各场景目标亮度基准值
#define TARGET_AUTO 128
#define TARGET_NIGHT 96
#define TARGET_BACKLIT 160
#define MIN_LUMA_DEFAULT 64
#define MAX_LUMA_DEFAULT 192
#define ADJUST_STEP_DEFAULT 4
// 初始化AE目标亮度上下文
void ae_target_init(ae_target_ctx_t *ctx, scene_mode_t scene);
// 切换场景模式,重置目标亮度
void ae_target_set_scene(ae_target_ctx_t *ctx, scene_mode_t scene);
// 根据当前帧平均亮度动态调整目标亮度
// frame_luma: 当前帧平均亮度(0-255)
// 返回调整后的目标亮度
uint8_t ae_target_adjust(ae_target_ctx_t *ctx, uint8_t frame_luma);
#endif // AE_TARGET_LUMA_H
// ae_target_luma.c
#include "ae_target_luma.h"
static uint8_t scene_base_luma(scene_mode_t scene) {
switch (scene) {
case SCENE_NIGHT: return TARGET_NIGHT;
case SCENE_BACKLIT: return TARGET_BACKLIT;
case SCENE_AUTO:
default: return TARGET_AUTO;
}
}
void ae_target_init(ae_target_ctx_t *ctx, scene_mode_t scene) {
if (!ctx) return;
ctx->scene = scene;
ctx->min_luma = MIN_LUMA_DEFAULT;
ctx->max_luma = MAX_LUMA_DEFAULT;
ctx->adjust_step = ADJUST_STEP_DEFAULT;
ctx->target_luma = scene_base_luma(scene);
}
void ae_target_set_scene(ae_target_ctx_t *ctx, scene_mode_t scene) {
if (!ctx || scene >= SCENE_MAX) return;
ctx->scene = scene;
ctx->target_luma = scene_base_luma(scene);
}
uint8_t ae_target_adjust(ae_target_ctx_t *ctx, uint8_t frame_luma) {
if (!ctx) return 0;
// 动态调整策略:若当前帧亮度偏离目标值过大,则向目标方向逐步逼近
int16_t diff = (int16_t)frame_luma - (int16_t)ctx->target_luma;
// 死区:亮度差小于步长时不调整,避免抖动
if (diff > ctx->adjust_step) {
ctx->target_luma += ctx->adjust_step;
} else if (diff < -ctx->adjust_step) {
ctx->target_luma -= ctx->adjust_step;
}
// 限制在合法范围内
if (ctx->target_luma < ctx->min_luma)
ctx->target_luma = ctx->min_luma;
if (ctx->target_luma > ctx->max_luma)
ctx->target_luma = ctx->max_luma;
return ctx->target_luma;
}
// 测试入口
#include <stdio.h>
#include "ae_target_luma.h"
int main() {
ae_target_ctx_t ctx;
uint8_t frame_luma = 200; // 模拟当前帧较亮
// 场景:背光,目标应趋向160
ae_target_init(&ctx, SCENE_BACKLIT);
printf("初始目标亮度: %u\n", ctx.target_luma);
// 模拟连续帧调整
for (int i = 0; i < 5; i++) {
uint8_t t = ae_target_adjust(&ctx, frame_luma);
printf("帧%d调整后目标亮度: %u\n", i + 1, t);
}
// 切换场景到夜景
ae_target_set_scene(&ctx, SCENE_NIGHT);
printf("切换夜景后目标亮度: %u\n", ctx.target_luma);
return 0;
}
编译与运行
gcc -o ae_target_test ae_target_luma.c test_ae_target.c
./ae_target_test
验证方法
程序输出应满足以下条件即判定通过:
- 初始目标亮度为160(背光场景基准值)
- 连续5帧调整后,目标亮度从160逐步递增(每帧+4),最终达到192(上限值)
- 切换夜景场景后,目标亮度重置为96
预期输出示例:
初始目标亮度: 160
帧1调整后目标亮度: 164
帧2调整后目标亮度: 168
帧3调整后目标亮度: 172
帧4调整后目标亮度: 176
帧5调整后目标亮度: 180
切换夜景后目标亮度: 96
注意:由于帧亮度200高于目标值,目标会向200方向递增直至达到max_luma=192上限。若需验证下限逻辑,可将frame_luma改为小于目标值的输入(如30),观察目标递减至min_luma=64。
关键说明
- 目标亮度调整采用步进方式,每帧最多变化
adjust_step(默认4),避免画面突变 - 死区机制(|diff| ≤ step时不调整)防止目标值在基准附近来回抖动
- 实际ISP集成时,
frame_luma由3A统计模块提供(通常为Y通道平均值),调整后的target_luma作为曝光收敛的参考值传入AE控制器 - 场景切换通过
ae_target_set_scene立即重置目标值,适用于用户手动切换场景或场景检测回调