# ISP - AF统计模块功能

## 功能描述

自动对焦通过分析图像的对比度，自动调整相机的镜头达到对焦的目标。自动对焦算法的统计信息由ISP中的AFM模块提供，AFM模块通过内置的滤波器对RAW数据进行卷积计算得到图像的清晰值FV（Focus Value），AFM模块的统计位置位于RAW域的最后。

AFM模块包含FIR和IIR的高低通滤波器，FIR高通滤波结果与IIR高通滤波结果融合，低通滤波结果与低通滤波结果融合，最终输出高通低通两组统计数据。统计区域为固定数量的15x15，总的统计区域大小可以配置。

## 通路介绍

![ Block ](./media/14-AFM_block.jpg)

## AFM统计模块接口


AFM统计数据获取接口
```c
int32_t hbn_isp_get_af_statistics(hbn_vnode_handle_t vnode_fd, hbn_isp_af_statistics_t *p_data);

typedef struct hbn_isp_af_statistics_s {
        uint32_t sharpnessLowPass[HBN_ISP_AFM_BLOCK_NUM];
        uint32_t sharpnessHighPass[HBN_ISP_AFM_BLOCK_NUM];
        uint32_t histLowData[HBN_ISP_AFM_BLOCK_NUM];
        uint32_t histHighData[HBN_ISP_AFM_BLOCK_NUM];
        uint32_t frame_id;      // 当前对应frame id(备用)
} hbn_isp_af_statistics_t;

```

AFM统计模块参数接口

```c
int32_t hbn_isp_get_afm_attr(hbn_vnode_handle_t vnode_fd, hbn_isp_afm_attr_t *p_attr);
int32_t hbn_isp_set_afm_attr(hbn_vnode_handle_t vnode_fd, hbn_isp_afm_attr_t *p_attr);

typedef struct hbn_isp_afm_ldg_s {
	float iir_highpass_y[HBN_ISP_AFM_LDG_Y_NUM];	/**< IIR high pass on Y axis */
	uint8_t iir_highpass_x[HBN_ISP_AFM_LDG_X_NUM];	/**< IIR high pass on X axis */
	float iir_lowpass_y[HBN_ISP_AFM_LDG_Y_NUM];	/**< IIR low pass on Y axis */
	uint8_t iir_lowpass_x[HBN_ISP_AFM_LDG_X_NUM];	/**< IIR low pass on X axis */
	float fir_highpass_y[HBN_ISP_AFM_LDG_Y_NUM];	/**< FIR high pass on Y axis */
	uint8_t fir_highpass_x[HBN_ISP_AFM_LDG_X_NUM];	/**< FIR high pass on X axis */
	float fir_lowpass_y[HBN_ISP_AFM_LDG_Y_NUM];	/**< FIR low pass on Y axis */
	uint8_t fir_lowpass_x[HBN_ISP_AFM_LDG_X_NUM];	/**< FIR low pass on X axis */
} hbn_isp_afm_ldg_t;

typedef struct hbn_isp_afm_coring_s {
	uint8_t iir_highpass[HBN_ISP_AFM_CORING_COEFF_NUM];	/**< IIR high pass */
	uint8_t iir_lowpass[HBN_ISP_AFM_CORING_COEFF_NUM];	/**< IIR low pass */
	uint8_t fir_highpass[HBN_ISP_AFM_CORING_COEFF_NUM];	/**< FIR high pass */
	uint8_t fir_lowpass[HBN_ISP_AFM_CORING_COEFF_NUM];	/**< FIR low pass */
} hbn_isp_afm_coring_t;

typedef struct hbn_isp_afm_iir_s {
	uint8_t data_shift;	/**< Data shift */
	uint8_t data_shift_v;	/**< Data shift Vetical*/
	float highpass_weight;	/**< High pass weight */
	float lowpass_weight;	/**< Low pass weight */
	float highpass_coeff[HBN_ISP_AFM_IIR_FILTER_NUM][HBN_ISP_AFM_IIR_FILTER_COEFF_NUM];  /**< High pass coefficient */
	float lowpass_coeff[HBN_ISP_AFM_IIR_FILTER_NUM][HBN_ISP_AFM_IIR_FILTER_COEFF_NUM];   /**< Low pass coefficient */
} hbn_isp_afm_iir_t;

typedef struct hbn_isp_afm_fir_s {
	uint8_t data_shift;		/**< Data shift */
	uint8_t data_shift_v;		/**< Data shift Vetical*/
	float highpass_weight;		/**< High pass weight */
	float lowpass_weight;		/**< Low pass weight */
	uint8_t highdata_shift;
	uint8_t highdata_shift_v;
	uint8_t lowdata_shift;
	uint8_t lowdata_shift_v;
	uint8_t highpass_coeff[HBN_ISP_AFM_FIR_HIGHPASS_COEFF_NUM];	/**< High pass coefficient */
	uint8_t lowpass_coeff[HBN_ISP_AFM_FIR_LOWPASS_COEFF_NUM];	/**< Low pass coefficient */
} hbn_isp_afm_fir_t;

typedef struct hbn_isp_afm_attr_s {
	uint16_t bls;					/**< BLS components */
	uint8_t hist_threshold;				/**< Histogram threshold */
	float gamma;					/**< Gamma value */
	uint16_t hw_roi[HBN_ISP_AFM_BLOCK_POINT_NUM];	/**< Hardware ROI */
	hbn_isp_afm_ldg_t ldg;				/**< Level Dependent Gain configuration */
	hbn_isp_afm_coring_t coring;			/**< Coring configuration */
	hbn_isp_afm_iir_t iir;				/**< IIR configuration */
	hbn_isp_afm_fir_t fir;				/**< FIR configuration */
} hbn_isp_afm_attr_t;

```


## 输入图像裁剪

AFM模块支持对输入图像统计位置的配置由结构体`hbn_isp_afm_attr_t`中的`hw_roi`参数配置，四个结构体成员分别对应xy的起始位置与最终位置。


## 输入图像预处理

AFM模块在进行滤波器计算之前包含BLC和Gamma两步预处理，可以配置参数去除一定的黑电平，Gamma参数只需要配置一个Gamma系数，软件将自动计算对应的Gamma曲线配置到硬件。

这两个参数分别对应结构体`hbn_isp_afm_attr_t`中的`bls`与`gamma`参数。

## 输出数据后处理

AFM模块在进行滤波器计算之后包含Coring和LDG两步后处理。这两个参数分别对应结构体`hbn_isp_afm_attr_t`中的`coring`与`ldg`参数。

coring功能在低光区域消除噪音以增加清晰度。低于某一阈值的像素值根据coring曲线被切割。
第一个参数x1，如果输入x < x1，则y = 0。第二个参数x2，如果 x1 < x < x2，则 y = ( x - x1) * x2 / 16。第三个参数x3，直线映射阶段的斜率。 默认参数如下，代表32到230区间映射斜率为1。

![ Block ](./media/14-coring.jpg)


电平依赖增益（LDG）根据像素值调节清晰度。它根据LDG曲线增加低像素值，减少高像素值。LDG是在IIR滤波器和FIR滤波器之后进行的。
以高通IIR滤波为例，iirHighPassY[0~2]：高通IIR滤波的LDG curve的Y轴，代表针对输入x的放大倍数，即1.0为 y = x * 1，2.0为 y = 2 * x。iirHighPassX[0~3]：高通IIR滤波的LDG curve的x轴，分别对应图中的x[0~3]，代表判定输入x在数值判定范围，根据不同范围决定其映射的放大斜率。

![ Block ](./media/14-ldg.jpg)


## 数据融合

AF的统计数据包含highdata与lowdata，分别代表FIR和IIR高通滤波结果的加权结果与FIR和IIR低通滤波结果的加权结果。

```c
highdata = (fir.highdata * fir.highpassweight + iir.highdata * iir.highpassweight) / 2;
lowdata = (fir.lowdata * fir.lowpassweight + iir.lowdata * iir.lowpassweight) / 2;
```

iir与fir的highpassweight建议其之和等于2，iir与fir的lowpassweight建议其之和等于2，这样不会让数据有额外的倍数引入。


## 点光源处理

当场景中出现点光源时，受到光晕的影响统计数据会出现图像越模糊越大的反常现象，对于这种情况，AFM有亮度统计模块，可以帮助用户做一些调试策略。配置亮度的阈值，可以获取超过或者低于此阈值的像素个数，用户可以依据此判断此区域是否是一个光源，然后选择剔除掉这一区域的数据，或者通过亮点个数的变化判断该区域是对焦或者失焦。

亮度的阈值为结构体`hbn_isp_afm_attr_t`中的`hist_threshold`参数。


## 数据移位


|                 参数                 |                                        含义                                         |
| :----------------------------------: | :---------------------------------------------------------------------------------: |
|  fir.highDataShift/fir.lowDataShift  |                每个像素点，在fir滤波器的水平梯度在求平方之前的位移数                |
| fir.lowDataShiftV/fir.highDataShiftV |                每个像素点，在fir滤波器的垂直梯度在求平方之前的位移数                |
|    fir.data_shift/iir.data_shift     | 每个block统计的时候，block中每一行的sharpness加起来后的位移数。高通低通都是这个参数 |
|  fir.data_shift_v/iir.data_shift_v   |          每个block统计的时候，所有点加起来后的位移数。高通低通都是这个参数          |


## IIR参数生成步骤参考

接口选用切比雪夫 II 型滤波器，第一个参数为3阶，最后一个参数为带通"bandpass" ，这两个参数是不可改变的。
然后利用tf2sos分解成2阶。得出的参数与json中的参数对应关系如下：

1. a2的三个参数对应json第一列的前三个参数，b3的第二个参数对应json中第一列的第四个参数。
2. a3的三个参数对应json第二列的前三个参数，b2的第二个参数对应json中第二列的第四个参数。
3. a1的三个参数对应json第三列的前三个参数，b1的第二个参数对应json中第三列的第四个参数。


![ matlab_iir ](./media/14-matlab_iir.png)


## 推荐参数配置

```json

"AFM_3": {
	"bls": 0,
	"coring": {
		"firHighPass": [32,230,16],
		"firLowPass": [32,230,16],
		"iirHighPass": [32,230,16],
		"iirLowPass": [32,230,16]
	},
	"fir": {
		"dataShift": 12,
		"dataShiftV": 3,
		"highPassWeight": 1.0,
		"lowPassWeight": 1.0,
		"highDataShift": 0,
		"highDataShiftV": 0,
		"lowDataShift": 3,
		"lowDataShiftV": 3,
		"highPassCoeff": [2, 1],
		"lowPassCoeff": [12, 6, 4, 3]
	},
	"gamma": 2.2,
	"histThreshold": 128,
	"hwRoi": [0,0,1920,1080],
	"iir": {
		"dataShift": 3,
		"dataShiftV": 3,
		"highPassWeight": 1.0,
		"highPassCoeff": [[0.573, -1.4474, 0.774, -1.98],[0.573, -1.875, 0.915, -1.31],[0.217, -1.467, 0.566, 0.0]],
		"lowPassWeight": 1.0,
		"lowPassCoeff": [[0.6, -0.445, 0.624, -1.92],[0.6, -1.67, 0.823, 0.215],[0.383, -1.465, 0.566, 0.0]]
	},
	"ldg": {
		"firHighPassX": [16, 96, 160, 208],
		"firHighPassY": [4.0, 8.0, 4.0],
		"firLowPassX": [16, 96, 160, 208],
		"firLowPassY": [4.0, 8.0, 4.0],
		"iirHighPassX": [16, 96, 160, 208],
		"iirHighPassY": [1.0, 2.0, 1.0],
		"iirLowPassX": [16, 96, 160, 208],
		"iirLowPassY": [1.0, 2.0, 1.0]
	},
}

```

## 调试建议

1. coring参数用于去除噪声的影响，在曝光增益较高的场景，可以适当增加coring的第一个参数，能够减弱噪声导致的数值波动，但整体FV值会后所下降。
2. 高对比度的场景如果出现双波峰曲线，这可能是垂直方向的滤波数据过大导致的，可以调整fir的滤波核参数，适当减少垂直方向的参数，来减少垂直方向的对比度影响。
3. 信息不足的场景，经过AFM输出的统计数据通常较小，可以适当减少各级datashift，适当增加ldg中间区域的数值以增大最终的统计数据，不建议将参数调整偏离过大，会影响到普通场景的统计数据结果。

