智能车制作

 找回密码
 注册

扫一扫,访问微社区

查看: 2263|回复: 9
打印 上一主题 下一主题

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

[复制链接]

14

主题

45

帖子

0

精华

金牌会员

Rank: 6Rank: 6

积分
1056
威望
497
贡献
285
兑换币
278
注册时间
2014-7-23
在线时间
137 小时
毕业学校
辽宁科技大学
跳转到指定楼层
1#
发表于 2015-3-27 07:32:18 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
/***************************************************************
名称: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








评分

1

查看全部评分

回复

使用道具 举报

14

主题

45

帖子

0

精华

金牌会员

Rank: 6Rank: 6

积分
1056
威望
497
贡献
285
兑换币
278
注册时间
2014-7-23
在线时间
137 小时
毕业学校
辽宁科技大学
2#
 楼主| 发表于 2015-3-27 07:33:49 | 只看该作者
测试程序 优化很差吧
回复 支持 反对

使用道具 举报

10

主题

1514

帖子

0

精华

金牌会员

智能车,首选泰庆

Rank: 6Rank: 6

积分
1715

活跃会员奖章在线王奖章

QQ
威望
427
贡献
400
兑换币
497
注册时间
2014-11-4
在线时间
444 小时
3#
发表于 2015-3-27 08:10:42 | 只看该作者
= =。
回复 支持 反对

使用道具 举报

32

主题

3009

帖子

0

精华

杰出人士

学期班的来卖萌?

Rank: 12Rank: 12Rank: 12

积分
14832

在线王奖章活跃会员奖章优秀会员奖章论坛元老奖章资源大师奖章

威望
5952
贡献
3172
兑换币
4257
注册时间
2013-11-26
在线时间
2854 小时
4#
发表于 2015-3-27 08:28:07 | 只看该作者
导数求了绝对值,就会失去原本的位置信息
回复 支持 反对

使用道具 举报

14

主题

45

帖子

0

精华

金牌会员

Rank: 6Rank: 6

积分
1056
威望
497
贡献
285
兑换币
278
注册时间
2014-7-23
在线时间
137 小时
毕业学校
辽宁科技大学
5#
 楼主| 发表于 2015-3-27 15:11:08 | 只看该作者
zhou1994 发表于 2015-3-27 08:28
导数求了绝对值,就会失去原本的位置信息

恩 谢谢指导
回复 支持 反对

使用道具 举报

11

主题

127

帖子

0

精华

金牌会员

Rank: 6Rank: 6

积分
2181
威望
899
贡献
502
兑换币
567
注册时间
2014-10-14
在线时间
390 小时
毕业学校
西华
6#
发表于 2015-5-14 19:16:02 | 只看该作者
zhou1994 发表于 2015-3-27 08:28
导数求了绝对值,就会失去原本的位置信息

大神 差分法有没有办法解决窜道问题呀
回复 支持 反对

使用道具 举报

32

主题

3009

帖子

0

精华

杰出人士

学期班的来卖萌?

Rank: 12Rank: 12Rank: 12

积分
14832

在线王奖章活跃会员奖章优秀会员奖章论坛元老奖章资源大师奖章

威望
5952
贡献
3172
兑换币
4257
注册时间
2013-11-26
在线时间
2854 小时
7#
发表于 2015-5-14 20:32:23 | 只看该作者
xianyu1993 发表于 2015-5-14 19:16
大神 差分法有没有办法解决窜道问题呀

差分和窜道没有直接关系
回复 支持 反对

使用道具 举报

11

主题

127

帖子

0

精华

金牌会员

Rank: 6Rank: 6

积分
2181
威望
899
贡献
502
兑换币
567
注册时间
2014-10-14
在线时间
390 小时
毕业学校
西华
8#
发表于 2015-5-14 21:57:17 | 只看该作者
zhou1994 发表于 2015-5-14 20:32
差分和窜道没有直接关系

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

回复 支持 反对

使用道具 举报

32

主题

3009

帖子

0

精华

杰出人士

学期班的来卖萌?

Rank: 12Rank: 12Rank: 12

积分
14832

在线王奖章活跃会员奖章优秀会员奖章论坛元老奖章资源大师奖章

威望
5952
贡献
3172
兑换币
4257
注册时间
2013-11-26
在线时间
2854 小时
9#
发表于 2015-5-14 22:00:45 | 只看该作者
xianyu1993 发表于 2015-5-14 21:57
这个是的,但我差分后从左往右巡线后如果采集到的图像窜道,大部分能判断出那根线是错误信息,可是有的情 ...

你留。我加你
回复 支持 反对

使用道具 举报

11

主题

127

帖子

0

精华

金牌会员

Rank: 6Rank: 6

积分
2181
威望
899
贡献
502
兑换币
567
注册时间
2014-10-14
在线时间
390 小时
毕业学校
西华
10#
发表于 2015-5-14 22:05:05 | 只看该作者

849029156
回复 支持 反对

使用道具 举报

您需要登录后才可以回帖 登录 | 注册

本版积分规则

关于我们|联系我们|小黑屋|智能车制作 ( 黑ICP备2022002344号

GMT+8, 2025-2-23 07:44 , Processed in 0.102874 second(s), 31 queries , Gzip On.

Powered by Discuz! X3.2

© 2001-2013 Comsenz Inc.

快速回复 返回顶部 返回列表