本算法只用于自己写的测试软件进行模组图像对焦,并不是手机拍照功能的对焦算法。
自动对焦目前我想到的实现方法有两种:
第一种,穷举法,
将VCM马达从0往上推或者从1023往下推,将每个code值所拍到的buffer进行图像清晰度测试,再将产生的数据形成数组,进行最大值计算。
第二种,数据对比,
将VCM马达从0往上推或者从1023往下推,前一个code值所计算的清晰度数据a1和后一个code值所计算的清晰度数据a2进行对比,if(a1<a2),则继续同方向推马达,if(a1>a2),则将步幅减为原步幅的1/3,进行反方向推马达,之后再碰到a1>a2时,跳回前一个code值,这个code值就是对焦值。
实现方法:
第一种:穷举法
1 //设置步数 2int b_test=50; 3 if(b_test>=0) 4 { 5 int i; 6 //获取刚开始的步数,即50 7 i= 50; 8 9 if(b_test>0) 10 { 11 try{ 12 double a; 13 //获取清晰度值,清晰度算法参考opencv清晰度测试 14 a=GetAFcode(pBuffer); 15 testArr[i-b_test]=a; 16 USHORT b; 17 //读取当前code值 18 ReadSensorReg(0x1c,0x03,&b,0x02,0); 19 codeArr[i-b_test]=b; 20 qDebug()<<"第"<<i-b_test<<"次,清晰度为:"<<a<<"。code值为:"<<b; 21 USHORT c=1023/i; 22 //写入下一个code值, 23 WriteSensorReg(0x1c,0x03,b-c,0x02,0); 24 Sleep(10); 25 } 26 catch(Exception e){ 27 qDebug()<<"Af错误"; 28 } 29 } 30 else//当b_test==0时,即穷举完成,即将进行数组最大值获取 31 { 32 //获取数组中最大的数据 33 int max=max_element(testArr,testArr+i)-testArr; 34 qDebug()<<"清晰度最高的下标为:"<<max; 35 //写入图像最清晰时的code值 36 WriteSensorReg(0x1c,0x03,codeArr[max],0x02,0); 37 } 38 b_test=b_test-1; 39 }
第二种:数据对比法
1 int bac=0; 2 double AFval1=0; 3 double AFval2=0; 4 double AFval3=0; 5 if(b_AFtest) 6 { 7 if(bac>0)//反向后 8 { 9 USHORT a; 10 ReadSensorReg(0x1c,0x03,&a,0x02,0); 11 AFval3=GetAFcode(pBuffer);//当前清晰度获取 12 if(AFval3>AFval1)//证明没过峰值,继续向前跑 13 { 14 WriteSensorReg(0x1c,0x03,a-10,0x02,0);//vcm反向走10步 15 bac=bac+1; 16 AFval1=AFval3; 17 AFval3=0; 18 } 19 else if(AFval3<AFval1)//越过峰值,即可认为上一个code值为最佳 20 { 21 qDebug()<<"即可认为上一个code值为最佳"; 22 WriteSensorReg(0x1c,0x03,a+10,0x02,0);//vcm反向走10步 23 b_AFtest=FALSE;//结束自动对焦 24 } 25 } 26 else if(bac==0)//还没有反向推焦 27 { 28 if(AFval1==0)//第一次测清晰度 29 { 30 qDebug()<<"第一次"; 31 AFval1=GetAFcode(pBuffer);//获取第一个清晰度值 32 WriteSensorReg(0x1c,0x03,1023-50,0x02,0);//vcm向前50 33 // Sleep(5000); 34 stepNum=stepNum-1;//减少一步 35 qDebug()<<"AFval1:"<<AFval1; 36 } 37 else 38 { 39 AFval2=GetAFcode(pBuffer);//获取当前清晰度值 40 qDebug()<<"AFval2="<<AFval2; 41 if(AFval2>AFval1)//清晰度在提高,移动方向正确 42 { 43 44 USHORT a; 45 ReadSensorReg(0x1c,0x03,&a,0x02,0); 46 WriteSensorReg(0x1c,0x03,a-50,0x02,0);//vcm继续向前50 47 Sleep(50); 48 qDebug()<<"AFval1:"<<AFval1; 49 AFval1=AFval2;//将AFval2传给AFval1 50 AFval2=0;//清空AFval2 51 stepNum=stepNum-1;//减少一步 52 53 54 qDebug()<<"向前"; 55 // b_AFtest=FALSE; 56 } 57 else if(AFval2<AFval1)//AFval2<AFval1,证明越过峰值了 58 { 59 qDebug()<<"2<1"; 60 61 USHORT a; 62 ReadSensorReg(0x1c,0x03,&a,0x02,0); 63 WriteSensorReg(0x1c,0x03,a+40,0x02,0);//往回跑40code 64 Sleep(50); 65 66 stepNum=stepNum-1;//减少一步 67 AFval1=AFval2;//将AFval2传给AFval1 68 qDebug()<<"AFval1:"<<AFval1; 69 AFval2=0; 70 qDebug()<<"应该反向了"; 71 bac=bac+1; 72 } 73 } 74 } 75 }
自动对焦逻辑理解:
code值先设置到最大,然后慢慢往后退,检测当前清晰度和前一个清晰度进行大小对比,如果前一个比后一个清晰度要小,证明还没到峰值,继续往后退,如果前一个比后一个要大,证明越过了峰值,要进行反推,步幅减少为之前的1/5,再次判断,如果如果前一个比后一个小,继续反推,否者就判断前一个code值为最佳。该清晰度算法测试不精准且容易受环境影响,迟些再完善。
ps,清晰度数据可以通过OPENCV来获取。