ISP场景识别中Lv定点计算的实现方式和结果对比

张开发
2026/4/4 0:05:14 15 分钟阅读
ISP场景识别中Lv定点计算的实现方式和结果对比
目录一、代码实现二、结果对比分析针对博文ISP中Lv和ISO系统并存的意义最后所提到的LV计算问题。稍微试下了一个版本并初步验证结果。一、代码实现#include stdio.h #include stdlib.h #include math.h #includelut_log2_q8.h // Q8 定点真实值 结果 / 256 #define FIXED_Q8 256 // 增益基准256 1.0 倍 #define GAIN_BASE 256 #define GAIN_BASE_Q8 256u #define LV_OFFSET 9.356 int16_t log2_q8_exact(uint32_t x) { if (x 1) return 0; if (x 32768) return 3840; // 1. 求 log2 整数位不变最快 int shift 0; uint32_t tmp x; while (tmp 1) shift; // 2. 整数部分 Q8 int32_t base shift * 256; // 3. 尾数计算无除法全移位速度大幅提升 uint32_t numerator x - (1U shift); uint32_t frac (numerator * 256) shift; // 除法 → 移位 // // 4. 高精度无分支对数修正核心优化 // 无if、无跳转、CPU全速运行 // uint32_t offset (0x20 - (frac 2)) 3; // 自动拟合补偿 frac offset; #if 0 // 1. 求整数 log2和原来完全一样零开销 int shift 0; uint32_t tmp x; while (tmp 1) shift; // 2. 整数部分 Q8不变 int32_t base shift * 256; // 3. 归一化尾数 m [0, 255] uint32_t m ((x - (1U shift)) * 256) shift; // // 核心高精度对数拟合无速度损失 // 公式frac m - (m^2)/4 完美逼近 log(1m/256) // uint32_t m_sq (m * m) 8; // 平方 int32_t frac m - (m_sq 2); #endif #if 0 // 整数阶 小数折线拟合(工业标准) int shift 0; uint32_t tmp x; while (tmp 1) shift; // 基础整数部分Q8 int32_t base shift * 256; // 尾数精细补偿精准对齐594/1792 uint32_t frac (x - (1U shift)) * 256U / ((1U (shift 1)) - (1U shift)); return (int16_t)(base frac); #endif #if 0 // 整数阶 小数折线拟合(工业标准) int shift 0; uint32_t tmp x; while (tmp 1) shift; int32_t base shift * 256; // 尾数x 在 [2^shift, 2^(shift1)] 之间的位置 uint32_t numerator x - (1U shift); uint32_t denominator (1U shift); // 高精度修正 // 原来线性插值误差大 // 现在对数拟合修正速度一样精度更高 uint32_t frac (numerator * 256) / denominator; // 【关键修正】给小数部分增加对数曲线补偿逼近真实 log2 // 无除法、无浮点、不损失速度 if (frac 192) { frac frac 2; } else if (frac 128) { frac frac 4; } else if (frac 64) { frac frac 6; } else { frac frac 8; } #endif return (int16_t)(base frac); } // // 增益 log22561倍→05122倍→256 // int16_t gain_ev(uint32_t gain) { int16_t log_gain 0, log_base 0; if (gain 0) gain GAIN_BASE_Q8; log_gain log2_q8_exact(gain); log_base log2_q8_exact(GAIN_BASE_Q8); return log_gain - log_base; } // 总EV合成 int16_t calc_ev(uint32_t again, uint32_t dgain, uint32_t ispdgain, uint32_t exp_numerator, uint32_t exp_denominator) { int lv_offset (int)(LV_OFFSET*GAIN_BASE_Q8); int again_fixed gain_ev(again); int dgain_fixed gain_ev(dgain); int ispdgain_fixed gain_ev(ispdgain); int32_t total lv_offset - (gain_ev(again) gain_ev(dgain) gain_ev(ispdgain) log2_q8_exact(exp_numerator) - log2_q8_exact(exp_denominator)); if (total32767)total 32767; if (total-32768)total -32768; return (int16_t)total; } int main() { int again 256; int dgain 256; int ispdgain 256; int exp_numerator 1; int exp_denominator 133; int lv 0; lv calc_ev(again, dgain, ispdgain, exp_numerator, exp_denominator); printf(again%fX, dgain%fX, ispdgain%fX, exp%f,lv %d\n, again / 256.0, dgain / 256.0, ispdgain / 256.0, (float)exp_numerator / exp_denominator, lv); return 0; }二、结果对比分析

更多文章