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

相关推荐
大熊背11 天前
ISPPipeline中的图像噪声问题解析
图像处理·人工智能·计算机视觉·去噪·isppipeline
大熊背18 天前
树莓派 libcamera IPA 框架解析
linux·ipa·isppipeline
大熊背23 天前
树莓派IspPipeline LSC模块原理详解
算法·lsc·isppipeline·mesh lsc
大熊背1 个月前
树莓派相机自动白平衡详解(四)
算法·树莓派·白平衡·isppipeline
大熊背1 个月前
树莓派相机自动白平衡详解(二)
算法·白平衡·isppipeline
大熊背2 个月前
双目拼接亮度差优化
isppipeline·双目拼接·亮度差消除
大熊背4 个月前
安防摄像头 白天 ↔ 全彩 模式切换逻辑设计
软光敏·isppipeline
大熊背4 个月前
Binning模式下和Normal模式下加权平均亮度差异分析以及优化
人工智能·算法·自动曝光
大熊背5 个月前
ISP Pipeline中Lv实现方式探究之六--lv值计算再优化
网络·算法·自动曝光·lv