
- ISP Pipeline中Lv实现方式探究之二
- ISP Pipeline中Lv实现方式探究之三--lv计算定点实现
- ISP Pipeline中Lv实现方式探究之四----正LV值定点实现
- ISP Pipeline中Lv实现方式探究之五--lv值计算框架优化
- ISP Pipeline中Lv实现方式探究之六--lv值计算再优化
一、Lv值的计算 公式
LV = log₂(1/(T·Gain)) + Lv_Offset
其中,T表示秒为单位的曝光时间,Gain为总的增益倍数,Lv_offset=8
二、Lv节点具体表现
前 7 段:T=1/512,1/256,1/128,1/64,1/32,1/16,1/8,1/4,Gain=1
后 10 段:T=1/4,Gain=2,4,8,16,32,64,128,256,512
三、下述类似Lv节点代码实现

代码实现:
cpp
#define LUT_SIZE_64 64
static const int16_t log2_table_q10_64[LUT_SIZE_64 + 1] = {
0, 23, 45, 68, 90, 111, 132, 153,
174, 194, 214, 234, 254, 273, 292, 311,
330, 348, 366, 384, 402, 419, 436, 454,
470, 487, 504, 520, 536, 552, 568, 584,
599, 614, 629, 644, 659, 674, 689, 703,
717, 731, 745, 759, 773, 787, 800, 813,
827, 840, 853, 866, 879, 891, 904, 916,
929, 941, 953, 965, 977, 989, 1001, 1012,
1024,
};
int32_t q10_log2_64lut(uint32_t x)
{
uint32_t val = x;
int32_t exp = 0;
if (x <= 0) return 0;
// 归一化到 [1024, 2047]
while (val >= 2UL * Q10_SCALE) {
val >>= 1; exp++;
}
while (val < Q10_SCALE) {
val <<= 1; exp--;
}
uint32_t delta = val - Q10_SCALE;
uint8_t idx = (uint8_t)(delta >> 4); // 64点:右移4位
uint8_t frac = (uint8_t)(delta & 0x0F); // 插值 0~15
int16_t y0 = log2_table_q10_64[idx];
int16_t y1 = log2_table_q10_64[idx + 1];
// 插值公式:y0 + (y1-y0)*frac/16
int32_t interp = y0 + (((int32_t)(y1 - y0) * frac) >> 4);
int32_t res = (exp * Q10_SCALE) + interp;
return res;
}
int32_t calc_log2_ev_q10(
uint32_t again_q8,
uint32_t dgain_q8,
uint32_t ispd_q8,
uint32_t exp)
{
int16_t la = q10_log2_64lut(again_q8*4);
int16_t ld = q10_log2_64lut(dgain_q8*4);
int16_t li = q10_log2_64lut(ispd_q8 * 4);
int16_t le = q10_log2_64lut(exp * 1024);
return le - (la + ld + li) + 8 * Q10_SCALE; // Q10 格式输出
}
int main() {
int i;
int again = 6318;
int dgain = 256;
int ispdgain = 256;
int exp_numerator = 1;
int exp_denominator = 4;
int lv = 0;
int rand_gain,rand_exp;
srand((unsigned int)time(NULL));
int couont = 500;
int gain_min = 256;
int gain_max = 131072;
int exp_min = 4;
int exp_max = 512;
FILE *fp = fopen("lv_fixed_q10_LUT-new-rand-rand_gain_exp.txt", "w");
fprintf(fp, "Q8fixAgain ori_Again Dgain ispdgain exp_time exp_time(s) lv lv理论值\n");
for (i = 0; i <= couont; i++)
{
rand_gain = rand() % (gain_max - gain_min + 1) + gain_min;
rand_exp = rand() % (exp_max - exp_min + 1) + exp_min;
lv = calc_log2_ev_q10(rand_gain, dgain, ispdgain, rand_exp);
fprintf(fp, "%6d %10f %4d %4d %d %.8f %4d %.8f\n", rand_gain, (float)rand_gain / 256.0, dgain, ispdgain, rand_exp, 1.0 / rand_exp, lv, lv / 1024.0);
}
return 0;
}
增益和曝光时间随机改变,代码计算最终的lv值和excel计算的lv值对比。误差非常小,完全可以在驱动块使用定点实现代码计算Lv值。数据比较如下:
