找回密碼
 立即注冊(cè)

QQ登錄

只需一步,快速開(kāi)始

搜索
查看: 6248|回復(fù): 1
打印 上一主題 下一主題
收起左側(cè)

飛思卡爾智能車(chē)國(guó)賽CCD攝像頭組源程序

[復(fù)制鏈接]
跳轉(zhuǎn)到指定樓層
樓主
ID:287405 發(fā)表于 2018-3-4 12:58 | 只看該作者 回帖獎(jiǎng)勵(lì) |倒序?yàn)g覽 |閱讀模式
飛思卡爾國(guó)賽攝像頭組程序

單片機(jī)源程序如下:
  1. #include "include.h"
  2. #include "calculation.h"
  3. #include"VisualScope.h"
  4. #include "CCD.h"
  5. #include "LQ12864.h"
  6. s16 INT_COUNT=100;          //LPT 產(chǎn)生中斷的計(jì)數(shù)次數(shù)
  7. extern u32 LPT_INT_count;
  8. s16 count;
  9. #define duoji_center 2400//*舵機(jī)中值,根據(jù)自己的小車(chē)自行修改
  10. /*  接口:PWM:PTC1,PTC2,PTC3,PTC4
  11.           舵機(jī):PTA8
  12.          攝像頭:行中斷:PTD13,場(chǎng)中斷:PTC8,PCLK:PTD12,數(shù)據(jù)端:PTD0~PTD7
  13. 帶有//*的是需要修改的參數(shù)  關(guān)于下面的P、I、D最好先清零,即SpeedKP=0,SpeedKI=0,TurnP=0,TurnD=0*/
  14. //PID參數(shù)
  15. float TurnP=4.4,TurnD=0.6;//*轉(zhuǎn)向PD
  16. float SpeedKP =6;//*速度P  過(guò)大,車(chē)輪旋轉(zhuǎn)一前轉(zhuǎn)一后轉(zhuǎn),表現(xiàn)為走走停停
  17. float SpeedKI =1;//*速度I
  18. float g_Speedgoal=500;//*目標(biāo)速度 即編碼器的目標(biāo)脈沖值
  19. //時(shí)間標(biāo)志位
  20. extern u8 TIME1flag_100ms,flag_1ms ;
  21. extern u8 TIME1flag_1s   ;  //PT1口1s定時(shí)標(biāo)志位
  22. int start_flag=0,stop_jiasu=0;//開(kāi)機(jī)靜止跑道2秒標(biāo)志
  23. s32 ATimeCount=0;//100ms進(jìn)入pid標(biāo)志
  24. s32 TimeCount ;//1ms中斷標(biāo)志
  25. //速度變量
  26. s16 g_nLeftMotorPulse,g_nRightMotorPulse,g_nLeftMotorPulseSigma,g_nRightMotorPulseSigma,lm,rm;
  27. extern s32 LeftMotorOut ,RinghtMotorOut ;
  28. float g_SpeedControlOutNew,g_SpeedControlOutOld ;
  29. s16 SpeedPeriodCount=0 ;
  30. s32 SpeedPWM = 0 ;
  31. s32 LastSpeedPWM = 0 ;
  32. s32 MotorSpeedPWM,MotorTurnPWM ;
  33. s32 PWMout ;
  34. s16 zhidao=1,wandao=0;
  35. //CCD變量
  36. extern s32  g_SpeedControlIntegral;
  37. s16 TurnPeriodCount=0 ;
  38. s16 TurnPWMOUT=0 ;
  39. s16 LastTurnPWMOUT=0;
  40. int sudu_xianshi=0;
  41. void run();
  42. void main()
  43. {
  44.    DisableInterrupts; //禁止總中斷
  45.    uart_init (UART0,9600);//初始化UART0,串口頻率 9600
  46.    FTM2_QUAD_Iint();//一路正交解碼 A相---PTA10 B相---PTA11
  47.    gpio_init (PORTA , 17, GPO,HIGH); //程序運(yùn)行燈
  48.   // oled_init();
  49.    CCD_init ();  //攝像頭初始化
  50.    pit_init_ms(PIT0, 1);  //初始化PIT0,定時(shí)時(shí)間為: 1ms
  51.    pit_init_ms(PIT1, 100);//初始化PIT1,定時(shí)時(shí)間為: 100ms
  52.    set_irq_priority (90,3);//行中斷
  53.    set_irq_priority (89,2);//場(chǎng)中斷
  54.    set_irq_priority (84,1);//PIT0中斷 優(yōu)先級(jí)最高
  55.    FTM_init() ; //FTM初始化
  56.    lptmr_counter_init(LPT0_ALT2,INT_COUNT,2,LPT_Rising);//PTC5腳 脈沖累加計(jì)數(shù)器
  57.    EnableInterrupts;//開(kāi)總中斷  
  58.    uart_irq_EN(UART0);//開(kāi)串口0中斷
  59.    while(1)
  60.     {
  61.      if(flag_1ms==1)//運(yùn)行run函數(shù)
  62.      {
  63.        flag_1ms=0;
  64.        run();
  65.      }
  66.    // display_suducaiji();//速度顯示函數(shù)
  67.   }
  68. }
  69. void run()//在isr.c中的1ms中斷中調(diào)用  PIT0_IRQHandler
  70. {   
  71.   TimeCount++ ;
  72.   SpeedPeriodCount++;
  73.   TurnPeriodCount++;
  74.   MotorTurnPWM  = TurnPWMOut(TurnPWMOUT,LastTurnPWMOUT,TurnPeriodCount) ;
  75.   MotorSpeedPWM = SpeedPWMOut(g_SpeedControlOutNew ,g_SpeedControlOutOld,SpeedPeriodCount);  
  76.   if(TimeCount>=5)//讀速度  5us
  77.   {
  78.     TimeCount=0;
  79.     GetMotorPulse();//正交解碼讀取其中一路速度
  80.   }  
  81.   else if(TimeCount == 1)//為空
  82.   {     
  83.     PWMout=MotorSpeedOut(MotorSpeedPWM);//電機(jī)輸出
  84.   }
  85.    else if(TimeCount == 2)//速度控制
  86.    {
  87.      ATimeCount ++ ;
  88.      if(ATimeCount >= 20)
  89.      {
  90.        ATimeCount=0;
  91.        sudu_xianshi=1;//采集完速度的標(biāo)志,用于向上位機(jī)發(fā)送速度
  92.        count =get_counter_value(); //讀取LPTMR0_CNR之前需要先對(duì)這個(gè)寄存器賦值!��!
  93.        lptmr_counter_clean(); //清空脈沖計(jì)數(shù)器計(jì)算值(馬上清空,這樣才能保證計(jì)數(shù)值準(zhǔn)確)
  94.        g_nLeftMotorPulseSigma=LPT_INT_count*INT_COUNT+count;//每LPT_INT_count個(gè)脈沖產(chǎn)生一次中斷,LPT_INT_count為中斷的次數(shù),
  95.        if(PWMout>0)//由于這一路沒(méi)有使用正交解碼,因此速度脈沖方向由電機(jī)方向判定
  96.          g_nLeftMotorPulseSigma=-g_nLeftMotorPulseSigma;
  97.        LPT_INT_count=0;//對(duì)中斷次數(shù)清零 //count為不足產(chǎn)生一次中斷的值
  98.        lm=g_nLeftMotorPulseSigma;//獲得左、右輪速度用于上位機(jī)顯示
  99.        rm=g_nRightMotorPulseSigma;
  100.        SpeedPID() ; //速度PI調(diào)節(jié)
  101.        SpeedPeriodCount = 0 ;
  102.      }
  103.    }
  104.   else if(TimeCount == 3)//方向控制
  105.   {
  106.      FTM_CnV_REG(FTMx[FTM1], CH0) =MotorTurnPWM+duoji_center;//方向控制  要加上舵機(jī)中值
  107.      LastTurnPWMOUT = TurnPWMOUT ;
  108.      TurnPeriodCount = 0 ;
  109.   }  
  110.   else if(TimeCount == 4)
  111.   {
  112.     if(TIME1flag_1s == 1)//程序運(yùn)行燈
  113.     {
  114.       TIME1flag_1s=0;
  115.       PTA17_OUT=~PTA17_OUT;
  116.     }
  117.   }
  118. }

復(fù)制代碼
  1. #include "common.h"
  2. #include "include.h"
  3. #include "calculation.h"
  4. #include "CCD.h"
  5. #include"VisualScope.h"
  6. #include "LQ12864.h"
  7. extern s16 zhidao,wandao;  
  8. float S_xy=0,S_xx=0,x=0,y=0,S_y=0,S_x=0;//算斜率的
  9. int slope=0;
  10. int youbian_ysy=0,jinduan_ybx=0,zuobian_ysy=0,jinduan_zbx=0,ztuichu=0;//擬合中線(xiàn)
  11. int yici_zuo=0,yici_you=0;
  12. int zuoqishi=0,youqishi=0,zzxqishi=0,yzxqishi=0,zxqishi=0,zstop=0,ystop=0;
  13. int yx_left=0,yx_right=0;//根據(jù)近端中線(xiàn)方向判別斷行處應(yīng)該具有的方向
  14. int youbian_qi=0,zuobian_qi=0;//判斷是否為彎道
  15. int zuobian_youxiao=0,zuobian_stop=0,youwan_youxiao=0,youwan_flag=0,youwan_center=0,youwan_centerstop=0;
  16. int youbian_youxiao=0,youbian_stop=0,zuowan_youxiao=0,zuowan_flag=0,zuowan_center=0,zuowan_centerstop=0;
  17. int value=0,wandao_youxiao=0,zuowan=0,youwan=0;
  18. int zhangai_qishi=0,zhangai_jieshu=0;//障礙起始  可惜沒(méi)用上
  19. int start_y=0,yous=0,stop_z=0,start_z=0,zuos=0,stop_y=0,zuozs=0,youzs=0,youss=0,zuoss=0;//十字 有點(diǎn)復(fù)雜
  20. int left_sz=0,right_sz=0,left_xsz=0,right_xsz=0;
  21. int zshizi=0,zxshizi=0,yxshizi=0;
  22. int xieshizi_zuoflag=0,youxiaozuoxieshizi=0,xiexs=0,xieys=0;//斜十字標(biāo)志
  23. int xieshizi_youflag=0,youxiaoyouxieshizi=0,xiees=0,xiefs=0;
  24. int left=0,right=0,leftzuo=0,rightzuo=0,leftyou=0,rightyou=0,rightsz=0,leftsz=0;
  25. s16 centerxunizuo[50],centerxuniyou[50];//虛擬中心 判別用
  26. s16 centerszyupan[50],centerzuoyupan[50],centeryouyupan[50];
  27. int youxiaoyoubianyan=0,lastyoubianyan=0;
  28. int youxiaozuo=0,youxiaoyoubian=0;
  29. int youxiaoyou=0,youxiaozuobian=0;
  30. int as,bs,cs,ds;
  31. int is,js,jz,shizi_flag=0,youxiao_shizi=0,jieshu_shizi=0,qishi_shizi=0;
  32. int xs=0,ys=0,es=0,fs=0;
  33. int szis=0;
  34. int jdt=0,id,jd;
  35. s16 direction,TurnPosition,TurnMidPosition=78;//靠左減小值
  36. float lasterror ;
  37. float sum=0;
  38. int zhengshizi=0;
  39. int szq=0,szs=0;
  40. int m1=0,m2=0,m3=0,m4=0,m5=0,m6=0;
  41. int n1=0,n2=0,n3=0,n4=0,n5=0,n6=0;
  42. extern float TurnP,TurnD;
  43. extern s16 g_nDirectionControlFlag ;
  44. s16 yuzhizhi;//閾
  45. extern s16 TurnPWMOUT ,LastTurnPWMOUT;//轉(zhuǎn)向PWM
  46. u8 ImageBuf[DATALINE][lie];
  47. u8 shizibx[DATACOUNT];
  48. u8 yuzhipd[50];
  49. u8 ImageBuf2[DATALINE][DATACOUNT];
  50. s16 blackright[DATALINE];
  51. s16 blackleft[DATALINE];
  52. s16 center[DATALINE];
  53. s16 valuerownum=0,value_flag=0,value_yici=0;
  54. s8 badframe=0;
  55. float CenterEx[3]={0,0,0};
  56. int CenterEq=0;
  57. //加權(quán)平均參數(shù),一般是遠(yuǎn)大近小,間隔均勻,根據(jù)小車(chē)情況調(diào)
  58. float CorrectEx[50]={2.6,2.6,2.6,2.6,2.6,2.56,2.52,2.48,2.44,2.4,      
  59.                      2.36,2.32,2.3,2.26,2.22,2.18,2.14,2.1,2.06,2.02,
  60.                      1.98,1.94,1.9,1.86,1.82,1.78,1.74,1.7,1.66,1.62,
  61.                      1.58,1.54,1.5,1.47,1.42,1.38,1.34,1.3,1.26,1.22,
  62.                      1.18,1.14,1.10,1.07,1.03,1.0,1.0,1.0,1.0,1.0
  63.                     };
  64. u8 bxiankuan[50]={21,22,22,23,24,24,25,26,26,27,
  65.                    28,28,29,30,30,31,32,33,33,34,
  66.                    34,35,36,37,37,38,39,40,41,42,
  67.                    43,45,46,47,49,50,51,52,53,54,
  68.                    55,56,57,58,59,59,59,60,60,61};//賽道寬度的一半
  69. void CCD_init (void)
  70. {
  71.   exti_init(PORTC,8, falling_down) ;          //場(chǎng)中斷
  72.   exti_init(PORTD,13, falling_down) ;         //行中斷
  73. }
  74. void fasongtuxiang()//發(fā)送原始圖像到紅樹(shù)偉業(yè)上位機(jī)
  75. {
  76.   int i,j;
  77.   for(i=0;i<DATALINE;i++)//采樣行數(shù) 50
  78.   {        
  79.     for(j=32;j<lie;j++)//采樣點(diǎn)數(shù) 100
  80.     {
  81.       if(ImageBuf[i][j]==0xff)
  82.         ImageBuf[i][j]=0xfe;
  83.       uart_putchar (UART0,ImageBuf[i][j]);
  84.     }  
  85.   }
  86.   uart_putchar (UART0,0xff );
  87. }  
  88. float absx(float i)//作用: 求絕對(duì)值  浮點(diǎn)型
  89. {
  90.   if(i<0) return (-i);
  91.   else  return i;
  92. }
  93. s32 absi(s32 i)//作用: 求絕對(duì)值  int型
  94. {
  95.   if(i<0) return (-i);
  96.   else  return i;
  97. }
  98. u16  yuzhi(u16 i)//作用: 求一行的閾值
  99. {
  100.   u16 j,max=0,min=255;
  101.   for(j=0;j<DATACOUNT;j++)//采樣點(diǎn)數(shù)  100
  102.   {                                                                                                                                
  103.    if(ImageBuf[i][j]>max)
  104.    {
  105.      max=ImageBuf[i][j];
  106.    }
  107.    else if(ImageBuf[i][j]<min)
  108.    {
  109.      min=ImageBuf[i][j];
  110.     }
  111.   }  
  112.   return (u16)((min+max)/2);//此處需要-20;自己試試
  113. }

  114. void erzhihua()//作用: 將采集的數(shù)據(jù)二值化
  115. {
  116.   u16 i,j;
  117.   for(i=0;i<DATALINE;i++)//由于實(shí)驗(yàn)室光線(xiàn)不均勻,近端與遠(yuǎn)端使用不同的閾值
  118.   {  
  119.     if(i>30)//近端
  120.       yuzhizhi=yuzhi(i)+12;//加大后黑色變多  根據(jù)場(chǎng)地不同調(diào)參數(shù)
  121.     else    //遠(yuǎn)端
  122.       yuzhizhi=yuzhi(i)+19;//根據(jù)場(chǎng)地不同調(diào)參數(shù)
  123.       for(j=32;j<lie;j++)
  124.      {     
  125.        if(ImageBuf[i][j]<yuzhizhi)   //二值化為0和1 白為0,黑為1
  126.          ImageBuf2[i][j-32]=0x01;        
  127.        else
  128.          ImageBuf2[i][j-32]=0x00;   
  129.     }  
  130.   }
  131. }
  132. s16 yp_left=0,yp_right=0;
  133. s16 yupan_fangxiang(s16 yp_qishi)//只是預(yù)判,與最終中線(xiàn)無(wú)關(guān)�。。�
  134. {
  135.   yp_left=0,yp_right=0,szis=0;
  136.   for(is=yp_qishi;is<=48;is++)
  137.   {
  138.      if(blackright[is]>(DATACOUNT-2)&&blackleft[is]==0)
  139.        centerzuoyupan[is]=DATACOUNT/2;//中心預(yù)判
  140.      else if(blackright[is]>(DATACOUNT-2)&&blackleft[is]!=0&&(is>0))
  141.        centerzuoyupan[is]=blackleft[is]+bxiankuan[is];//一端沒(méi)線(xiàn),粗略地根據(jù)賽道進(jìn)行平移
  142.      else if(blackright[is]<(DATACOUNT-2)&&blackleft[is]==0&&(is>0))
  143.        centerzuoyupan[is]=blackright[is]-bxiankuan[is];
  144.      else
  145.        centerzuoyupan[is]=(blackright[is]+blackleft[is])/2;//兩邊都有,取中值
  146.      szis++;
  147.    if(szis>=1)
  148.    {
  149.       if((centerzuoyupan[is]-centerzuoyupan[is-1])<=-1)
  150.         yp_right++;//右傾
  151.       else if((centerzuoyupan[is]-centerzuoyupan[is-1])>=1)
  152.         yp_left++;//左傾
  153.    }
  154. }
  155. if((yp_right>=(yp_right+yp_left+1)/2))
  156.    return 1 ;//右傾較多
  157. if((yp_left>=(yp_right+yp_left+1)/2))
  158.    return 2;//左傾較多
  159. }
  160. //作用: 求有效行,并且求左右邊緣,最終求的中心
  161. void countcenter()
  162. {
  163.   s16 i,j,m;
  164.   s16 rightstart,leftstart,rightend,leftend;
  165.   m1=0,m2=0,n1=0,n2=0;
  166.   for(i=0;i<DATALINE;i++)//對(duì)圖像處理參數(shù)初始化
  167.   {
  168.     blackright[i]=DATACOUNT;
  169.     blackleft[i]=0;
  170.     center[i]=0;
  171.     centerxunizuo[i]=centerxuniyou[i]=DATACOUNT/2;
  172.     centerszyupan[i]=centerzuoyupan[i]=centeryouyupan[i]=0;
  173.     right=left=0;
  174.     rightzuo=leftzuo=0;
  175.     rightyou=leftyou=0;
  176.     rightsz=leftsz=0;
  177.     zuoqishi=youqishi=0;
  178.   }
  179.   //計(jì)算前2行的左右邊緣
  180.   for(i=DATALINE-1;i>DATALINE-3;i--)
  181.   {
  182.     for(j=(DATACOUNT/2-10);j<(DATACOUNT-1);j++)//計(jì)算前2行右邊界  起始點(diǎn)靠左一點(diǎn)
  183.     {
  184.        if(ImageBuf2[i][j-1]==0&&ImageBuf2[i][j]==1&&ImageBuf2[i][j+1]==1&&blackright[i]==DATACOUNT)//省掉break,
  185.        {
  186.          blackright[i]=j;
  187.        }
  188.     }
  189.     for(m=(DATACOUNT/2+10);m>0;m--)        //計(jì)算前2行左邊界  起始點(diǎn)靠右一點(diǎn)
  190.     {
  191.       if(ImageBuf2[i][m-1]==1&&ImageBuf2[i][m]==1&&ImageBuf2[i][m+1]==0&&blackleft[i]==0)//省掉break,
  192.       {
  193.         blackleft[i]=m;
  194.       }
  195.     }   
  196.     if(blackleft[i]!=0&&blackright[i]!=DATACOUNT)
  197.      centerxunizuo[i]=(blackleft[i]+blackright[i])/2;//算出虛擬中線(xiàn),為后面決策作參考
  198.     else if(blackleft[i]==0&&blackright[i]!=DATACOUNT)
  199.       centerxunizuo[i]=blackright[i]-bxiankuan[i];
  200.     else if(blackleft[i]!=0&&blackright[i]==DATACOUNT)
  201.       centerxunizuo[i]=blackleft[i]+bxiankuan[i];
  202.   }
  203. //前2行循環(huán)
  204. //over
  205.   rightstart=blackright[DATALINE-2]-3;//根據(jù)前兩行來(lái)確定搜索的起始點(diǎn)
  206.   rightend=blackright[DATALINE-2]+3;
  207.   leftstart=blackleft[DATALINE-2]+3;
  208.   leftend=blackleft[DATALINE-2]-3;
  209.   if(leftend<=0)
  210.     leftend=0;
  211.   if(rightend>=DATACOUNT)         
  212.     rightstart=DATACOUNT;
  213. //計(jì)算右邊界的有效行數(shù)和右邊界
  214.   for(i=DATALINE-3;i>=0;i--)//
  215.   {
  216.     for(j=rightstart;j<rightend;j++)//右線(xiàn)用0xx011,比較穩(wěn)定可靠
  217.     {
  218.        if(rightend>=DATACOUNT)
  219.          rightend=DATACOUNT;
  220.        if(ImageBuf2[i][j-4]==0&&ImageBuf2[i][j-1]==0&&ImageBuf2[i][j]==1&&ImageBuf2[i][j+1]==1)  //在范圍內(nèi)找到黑線(xiàn),這個(gè)地方需要注意
  221.        {
  222.          blackright[i]=j;
  223.          rightstart=j-4;//找到黑線(xiàn),為下一行的起始賦值
  224.          rightend=j+4;
  225.          if(rightstart<=1)         
  226.            rightstart=1;
  227.          if(rightend>=DATACOUNT)
  228.          rightend=DATACOUNT;
  229.          m1++;//無(wú)用,可刪掉
  230.          break;
  231.        }
  232.    }
  233.    if(j==rightend)         //在范圍內(nèi)沒(méi)有找到黑線(xiàn)
  234.    {
  235.      rightstart=rightstart-bxiankuan[i];//平移半個(gè)賽道寬重新找黑線(xiàn)  可優(yōu)化
  236.      rightend=DATACOUNT;//
  237.      if(rightstart<=1)         
  238.        rightstart=1;
  239.      for(j=rightstart;j<rightend;j++)//同樣是0xx011
  240.      {
  241.         if(ImageBuf2[i][j-4]==0&&ImageBuf2[i][j-1]==0&&ImageBuf2[i][j]==1&&ImageBuf2[i][j+1]==1) //在范圍內(nèi)找到黑線(xiàn)&&ImageBuf2[i-1][j+1]==1
  242.         {
  243.          blackright[i]=j;
  244.          rightstart=j-4;
  245.          rightend=j+4;
  246.          if(rightstart<=1)         
  247.            rightstart=1;
  248.          if(rightend>=DATACOUNT)
  249.          rightend=DATACOUNT;
  250.          m2++;                                                                                       
  251.          break;
  252.         }
  253.         
  254.      }
  255.      if(j==rightend)         //在范圍內(nèi)沒(méi)有找到黑線(xiàn)
  256.         rightstart=rightstart+bxiankuan[i];//還未找到?起始點(diǎn)還原到上次確定的起始點(diǎn)
  257.    }  
  258.     for(m=leftstart;m>leftend;m--)//左線(xiàn)用110xx0   以下有上面對(duì)稱(chēng),不再注釋
  259.      {
  260.         if(ImageBuf2[i][m+4]==0&&ImageBuf2[i][m+1]==0&&ImageBuf2[i][m]==1&&ImageBuf2[i][m-1]==1)
  261.         {
  262.           blackleft[i]=m;
  263.           leftstart=m+4;
  264.           leftend=m-4;
  265.           if(leftend<=0)
  266.             leftend=0;
  267.           if(leftstart>=DATACOUNT)
  268.             leftstart=DATACOUNT;
  269.           n1++;
  270.           break;
  271.        }
  272.      }
  273.      if(m==leftend)
  274.      {
  275.         leftstart=leftstart+bxiankuan[i];//centerxunizuo[i+1];
  276.         leftend=0;//leftend-6;  
  277.         if(leftend<=0)
  278.           leftend=0;
  279.         if(leftstart>=DATACOUNT)
  280.            leftstart=DATACOUNT;
  281.         for(m=leftstart;m>leftend;m--)
  282.         {
  283.             if(ImageBuf2[i][m+4]==0&&ImageBuf2[i][m]==1&&ImageBuf2[i][m+1]==0&&ImageBuf2[i][m-1]==1)
  284.             {
  285.               blackleft[i]=m;
  286.               leftstart=m+3;
  287.               leftend=m-3;
  288.               if(leftend<=0)
  289.                 leftend=0;
  290.               if(leftstart>=DATACOUNT)
  291.                 leftstart=DATACOUNT;
  292.               n2++;
  293.               break;
  294.             }
  295.             
  296.        }
  297.        if(m==leftend)
  298.          leftstart=leftstart-bxiankuan[i];
  299.    }//右邊界循環(huán)結(jié)束
  300.     if(blackleft[i]!=0&&blackright[i]!=DATACOUNT)
  301.      centerxunizuo[i]=(blackleft[i]+blackright[i])/2;//計(jì)算虛擬中線(xiàn)
  302.     else if(blackleft[i]==0&&blackright[i]!=DATACOUNT)
  303.       centerxunizuo[i]=blackright[i]-bxiankuan[i];
  304.     else if(blackleft[i]!=0&&blackright[i]==DATACOUNT)
  305.       centerxunizuo[i]=blackleft[i]+bxiankuan[i];
  306.   }
  307. }
  308. //十字處理函數(shù),比較麻煩,情況分為正十字(分為遠(yuǎn)處四點(diǎn)都有,近處只有兩點(diǎn)兩種情況),左斜十字和右斜十字,
  309. //在實(shí)際操作時(shí)可能會(huì)發(fā)現(xiàn),各自分類(lèi)的界限并沒(méi)有很明確,可能斜十字的情況在正十字里就補(bǔ)好線(xiàn)了,這是為了
  310. //有交集,這樣不會(huì)丟失各種情況,不會(huì)有“都不管”的情況
  311. void shizi_handle()
  312. {
  313.     int i,kk,jj,tt,ss;
  314.     zshizi=0,zxshizi=0,yxshizi=0;
  315.     shizi_flag=youxiao_shizi=0, jieshu_shizi=0,qishi_shizi=0;
  316.     xs=ys=fs=es=0,left_sz=0,right_sz=0;
  317.     zstop=0,ystop=0,zxqishi=0,zzxqishi=0,yzxqishi=0;
  318.     start_y=0,yous=0,stop_z=0,start_z=0,zuos=0,stop_y=0,zuozs=0,youzs=0;
  319. /////////////////////////正十字補(bǔ)線(xiàn)///////////////////////
  320.     //連續(xù)3行以上都是全白,且中點(diǎn)也是白
  321.     for(is=DATALINE-1;is>=10;is--)//提取特征:兩端都是白色的,搜不到黑線(xiàn)
  322.     {
  323.        if(youxiao_shizi==0&&(blackleft[is]==0)&&(blackright[is]==DATACOUNT)&&(blackleft[is-1]==0)&&(blackright[is-1]==DATACOUNT)&&(blackleft[is-2]==0)&&(blackright[is-2]==DATACOUNT)&&
  324.           ImageBuf2[is][blackleft[is]]==0&&ImageBuf2[is-1][blackleft[is-1]]==0&&ImageBuf2[is][blackright[is]-1]==0&&ImageBuf2[is-1][blackright[is-1]-1]==0&&ImageBuf2[is][DATACOUNT/2]==0)
  325.              youxiao_shizi=is;//十字開(kāi)始行
  326.        if(shizi_flag==0&&youxiao_shizi!=0&&blackleft[is]==0&&blackright[is]==DATACOUNT&&blackleft[is-1]==0&&(blackright[is-1]==DATACOUNT)&&(ImageBuf2[is][blackleft[is]]==0)&&
  327.           (ImageBuf2[is-1][blackleft[is-1]]==0)&&(ImageBuf2[is][blackright[is]-1]==0)&&(ImageBuf2[is-1][blackright[is-1]-1]==0)&&ImageBuf2[is][DATACOUNT/2]==0&&
  328.             (ImageBuf2[is-2][blackright[is-2]-1]==1||ImageBuf2[is-2][blackleft[is-2]]==1||blackleft[is-2]>0||blackright[is-2]<=(DATACOUNT-1)))
  329.        {                                                                         //其實(shí)前面兩條就夠了,后面這兩條為了保險(xiǎn)才加的
  330.           shizi_flag=is-1; //十字結(jié)束行 在起始行的基礎(chǔ)上繼續(xù)搜索得到
  331.           break;//跳出,省時(shí)間
  332.        }
  333.    }
  334.    if((youxiao_shizi-shizi_flag)>=1&&(youxiao_shizi-shizi_flag)<=25)//對(duì)白色縱向?qū)挾茸鱿拗?br />
  335.    {
  336.      for(is=DATALINE-1;is>youxiao_shizi;is--)
  337.      { //左下端特征:邊線(xiàn)存在且大于0;拐點(diǎn)之下由近端到拐點(diǎn)呈遞增趨勢(shì)(且比較陡),之上呈遞減趨勢(shì)(且比較緩).
  338.         if(blackleft[is]>1&&blackleft[is+1]>1&&(blackleft[is]-blackleft[is+1])>=0&&
  339.            (blackleft[is]-blackleft[is-1])>=1&&(blackleft[is]-blackleft[is-2])>=3&&zstop==0)
  340.         {
  341.           zzxqishi=is;//由近到遠(yuǎn) 尋找左下端拐點(diǎn)
  342.           zstop=1;
  343.         }
  344.         //右下端特征:邊線(xiàn)存在且小于DATACOUNT;拐點(diǎn)之下由近端到拐點(diǎn)呈遞減趨勢(shì)(且比較陡),之上呈遞增趨勢(shì)(且比較緩).
  345.         if(blackright[is]<DATACOUNT&&blackright[is+1]<DATACOUNT&&(blackright[is]-blackright[is+1])<=0&&
  346.            (blackright[is]-blackright[is-1])<=-1&&(blackright[is]-blackright[is-2])<=-3&&ystop==0)
  347.         {
  348.           yzxqishi=is;//尋找右下端拐點(diǎn)
  349.           ystop=1;
  350.         }
  351.      }
  352.      //此處針對(duì)靠下的拐點(diǎn)
  353.      if(zzxqishi>=yzxqishi&&(zzxqishi<=47))         zxqishi=zzxqishi;//比較后使用最靠近車(chē)的行
  354.      else if (zzxqishi<yzxqishi&&(yzxqishi<=47))   zxqishi=yzxqishi;
  355.      else if(zzxqishi==0&&yzxqishi!=0) zxqishi=yzxqishi;//一端沒(méi)有,用另一端的作為最后的拐點(diǎn)
  356.      else if(zzxqishi!=0&&yzxqishi==0) zxqishi=zzxqishi;
  357.      else zxqishi=0;//兩端都沒(méi)有,即車(chē)體進(jìn)入十字中,此時(shí)沒(méi)有最下端的拐點(diǎn)
  358.     // yupan_fangxiang(zxqishi);//主要為下面服務(wù)的  預(yù)判函數(shù)
  359.    }
  360.    if((youxiao_shizi-shizi_flag)>=1&&(youxiao_shizi-shizi_flag)<=25)
  361.    {//由于存在十字的原因,之前搜到的邊線(xiàn)可能不準(zhǔn),需要重新搜線(xiàn),需要確定搜線(xiàn)的起始列,即left_sz,right_sz
  362.       //最遠(yuǎn)行對(duì)應(yīng)的列坐標(biāo)應(yīng)該位于賽道的中心位置�。�!
  363.      for(int jdf=0;jdf<DATACOUNT;jdf++)
  364.        shizibx[jdf]=shizi_flag;//初始化為十字的結(jié)束行
  365.      jdt=shizi_flag;//初始化為十字的結(jié)束行
  366.      for(jd=0;jd<DATACOUNT;)//縱向搜線(xiàn),尋找最遠(yuǎn)端
  367.      {
  368.        for(id=shizi_flag;id>0;id--)//從十字的結(jié)束行往上搜索直到第一行
  369.        {
  370.          if(ImageBuf2[id+1][jd]==0&&ImageBuf2[id][jd]==1&&ImageBuf2[id-1][jd]==1)
  371.          {//由下到上縱向搜索,011成立便找到點(diǎn)了
  372.            shizibx[jd]=id;//將第id行存入數(shù)組中
  373.            break;
  374.          }
  375.        }
  376.        jd+=10;//此時(shí)只是粗略地找最遠(yuǎn)端,所以不需要每一列都搜索,隔10列可以節(jié)約時(shí)間
  377.      }
  378.      for(int jdf=0;jdf<DATACOUNT;jdf++)
  379.      {//最遠(yuǎn)處的行應(yīng)小于“上一次的最遠(yuǎn)行”!�。�,且不等于結(jié)束行
  380.        if((shizibx[jdf]<shizibx[jdt])&&shizibx[jdf]!=shizi_flag)
  381.         jdt=jdf;//獲得最遠(yuǎn)行對(duì)應(yīng)的列坐標(biāo),如此反復(fù)進(jìn)入幾次就能把最遠(yuǎn)行對(duì)應(yīng)的列坐標(biāo)求出
  382.      }
  383.        left_sz=jdt+10;//有了列坐標(biāo)就能推出左右的起始列了。因?yàn)樽钸h(yuǎn)行對(duì)應(yīng)的列坐標(biāo)應(yīng)該位于賽道的中心位置�。。�
  384.        right_sz=jdt-10;//左右都平移一段距離,留出余量
  385.      //重新遍歷后面的行
  386.      for(int ig=youxiao_shizi;ig>=0;ig--)
  387.      {
  388.        if(left_sz>blackright[ig])   left_sz=blackright[ig];//越界限制
  389.        for(int jg=left_sz;jg>=1;jg--)//左線(xiàn)是110,且列大于左下端點(diǎn)的列坐標(biāo)或 其根本沒(méi)有下端點(diǎn)
  390.        {
  391.          if(ImageBuf2[ig][jg-1]==1&&ImageBuf2[ig][jg]==1&&ImageBuf2[ig][jg+1]==0&&(jg>=blackleft[zzxqishi]||zxqishi==0)) //在范圍內(nèi)找到黑線(xiàn)  
  392.          {
  393.             blackleft[ig]=jg;
  394.             kk++;
  395.             break;
  396.          }
  397.        }
  398.        if(kk>5&&((blackright[ig+1]-blackleft[ig+1])<(2*bxiankuan[ig+1]+10)))//限制條件,求出的賽道寬度小于直道的寬度加一個(gè)允許波動(dòng)值
  399.        {//由于賽道不是直線(xiàn),每5行更新一次left_sz,作為下一次搜線(xiàn)的起始列
  400.          kk=0;
  401.          left_sz=blackleft[ig+1]+bxiankuan[ig+1];//根據(jù)上一行的左線(xiàn)虛擬出下一次的起始列
  402.        }

  403.        if(right_sz<blackleft[ig])   right_sz=blackleft[ig];//越界限制
  404.        for(int mg=right_sz;mg<=DATACOUNT-1;mg++)//右線(xiàn)是011,且列小于右下端點(diǎn)的列坐標(biāo)或 其根本沒(méi)有下端點(diǎn)
  405.        {
  406.          if(ImageBuf2[ig][mg-1]==0&&ImageBuf2[ig][mg]==1&&ImageBuf2[ig][mg+1]==1&&(mg<=blackright[yzxqishi]||zxqishi==0)) //在范圍內(nèi)找到黑線(xiàn)
  407.          {
  408.             blackright[ig]=mg;
  409.             jj++;
  410.             break;
  411.          }
  412.          if(jj>5&&((blackright[ig+1]-blackleft[ig+1])<(2*bxiankuan[ig+1]+10)))
  413.          {//由于賽道不是直線(xiàn),每5行更新一次right_sz,作為下一次搜線(xiàn)的起始列
  414.            jj=0;
  415.            right_sz=blackright[ig+1]-bxiankuan[ig+1];//根據(jù)上一行的右線(xiàn)虛擬出下一次的起始列
  416.          }
  417.        }
  418.      }
  419.      for(is=DATALINE-3;is>1;is--)//求出拐點(diǎn)!
  420.      {
  421.         as=(blackleft[is]-blackleft[is-2]);//與上兩行做一次差        
  422.         bs=(blackleft[is]-blackleft[is+2]);//與下兩行做一次差
  423.         js=blackleft[is]; //為該行的列坐標(biāo)
  424.         if((bs>=5&&as<=0)&&xs==0&&(absi(as)<=6)&&(is<=shizi_flag)&&(is>=(shizi_flag-18))&&(blackleft[is]>1)&&((ImageBuf2[is+1][js+1]+ImageBuf2[is+1][js]+ImageBuf2[is+1][js-1])<=1))
  425.           xs=is;//上面  左上拐點(diǎn)的特征:之下為遞增(或直接增),之上為遞增,之下兩行的絕對(duì)值比較小,左上拐點(diǎn)在十字起始行上面,且在一個(gè)范圍內(nèi),周?chē)鷰讉€(gè)點(diǎn)的白色多一些
  426.         if((as>=4&&bs>=0)&&ys==0&&(absi(bs)<=6)&&(is>=xs)&&(is>=youxiao_shizi)&&blackleft[is]>1&&((ImageBuf2[is-1][js+1]+ImageBuf2[is-1][js]+ImageBuf2[is-1][js-1])<=1))
  427.           ys=is;//下面 左下拐點(diǎn)的特征:之下為遞增,之上為遞減(或直接減),在十字起始行下面
  428.         cs=(blackright[is]-blackright[is-2]);
  429.         ds=(blackright[is]-blackright[is+2]);  
  430.         jz=blackright[is];
  431.         if((ds<=-5&&cs>=0)&&es==0&&(absi(cs)<=6)&&(is<=shizi_flag)&&(is>=(shizi_flag-18))&&(blackright[is]<=(DATACOUNT-2))&&((ImageBuf2[is+1][jz+1]+ImageBuf2[is+1][jz]+ImageBuf2[is+1][jz-1])<=1))
  432.           es=is;//上面  右上拐點(diǎn)的特征:之下為遞減(或直接減),之上為遞減,。。。
  433.         if((ds<=0&&cs<=-3)&&fs==0&&(absi(ds)<=6)&&(is>=es)&&(is>=youxiao_shizi)&&(blackright[is]<=(DATACOUNT-2))&&((ImageBuf2[is-1][jz+1]+ImageBuf2[is-1][jz]+ImageBuf2[is-1][jz-1])<=1))
  434.           fs=is;//下面  右下拐點(diǎn)的特征:之下為遞減,之上為遞增(或直接增)
  435.      }
  436. //有下端拐點(diǎn)的進(jìn)來(lái)�。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。�!     
  437.      //下端拐點(diǎn)在十字開(kāi)始行的下面,且(左線(xiàn)在中線(xiàn)以左   或              下端拐點(diǎn)處的右線(xiàn)在中線(xiàn)以右),
  438.      if((zxqishi-12)<youxiao_shizi&&((blackleft[zxqishi]<(DATACOUNT/2-10))||blackright[zxqishi]>(DATACOUNT/2+10))&&
  439.         zxqishi!=0&&(zzxqishi!=0||yzxqishi!=0)&&zxqishi<=(DATACOUNT-3))                             //有拐點(diǎn)的進(jìn)來(lái)
  440.      {//且下端拐點(diǎn)的確存在,且左、右拐點(diǎn)至少存在一個(gè);限幅
  441.         if(xs!=0&&ys!=0&&ys<=(zxqishi+10)&&ys>=(zxqishi-10)&&blackleft[xs]>=blackleft[ys])//左側(cè)進(jìn)行連線(xiàn)
  442.         {//左側(cè)上下拐點(diǎn)都存在,且下拐點(diǎn)在下端點(diǎn)拐點(diǎn)的合理范圍之內(nèi),左上拐點(diǎn)比左下拐點(diǎn)靠右
  443.           for(int iz=xs-1;iz<=ys+1;iz++)//一次函數(shù)連線(xiàn)
  444.           {//為了更加平滑,各讓一步
  445.              blackleft[iz+1]=(blackleft[iz]-blackleft[ys+1])/(iz-ys-1)+blackleft[iz];//注意順序,上面拐點(diǎn)在左還是在右
  446.              zshizi=1;//正入十字標(biāo)志置1,為下面使用
  447.           }
  448.         }//同樣,不作注釋
  449.         if(es!=0&&fs!=0&&fs<=(zxqishi+10)&&fs>=(zxqishi-10)&&blackright[fs]>=blackright[es])//右側(cè)進(jìn)行連線(xiàn)
  450.         {
  451.           for(int iz=es-1;iz<=fs+1;iz++)
  452.           {
  453.              blackright[iz+1]=((blackright[fs+1]-blackright[iz])/(fs+1-iz))+blackright[iz];
  454.              zshizi=1;//正入十字標(biāo)志置1,為下面使用
  455.           }
  456.         }
  457.         //為了下面求中線(xiàn)的起始行和結(jié)束行而使用
  458.         if(xs>=es)  szq=es;//僅為標(biāo)準(zhǔn)正十字服務(wù)
  459.         else        szq=xs;//十字起始行以上為主
  460.         if(ys>=fs)  szs=ys;
  461.         else        szs=fs;//十字接收行以下為主
  462.         if(xs!=0&&ys!=0&&es!=0&&fs!=0)//標(biāo)準(zhǔn)正十字 四拐點(diǎn)都存在
  463.         {
  464.           for(i=szq-1;i<=szs+1;i++)//為了平滑,各讓一步
  465.             if(center[i]==0)//由于前面已經(jīng)補(bǔ)線(xiàn)了,此處只需求中值即可
  466.                center[i]=(blackright[i]+blackleft[i])/2;
  467.         }
  468.         else if(xs!=0&&ys!=0&&(es==0||fs==0))//右側(cè)丟失
  469.         {
  470.           for(i=xs-1;i<=ys+1;i++)
  471.             if(center[i]==0)//中線(xiàn)靠左線(xiàn)加賽道寬度而得
  472.               center[i]=(bxiankuan[i]+blackleft[i]);
  473.         }
  474.         else if(es!=0&&fs!=0&&(xs==0||ys==0))//左側(cè)丟失
  475.         {  
  476.           for(i=es-1;i<=fs+1;i++)
  477.             if(center[i]==0)//中線(xiàn)靠右線(xiàn)減賽道寬度而得
  478.              center[i]=(blackright[i]-bxiankuan[i]);
  479.         }
  480.      }
  481. //近端處理  無(wú)下拐點(diǎn)的進(jìn)來(lái)�。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。�
  482.     else if(youxiao_shizi>=30&&shizi_flag>=24&&(es!=0&&xs!=0)&&(es>=(xs-13)&&xs>=(es-13)))//如果剛進(jìn)入十字,則只有最上面兩個(gè)拐點(diǎn),
  483.     {     //十字比較靠近車(chē)                     且兩個(gè)上拐點(diǎn)都存在,es與xs在合理的范圍內(nèi)                              
  484.       for(int iz=xs-1;iz<DATALINE-1;iz++)//此時(shí)補(bǔ)線(xiàn)利用左拐點(diǎn)與左下角坐標(biāo)值連線(xiàn),右拐點(diǎn)與右下角坐標(biāo)值連線(xiàn)
  485.       {//一次函數(shù)連線(xiàn)
  486.         blackleft[iz+1]=-(blackleft[iz])/(DATALINE-1-iz)+blackleft[iz];//注意順序,上面拐點(diǎn)在左還是在右
  487.         zshizi=1;//正入十字標(biāo)志置1,為下面使用
  488.       }
  489.       for(int iz=es-1;iz<DATALINE-1;iz++)
  490.       {
  491.         blackright[iz+1]=((DATACOUNT-blackright[iz])/(49-iz))+blackright[iz];
  492.         zshizi=1;//正入十字標(biāo)志置1,為下面使用
  493.       }
  494.       if(xs>=es)    szq=es;//選取靠上的拐點(diǎn),作為下面求中線(xiàn)的起始行
  495.       else          szq=xs;
  496.       for(i=szq;i<=49;i++)
  497.         center[i]=(blackright[i]+blackleft[i])/2;
  498.     }
  499.     //十字后期處理  主要處理一些不常見(jiàn)的情況,可不看
  500.     if(zshizi==1)
  501.     {
  502.       for(i=DATALINE-1;i>1;i--)
  503.       {
  504.         if(blackleft[i]<=1&&blackright[i]<(DATACOUNT-1)&¢er[i]==0)//左線(xiàn)丟失
  505.         {
  506.           if(center[i-1]!=0)//給下端補(bǔ)線(xiàn)
  507.             center[i]=blackright[i]-(blackright[i-1]-center[i-1]+1);
  508.           else if(center[i+1]!=0)//給上端補(bǔ)線(xiàn)
  509.             center[i]=blackright[i]-(blackright[i+1]-center[i+1]-1);
  510.           else
  511.             center[i]=blackright[i]-bxiankuan[i];
  512.         }
  513.         if(blackleft[i]>1&&blackright[i]==DATACOUNT&¢er[i]==0)//右線(xiàn)丟失
  514.         {
  515.           if(center[i-1]!=0)//給下端補(bǔ)線(xiàn)
  516.             center[i]=blackleft[i]+(center[i-1]-blackleft[i-1]+1);
  517.           else if(center[i+1]!=0)//給上端補(bǔ)線(xiàn)
  518.             center[i]=blackleft[i]+(center[i+1]-blackleft[i+1]-1);
  519.           else
  520.             center[i]=blackleft[i]+bxiankuan[i];
  521.         }
  522.       }
  523.     }
  524.    }
  525. //左側(cè)斜十字補(bǔ)線(xiàn)     各標(biāo)志位清零
  526.    xieshizi_zuoflag=0,xieshizi_youflag=0,youxiaozuoxieshizi=0,youxiaoyouxieshizi=0,xiexs=0,xieys=0,xiees=0,xiefs=0;
  527.    for(is=DATALINE-3;is>5;is--)
  528.    {//連續(xù)兩行的左線(xiàn)都存在  下增上減
  529.      if(blackleft[is]>1&&blackleft[is+1]>1&&(blackleft[is]-blackleft[is+1])>=0&&
  530.         (blackleft[is]-blackleft[is+2])>=1&&(blackleft[is]-blackleft[is-1])>=1&&(blackleft[is]-blackleft[is-2])>2)
  531.       {
  532.         zuoqishi=is;//先尋找左下拐點(diǎn)
  533.         break;
  534.       }
  535.    }
  536.    if(zuoqishi!=0)//左下拐點(diǎn)存在才能進(jìn)入
  537.    {
  538.      for(is=zuoqishi;is>2;is--)//從左下拐點(diǎn)向上尋找
  539.      {                       //連續(xù)三行左端都沒(méi)找到線(xiàn)
  540.        if(youxiaozuoxieshizi==0&&blackleft[is]==0&&blackleft[is-1]==0&&blackleft[is-2]==0&&
  541.           ImageBuf2[is][blackleft[is]]==0&&ImageBuf2[is-1][blackleft[is-1]]==0)
  542.        {//并且連續(xù)兩行左端 二值化圖像 都是白的
  543.           if(youxiaozuoxieshizi==0)//進(jìn)行遍歷,尋找起始行
  544.              youxiaozuoxieshizi=is;
  545.        }                        //連續(xù)兩行沒(méi)找到線(xiàn),且從下到上是白到黑或左線(xiàn)找到了
  546.        if(youxiaozuoxieshizi!=0&&blackleft[is]==0&&blackleft[is-1]==0&&ImageBuf2[is-1][blackleft[is-1]]==0&&
  547.           (ImageBuf2[is-2][blackleft[is-2]]==1||blackleft[is-2]!=0))//一般上側(cè)結(jié)束行都是極值,只有分辨圖像是黑是白
  548.        {
  549.          xieshizi_zuoflag=is-1;//尋找結(jié)束行
  550.          break;//找到就跳出,省時(shí)間
  551.        }
  552.      }
  553.    }
  554. //斜十字補(bǔ)線(xiàn) 左側(cè)  白色區(qū)域在合理范圍內(nèi),                                               下拐點(diǎn)在白色下面
  555.     if((youxiaozuoxieshizi-xieshizi_zuoflag)>2&&(youxiaozuoxieshizi-xieshizi_zuoflag)<30&&(zuoqishi-15)<youxiaozuoxieshizi&&
  556.         (blackleft[zuoqishi]<(DATACOUNT/2+30))&&zuoqishi!=0&&yupan_fangxiang(zuoqishi)==1)
  557.      {           //                                            右傾較多
  558.         left_xsz=centerxunizuo[zuoqishi]+25;//根據(jù)預(yù)判得出虛擬中線(xiàn),
  559.         for(int ig=zuoqishi;ig>0;ig--)//重新搜線(xiàn)
  560.         {  
  561.           if(left_xsz>=blackright[ig])  left_xsz=blackright[ig];
  562.            for(int jg=left_xsz;jg>=0;jg--)
  563.            {
  564.              if(ImageBuf2[ig][jg+1]==0&&ImageBuf2[ig][jg]==1&&ImageBuf2[ig][jg-1]==1&&jg>=blackleft[zuoqishi]) //在范圍內(nèi)找到黑線(xiàn)
  565.              {
  566.                 blackleft[ig]=jg;  //更新左線(xiàn)數(shù)組
  567.                 ss++;
  568.                 break;
  569.              }
  570.            }
  571.            if(ss>4)
  572.            {
  573.              ss=0;
  574.              left_xsz=blackleft[ig+1]+bxiankuan[ig+1];
  575.            }
  576.        }
  577.        xieshizi_zuoflag=0;
  578.        for(is=zuoqishi;is>5;is--)//斜十字補(bǔ)線(xiàn) 再判斷 由于前面更新了左線(xiàn)數(shù)組,此時(shí)再次確認(rèn)無(wú)誤
  579.        {
  580.          if(youxiaozuoxieshizi==0&&blackleft[is]==0&&blackleft[is-1]==0&&blackleft[is-2]==0)
  581.          {
  582.            if(youxiaozuoxieshizi==0)
  583.              youxiaozuoxieshizi=is;//得出起始行
  584.          }
  585.          if(youxiaozuoxieshizi!=0&&blackleft[is]==0&&blackleft[is-1]==0&&
  586.             ImageBuf2[is][blackleft[is]]==0&&ImageBuf2[is-1][blackleft[is-1]]==0&&(ImageBuf2[is-2][blackleft[is-2]]==1||blackleft[is-2]!=0))
  587.          {
  588.            xieshizi_zuoflag=is-1;//得出結(jié)束行
  589.            break;
  590.          }
  591.        }
  592.        for(is=DATALINE-3;is>=0;is--)//十字補(bǔ)線(xiàn),同正十字
  593.        {
  594.          as=absi(blackleft[is]-blackleft[is-2]);         
  595.          bs=absi(blackleft[is+2]-blackleft[is]);
  596.          js=blackleft[is]; //下面
  597.          if((as>5&&bs<=8)&&xieys==0&&(is>=(youxiaozuoxieshizi))&&((ImageBuf2[is-1][js+1]+ImageBuf2[is-1][js]+ImageBuf2[is-1][js-1])<=1))
  598.            xieys=is;
  599.          if((bs>5&&as<=6)&&xieys!=0&&(is<=xieshizi_zuoflag)&&(is>=(xieshizi_zuoflag-12))&&blackleft[is]>=blackleft[xieys]&&(blackleft[is]>1)&&((ImageBuf2[is+1][js+1]+ImageBuf2[is+1][js]+ImageBuf2[is+1][js-1])<=1))
  600.          {
  601.            xiexs=is;//上面
  602.            break;
  603.          }
  604.        }
  605.        if(xieys!=0&&xiexs!=0&&xieys>xiexs)
  606.        {
  607.          for(int iz=xiexs;iz<=xieys;iz++)//只能補(bǔ)一側(cè)
  608.          {
  609.            blackleft[iz+1]=((blackleft[xieys]-blackleft[iz])/(xieys-iz))+blackleft[iz];
  610.            center[iz+1]=(bxiankuan[iz+1]+blackleft[iz+1]);
  611.            zxshizi=1;//左斜十字標(biāo)志置1
  612.          }
  613.          for(int iz=DATALINE-1;iz>=3;iz--)//把右側(cè)沒(méi)搜到線(xiàn)的行的中線(xiàn)根據(jù)左側(cè)補(bǔ)出來(lái)
  614.          {
  615.            if(blackleft[iz]>=1&&blackright[iz]>=(DATACOUNT-1))
  616.              center[iz]=blackleft[iz]+bxiankuan[iz];//
  617.          }
  618.        }
  619.      }
  620. //右側(cè) 斜十字補(bǔ)線(xiàn)/////
  621.      for(int is=DATALINE-3;is>=5;is--)//斜十字補(bǔ)線(xiàn)   右側(cè) 預(yù)判斷
  622.      {
  623.        if(blackright[is]<DATACOUNT&&blackright[is-1]<=DATACOUNT&&blackright[is-2]<=DATACOUNT&&(blackright[is]-blackright[is+1])<=0&&
  624.           (blackright[is]-blackright[is+2])<=0&&(blackright[is]-blackright[is-1])<=-1&&(blackright[is]-blackright[is-2])<-3)
  625.        {
  626.           youqishi=is;//右側(cè)的下端拐點(diǎn)
  627.           break;
  628.        }
  629.      }
  630.      for(is=youqishi;is>=5;is--)//得出白色區(qū)域
  631.      {
  632.         if(blackright[is]==DATACOUNT&&blackright[is-1]==DATACOUNT&&blackright[is-2]==DATACOUNT&&
  633.            ImageBuf2[is][blackright[is]-1]==0&&ImageBuf2[is-1][blackright[is-1]-1]==0)
  634.         {
  635.           if(youxiaoyouxieshizi==0)//開(kāi)始記錄白點(diǎn)
  636.             youxiaoyouxieshizi=is;
  637.         }
  638.         if(youxiaoyouxieshizi!=0&&xieshizi_youflag==0&&blackright[is]==DATACOUNT&&blackright[is-1]==DATACOUNT&&
  639.            ImageBuf2[is][blackright[is]-1]==0&&ImageBuf2[is-1][blackright[is-1]-1]==0&&(ImageBuf2[is-2][blackright[is-2]-1]==1||blackright[is-2]!=DATACOUNT))
  640.         {
  641.           xieshizi_youflag=is-1;//遇著黑點(diǎn)退出
  642.           break;
  643.         }
  644.      }                                                                                     //右下拐點(diǎn)靠右
  645.      if((youxiaoyouxieshizi-xieshizi_youflag)>1&&(youxiaoyouxieshizi-xieshizi_youflag)<30&&(blackright[youqishi]>(DATACOUNT/2-30))&&
  646.         youqishi!=0&&yupan_fangxiang(youqishi)==2)//左傾較多
  647.      {
  648.         right_xsz=(centerxunizuo[youqishi]-30);//根據(jù)得出的虛擬中線(xiàn),來(lái)確定再次搜線(xiàn)的起始列
  649.         for(int ig=youqishi;ig>=0;ig--)//對(duì)右線(xiàn)數(shù)組重新搜索
  650.         {
  651.           if(right_xsz<=blackleft[ig])   right_xsz=blackleft[ig];
  652.           if(right_xsz<1)   right_xsz=1;
  653.          
  654.           for(int jg=right_xsz;jg<=DATACOUNT;jg++)
  655.           {
  656.             if(ImageBuf2[ig][jg-1]==0&&ImageBuf2[ig][jg]==1&&ImageBuf2[ig][jg+1]==1&&jg<=blackright[youqishi]) //在范圍內(nèi)找到黑線(xiàn)
  657.             {
  658.                blackright[ig]=jg;
  659.                tt++;
  660.                break;
  661.             }
  662.           }
  663.          if(tt>2)
  664.           {
  665.             tt=0;
  666.             right_xsz=blackright[ig+1]-bxiankuan[ig+1];
  667.           }
  668.         }
  669.         xieshizi_youflag=0;
  670.         for(is=youqishi;is>=5;is--)//斜十字補(bǔ)線(xiàn)   由于更新了數(shù)組,需要再判斷
  671.         {
  672.           if(blackright[is]==DATACOUNT&&blackright[is-1]==DATACOUNT&&blackright[is-2]==DATACOUNT&&
  673.              ImageBuf2[is][blackright[is]-1]==0&&ImageBuf2[is-2][blackright[is-2]-1]==0)
  674.           {
  675.             if(youxiaoyouxieshizi==0)
  676.               youxiaoyouxieshizi=is;//得出起始行
  677.           }
  678.           if(youxiaoyouxieshizi!=0&&xieshizi_youflag==0&&blackright[is]==DATACOUNT&&blackright[is-1]==DATACOUNT&&
  679.              ImageBuf2[is][blackright[is]-1]==0&&ImageBuf2[is-1][blackright[is-1]-1]==0&&(blackright[is-2]!=DATACOUNT||ImageBuf2[is-2][blackright[is-2]-1]==1))
  680.           {
  681.             xieshizi_youflag=is-1;//結(jié)束行
  682.             break;
  683.           }
  684.         }
  685.         for(is=DATALINE-3;is>=0;is--)//斜十字補(bǔ)線(xiàn)
  686.         {
  687.           as=absi(blackright[is]-blackright[is-2]);         
  688.           bs=absi(blackright[is+1]-blackright[is]);
  689.           js=blackright[is]; //下面
  690.           if((as>5&&bs<=6)&&xiefs==0&&(is>=(youxiaoyouxieshizi))&&is<(youqishi+4)&&is>(youqishi-4)&&((ImageBuf2[is-1][js+1]+ImageBuf2[is-1][js]+ImageBuf2[is-1][js-1])<=1))
  691.             xiefs=is;
  692.           if((bs>5&&as<=6)&&xiees==0&&xiefs!=0&&(is<=(xieshizi_youflag))&&(is>=(xieshizi_youflag-18))&&(blackright[is]<=(blackright[xiefs]))&&((ImageBuf2[is+1][js+1]+ImageBuf2[is+1][js]+ImageBuf2[is+1][js-1])<=1))
  693.              xiees=is;//上面(is<=ys)&&(blackleft[i+2]>=2)&&(blackleft[i-3]>=2)youxiao_xieshizi
  694.         }
  695.         if(xiefs!=0&&xiees!=0&&xiefs>xiees)//斜十字畸變較大,前后多找些點(diǎn)進(jìn)行補(bǔ)
  696.         {
  697.           for(int iz=xiees;iz<(xiefs+3);iz++)//對(duì)右側(cè)補(bǔ)完線(xiàn)并求中心值
  698.           {
  699.             blackright[iz+1]=((blackright[xiefs+3]-blackright[iz])/(xiefs+3-iz))+blackright[iz];
  700.             center[iz+1]=(blackright[iz+1]-bxiankuan[iz+1]);
  701.             yxshizi=1;//右斜十字置1
  702.           }
  703.           for(int iz=49;iz>=1;iz--)
  704.          {
  705.            if(blackleft[iz]==0&&blackright[iz]<DATACOUNT)
  706.              center[iz]=blackright[iz]-bxiankuan[iz];
  707.            else if((blackleft[iz]==0&&blackright[iz]>=DATACOUNT))
  708.              center[iz]=DATACOUNT/2;
  709.          }
  710.         }
  711.      }
  712. }
  713. /////////////對(duì)尋到的邊情況分類(lèi)并處理擬合中線(xiàn)////////
  714. void nihe_center()
  715. {
  716.   int i=0;
  717.   youxiaoyou=0,yici_you=0,youxiaozuobian=0,yici_zuo=0,youxiaoyoubian=0,youxiaozuo=0;
  718.   youbian_ysy=0,jinduan_ybx=0,zuobian_ysy=0,jinduan_zbx=0,ztuichu=0;
  719.   for(i=DATALINE-1;i>=0;i--)
  720.   {
  721.     if(center[i]==0)
  722.     {
  723.        if(blackright[i]>=(DATACOUNT-2)&&blackleft[i]<=1&¢er[i]==0)//兩邊都有取圖像中心
  724.          center[i]=DATACOUNT/2;
  725.        else if(blackright[i]>(DATACOUNT-2)&&blackleft[i]!=0&¢er[i]==0&&ImageBuf2[i][blackright[i]-1]==0)//右側(cè)丟線(xiàn)
  726.        {
  727.          if(yici_you==0)//右側(cè)開(kāi)始丟線(xiàn)處
  728.            yici_you=i;//記錄起始行
  729.          if(youxiaoyou==0)
  730.          {
  731.            for(int bs=i;bs>2;bs--)
  732.            {//連續(xù)三行的右線(xiàn)為都有值   或連續(xù)兩行是二值化值是黑的
  733.              if((blackright[bs]!=DATACOUNT&&blackright[bs-1]!=DATACOUNT&&blackright[bs-2]!=DATACOUNT)||
  734.                 ImageBuf2[bs][blackright[bs]-1]==1&&ImageBuf2[bs-1][blackright[bs-1]-1]==1)
  735.              {
  736.                youxiaoyou=bs;//結(jié)束行
  737.                break;
  738.              }
  739.            }
  740.          }
  741.          if(youxiaozuobian==0)
  742.          {
  743.            for(int bs=i;bs>youxiaoyou-5;bs--)//判斷左線(xiàn)連續(xù)性,并確定不連續(xù)行
  744.            {
  745.              if((blackleft[bs]-blackleft[bs-1])>0||blackleft[bs]>=(DATACOUNT-1)||blackleft[bs-1]>=(DATACOUNT-1))
  746.              {//本來(lái)左線(xiàn)是遞增向右的,當(dāng)遇到左線(xiàn)遞減了或跑到右邊沿了就進(jìn)入,
  747.                youxiaozuobian=bs;
  748.                break;
  749.              }
  750.              else if((blackleft[bs]-blackleft[bs-1])<=0||blackleft[bs]<(DATACOUNT-1)||blackleft[bs-1]<(DATACOUNT-1))
  751.                youxiaozuobian=bs;//遞增時(shí)一直更新此值
  752.            }
  753.          }
  754.          if(i==49||i==48||(i==47))//如果靠近車(chē),應(yīng)該是近端丟線(xiàn),先判斷下
  755.          {
  756.            if(yici_you>=47&&jinduan_ybx==0)
  757.            {
  758.              for(as=(youxiaoyou-2);as>1;as--)
  759.              {
  760.                if((blackright[as]-blackright[as-1])>=-1&&blackright[as]<DATACOUNT)
  761.                {//向上遞減
  762.                  youbian_ysy=as;
  763.                  if(youbian_ysy<39&&(youxiaoyou-youbian_ysy)>6)//驗(yàn)證是否確實(shí)是近端丟線(xiàn)  此值應(yīng)離丟線(xiàn)處不遠(yuǎn)
  764.                  {
  765.                    for(int as=youxiaoyou;as<=49;as++)//能進(jìn)來(lái),可以確定確實(shí)近端丟線(xiàn)了
  766.                    {
  767.                       if(center[as]==0)
  768.                       {
  769.                         jinduan_ybx=1;//置位標(biāo)志  //根據(jù)前一行的中線(xiàn)求出該行的中線(xiàn)
  770.                         center[as]=(blackleft[as-1]+blackright[as-1])/2-blackleft[as-1]+1+blackleft[as];
  771.                       }
  772.                    }
  773.                  }
  774.                  if(jinduan_ybx==1)  break;//補(bǔ)線(xiàn)完成跳出程序
  775.                }
  776.                else break;//若為進(jìn)入急彎,則會(huì)跳出
  777.              }
  778.            }
  779.            if(jinduan_ybx==0&&yici_you>=46&&youxiaoyou<38&&(youxiaozuobian<=yici_you))//如果不是近端丟線(xiàn),而是進(jìn)入急彎  不
  780.            {//建議攝像頭的鏡頭在120度以上,90度的容易進(jìn)入此處
  781.              for(int as=49;as>youxiaoyou;as--)
  782.              {
  783.                 if(center[as]==0&&blackleft[as]!=0)
  784.                 {
  785.                  center[as]=blackleft[as]+bxiankuan[as]+1;//改變系數(shù)1的大小,可改善進(jìn)入急彎的轉(zhuǎn)向能力
  786.                 }
  787.              }
  788.            }
  789.         }
  790.          else  if(center[i]==0&&blackleft[i]!=0)//彎道丟線(xiàn)時(shí)
  791.           center[i]=center[i+1]-blackleft[i+1]+blackleft[i]+4;//改變系數(shù)4的大小,可改善進(jìn)入急彎的轉(zhuǎn)向能力
  792.        }
  793.        else if(blackright[i]<(DATACOUNT-1)&&blackleft[i]==0&¢er[i]==0)//左側(cè)丟線(xiàn)
  794.        {
  795.          if(yici_zuo==0)//開(kāi)始丟線(xiàn)處起始
  796.            yici_zuo=i;
  797.          if(youxiaozuo==0)
  798.          {
  799.            for(int ks=i;ks>2;ks--)//重新遍歷,確定丟線(xiàn)最上行
  800.            {
  801.              if(blackleft[ks]!=0||ImageBuf2[ks][blackleft[ks]+1]==1)
  802.              {
  803.                youxiaozuo=ks;
  804.                break;
  805.              }
  806.            }
  807.          }
  808.          if(youxiaoyoubian==0)
  809.          {
  810.            for(int ks=i;ks>youxiaozuo-5;ks--)//判斷右線(xiàn)連續(xù)性,并確定不連續(xù)行
  811.            {
  812.              if((blackright[ks]-blackright[ks-1])<0||blackright[ks]<=0||blackright[ks-1]<=0)
  813.              {
  814.                youxiaoyoubian=ks;
  815.                break;
  816.              }
  817.              else if((blackright[ks]-blackright[ks-1])>0||blackright[ks]>0||blackright[ks-1]>0)
  818.                youxiaoyoubian=ks;
  819.                
  820.            }
  821.          }
  822.         //重新遍歷最近端的點(diǎn)   判斷是否進(jìn)入急彎,即左側(cè)或右側(cè)一大塊沒(méi)尋到線(xiàn)的地方
  823.          if(i==49||i==48||(i==47))
  824.          {
  825.            if(i>=47&&yici_zuo>=47&&jinduan_zbx==0&&ztuichu==0)
  826.            {
  827.              for(as=(youxiaozuo-2);as>1;as--)
  828.              {
  829.                if((blackleft[as]-blackleft[as-1])<=1&&blackleft[as]>0&&ztuichu==0)
  830.                {
  831.                  zuobian_ysy=as;
  832.                  if(zuobian_ysy<39&&(youxiaozuo-zuobian_ysy)>6)//驗(yàn)證是否確實(shí)是近端丟線(xiàn)
  833.                  {
  834.                    for(int as=youxiaozuo;as<=49;as++)
  835.                    {
  836.                     if(center[as]==0)
  837.                     {
  838.                       jinduan_zbx=1;//置位標(biāo)志
  839.                        center[as]=blackright[as]-(blackright[as-1]-(blackright[as-1]+blackleft[as-1]+1)/2+1);
  840.                     }
  841.                    }
  842.                  }
  843.                  if(jinduan_zbx==1)  break;//補(bǔ)線(xiàn)完成跳出程序
  844.                }
  845.                else
  846.                  break;//若為進(jìn)入急彎,則會(huì)跳出
  847.              }
  848.            }
  849.            if(i>47&&jinduan_zbx==0&&yici_zuo>=48&&youxiaozuo<40&&(youxiaoyoubian<=yici_zuo))//如果不是近端丟線(xiàn),而是進(jìn)入急彎
  850.            {
  851.              for(int as=49;as>youxiaozuo;as--)
  852.                 if(center[as]==0)
  853.                 {
  854.                    center[as]=blackright[as]-bxiankuan[as]-4;
  855.                 }
  856.            }
  857.          }
  858.          else if(blackright[i]!=DATACOUNT&¢er[i]==0)//進(jìn)入彎道
  859.          {         
  860.            center[i]=blackright[i]-(blackright[i+1]-center[i+1]+3);//改變系數(shù)3的大小,可改善進(jìn)入急彎的轉(zhuǎn)向能力
  861.          }
  862.        }
  863.        else if(center[i]==0)//其他情況,直接取中值
  864.        {
  865.          center[i]=(blackright[i]+blackleft[i])/2;  
  866.        }
  867.    }
  868.   }
  869. }

  870. void countvaluerow()
  871. {
  872.    s16 i;
  873.   yx_left=0,yx_right=0;
  874.    value_flag=0,valuerownum=0;
  875.    S_xy=0,S_xx=0,x=0,y=0,S_y=0,S_x=0,slope=0;
  876.    for(i=DATALINE-3;i>=1;i--)
  877.    {
  878.      if(center[i]>=DATACOUNT)   center[i]=DATACOUNT;
  879.      else if(center[i]<=0)      center[i]=0;
  880.      if(center[i-1]>=DATACOUNT) center[i-1]=DATACOUNT;
  881.      else if(center[i-1]<=0)    center[i-1]=0;
  882.      if(center[i-2]>=DATACOUNT) center[i-2]=DATACOUNT;
  883.      else if(center[i-2]<=0)    center[i-2]=0;
  884.      if((((absx(center[i]-center[i-1])>5)&&(absx(center[i]-center[i-2])>7))||(center[i]<=0)||(center[i]>=DATACOUNT)||(ImageBuf2[i][center[i]]==1||
  885.       ImageBuf2[i][center[i]+1]==1||ImageBuf2[i][center[i]-1]==1||ImageBuf2[i][center[i]+2]==1||ImageBuf2[i][center[i]-2]==1))&&value_flag==0&&valuerownum==0)
  886.      {  
  887.          valuerownum=i;//中心壞行標(biāo)號(hào)
  888.          value_yici=i;
  889.          value_flag=1;
  890.      }
  891.      if((center[i]-center[i-1])<=-1)
  892.        yx_right++;
  893.      else if((center[i]-center[i-1])>=1)
  894.        yx_left++;
  895.      if(value_flag!=0&&valuerownum!=0)
  896.      {
  897.        if((yx_right>(yx_right+yx_left)*3/4)||(i>43&&((center[i]-center[i-1])<0&&(center[i]-center[i-2])<0)))
  898.        {
  899.          if(((center[i]-center[i-1])>0&&(center[i]-center[i-2])>0)||(center[i]<=0)||(center[i]>=DATACOUNT)||(ImageBuf2[i][center[i]]==1||
  900.               ImageBuf2[i][center[i]+1]==1||ImageBuf2[i][center[i]-1]==1||ImageBuf2[i][center[i]+2]==1||ImageBuf2[i][center[i]-2]==1))
  901.          {
  902.             valuerownum=i;
  903.             break;
  904.          }
  905.        }
  906.        else if((yx_left>(yx_right+yx_left)*3/4)||(i>43&&((center[i]-center[i-1])>0&&(center[i]-center[i-2])>0)))
  907.        {
  908.           if(((center[i]-center[i-1])<0&&(center[i]-center[i-2])<0)||(center[i]<=0)||(center[i]>=DATACOUNT)||(ImageBuf2[i][center[i]]==1||
  909.               ImageBuf2[i][center[i]+1]==1||ImageBuf2[i][center[i]-1]==1||ImageBuf2[i][center[i]+2]==1||ImageBuf2[i][center[i]-2]==1))
  910.           {
  911.              valuerownum=i;
  912.              break;
  913.           }
  914.        }
  915.        else break;
  916.      }
  917.    }
  918. }
  919. //作用:計(jì)算有效行          根據(jù)上面黑線(xiàn)的中心偏差來(lái)求解有效行
  920. //改變?nèi)肿兞浚?valuerownum
  921. int wanqishi=0;
  922. void panduan_youxiao()
  923. {
  924.   zuobian_youxiao=0,zuobian_stop=0,youwan_youxiao=0,youwan_flag=0,youwan_center=0,youwan_centerstop=0;
  925.   youbian_youxiao=0,youbian_stop=0,zuowan_youxiao=0,zuowan_flag=0,zuowan_center=0,zuowan_centerstop=0;
  926.   wandao_youxiao=0,zuowan=0,youwan=0,youbian_qi=0,zuobian_qi=0;
  927.   for(int i=wanqishi;i>valuerownum;i--)
  928.   {
  929.     if(center[i]<=0||center[i]>=DATACOUNT)
  930.       break;
  931.      if((center[i]-center[i-1])<=-1&¢er[i]!=0&¢er[i]!=DATACOUNT&¢er[i-1]!=0&¢er[i-1]!=DATACOUNT)
  932.        right++;
  933.      else if((center[i]-center[i-1])>=1&¢er[i]!=0&¢er[i]!=DATACOUNT&¢er[i-1]!=0&¢er[i-1]!=DATACOUNT)
  934.        left++;
  935.   }
  936.   if((right>(left+right+1)/2)&&(zshizi==0&&zxshizi==0&&yxshizi==0))//右彎
  937.   {
  938.     for(int xk=wanqishi;xk>=valuerownum;xk--)
  939.     {
  940.       if((blackleft[xk]-blackleft[xk-1])<=0&&(blackleft[xk]-blackleft[xk-2])<=0&&zuobian_qi==0)
  941.         zuobian_qi=xk-2;
  942.       if((blackleft[xk]-blackleft[xk-1])<=0&&(blackleft[xk]-blackleft[xk-2])<=0&&zuobian_stop==0)
  943.         zuobian_youxiao=xk-2; //右彎左側(cè)連續(xù)
  944.       else
  945.         zuobian_stop=1;
  946.       if(blackright[xk]==DATACOUNT&&blackright[xk+1]==DATACOUNT&&blackright[xk-1]==DATACOUNT&&youwan_flag==0
  947.          &&ImageBuf2[xk-1][blackright[xk-1]-1]==0&&ImageBuf2[xk+1][blackright[xk+1]-1]==0)
  948.       {
  949.         youwan++;
  950.         if(youwan>5)
  951.         {
  952.           youwan_youxiao=xk;//并且右邊有極點(diǎn)
  953.           youwan_flag=1;
  954.         }
  955.       }
  956.       else if(blackright[xk]==DATACOUNT&&blackright[xk+1]==DATACOUNT&&blackright[xk-1]!=DATACOUNT&&youwan_flag==0)
  957.       {
  958.         youwan_youxiao=xk;//并且右邊有極點(diǎn)
  959.         youwan_flag=1;
  960.       }
  961.      // if(((center[xk]-center[xk-1])>=0)&&(youwan_centerstop==0)&&xk<43)
  962.       if(((center[xk]-center[xk-1])>0||center[xk-1]>=DATACOUNT)&&(youwan_centerstop==0)&&xk<(wanqishi-4))
  963.     //  if(((center[xk]-center[xk-1])<=0&¢er[xk-1]<=DATACOUNT)&&(youwan_centerstop==0)&&xk<(wanqishi-4))
  964.       {
  965.         youwan_center=xk;//并且平滑后的中心線(xiàn)的方向一致
  966.         youwan_centerstop=1;
  967.       }
  968.      // else if(((center[xk]-center[xk-1])>0||center[xk-1]>=DATACOUNT)&&(youwan_centerstop==0)&&xk<(wanqishi-4))
  969.         //if(((center[xk]-center[xk-1])>0||center[xk-1]>=DATACOUNT)&&(youwan_centerstop==0)&&xk<(wanqishi-4))
  970.         
  971.     }
  972.     if(youwan_flag==1&&youwan_centerstop&&zuobian_youxiao>4&&(zuobian_youxiao<=youwan_center))
  973.     {
  974.       value=youwan_center;//符合以上條件,判定為右彎,重新選擇有效行youwan_youxiao
  975.       wandao_youxiao=1;
  976.     }
  977.   }
  978.   if((left>(left+right+1)/2)&&(zshizi==0&&zxshizi==0&&yxshizi==0))//左彎
  979.   {
  980.     for(int xk=wanqishi;xk>=valuerownum;xk--)
  981.     {
  982.       if((blackright[xk]-blackright[xk-1])>=0&&(blackright[xk]-blackright[xk-2])>=0&&youbian_qi==0)
  983.         youbian_qi=xk-2;
  984.       if(youbian_qi!=0&&(blackright[xk]-blackright[xk-1])>=0&&(blackright[xk]-blackright[xk-2])>=0&&youbian_stop==0)
  985.         youbian_youxiao=xk-2; //左彎右側(cè)連續(xù)
  986.       else
  987.         youbian_stop=1;
  988.       if(blackleft[xk]==0&&blackleft[xk+1]==0&&blackleft[xk-1]==0&&zuowan_flag==0)
  989.       {
  990.         zuowan++;
  991.         if(zuowan>5)
  992.         {
  993.         zuowan_youxiao=xk;//并且左邊有極點(diǎn)
  994.         zuowan_flag=1;
  995.         }
  996.       }
  997.       else if(blackleft[xk]==0&&blackleft[xk+1]==0&&blackleft[xk-1]!=0&&zuowan_flag==0
  998.               &&ImageBuf2[xk-1][blackleft[xk-1]]==0&&ImageBuf2[xk+1][blackleft[xk+1]]==0)
  999.       {
  1000.         zuowan_youxiao=xk;//并且左邊有極點(diǎn)
  1001.         zuowan_flag=1;
  1002.       }
  1003.      // if((((center[xk]-center[xk-1])<=0))&&zuowan_centerstop==0&&(xk<43))
  1004.        if((((center[xk]-center[xk-1])<0)||center[xk]<=0)&&zuowan_centerstop==0&&(xk<43))
  1005.       // if((((center[xk]-center[xk-1])>=0)&¢er[xk]>=0)&&zuowan_centerstop==0&&(xk<(wanqishi-4)))
  1006.       {
  1007.         zuowan_center=xk;//并且平滑后的中心線(xiàn)的方向一致
  1008.         zuowan_centerstop=1;
  1009.       }
  1010.      // else //if((((center[xk]-center[xk-1])<0)||center[xk]<0)&&zuowan_centerstop==0&&(xk<(wanqishi-4)))
  1011.         
  1012.     }
  1013.     if(zuowan_flag==1&&zuowan_centerstop&&youbian_youxiao>4&&(youbian_youxiao<=zuowan_center))
  1014.     {
  1015.       
  1016.       value=zuowan_center;//符合以上條件,判定為左彎,重新選擇有效行zuowan_youxiao
  1017.       wandao_youxiao=1;
  1018.     }
  1019.   }
  1020. }
  1021. int ii,jj;
  1022. void TurnPWM()
  1023. {
  1024.    if(valuerownum>=47)//有效行離車(chē)太近,可能沖出賽道了
  1025.    {
  1026.      wanqishi=45;//虛擬起始點(diǎn),判斷是否有噪點(diǎn)影響了有效行的讀取
  1027.      valuerownum=valuerownum-13;
  1028.      panduan_youxiao();//克服平滑濾波帶來(lái)的影響,尋找真正有效點(diǎn)
  1029.      if(wandao_youxiao==1)//如果是彎道
  1030.        valuerownum=46; //這樣,數(shù)據(jù)就不會(huì)丟棄了,就會(huì)進(jìn)入下一個(gè)if語(yǔ)句里
  1031.      else
  1032.        badframe=1;//不是彎道,舍棄數(shù)據(jù)
  1033.    }
  1034.    if(!badframe)//如果數(shù)據(jù)有效
  1035.    {
  1036.      CenterEx[1]=CenterEq;
  1037.      sum=0;ii=0;
  1038.      if(valuerownum>=35)//最近處,一般是急彎道
  1039.      {   
  1040.       
  1041.         wanqishi=valuerownum+5;//虛擬起始點(diǎn),判斷是否有噪點(diǎn)影響了有效行的讀取   下同,不做進(jìn)一步注釋
  1042.         if(wanqishi>46)  wanqishi=46;
  1043.         valuerownum=valuerownum-10;
  1044.         panduan_youxiao();//克服平滑濾波帶來(lái)的影響,尋找真正有效點(diǎn)
  1045.         if(wandao_youxiao==1)
  1046.           valuerownum=value;//有效的話(huà)把實(shí)際的有效行求出
  1047.         else
  1048.           valuerownum=valuerownum+10;//無(wú)效的話(huà),還原原值
  1049.      }
  1050.      else if(valuerownum>=17&&valuerownum<35)//有效行在圖像中部
  1051.      {
  1052.        wanqishi=valuerownum+9;
  1053.         valuerownum=valuerownum-8;
  1054.         panduan_youxiao();
  1055.         if(wandao_youxiao==1)
  1056.         {
  1057.           valuerownum=value;
  1058.         }
  1059.         else
  1060.           valuerownum=valuerownum+8;
  1061.      }
  1062.       else  if(valuerownum>=9&&valuerownum<17)//有效行靠前,離車(chē)較遠(yuǎn)了
  1063.       {   
  1064.         wanqishi=valuerownum+12;
  1065.         valuerownum=valuerownum-2;
  1066.         if(valuerownum<=0)  valuerownum=0;      
  1067.         panduan_youxiao();
  1068.         if(wandao_youxiao==1)
  1069.         {
  1070.           valuerownum=value;
  1071.         }
  1072.         else
  1073.         {
  1074.           valuerownum=valuerownum+2;
  1075.         }  
  1076.      }
  1077.      else  if(valuerownum>=0&&valuerownum<9)//有效行離車(chē)更遠(yuǎn)了,說(shuō)明是直道或小s
  1078.      {   
  1079.         zhidao=1;
  1080.         wandao=0;
  1081.      }
  1082.      for(int i=47;i>(valuerownum+1);i--)//五點(diǎn)平滑濾波,使中線(xiàn)更平滑
  1083.         center[i]=(center[i+2]+center[i+1]+center[i]+center[i-1]+center[i-2])/5;
  1084.      for(jj=valuerownum;jj<DATALINE;jj++)//濾波后進(jìn)行加權(quán)平均,
  1085.      {
  1086.        sum+=(center[jj]-TurnMidPosition)*CorrectEx[jj];
  1087.        ii++;      
  1088.      }
  1089.      CenterEq=(sum/ii); //得到平均值
  1090.    }                                                                 
  1091.    else//無(wú)效時(shí)保持原來(lái)的數(shù)據(jù)
  1092.    {      
  1093.       CenterEq=lasterror;
  1094.       lasterror=CenterEq;
  1095.       badframe=0;
  1096.    }
  1097.    if(CenterEq>70)//對(duì)加權(quán)平均進(jìn)行限幅,也可不限,數(shù)值根據(jù)自己的小車(chē)定,
  1098.    {              //一般達(dá)不到限幅值,為了防止突發(fā)情況
  1099.      CenterEq=70;
  1100.    }
  1101.     else if(CenterEq<-70)
  1102.     {
  1103.       CenterEq=-70;
  1104.     }
  1105.     LastTurnPWMOUT=TurnPWMOUT;//新的給舊的
  1106.     TurnPWMOUT=(-TurnP*CenterEq-TurnD*lasterror) ; //得出轉(zhuǎn)向PWM,但此時(shí)還未加舵機(jī)中值
  1107.     lasterror=(CenterEq-CenterEx[1]);
  1108.    
  1109. }

  1110. /***********************************************************
  1111. 函數(shù)名稱(chēng):TurnPWMOut
  1112. 函數(shù)功能:
  1113. 入口參數(shù):NewspeedPWM      當(dāng)前的電機(jī)輸出PWM
  1114.           LastspeedPWM     上次電機(jī)輸出PWM
  1115.           PeriodCount      平滑周期
  1116. ***********************************************************/
  1117. #define TURNPERIODFAV  (30) //攝像頭一幀33ms,取30,容易整除,也可不用平滑輸出
  1118. s16 TurnPWMOut(s16 NewturnPWM ,s16 LastturnPWM,s16 PeriodCount)
  1119. {
  1120.   s16  turnPWMfav ;
  1121.   s16  turnOUT ;
  1122.   turnPWMfav = NewturnPWM - LastturnPWM ;
  1123.   turnOUT = turnPWMfav *(PeriodCount)/TURNPERIODFAV + LastturnPWM ;
  1124.   return turnOUT ;
  1125. }
  1126. void fasong_erzhihua_bianxian()//發(fā)送到串口調(diào)試助手
  1127. {
  1128.   int i,j,cha;
  1129.   for(i=49;i>=0;i--)
  1130.   {
  1131.   ImageBuf2[i][center[i]]='*';
  1132.   }  
  1133.   uart_putchar (UART0,'\n' );
  1134.   uart_putchar (UART0,'0' );
  1135.   uart_putchar (UART0,'0' );
  1136.   uart_putchar (UART0,'0' );
  1137.   for(i=0;i<13;i++)
  1138.   {
  1139.     for(j=0;j<10;j++)
  1140.     {
  1141.        uart_putchar (UART0,j+0x30 );
  1142.     }
  1143.   }
  1144.   uart_sendStr(UART0,"  ");
  1145.   uart_sendStr(UART0,"XL:");
  1146.   if(slope<0)
  1147.   {
  1148.     uart_putchar(UART0,'-');
  1149.     slope=-slope;
  1150.   }
  1151. ……………………

  1152. …………限于本文篇幅 余下代碼請(qǐng)從51黑下載附件…………
復(fù)制代碼

所有資料51hei提供下載:
國(guó)賽攝像頭程序.rar (12.99 MB, 下載次數(shù): 133)


分享到:  QQ好友和群QQ好友和群 QQ空間QQ空間 騰訊微博騰訊微博 騰訊朋友騰訊朋友
收藏收藏3 分享淘帖 頂1 踩
回復(fù)

使用道具 舉報(bào)

沙發(fā)
ID:702441 發(fā)表于 2020-3-6 14:40 | 只看該作者
你好,我下載了你的程序,但是沒(méi)有發(fā)現(xiàn)程序打開(kāi)的地方啊,是keil還是什么軟件
回復(fù)

使用道具 舉報(bào)

本版積分規(guī)則

手機(jī)版|小黑屋|51黑電子論壇 |51黑電子論壇6群 QQ 管理員QQ:125739409;技術(shù)交流QQ群281945664

Powered by 單片機(jī)教程網(wǎng)

快速回復(fù) 返回頂部 返回列表