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

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