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立即重置目标值,适用于用户手动切换场景或场景检测回调