本算法只用於自己寫的測試軟件進行模組圖像對焦,並不是手機拍照功能的對焦算法。
自動對焦目前我想到的實現方法有兩種:
第一種,窮舉法,
將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來獲取。