46. 3A development User Guide¶
46.1. AF Statistics Instructions¶
46.1.1. Function Overview¶
Auto focus is to get the current image clarity value FV(Focus Value) by analyzing the characteristics of the image. Because the clearer the image is, the greater the FV is. Therefore, by comparing the clarity value of each position, the highest point of FV value curve can be found, which is the focus. After finding the focus, the user can control the focusing horse to reach the best position to complete auto focus.
At present, AF provides four filters and brightness information, which are the horizontal direction H1, H2 and the vertical direction v1. In the horizontal direction, a low-pass filter is used first, and then two high pass filters are used to get the values of H1 and H2. In the vertical direction, only high pass filters are used. Currently, AF only supports statistical information in Bayer domain.

46.1.2. Crop Input Image¶
AF supports clipping of input image. Users can determine the current statistical area of AF by X, y, W and h in stCrop. For details, refer to ISP_STATISTICS_CFG_S for relevant structure information
46.1.3. Configuration of Bayer Domain¶
There are two pre-processing methods for data before entering AF module
Users can choose whether to go through gamma or not. If necessary, they need to enable gamma and fill in the appropriate gamma curve
User can choose whether to turn on pre filtering to eliminate the influence of salt and pepper noise on statistics
46.1.4. Suppress the Influence of Light Source on FV Value¶
When there is a point light source in the image, the FV value will be affected by the halo diffusion, but the FV value will increase.
In order to suppress this phenomenon, u16HlCnt is added to count the value of high brightness points in the window.
The user can adjust u16HighLumaTh to determine the threshold value of highlight points.
When the window is blurred, the number of highlights in the window increases, and when the window is clear, the number of highlights in the window is the least.
The user can use this information to determine the most suitable focus
46.1.5. Notes on Statistical Information Configuration¶
Type |
Description |
---|---|
Block size |
Maxiumum 17 * 15 |
Work domain of statistics module |
RAW |
Whether Bayer statistical parameter subtracts black level |
Subtracted |
46.1.6. Acquisition of FV Value¶
When the last pixel of the image passes, the statistical information can be obtained, and the user can synchronously obtain the statistical value through CVI_ISP_GetVDTimeOut.
Please refer to the process of 33.1.8.
46.1.7. Calculation of FV Value¶
There are three kinds of statistical values that can be obtained by a block: H0 obtained by the first group of Horizontal filters, H1 obtained by the second group of Horizontal filters, and V0 obtained by the Vertical filters. We name the FV value of each block FVn , and set their own weights for each statistical value, which are W0 / W1 / W2 respectively. Then the FVn value is

The final FV value also needs to add weight to the FV of each block. Assuming that the weight of the nth block is Wn, the final FV value is:

46.1.8. FV Calculation Reference Code¶
ISP_AF_STATISTICS_S afStat;
CVI_U32 row, col;
CVI_S32 s32Ret = CVI_SUCCESS;
CVI_U64 stsValue = 0;
VI_PIPE ViPipe = 0;
ISP_VD_TYPE_E enIspVDType = ISP_VD_FE_START;
CVI_CHAR input[10];
ISP_STATISTICS_CFG_S stsCfg;
ISP_PUB_ATTR_S stPubAttr;
struct timeval t1, t2;
// AF weighting table
static int AFWeight[15][17] = {{1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1},
{1,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,1},
{1,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,1},
{1,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,1},
{1,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,1},
{1,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,1},
{1,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,1},
{1,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,1},
{1,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,1},
{1,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,1},
{1,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,1},
{1,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,1},
{1,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,1},
{1,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,1},
{1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1}};
// Get current statistic and related size setting.
s32Ret = CVI_ISP_GetStatisticsConfig(ViPipe, &stsCfg);
s32Ret |= CVI_ISP_GetPubAttr(ViPipe, &stPubAttr);
if (s32Ret != CVI_SUCCESS) {
CVI_TRACE_LOG(CVI_DBG_ERR, "Get Statistic info fail with %#x!\n", s32Ret);
return s32Ret;
}
// Config AF Enable.
stsCfg.stFocusCfg.stConfig.bEnable = 1;
// Config low pass filter.
stsCfg.stFocusCfg.stConfig.u8HFltShift = 0;
stsCfg.stFocusCfg.stConfig.s8HVFltLpCoeff[0] = 0;
stsCfg.stFocusCfg.stConfig.s8HVFltLpCoeff[1] = 1;
stsCfg.stFocusCfg.stConfig.s8HVFltLpCoeff[2] = 2;
stsCfg.stFocusCfg.stConfig.s8HVFltLpCoeff[3] = 3;
stsCfg.stFocusCfg.stConfig.s8HVFltLpCoeff[4] = 4;
// Config gamma enable.
stsCfg.stFocusCfg.stConfig.stRawCfg.PreGammaEn = 0;
// Config pre NR enable.
stsCfg.stFocusCfg.stConfig.stPreFltCfg.PreFltEn = 1;
// Config H & V window.
stsCfg.stFocusCfg.stConfig.u16Hwnd = 17;
stsCfg.stFocusCfg.stConfig.u16Vwnd = 15;
// Config crop related setting. Has some limitation
stsCfg.stFocusCfg.stConfig.stCrop.bEnable = 1;
stsCfg.stFocusCfg.stConfig.stCrop.u16X = 8;
stsCfg.stFocusCfg.stConfig.stCrop.u16Y = 2;
stsCfg.stFocusCfg.stConfig.stCrop.u16W = stPubAttr.stWndRect.u32Width - 8 * 2;
stsCfg.stFocusCfg.stConfig.stCrop.u16H = stPubAttr.stWndRect.u32Height - 2 * 2;
// Config first horizontal high pass filter.
stsCfg.stFocusCfg.stHParam_FIR0.s8HFltHpCoeff[0] = 0;
stsCfg.stFocusCfg.stHParam_FIR0.s8HFltHpCoeff[1] = -3;
stsCfg.stFocusCfg.stHParam_FIR0.s8HFltHpCoeff[2] = 0;
stsCfg.stFocusCfg.stHParam_FIR0.s8HFltHpCoeff[3] = -10;
stsCfg.stFocusCfg.stHParam_FIR0.s8HFltHpCoeff[4] = 0;
// Config 2nd horizontal high pass filter.
stsCfg.stFocusCfg.stHParam_FIR1.s8HFltHpCoeff[0] = 0;
stsCfg.stFocusCfg.stHParam_FIR1.s8HFltHpCoeff[1] = -3;
stsCfg.stFocusCfg.stHParam_FIR1.s8HFltHpCoeff[2] = 0;
stsCfg.stFocusCfg.stHParam_FIR1.s8HFltHpCoeff[3] = -10;
stsCfg.stFocusCfg.stHParam_FIR1.s8HFltHpCoeff[4] = 0;
// Config vertical high pass filter.
stsCfg.stFocusCfg.stVParam_FIR.s8VFltHpCoeff[0] = 8;
stsCfg.stFocusCfg.stVParam_FIR.s8VFltHpCoeff[1] = -15;
stsCfg.stFocusCfg.stVParam_FIR.s8VFltHpCoeff[2 ] = 0;
stsCfg.unKey.bit1FEAfStat = 1;
s32Ret = CVI_ISP_SetStatisticsConfig(ViPipe, &stsCfg);
if (s32Ret != CVI_SUCCESS) {
CVI_TRACE_LOG(CVI_DBG_ERR, "ISP Set Statistic failed with %#x!\n", s32Ret);
return s32Ret;
}
printf("select. c -> Fv curve\n");
printf("........ h0 -> print h0 blocks statistic\n");
printf("........ h1 -> print h1 blocks statistic\n");
printf("........ v0 -> print v0 blocks statistic\n");
printf("........ hlc -> print hlcnt blocks statistic\n");
scanf("%s", input);
while(1) {
// Wait VD start for get focus statistic data.
s32Ret = CVI_ISP_GetVDTimeOut(ViPipe, enIspVDType, 5000);
s32Ret |= CVI_ISP_GetFocusStatistics(ViPipe, &afStat);
if (s32Ret != CVI_SUCCESS) {
CVI_TRACE_LOG(CVI_DBG_ERR, "Get Statistic failed with %#x\n", s32Ret);
return CVI_FAILURE;
}
// print each focus statistic.
if (strncmp(input, "c", 1) != 0) {
for (row = 0; row < AF_ZONE_ROW; row++) {
for (col = 0; col < AF_ZONE_COLUMN; col++) {
if (strncmp(input, "h0", 2) == 0) {
stsValue = afStat.stFEAFStat.stZoneMetrics[row][col].u64h0;
} else if (strncmp(input, "h1", 2) == 0) {
stsValue = afStat.stFEAFStat.stZoneMetrics[row][col].u64h1;
} else if (strncmp(input, "v0", 2) == 0) {
stsValue = afStat.stFEAFStat.stZoneMetrics[row][col].u32v0;
} else {
stsValue = afStat.stFEAFStat.stZoneMetrics[row][col].u16HlCnt;
}
printf("%d ", stsValue);
}
printf("\n");
}
continue;
}
CVI_U64 FVn = 0, FV = 0;
CVI_U32 totalWeightSum = 0;
// weight for each statistic
const CVI_U32 weight1 = 1, weight2 = 1, weight3 = 1;
const CVI_U32 blockWeightSum = weight1 + weight2 + weight3;
// calculate AF statistics
for (row = 0; row < AF_ZONE_ROW; row++) {
for (col = 0; col < AF_ZONE_COLUMN; col++) {
CVI_U64 h0 = afStat.stFEAFStat.stZoneMetrics[row][col].u64h0;
CVI_U64 h1 = afStat.stFEAFStat.stZoneMetrics[row][col].u64h1;
CVI_U32 v0 = afStat.stFEAFStat.stZoneMetrics[row][col].u32v0;
FVn = (weight1 * h0 + weight2 * h1 + weight3 * v0) / blockWeightSum;
FV += FVn * AFWeight[row][col];
totalWeightSum += AFWeight[row][col];
}
}
FV = FV / totalWeightSum;
}
return CVI_SUCCESS;