之前预研过激光对焦,demo已经做好了,对焦速度和准确度都还不错,但因为激光测距对矿泉水瓶等透明或反射性强的物体容易测距不准,再加上其他一些因素最终未能量产到项目,在此简单记录一下,以备查询.
主要是利用stmvl6180来红外激光测距(<40mm)并定时input上报给系统,建立一个线程接收测距,每帧图像都会对比当前镜头位置是否在景深范围内,如果在则镜头不动,如果不在则利用基本的光学公式1/u + 1/v = 1/f 和景深计算公式调整镜头位置,再就是,如果测距在40mm以内就用激光对焦方式,如果在40mm以外就用普通反差式对焦(40mm以内基本覆盖了马达的80%动作距离).
int LaserEvents::PreLaserAFCode(int Laserdist)
{//Laserdist ( mm )
//int Laserdist = LaserRanging() - 10;
if ((Laserdist > 400)/*||(Laserdist<70)*/){
MY_LOG("maleijie out of range\n");
Laserdist = 1000000;
return -1;
}
CalcDepth(&d_front,&d_back,Laserdist);
if(!((d_front>pre_back)||(d_back<pre_front))){//说明在原景深范围内
MY_LOG("maleijie PreLaserAF pre_code:%...\n",pre_code);
return pre_code;
}
Laserdist=Laserdist*100;
//计算物距
long iamge_laser_dist = EFL*Laserdist/(Laserdist - EFL);
//计算直线方程
long A_Code = A_CODE;//150 code
long A_Obj_Dist = A_OBJ_DIST*100;//5000mm
long A_Distance = EFL*A_Obj_Dist/(A_Obj_Dist - EFL);
long B_Code = B_CODE;//850 code
long B_Obj_Dist = B_OBJ_DIST*100;//70mm
long B_Distance = EFL*B_Obj_Dist/(B_Obj_Dist - EFL);
ALOGE("maleijie PreLaserAF Laserdist %d,iamge_laser_dist %d,A_Code %d,A_Obj_Dist %d,A_Distance %d,B_Code %d,B_Obj_Dist %d,B_Distance %d\n",
Laserdist,iamge_laser_dist,A_Code,A_Obj_Dist,A_Distance,B_Code,B_Obj_Dist,B_Distance);
//long k = (A_Distance - B_Distance) / (A_Code - B_Code);
//long b = A_Distance - A_Code*(A_Distance - B_Distance)/(A_Code - B_Code);//A_Distance - k*A_Code;
//long y = (iamge_laser_dist - b)*(A_Code - B_Code)/(A_Distance - B_Distance);//(iamge_laser_dist - b)/k;
long y=((iamge_laser_dist-A_Distance)*(B_Code-A_Code))/(B_Distance-A_Distance)+A_Code;
MY_LOG("maleijie PreLaserAF Laser Focus Code %d\n", y);
//y=y/100;
pre_front=d_front; pre_back=d_back; pre_code=y;//
return y;//lens code
}
int LaserEvents::CalcDepth(int* before,int* after,int laserdist){
long front,back;
front=(FNO*DEL*laserdist*laserdist)/(EFL*EFL*100+FNO*DEL*laserdist);//分子分母都*1000000
back=(FNO*DEL*laserdist*laserdist)/(EFL*EFL*100-FNO*DEL*laserdist);//or ~ , 分子分母都*1000000
MY_LOG("maleijie CalcDepth before:%d,after:%d\n",(laserdist-front),(laserdist+back));
*before=laserdist-front;
*after=laserdist+back;// or ~
return 0;
}