智能车制作

标题: CCD算法 单方向跳变算法 解决平衡车角度影响数值问题(存在缺陷左右边线不能超过64) [打印本页]

作者: vireague    时间: 2015-3-27 07:32
标题: CCD算法 单方向跳变算法 解决平衡车角度影响数值问题(存在缺陷左右边线不能超过64)
/***************************************************************
名称:CCD相关函数
输入:
输出:
描述:
    :
****************************************************************/
#include "common.h"
#include "include.h"

/***************************************************************
名称:基本定义
输入:
输出:
描述:
    :
****************************************************************/
#define SOBEL_MIN 10                              //最小跳变沿距离
#define SOBEL_BIN_MIN 20                          //CCD最小处理跳变沿阈值
#define LENTH_WIDTH   20                          //双线丢线 判断
#define CCD_recovery 0.8                          //角度校正 CCD 数据
#define WAY_value_change_MAX 20                   //允许最大坐标变化值
#define LINE_width_MIN       40                   //允许的最小路宽
#define WAY_anxious          40                   //切线比例 越大跑法内切越大

uint8 CCD_BUFF[TSL1401_SIZE];                    //0 原图   1      2 二值化图  
uint8 tempArray[TSL1401_SIZE];                   //SOBEL  导数图
uint8 tempArray_bin[TSL1401_SIZE];               //SOBEL  导数二值图
uint8 tempArray_creat[TSL1401_SIZE];              //边线图

int16 WAY_value =   0;                            //方向偏移   - 左偏   + 右偏
int16 WAY_value_sorce = 0;                        //CCD无内切原始数值
int16 WAY_value_last =   0;                            //方向偏移   - 左偏   + 右偏

uint8 thresholding = 0;                           //导数阈值 (程序计算)

uint8 LINE_width = 0;
char LINE_number = 0;                             //线数
char CCD_exposure_time = 10;                      //曝光时间

int16 LINE_1[1];                                  //线数为一时保存的坐标
int16 LINE_2[2];
int16 LINE_3[3];
int16 LINE_4[4];

int16 LINE_1_last[1];                                  //线数为一时保存的坐标
int16 LINE_2_last[2];
int16 LINE_3_last[3];
int16 LINE_4_last[4];

char CROSS_static = 0;                            //  1直线 2弯道 3人字路口 6右直角 7左直角 8十字路口
uint8 right_angle_state = 0;

/***************************************************************
名称:函数声明
输入:
输出:
描述:
    :
****************************************************************/
void CCD_sobel(void);            //求导声明
void CCD_line_count(void);       //线数计算
void CCD_measure(void);

/***************************************************************
名称:CCD初始化
输入:
输出:
描述:
    :
****************************************************************/
void CCD_init(void)
{
    tsl1401_set_addrs(TSL1401_MAX,(uint8 *)&CCD_BUFF[0]);
    tsl1401_init();                               //初始化 线性CCD ,配置 中断时间为 time  
}

/***************************************************************
名称:CCD采集与处理
输入:
输出:
描述:
    :
****************************************************************/
void CCD_hand(void)
{
    tsl1401_get_img();                             //采集 线性CCD 图像
    CCD_sobel();  //导数计算
    CCD_line_count();//线数计算
    CCD_measure();
}


/***************************************************************
名称:导数计算
输入:
输出:
描述:
    :
****************************************************************/
void CCD_sobel()
{

  int8 gradX;

  uint8 thresholding_deal = 0;

  CCD_BUFF[0] = CCD_BUFF[1];
  CCD_BUFF[127] = CCD_BUFF[126];

  for (int j = 1; j < 127; j++)
  {

      gradX = CCD_BUFF[j + 1] - CCD_BUFF[j - 1];

      tempArray[j] = ABS(gradX);                 //CCD 导数图 tempArray

      if(tempArray[j] > thresholding_deal)      
      {
        thresholding_deal = tempArray[j];
      }
  }



  thresholding = thresholding_deal;                 //保存导数最大值

  if(thresholding < SOBEL_BIN_MIN)
  {
    thresholding = SOBEL_BIN_MIN;
  }

  for (int i = 0; i < 128; i++)
  {
      if (tempArray[i] > (uint8)(thresholding*0.6) )
      {
          tempArray_bin[i] = 120;                             //bin 存储导数阈值
      }
      else
      {
          tempArray_bin[i] = 0;
      }
  }


}

/***************************************************************
名称:
输入:
输出:
描述:
    :
****************************************************************/
void CCD_line_count()
{
  int16 LINE_all[10];

  char temp;
  char line_num = 1;  

  temp = (char)(ABS(ANGLE_final) * CCD_recovery);    //计算还原数据
  LINE_all[0] = -SOBEL_MIN;

  for(int i = 0; i < 128; i++)
  {
    if(tempArray_bin[i] == 120)
    {   

      if(i - LINE_all[line_num - 1] >= SOBEL_MIN)
      {
        LINE_all[line_num] = i;
        line_num++;
      }
      else
      {
        LINE_all[line_num - 1] = (int16) (    ( i + LINE_all[line_num - 1])   /2 );
      }
    }
    else
    {
      ;
    }
  }

  LINE_number = line_num - 1;                          //LINE_number为图中的线数

  for(int i = 0; i < 128; i++)
  {
    tempArray_creat[i] = 0;
  }

  for(int i = LINE_number; i > 0; i--)
  {
    tempArray_creat[LINE_all[i] ] = 255;                           //CRE 为生成线后的图  没有使用 仅是看
  }

  switch(LINE_number)
  {

    char i;

    case 0: break;

    case 1:
      for(i = 0; i < 1; i++)
        {
            LINE_1[i] = (int16)(  (LINE_all[i+1] - 64) -  temp*(LINE_all[i+1] - 64)/64);//temp * (60 - 行数) / 60  *  (LINE_all[i+1] - 40)/40)  
        }
      break;

    case 2:

      for(i = 0; i < 2; i++)
        {
            LINE_2[i] = (int16)(  (LINE_all[i+1] - 64) -  temp*(LINE_all[i+1] - 64)/64);
        }


      break;

    case 3:

      for(i = 0; i < 3; i++)
        {
            LINE_3[i] = (int16)(  (LINE_all[i+1] - 64) -  temp*(LINE_all[i+1] - 64)/64);
        }
      break;

    case 4:

      for(i = 0; i < 4; i++)
        {
            LINE_4[i] = (int16)(  (LINE_all[i+1] - 64) -  temp*(LINE_all[i+1] - 64)/64);
        }
      break;

    default: break;
  }
}

/***************************************************************
名称:
输入:
输出:
描述:
    :
****************************************************************/
void CCD_measure(void)
{
  switch(LINE_number)
  {

/*********************************************
  *名称:0线
  ********************************************/   
  case 0:
    {
      WAY_value = 0;
    }break;

/*********************************************
  *名称:1线
  ********************************************/      
  case 1:
    {
//      if(right_angle_state == 1)
//      {
//        
//        right_angle_state = 0;
//        WAY_value = 90;
//      }
//      else
//      {
        /*********************************************
        *名称:位置猜测位置
        ********************************************/   
          if(LINE_1[0] < 0)
          {
            LINE_2[0] = -32;
            LINE_2[1] = +32;
            WAY_value = LINE_1[0] + LINE_width/2;
          }
          else
          {
            LINE_2[1] = 32;
            LINE_2[0] = -32;
            WAY_value = LINE_1[0] - LINE_width/2;
          }
//      }

    /*********************************************
    *名称:变化猜测位置
    ********************************************/   
//      if(ABS(LINE_1[0] - LINE_2[0]) < LENTH_WIDTH)
//      {
//        LINE_2[0] = LINE_1[0];
//        LINE_2[1] = LINE_1[0] + LINE_width;
//        WAY_value = LINE_1[0] + LINE_width/2;
//      }
//      else
//      {
//        if(ABS(LINE_1[0] - LINE_2[1]) < LENTH_WIDTH)
//        {
//          LINE_2[1] = LINE_1[0];
//          LINE_2[0] = LINE_1[0] - LINE_width;
//          WAY_value = LINE_1[0] - LINE_width/2;
//        }
//      }

    }break;

/*********************************************
  *名称:2线
  ********************************************/                  
  case 2:
    {
       if((LINE_2[1] - LINE_2[0]) < LINE_width_MIN)
       {
          if(ABS(WAY_value_sorce - LINE_2[0]) >  ABS(WAY_value_sorce - LINE_2[1]) )
          {
             WAY_value = LINE_2[1];
          }
          else
          {
            WAY_value = LINE_2[0];
          }
       }
       else
       {
          if(LINE_2[0] > 0 || LINE_2[1] < 0)
          {
            LINE_2[0] = LINE_2_last[0];
            LINE_2[1] = LINE_2_last[1];
          }

            LINE_2_last[0] = LINE_2[0];
            LINE_2_last[1] = LINE_2[1];

           if((LINE_2[1] - LINE_2[0]) > LINE_width_MIN)
           {
             LINE_width = ABS(LINE_2[1] - LINE_2[0]);
           }

           WAY_value = (LINE_2[0] + LINE_2[1])/2;

           CROSS_static = 0;
       }


    }break;


/*********************************************
  *名称:3线
  ********************************************/  
  case 3:
    {
       WAY_value = (LINE_3[0] + LINE_3[2])/2;
    }break;

  /*********************************************
  *名称:4线
  ********************************************/  
  case 4:
    {
            led(BEEP,LED_OFF);                        //蜂鸣器响


      if(ABS(LINE_4[0] - LINE_4[1]) > ABS(LINE_4[2] - LINE_4[3]) )
      {
        WAY_value = (LINE_4[0] + LINE_4[1])/2;
      }
      else
      {
        WAY_value = (LINE_4[2] + LINE_4[3])/2;
      }

            led(BEEP,LED_ON);                        //蜂鸣器响
    }break;

    default: break;   
  }

  /*********************************************
  *名称:切内道补偿数值
  ********************************************/  
   WAY_value_sorce = WAY_value;
   WAY_value = (int)(WAY_value + (float)(WAY_value)/64*WAY_anxious);


}






/***************************************************************
名称:CCD相关函数
输入:
输出:
描述:
    :
****************************************************************/
#ifndef _CCD_H_
#define _CCD_H_

extern uint8 CCD_BUFF[TSL1401_SIZE];  //图像存储区
extern uint8 tempArray[TSL1401_SIZE];
extern uint8 tempArray_bin[TSL1401_SIZE];               //SOBEL  导数二值图
extern uint8 tempArray_creat[TSL1401_SIZE];

extern int16 WAY_value;                              //方向偏移   - 左偏   + 右偏

extern uint8 thresholding;

extern char LINE_number;
extern char CROSS_static;                            //道路信息
extern uint8 right_angle_state;                      //检测直角状态

extern char CCD_exposure_time;



extern int16 LINE_1[1];
extern int16 LINE_2[2];
extern int16 LINE_3[3];
extern int16 LINE_4[4];

extern void CCD_init(void);                          //CCD 初始化函数
extern void CCD_hand(void);                          //CCD 处理函数

#endif









作者: vireague    时间: 2015-3-27 07:33
测试程序 优化很差吧
作者: 泰庆电子    时间: 2015-3-27 08:10
= =。
作者: zhou1994    时间: 2015-3-27 08:28
导数求了绝对值,就会失去原本的位置信息
作者: vireague    时间: 2015-3-27 15:11
zhou1994 发表于 2015-3-27 08:28
导数求了绝对值,就会失去原本的位置信息

恩 谢谢指导

作者: xianyu1993    时间: 2015-5-14 19:16
zhou1994 发表于 2015-3-27 08:28
导数求了绝对值,就会失去原本的位置信息

大神 差分法有没有办法解决窜道问题呀

作者: zhou1994    时间: 2015-5-14 20:32
xianyu1993 发表于 2015-5-14 19:16
大神 差分法有没有办法解决窜道问题呀

差分和窜道没有直接关系

作者: xianyu1993    时间: 2015-5-14 21:57
zhou1994 发表于 2015-5-14 20:32
差分和窜道没有直接关系

这个是的,但我差分后从左往右巡线后如果采集到的图像窜道,大部分能判断出那根线是错误信息,可是有的情况判断不出来。能不能留个qq 请教一下


作者: zhou1994    时间: 2015-5-14 22:00
xianyu1993 发表于 2015-5-14 21:57
这个是的,但我差分后从左往右巡线后如果采集到的图像窜道,大部分能判断出那根线是错误信息,可是有的情 ...

你留。我加你

作者: xianyu1993    时间: 2015-5-14 22:05
zhou1994 发表于 2015-5-14 22:00
你留。我加你

849029156





欢迎光临 智能车制作 (http://dns.znczz.com/) Powered by Discuz! X3.2