基于Hi3519AV100 AF的研究与实现

我们将基于Hi3519AV100 SDK包 已有sample_ist 模块二次实现AF 功能。使用被动式对焦,被动式自动对焦一般是通过分析图像特征得出图像清晰度值 FV(Focus Value), 通过驱动对焦马达调节焦点到最佳位置。

1.AF 模块框架

hi_sample_ist 模块的使用

sample_ist 本质是一个标准 LINUK内核模块(MODULE),编译后生成.ko文件。
.ko是kernel object文件(内核模块),该文件的意义就是把内核的一些功能移动到内核外边, 需要的时候插入内核,不需要时卸载。

在Hi3519AV100 系统之中,可以使用标准模块插入命令:

insmod extdrv/hi_sample_ist.ko

删除命令:

rmmod extdrv/hi_sample_ist.ko

该模块使用前需要确保 ISP 驱动已加载。
可以在load3519av100 文件按中直接添加

AF 同步回调

当一帧图像最后一个 pixel 通过 AF 模块后,统计值即更新,如果用户使用的是 LINUX 系统,因为 user space 任务调度不能保证一致的实时性,建议将需要保证实时性的驱动配置放在 kernel space 完成。ISP 提供同步回调接口的注册,可以实现与 VD 同步。在本章有相应的接口使用描述,用户可以将实时性要求较高的任务放在同步回调里面,底层提供 HwIRQ,Workqueue 两种方式实现,可以选择相应的实现方式以确定实时级别。HiwIRQ 是指任务放在中断服务中实现,实时性最高;Workqueue 的实时性取决于 linux 系统调用。
在这里插入图片描述
所以将在模块初始化的时刻,向ISP 进行同步回调函数的注册。

hi_sample_ist 模块的初始化

//定义同步回调节点信息。
ISP_SYNC_TASK_NODE_S syncNode[MAX_TEST_NODES] =
{
    {
        .enMethod = ISP_SYNC_TSK_METHOD_HW_IRQ,
        .pfnIspSyncTskCallBack = sync_af_calc,
        .u64Data = 0,
        .pstFocusStat = &stFocusStat,
        .pszId = "hw_0"
    },
    {
        .enMethod = ISP_SYNC_TSK_METHOD_HW_IRQ,
        .pfnIspSyncTskCallBack = sync_call_back,
        .u64Data = 1,
        .pstFocusStat = NULL,
        .pszId = "hw_1"
    },
    {
        .enMethod = ISP_SYNC_TSK_METHOD_WORKQUE,
        .pfnIspSyncTskCallBack = sync_call_back,
        .u64Data = 3,
        .pstFocusStat = NULL,
        .pszId = "wq_0"
    },
    {
        .enMethod = ISP_SYNC_TSK_METHOD_WORKQUE,
        .pfnIspSyncTskCallBack = sync_call_back,
        .u64Data = 4,
        .pstFocusStat = NULL,
        .pszId = "wq_1"
    }
};

//sample_ist 模块初始化
static int __init sample_ist_init(void)
{

    int  i, ret;
    ret = misc_register(&sample_ist_dev);
    if (ret != 0)
    {
        printk("register sample_ist device failed with %#x!\n", ret);
        return -1;
    }

    for (i = 0; i < MAX_TEST_NODES; i++)
    {
        //hi_isp_sync_task_register(0, &syncNode[i]);向 ISP 注册同步回调接口。
        if (CKFN_ISP_RegisterSyncTask())
        {
            CALL_ISP_RegisterSyncTask(ViPipe, &syncNode[i]);//向 ISP 注册同步回调接口。
			printk("register sample_ist device  %#x!\n", i);
        }
    }

	//init af pos

    return 0;
}

sample_ist 模块向ISP 注册同步回调函数后,ISP 同步任务调度(ISP Synchronize Task Schedule)将会向注册时定义的函数接口进行回调。

2.FV 值计算

被动式自动对焦一般是通过分析图像特征得出图像清晰度值 FV(Focus Value), 通过驱动对焦马达调节焦点到最佳位置,如图 13-4 所示,图像越清晰 FV 值越大,Peak 点对应聚焦清晰点。获取图像清晰度算法有多种,如灰度梯度法,高频分量法等,本文采用高频分量法来计算 FV,即图像越清晰的时候高频部分幅值越大,将图像通过高通滤波器便可以得到高频分量,一共提供四个滤波器和亮度信息,分别为水平方向滤波 H1,H2,垂直方向滤波 V1,V2,以及 Y 和高亮计数器 HlCnt。
在这里插入图片描述

Hi3519AV100 最大支持 17*15 个blocks的AF统计值的计算。
FV1 使用在低照度场合,FV2 使用在正常照度场合。
对于每一个 block,FV1,FV2 的计算方式为:FV 的计算方式为:

FV1_n = α ∗ H1_n+(1 − α) ∗ V1_n
FV2_n = β ∗ H2_n+(1 − β) ∗ V2_n

u32Fv1_n = (u32H1 * ALPHA + u32V1 * ((1 << BLEND_SHIFT) - ALPHA)) >> BLEND_SHIFT;
u32Fv2_n = (u32H2 * BELTA + u32V2 * ((1 << BLEND_SHIFT) - BELTA)) >> BLEND_SHIFT;

H1,H2,V1,V2 分别为水平垂直四组滤波器的统计值,可设置适当的权重对水平和垂直方向的滤波器输出统计值进行混合。
最中FV的值还需要对每个block 进行加权。

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},
};

HI_S32 sync_af_calc(HI_U64 u64Data)
{
	u32SumFv1 += AFWeight[i][j] * u32Fv1_n;
	u32SumFv2 += AFWeight[i][j] * u32Fv2_n;
	u32WgtSum += AFWeight[i][j];
}

3.AF 控制策略

我们使用被动式对焦,所以我们需要通过马达进行一步一步的尝试,从而确定图像最清晰的位置。

3.1 基于matlab的AF仿真

我们可以使用matlab对 AF马达做一个 爬坡的算法初步验证。
在这里插入图片描述
大概流程:
1.首先 生成一个正太分布,用来模拟山峰;
2.随机 产生一个起始点(0 号点)
3.以默认的一个step向左移动
4.如果上两个点的 高度差>0 ,则被认为是上升趋势,则下个点不改变方向;若高度差<0,则下个点改变方向。

    if(cur_k > 0)
       dir = -dir; 

5.如果发现:本次高度差<0,上一次的高度差>0,则判断找到山峰。

    if(cur_k > 0)
       dir = -dir; 
        if ((last_k < 0)) %find 峰值

6.找到峰值后将step/10,改变方向,这时候需要将初始值设为 峰值+step。

	dir = -dir; 
    next_pos_x = last_pos_x - step*dir;

通过上述找山峰的方法,一次一次的逼近峰值,最终到达峰值。

以上Matlab 验证无问题后,直接移植至 之前说的hi_sample_ist 模块。

4.AF 驱动

该模组的驱动实现较为简单,控制马达的是通过I2C 写寄存器的方式。
其主要难度,是需要在该模块中 调用到I2C 的驱动,查看手册,实现内核中的I2C 驱动实现。


static int __init sample_ist_init(void)
{
	int x = 0;
	struct i2c_adapter *i2c_adap;

	for (x = 0; x < I2C_MAX_NUM; x++)
	{
		i2c_adap = i2c_get_adapter(x);
		sensor_client[x] = i2c_new_device(i2c_adap, &hi_info);

		i2c_put_adapter(i2c_adap);
	}


......
}

5.Matlab 源码

x=0:1:1023;
y1=10000*normpdf(x,512,200);
hold on;

plot(x,y1,'g');

% x2 = randi(1023);

init_x = randi(1023)
% init_x = 246;
init_y = 10000*normpdf(init_x,512,200)

scatter(init_x,init_y,'r');

step = 100;
dir = 1;
limit=1;

last_pos_x = init_x;
last_pos_y = init_y;
last_k=0;
flag_findH = 0;

cur_pos_x = last_pos_x - dir*step;
for i=1:10
    cur_pos_y = 10000*normpdf(cur_pos_x,512,200);

    scatter(cur_pos_x,cur_pos_y,'k');
    text(cur_pos_x,cur_pos_y+1,num2cell(i));
    plot([last_pos_x,cur_pos_x],[last_pos_y,cur_pos_y],'r');
    
    cur_k = (last_pos_y-cur_pos_y);

    if(cur_k > 0)
       dir = -dir; 
        if ((last_k < 0)) %find итох
            step = step/10;
%             cur_pos_x = last_pos_x;
            dir = -dir; 
            next_pos_x = last_pos_x - step*dir;
            cur_pos_x = next_pos_x;
            last_k = cur_k;
%             cur_pos_x = last_pos_x + 10;
            continue;
        end;
    end;
    next_pos_x = cur_pos_x - step*dir;
    next_pos_y = -1;
    
    last_pos_x = cur_pos_x;
    last_pos_y = cur_pos_y;
    cur_pos_x = next_pos_x;
%     cur_pos_y = next_pos_y;%-1
    last_k = cur_k;
end

plot([last_pos_x,last_pos_x],[last_pos_y,0],'b');


Matlab 源码:

https://download.csdn.net/download/weixin_42190974/15577064

Hi359AV100 源码:

https://download.csdn.net/download/weixin_42190974/15577064
  • 3
    点赞
  • 11
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值