代码汇总

本份文件仅整理个人认为有价值的代码部分,并不会将每一份代码的整体思路梳理一遍,而是注重于某一些单独的、可借鉴的方法。本文件按代码文件分类,方便读者根据压缩包文件找源代码阅读。

文件:2019四轮组代码

入环岛判断

根据圆环切点和拐点个数来判断圆环(目前不清楚如何判断切点)
可做辅助方法判断圆环
补线方法:粗暴简单,直接从储存右边界线的数组的第34个开始,每一行的值等于后一行的值减一(没懂为什么)

 /****************圆环循迹****************************/ 
      if(flagl_1 > 10 && flagl_2 == 0)
      {
        uint8 i = 33;
        left[i+1] = 3;
        for( ;i >= 18; --i)
        {
          left[i] = left[i+1] + 1;
          //更新中值
          mid[i] = (left[i] + right[i]) / 2;
        }
      }
      //只看到右圆环第一个标志位时,右边丢线,补上  
      if(flagr_1 > 10 && flagr_2 == 0)
      {
        uint8 i = 33;
        right[i+1] = 79;
        for( ; i >= 18; --i)
        {
    right[i] = right[i+1] - 1;
    //更新中值
    mid[i] = (left[i] + right[i]) / 2;
        }
      }
//flagl_1是进环岛拐角标志位,flagl_2圆切点标志

文件:camera补线 》image

(注:此代码用的巡线方法与【左右巡线求中线】的方法类似,故不做记录
此代码直接记录图片坐标,对坐标进行处理,以下许多处理都建立在此基础上)

提取拐点

基本思路:以屏幕中间行的两个中点为起始点,分别向左右扫描(此代码包含于f__edge_sp_czj函数中)以此为一条直线,从指定行向下(or上)移动,若判断有跳变点,则判断为拐点

名    称:                      提取“下拐左右”拐点函数

功能描述: 提取“下拐左右”拐点
入口参数: 图像数组
出口参数: 下左右拐点存在标志位 拐点坐标

备    注: 如果没找到下拐点 函数会强制返回一个固定的拐点 需要注意!!!
**********************************************************************************************/
void f__guaidian_X(uint8 img[][IMG_W_YS],uint8 *flg_l,zb_imgarr_t *gd_l,uint8 *flg_r,zb_imgarr_t *gd_r)
{
  uint8       nomeaning_tmp_l;  uint8       nomeaning_tmp_r;
  zb_imgarr_t I_l;              zb_imgarr_t I_r;
  zb_imgarr_t I_last_l;         zb_imgarr_t I_last_r;
  uint8       l_sdkd;           uint8       r_sdkd;
  uint8       l_sdkd_last;      uint8       r_sdkd_last;
  uint8       l_jxz_flg=1;      uint8       r_jxz_flg=1;//是否继续找标志位
  
  uint8 RANGE=93-30;
  
  *flg_l=0;
  *flg_r=0;
  
  //假如函数运行完没有找到下拐点 则会强制返回下面这个固定的拐点
  (*gd_l).i=79;
  (*gd_r).i=79;
  (*gd_l).j=0   + 45;
  (*gd_r).j=187 - 45;
  
  I_last_l.i=79;
  I_last_r.i=79;
  f__edge_sp_czj(img[79],RANGE,&nomeaning_tmp_l,&(I_last_l.j),&nomeaning_tmp_r,&(I_last_r.j));//跳变点判断,返回参数:跳变点存在性及坐标
  l_sdkd_last = 93 - I_last_l.j + 1;
  r_sdkd_last = I_last_r.j - 94 + 1;
  
  if(nomeaning_tmp_l==0)
  {
    l_jxz_flg=0;
  }
  if(nomeaning_tmp_r==0)
  {
    r_jxz_flg=0;
  }
  
  for( int16 Ci=78 ; Ci>=0 ; Ci=Ci-2 )
  {
    if(Ci==78)
    {
      if( (l_jxz_flg==0)&&(r_jxz_flg==0) ) break;
    }
    
    I_l.i=Ci;
    I_r.i=Ci;
    f__edge_sp_czj(img[Ci],RANGE,&nomeaning_tmp_l,&(I_l.j),&nomeaning_tmp_r,&(I_r.j));//跳变点判断,返回参数:跳变点存在性及坐标
    
    l_sdkd=93 - I_l.j + 1;
    r_sdkd=I_r.j - 94 + 1;
    
    if( (l_jxz_flg==1)&&((*flg_l)==0)&&((l_sdkd-l_sdkd_last)>2) )
    {
      *flg_l=1;
      
      (*gd_l).i=I_last_l.i;
      (*gd_l).j=I_last_l.j;
    }
    if( (r_jxz_flg==1)&&((*flg_r)==0)&&((r_sdkd-r_sdkd_last)>2) )
    {
      *flg_r=1;
      
      (*gd_r).i=I_last_r.i;
      (*gd_r).j=I_last_r.j;
    }
    
    if( ((*flg_l)==1)&&((*flg_r)==1) ) break;
    
    I_last_l=I_l;
    I_last_r=I_r;
    l_sdkd_last=l_sdkd;
    r_sdkd_last=r_sdkd;
    
    
    if(nomeaning_tmp_l==0)
    {
      l_jxz_flg=0;
    }
    if(nomeaning_tmp_r==0)
    {
      r_jxz_flg=0;
    }
    if( (l_jxz_flg==0)&&(r_jxz_flg==0) ) break;
  }
/**********************************************************************************************
名    称:                      提取“上拐左右”拐点函数

功能描述: 
入口参数: 
出口参数: 

备    注: 
**********************************************************************************************/
void f__guaidian_S(uint8 img[][IMG_W_YS],uint8 s_i,uint8 s_j_l,uint8 s_j_r,uint8 *flg_l,zb_imgarr_t *gd_l,uint8 *flg_r,zb_imgarr_t *gd_r)
{
  zb_imgarr_t I_last_l;       zb_imgarr_t I_last_r;     //上次点
  zb_imgarr_t I_l;            zb_imgarr_t I_r;          //本次点
  uint8       szkd_last_l;    uint8       szkd_last_r;  //上次竖直方向宽度
  uint8       szkd_l;         uint8       szkd_r;       //本次竖直方向宽度
  uint8       j_left;         uint8       j_right;

  *flg_l=0;//上拐点存在标志位清零
  *flg_r=0;//同上
  
  //提取“上左”拐点
  I_last_l.j  = s_j_l;
  I_last_l.i  = f__edge_cz_cktdbqvi( img , s_j_l , s_i );
  szkd_last_l = s_i - I_last_l.i + 1 ;
  for( j_left=s_j_l+1 ; j_left<=(93+40) ; j_left+=2 )
  {
    I_l.j  = j_left;
    I_l.i  = f__edge_cz_cktdbqvi( img , j_left , s_i );
    szkd_l = s_i - I_l.i + 1;
    
    if( ((*flg_l)==0)&&((szkd_l-szkd_last_l)>2) )
    {
      *flg_l=1;
      
      (*gd_l).i = I_last_l.i;
      (*gd_l).j = I_last_l.j;
    }
    if( (*flg_l)==1 ) break;
    
    I_last_l=I_l;
    szkd_last_l=szkd_l;
    
//  zb_imgarr_t p;
//  p.i=s_i;
//  p.j=j_left;
//  liang_dian_lian_xian(img,123,p,I_l);
  }
  
  //提取“上右”拐点
  I_last_r.j  = s_j_r;
  I_last_r.i  = f__edge_cz_cktdbqvi( img , s_j_r , s_i );
  szkd_last_r = s_i - I_last_r.i + 1 ;
  for( j_right=s_j_r-1 ; j_right>=(94-40) ; j_right-=2 )
  {
    I_r.j  = j_right;
    I_r.i  = f__edge_cz_cktdbqvi( img , j_right , s_i );
    szkd_r = s_i - I_r.i + 1;
    
    if( ((*flg_r)==0)&&(szkd_r-szkd_last_r)>2 )
    {
      *flg_r=1;
      
      (*gd_r).i = I_last_r.i;
      (*gd_r).j = I_last_r.j;
    }
    if( (*flg_r)==1 ) break;
    
    I_last_r=I_r;
    szkd_last_r=szkd_r;
    
//    zb_imgarr_t p;
//    p.i=s_i;
//    p.j=j_right;
//    liang_dian_lian_xian(img,123,p,I_r);
  }
}

十字补线

/**********************************************************************************************
名    称:                         十字补线程序

功能描述: 
入口参数: 
出口参数: 

备    注: 集成了 入十字 十字中 出十字 三个阶段的补线程序
**********************************************************************************************/
uint8 flg_msycsz;//马上要出十字标志位(每当判断出十字时,先将此标志位清零再执行下面的十字补线程序)
void shizi_bxcx(uint8 img_bin[][IMG_W_USED])
{
  static uint8 msycsz_bx_start_i;
  
  if( flg_msycsz==0 )
  {
    uint8 xgd_flag_l;//下左拐点是否找到标志位
    uint8 xgd_flag_r;//下右拐点是否找到标志位
    zb_imgarr_t xgd_l;//下左拐点
    zb_imgarr_t xgd_r;//下右拐点
    
    //先提取“下左右拐点”
    f__guaidian_X(img_bin,&xgd_flag_l,&xgd_l,&xgd_flag_r,&xgd_r);
    
    uint8 sgd_flag_l;     //上左拐点是否找到标志位
    uint8 sgd_flag_r;     //上右拐点是否找到标志位
    zb_imgarr_t sgd_l;    //上左拐点
    zb_imgarr_t sgd_r;    //上右拐点
    uint8 f_sgd_s_j_l;    //找上拐点的左侧起始j值
    uint8 f_sgd_s_j_r;    //找上拐点的右侧起始j值
    uint8 f_sgd_start_i;  //查找找上左右拐点的起始i值
    
    f_sgd_s_j_l = xgd_l.j-20; //计算上述j值
    f_sgd_s_j_r = xgd_r.j+20; //同上
    if( xgd_l.i69 )//当上左右拐点 低到一定程度时
      {
        flg_msycsz=1;
        
        msycsz_bx_start_i=MIN(sgd_l.i,sgd_r.i)-5;
      }
    }
    
    //十字补线
    zb_imgarr_t zdd_l;//最底部left
    zb_imgarr_t zdd_r;//最底部right
    zdd_l.i=79;
    zdd_r.i=79;
    uint8 nomeaning_l;
    uint8 nomeaning_r;
    f__edge_sp_czj(img_bin[79],93,&nomeaning_l,&(zdd_l.j),&nomeaning_r,&(zdd_r.j)); 
    if(sgd_flag_l==1)
    {
      liang_dian_lian_xian(img_bin,0,xgd_l,sgd_l);//上拐点找到了 上下拐点直接连线 补全十字边界
    }
    else
    {
      xiang_shang_hua_yan_shen_xian(img_bin,0,zdd_l,xgd_l);//上拐点没找到 画延伸线 补全十字边界
    }
    if(sgd_flag_r==1)
    {
      liang_dian_lian_xian(img_bin,0,xgd_r,sgd_r);//上拐点找到了 上下拐点直接连线 补全十字边界
    }
    else
    {
      xiang_shang_hua_yan_shen_xian(img_bin,0,zdd_r,xgd_r);//上拐点没找到 画延伸线 补全十字边界
    }
    
    //补完十字边界线后 再执行直道弯道补线程序 补出中线
    zhidao_wandao_bxcx(img_bin,79,10);
    
    //在图像上画出这几个拐点
    if(sgd_flag_l==1) gd_hua_zfx(img_bin,200,sgd_l);
    if(sgd_flag_r==1) gd_hua_zfx(img_bin,200,sgd_r);
    if(xgd_flag_l==1) gd_hua_zfx(img_bin,100,xgd_l); 
    if(xgd_flag_r==1) gd_hua_zfx(img_bin,100,xgd_r);
  }
  else//flg_msycsz==1 马上要出十字了
  {
    zhidao_wandao_bxcx(img_bin,msycsz_bx_start_i,10);
  }

入环岛判断

根据同一行赛道宽度是否增加而判断是否进入环形
宽度增加→环形
此方法有条件限制(比如要排除遇到十字的情况),但可以做辅助判断。

void huanxing_ru_bxcx(uint8 img_bin[][IMG_W_USED])
{
  uint8 xgd_flag_l;//下左拐点是否找到标志位
  uint8 xgd_flag_r;//下右拐点是否找到标志位
  zb_imgarr_t xgd_l;//下左拐点
  zb_imgarr_t xgd_r;//下右拐点
  
  //提取环形下左右拐点
  f__guaidian_X(img_bin,&xgd_flag_l,&xgd_l,&xgd_flag_r,&xgd_r);
  
  zb_imgarr_t yxcb_r;//环形中心的圆形侧边 右
  
  uint8 i_tmp;
  uint8 i_tmp_last;
  uint8 szkd;
  uint8 szkd_last;
  
  i_tmp_last = f__edge_cz_cktdbqvi( img_bin , xgd_l.j , xgd_l.i );
  szkd_last =  xgd_l.i - i_tmp_last + 1;
 uint8 sfdz_flg=0;//宽度是否递增标志位
  for( uint8 j_tmp=(xgd_l.j+1) ; j_tmp<=187 ; j_tmp++ )
  {
    i_tmp = f__edge_cz_cktdbqvi( img_bin , j_tmp , xgd_l.i );
    szkd =  xgd_l.i - i_tmp + 1;
    
    if( (szkd-szkd_last)>0)
    {
      sfdz_flg=1;
    }
    else
    {
      sfdz_flg=0;
    }
    
    if( ((szkd-szkd_last)>4)||((sfdz_flg==1)&&(i_tmp==0)&&(j_tmp>75)) )
    {
      yxcb_r.i=i_tmp_last;
      yxcb_r.j=j_tmp-1;
      
      break;
    }
    
    i_tmp_last=i_tmp;
    szkd_last=szkd;
  }

补线思路:两点连线,
先找出两个拐点,然后根据斜率补线

SaiDao_type_m  pdsdlx(uint8 img_bin[][IMG_W_USED])
{
  
  SaiDao_type_m sdlx_return;    //定义返回的赛道类型
  
  zb_imgarr_t l_1_img,r_1_img;            //定义第一行,第二行,第三行左右跳变沿图像坐标
  zb_imgarr_t l_2_img,r_2_img;
  zb_imgarr_t l_3_img,r_3_img;
 
  

  
  zb_math_t l_1_math,r_1_math;            //定义数学坐标
  zb_math_t l_2_math,r_2_math;
  zb_math_t l_3_math,r_3_math;

  
  slope_t K_l_13,K_r_13;                        //定义左右斜率
  slope_t K_l_12,K_r_12;
  
  uint8 kuandu_last;                      //定义上一次最后一行宽度数据
  uint8 kuandu;                           //定义最后一行宽度数据
  
  static uint8 leixing_flag=0;                  //定义判断类型标志位
  static uint8 chuhuanxing_flag=0;              //定义出环形标志位
  static uint8 shizi_huanxing_flag=0;           //定义十字环形标志位
  

  
  f__edge_sp_czj_plus(img_bin[Hang_1],93,&f_l_1,&left_1,&f_r_1,&right_1);//水平扫第一行
  f__edge_sp_czj_plus(img_bin[Hang_2],93-30,&f_l_2,&left_2,&f_r_2,&right_2);//水平扫第二行
  f__edge_sp_czj_plus(img_bin[Hang_3],93-50,&f_l_3,&left_3,&f_r_3,&right_3);//水平扫第三行
  f__edge_sp_czj_plus(img_bin[Hang_end],93,&f_l_end,&left_end,&f_r_end,&right_end);//水平扫最后一行
  
  l_1_img.i=Hang_1;     //  左1图像坐标赋值            //给图像坐标赋值 
  l_1_img.j=left_1;
  r_1_img.i=Hang_1;     //  右1图像坐标赋值
  r_1_img.j=right_1;
  
  l_2_img.i=Hang_2;     //  左2图像坐标赋值
  l_2_img.j=left_2;
  r_2_img.i=Hang_2;     //  右2图像坐标赋值
  r_2_img.j=right_2;
  
  l_3_img.i=Hang_3;     //  左3图像坐标赋值
  l_3_img.j=left_3;
  r_3_img.i=Hang_3;     //  右3图像坐标赋值
  r_3_img.j=right_3;


  l_end_img.i=Hang_end;   //最后一行图像坐标赋值
  l_end_img.j=left_end;
  r_end_img.i=Hang_end;
  r_end_img.j=right_end;      
      
  l_1_math=covert_zb(l_1_img);      //第一行,第三行左右跳变沿坐标转换用于计算斜率
  r_1_math=covert_zb(r_1_img);
  l_3_math=covert_zb(l_3_img);
  r_3_math=covert_zb(r_3_img);
  
  l_2_math=covert_zb(l_2_img);      //第二行左右跳变沿坐标转换
  r_2_math=covert_zb(r_2_img);      

  K_l_13=calcu_slope(l_1_math,l_3_math);    //计算1_3左斜率
  K_r_13=calcu_slope(r_1_math,r_3_math);    //计算1_3右斜率
  
  K_l_12=calcu_slope(l_1_math,l_2_math);    //计算1_2左斜率  尚未使用
  K_r_12=calcu_slope(r_1_math,r_2_math);    //计算1_2右斜率
  
  
  gpio_init (PTD15,GPO,1);      //指示赛道类型的灯      D15为直道和弯道
  gpio_init (PTE26,GPO,1);      //                      E26为十字
  
  shizi_huanxing_flag=huanxing_shizi(img_bin,79,7);      //判断十字环形左右两边的点的个数

文件:freescale_9th》scr》app_image

十字判断

以每行点的总和来判断是否进入十字
(白块为1,黑块为0,每行规定点数之和可以反应本行黑白块的数量之比,若120个全为白点,则可判断进入十字)

/*************************************************************************
*  函数名称:Cross_judge
*  功能说明:判断有无十字
*  参数说明:无
*  函数返回:无
*  修改时间:2012-2-14    已测试
*************************************************************************/
void Cross_judge()
{
    Cross_flag = 0;
    for(int i=H+20;i>H-20;i--)
    {
        if(sum_OneRow(i)==0)
        {
            Cross_flag = 1;
            black_centre = 160;
            break;
        }
    }
}
//计算一行40个数的总和
int sum_OneRow(unsigned int hang)
{
    int sum=0;
    for(int i=0;i<40;i++)
        sum+=Image_fire[hang][i];
    return sum;
}
//计算一列240个数的总和
int sum_OneCol(unsigned int lie)
{
    int sum=0;
    for(int i=0;i<240;i++)
        sum+=Image_fire[i][lie];
    return sum;
}

巡线方法

找到起始点后,直接用一条斜率为2 的直线来寻找边界线(右边界线同理)
此种方法可以提高巡线的效率,但容易丢失边界点

   //寻左边黑线
    for(i = 200;i>=170;i=i-2)
    {
        //以斜率为2划线
        Leftline2=Leftline2+2; 
        Leftline1=Leftline1+2;
        //在 Leftline2 列上遇到黑色
        if(Image_fire2Image(i,Leftline2) == 1)
        {
            Leftrow_pre = i;
            Leftcol_pre = Leftline2;
            Leftblack = 1;
            break;
        } //在 Leftline1 列上遇到黑色
        else if(Image_fire2Image(i,Leftline1) == 1)
        {
            Leftrow_pre = i;
            Leftcol_pre = Leftline1;
            Leftblack = 1;
            break;
        } //都没遇到黑色,左边没寻到黑线
        else
        {
            Leftblack = 0;
        }
    }  

文件:motor

本代码对坐标轴进行处理
整体特点:针对不同路况使用不同速度,并有相应速度记录

环岛拐点判断

基本思路:判断一个点左右是否都是白块,以及列数限定

void ChangzhidaoRuHuan()
{
  int i;
LeftRoundInflectionPointRow=0;//记录拐点的行
LeftRoundInflectionPointCol=0;//记录拐点的列
LeftRoundInflectionPointFlag=0;
  for(i=40;i>18;i--)
  {
     if(i<55&&LeftEdge[i+2]!=0&&LeftEdge[i+1]!=0&&LeftEdge[i]!=0
                &&(LeftEdge[i-1]==0&&LeftEdge[i-2]==0)&&LeftEdge[i]>10&&LeftEdge[i]-LeftEdge[i+1]>=0&&
                  RightEdge[i-3]<79&&RightEdge[i-5]<79)
        {
         
          if(LeftEdge[i]>=0&&img[i-3][LeftEdge[i]]==255
                &&img[i-4][LeftEdge[i]]==255 )
          {
            //找到右边线有拐点
          LeftRoundInflectionPointRow=i;//记录拐点的行
          LeftRoundInflectionPointCol=LeftEdge[i];//记录拐点的列
          LeftRoundInflectionPointFlag=1;
            break;//退出for
          }
        }
  
}


}

文件:Freescale-master》app》LandzoCamera

寻找拐点

  /*查找左边沿开始,找到边沿后跳出循环*/
  for(temp0=centre_lastblack;temp0>5;temp0--)               //检测左侧边沿
  {    
    for(temp1=temp0; temp1>( temp0-LINEWITH );temp1--)      //寻找一点附近的几个点是否能构成下降沿
    {    
      if(temp1<=0) break;                                   //不满足实际条件跳出循环             
      
      temp_value1= point[temp0]-point[temp1];               //比较白点附近的几个值
      
      if(temp_value1>=LEFTLINEFAV)                          //判断是否满足要求
      {
        leftcount++;                                        //满足条件计数值加一
   //     testarry[temp0]=temp_value1;
      }
      else
      {
        leftcount=0;   
   //     testarry[temp0]=0;
      }           
    }    
    
    if(leftcount >= LINEWITH-1 )                        //判断是否满足边沿条件
    {
      leftedge = temp0 ;                                  //满足条件边沿找到
      leftflag=0;                                         //找到边沿,标志位置1 
      break;
    }
    else
    {
      leftcount=0;                                        //未找到清除计数  
      leftflag=1;                                         //标志位清除
      leftedge=5;                                         // 边沿赋值 
    }
     
    if(leftedge<5) leftedge = 5;   
  } 
  /*左边沿查找结束*/

你可能感兴趣的:(代码汇总)