ISP Pipeline中Lv实现方式探究之七--lv值计算框架final_version

一、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值。数据比较如下:

相关推荐
大熊背4 天前
Serial over TCP实现原理
网络·tcp·isppipeline
大熊背14 天前
如何利用Lv值实现三级降帧
算法·自动曝光·lv·isppipeline
大熊背17 天前
ISP Pipeline中Lv实现方式探究之三--lv计算定点实现
数据结构·算法·自动曝光·lv·isppipeline
大熊背17 天前
ISP Pipeline中Lv实现方式探究之二
自动白平衡·自动曝光·lv·isppipeline·bv
大熊背17 天前
ISP中Lv和ISO系统并存的意义
自动曝光·iso·lv·isppipeline
大熊背17 天前
ISP Pipeline中Lv实现方式探究之一
算法·自动白平衡·自动曝光
大熊背20 天前
根据ISP各个ISO节点标定后的参数,如何插值生成当前增益下对应的ISP参数
iso·isppipeline·isp插值·log域
大熊背1 个月前
ISP图像效果参数压缩的可行性分析(二)差分序列做 BLE (RLE) 压缩原理
压缩·isppipeline
大熊背1 个月前
ISP图像效果参数压缩的可行性分析(一)
压缩·gamma·isppipeline