fzjz

原创:CCD摄像头的采集电路、动态阈值图像处理算法

0
阅读(8677)

今天刚考完操作系统,我把基于S12X的CCD摄像头的电路和原创代码上传,记得顶啊

一、先上电路图:

1、12V升压电路

2、视频分离电路:

3、片外AD电路:

先介绍下上述电路的原理:

1、采用的是CCD摄像头,所以需要12V的升压电路,采用的升压模块是LM2731。

2、视频信号输出后,经过LM1881N分离出行和场信号,这两个信号用于S12X的中断,采集视频信号。

3、片外AD TLC5510,输出8位的信号值,直接连接S12X的PA口就可以了。

二、代码

原创:可调节动态阈值搜索的区域,以及对比度

采用动态阈值对图像进行二值化处理,得到二值化的图像数组后,下面的赛道识别处理方式和智能车的运动控制就看你自己了。

#define   IMAGE_ROW  40                          //本系统采集40行和100列图像

#define   IMAGE_COLUMN  100


unsined char photo[IMAGE_ROW ][IMAGE_COLUMN]     // 本数组用于存放二值化后的图像

 //此算法在不丢失黑线的状况下有效,至少保证哪怕是一行中的一侧有黑线
 
 //此算法可调选窗口阈值的范围,以及图像的对比度
void   Dynamic_01(unsigned char start,unsigned char end,unsigned char contrast)
{          
      unsigned  char i,j;
      unsigned  char a,b,c;
      unsigned  char num,temp,max,min;
      unsigned  char max_temp,min_temp;
      unsigned  char Max_num[],Min_num[];
      unsigned  char hang_end,hang_start;
      unsigned  char total_max,total_min;
      unsigned  char contr;
     
      total_max=0;
      total_min=0;
     
      contr=contrst;
     
      hang_end=end;
      hang_start=start;
     
      for(i=hang_start;i<hang_end;i++)                //取视采集到的图像的某几行(连续行)
      {
        for(j=0;j<IMAGE_COLUMN;j=j+3)                 //对相邻的三个点取平均,找出最小的和最大的,构成窗口阈值
          {
              num=j;
              a=Buffer[15][num];
              num=num+1;
              b=Buffer[15][num];
              num=num+2;
              c=Buffer[15][num];
              min_temp=(a+b+c)/3;
              if(min>max)
              {
                  temp=min_temp;
                  min_temp=max_temp;
                  max_temp=temp;
              }               
          }
        Max_num[i]=max_temp;
        Min_num[i]=min_temp;         
      }
      for(i=hang_start;i<hang_end;i++)                
      {
         total_max=total_max+Max_num[i];
         total_min=total_min+Min_num[i];
      }
      max=total_max/(hang_end-hang_start)*(1-contr/100)       // white  对比度可调
      min=total_min/(hang_end-hang_start)*(1+contr/100)       // black
     
      //通过以上的运算,我们成功获得了窗口阈值,接下来我们便可以进行二值化处理
     
      for(i=0;i<IMAGE_ROW;i++)           //行
       {
          for(j=0; j<IMAGE_COLUMN; j++)   //列
           {
              if(Buffer[i][j]>=max)  photo[i][j]=1;
              if(Buffer[i][j]<=min)  photo[i][j]=0;
           }
         
       }
 
 
 
以下是摘抄别人的行场中断的代码
很简单的中断处理方法
不作解释
自己研究和改进
 
 
#pragma CODE_SEG __NEAR_SEG NON_BANKED
#pragma TRAP_PROC
void  Port1_interrupt(void)
 {    
     //测试行场信号是否接对
      if(chang_count++>=50)
      {
       PORTB_PB0 = ~PORTB_PB0;
       chang_count =0;
      }
     
      TFLG1_C1F=1;  // 清场中断标志
                
      heixian =0; //从置 行里面的信息 
      
      jiange_m=0; //行数清零
      
     //交换图像采集和处理缓存
      puca_BufferSample=puca_BufferProcess; 
      puca_BufferProcess=puca_BufferTemp;
      puca_BufferTemp=puca_BufferSample;
      
     
       TFLG1_C0F=1; // 清行中断标志 --注意这个是必须的。切记!!!!
       TIE_C0I =1;// 行中断       

     
/*
*****************************行中断*********************************************************************
*
************************* *******************************************************************************
*/
unsigned char hang_i=0; //行中断里面用的记录每行点的个数的变量
#define JIANGE_HANG 3  //这个数据必须大于3      当然也不能太大
void delay_hang(unsigned char tt) {
  while(tt-->0) {
 
   asm{
   nop;
   }
  }
}
unsigned char *H_puTemp= NULL;
 

#pragma CODE_SEG __NEAR_SEG NON_BANKED
#pragma TRAP_PROC
 void   Port0_interrupt(void)
{
   TFLG1_C0F=1; // 清中断标志
   if(jiange_m>JIANGE_HANG)      //if JIANGE_HANG ==3 每隔5行采集一次。  if 4 每隔6行
   {
       jiange_m = 0;
        
       //----------------ver------ 2.0  ---------------核心代码--------------------------------        
       if(heixian<IMAGE_ROW - IMAGE_ROW_DIS)
        {
             delay_hang(20);                                //延时来过滤行消隐区
            
             H_puTemp =puca_BufferSample+heixian*IMAGE_COLUMN;
            
             for(hang_i=0;hang_i<IMAGE_COLUMN;hang_i++)    //一共100个点,计满就算是完成一行的采集了
             {
              
                 *(H_puTemp+hang_i)=PORTA;
             }
              
             heixian ++;  //记录黑线的数目
                
             if(heixian ==(IMAGE_ROW - IMAGE_ROW_DIS))     //一共采集33行图像
             {
              g_car_show_yn = 1;                           //可以显示,可以处理这场数据了
             }
                           
        }     
        }
        
   jiange_m++; 
   TFLG1_C0F=1; // 清中断标志     
}  //end inter