从0开始的智能车代码(1)


代码从逐飞科技的开源库开始。

想要站在巨人的肩膀上,首先要爬上巨人。在抄别人的代码时,我将会经常发现一些不尽如人意的地方,但是为了使代码顺利运行,我将标记出这些问题而不改善。

在主循环中首先判断摄像头数据是否采集完成,然后使用大津法求阈值,根据阈值对原图像数组进行二值化。

大津法(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 波的占空比置零将车停下。


免责声明!

本站转载的文章为个人学习借鉴使用,本站对版权不负任何法律责任。如果侵犯了您的隐私权益,请联系本站邮箱yoyou2525@163.com删除。



 
粤ICP备18138465号  © 2018-2025 CODEPRJ.COM