代碼從逐飛科技的開源庫開始。
想要站在巨人的肩膀上,首先要爬上巨人。在抄別人的代碼時,我將會經常發現一些不盡如人意的地方,但是為了使代碼順利運行,我將標記出這些問題而不改善。
在主循環中首先判斷攝像頭數據是否采集完成,然后使用大津法求閾值,根據閾值對原圖像數組進行二值化。
大津法(OTSU)是一種確定圖像二值化分割閾值的算法,由日本學者大津於 1979 年提出。從大津法的原理上來講,該方法又稱作最大類間方差法,因為按照大津法求得的閾值進行圖像二值化分割后,前景與背景圖像的類間方差最大。
void imageBinary(void) { uint16 grayCount[256]={0}; uint32 graySum=0; uint16 pixelSum=0; float graypro[256]; uint8 threshold; uint16 i,j; uint16 step=2;//間隔 for(i=0;i<MT9V032_H;i+=step){ for(j=0;j<MT9V032_W;j+=step){ grayCount[image[i][j]]++; graySum+=image[i][j]; pixelSum++; } } for(i=0;i<256;i++){ graypro[i]=(float)grayCount[i]/pixelSum; } float w0,w1,u0Temp,u1Temp,u0,u1,u,deltaTemp,deltaMax; deltaMax=0; for(i=0;i<256;i++){ w0=w1=u0Temp=u1Temp=u0=u1=u=deltaTemp=0; for(j=0;j<256;j++){ if(j<=i){ w0+=graypro[j]; u0Temp+=j*graypro[j]; } else{ w1+=graypro[j]; u1Temp+=j*graypro[j]; } } u0=u0Temp/w0; u1=u1Temp/w1; u=u0Temp+u1Temp; deltaTemp=w0*(u0-u)*(u0-u)+w1*(u1-u)*(u1-u); if(deltaTemp>deltaMax){ deltaMax=deltaTemp; threshold=i; } } for(i=0;i<MT9V032_H;i++){ for(j=0;j<MT9V032_W;j++){ binaryImage[i][j]=(image[i][j]>threshold)?255:0; } } if(threshold<160){//出界停車 DisableInterrupts; ctimer_pwm_duty(TIMER1_PWMCH0_A18,0); ctimer_pwm_duty(TIMER2_PWMCH1_B4,0); } }
若求得閾值小於某個臨界值,則說明攝像頭已經幾乎看不到白色的賽道了,接下來要停止所有中斷並將電機輸出 PWM 波的占空比置零將車停下。