caijie001的个人空间 https://bbs.21ic.com/?1875788 [收藏] [复制] [RSS]

日志

无“飞卡”不青春~

已有 888 次阅读2018-1-13 00:46 |个人分类:飞思卡尔杯|系统分类:单片机

刚刚考完一科,放个小短假,来更新一下我的青春~飞思卡尔学习之旅吧
续前面的帖子:
无“飞卡”不青春~12-02日更新
https://bbs.21ic.com/icview-2389814-1-1.html?fromuid=1875788

基本的芯片操作我就不说了,这些都是基本的功夫,我只说处理数据的部分
怎么采集图像,这个我也不说了,我当时是直接调用山外的库的。。。。毕竟都是配套资料
首先,想要让车正确沿着赛道跑,那必须保证我们采集的图像是正确的。。。
我们需要用上位机看我们采集的图像,代码的实现,很简单,调用山外的库即可。
camera_get_img();     //摄像头获取图像//黑白摄像头
      img_extract(img,imgbuff, CAMERA_SIZE);               //解压图像,为了调用 
[/code]
上位机显示了我们的摄像头的图像,有一点就是图像分辨率越大上位机显示越卡顿,就是会一帧一帧的卡
所以,我使用   60*80  的分辨率
一开始,我们根本不需要想怎么弄懂摄像头采集的过程与原理,简单了解一下,我们只需要怎么使用这些数据即可。
其中,主要掌握的一些包括如何控制摄像头采集到自己想要的行数列数、修改摄像头的阈值来调节黑白程度、
调节摄像头的焦距、摄像头的前瞻以及高度等等(都是根据自己的实际情况解决的)不同的环境会有不同的效果
我当时是看着上位机的图像调整的,反正就是把摄像头放正中间,显示赛道的区域最大,前瞻不能太远,后期根据车速还会调整的
前瞻太远会导致远处图像不真实,摄像头安装的高度也不能太高(越高晃动越厉害)。。。。。。。。。。。。。。。。

现在的主要是要把摄像头的采集数据准确先。
摄像头的焦距不一样,采集的图像就是不一样的,可能会很大的失真,桶形,等等各种各样的奇怪形状,还有就是摄像头采集的频率,
我个人使用的好像是112hz的,这些都可以调整的,

能在上位机显示比较正常的图片,那就基本ok了。

还有一点是图片储存方式是二维数组:
uint8 img[CAMERA_H][CAMERA_W];[/code]这个用来做图像分析还是比较简单的,看英文就能理解意思了。
需要修改分辨率就修改这些的大小即可,我是60*80

采集到图像了,那就先滤波一下,把不需要的噪点去掉:
什么是噪点。。。。
一张图片解释一下:那些在干扰的点就是噪点,处理不好,会使得单片机寻找中线失误

//整场去燥 
void AllFilt()

  //count=0;
  int i,j;
  //unsigned char sum;
  for(i=1;i<ROW-1;i++)
  {
    for(j=1;j<COL-1;j++)
    {
      if(img[i][j]==0x00)
      {  if((img[i-1][j]==0x00 || img[i+1][j]==0x00) && (img[i][j-1]==0x00 || img[i][j+1]==0x00))
          {
               img[i][j]=0x00;  
             //  count++;
          }
         else  
               img[i][j]=0xff;
      }
      else if(img[i][j]==0xff)
      {
         if((img[i-1][j]==0xff || img[i+1][j]==0xff) && (img[i][j-1]==0xff || img[i][j+1]==0xff))
          {
               img[i][j]=0xff; 
          }
         else  
         {
               img[i][j]=0x00;
            //   count++;
         }
       
      }
    }
  }
}[/code]

把一些基本的干扰项滤去。
摄像头采集的数据一般都要进行滤波处理,它可以去除图像中跑道白色上的黑点及黑线处的白点,
以及使计算出的中线更为顺滑不会存在大的跳变点。

当然,上面说的滤波其实是我后面处理的,一开始谁想着滤波啊,都还没处理呢
下面我就说说处理摄像头采集的数据的方法。。。
一般正常情况,我们都是在直道调试的,我由于照片就没有了,在网上找几张差不多的,说说简单的分析

这个就是简单的基本搜线方式,从中间往两边搜索,搜索到左边黑边,就保存黑边的点
又往右边搜线,搜索到右边的黑边,又保存一下,,,然后根据图像的平米性质,得到第 i 行的中点是 j 
放在一个center 数组里面,就得到每行的中点了。。。
代码的实现:
for(i=ROW-1;i>ROW-5;i--)
  {
    for(j=(DATACOUNT/2-10);j<(DATACOUNT-1);j++)//计算前2行右边界  起始点靠左一点
    {
       if(img[i][j-2]==0xff&&img[i][j-1]==0xff&&img[i][j]==0x00&&img[i][j+1]==0x00&&blackright[i]==DATACOUNT)//省掉break,
       {
         blackright[i]=j; 
       }
    }
    for(m=(DATACOUNT/2+10);m>0;m--)        //计算前2行左边界  起始点靠右一点
    {
      if(img[i][m-1]==0x00&&img[i][m]==0x00&&img[i][m+1]==0xff&&img[i][m+2]==0xff&&blackleft[i]==0)//省掉break,
      {
        blackleft[i]=m;
      }
}[/code]上面的代码就是最简单的搜线方式,
只要你的车在赛道的正中间,并且两边都有黑边,那么,足以搜到中线。
但是你的车子不可能每时每刻都在赛道的正中间啊,可能搜到的线就是丢边了呢,怎么办。
那样会出现这种情况:
假设有一边丢线,那么,假设一边的值都丢边了,那么值都为 固定值 ,中线就会不正确:

就是这样子,这肯定是不准确的。
所以,我们要对赛道的一系列处理,防止这种情况的出现,
可以使用平移啊,假如丢边的情况,将另一条不丢边的赛道平移半个赛道宽度(半宽),可以近似认为是中线了。。。
怎么得到赛道的半宽?

实际上摄像头看远处的赛道是比较小的,整体看起来像梯形,所以,远处的赛道不能与近处的赛道一样平移那么多,所以,要自己结合修改一下。。

修正后的图像:

帖几个代码简单实现的东西:


for(i=ROW-1;i>=10;i--)    
  {
      if(blackright[i]<=(DATACOUNT-1)&&blackleft[i]>=1&&(i>=yuanhuan_flang)&¢er[i]==0)//两边都有取图像中心
       {
    
                
         lr_lost=i; 
         youxiaohang=i;
         center[i]=(blackleft[i]+blackright[i])>>1;  
       //  img[i][center[i]]=0x00;
       }[/code]
          
     if(blackright[i]>=DATACOUNT-1&&blackleft[i]>0&¢er[i]==0&&blackleft[i-3]-blackleft[i]>0)//右侧丢线
       {
         if(start_you==0)//右侧开始丢线处 
         {
           start_you=i;//记录起始行
         }
          if(end_you==0)
         {
            for(int kj=DATACOUNT-3;kj>DATACOUNT/2;kj--)//重新遍历,确定丢线最上行
           {
                   for(int ki=start_you;ki>15;ki--)
                   {
                                if(img[ki-5][kj]==0x00&&img[ki-1][kj]==0x00&&img[ki][kj]==0xff&&img[ki+5][kj]==0xff)
                                {
                                if(img[ki-5][kj+5]==0x00&&img[ki-1][kj+5]==0x00&&img[ki][kj+5]==0xff&&img[ki+5][kj+5]==0xff)
                                        {
                                                end_you= ki;
                                                youxiaohang = ki;
                                                break;
                                        }
                                }
                        }
           }
         }
     
         if((start_you<ROW-1)&&(center[i]==0&&blackleft[i]>0))                                //说明前几行有边线  弯道丢边
         {
       // if(i>=(ROW+end_you)>>1)
        //{         
           center[i]=blackleft[i-1]+(center[i+1]-blackleft[i]+2);//mark5
           
           if(center[i]>DATACOUNT)
           {
             center[i] = DATACOUNT;
              
           }
         // img[i][center[i]]=0x00;
          
         }
      //   }

          
       if(start_you>=ROW-1&&(center[i]==0&&blackleft[i]>0))                                                 //  ****近端丟线*****
        {       
           if(i>=(ROW+end_you)>>1)
           {
           if(i==ROW-1)
               center[i] = blackleft[i] + 35;
                 else  
             center[i]=blackleft[i-2]-blackleft[i]+center[i+1]+1;
                 
      if(center[i]>=DATACOUNT)
           {
             center[i] = DATACOUNT;
             
           }
        //  img[i][center[i]]=0x00;
                  
                
                //break;
        }
[/code]

声明:图片来自彭岸辉的博客,此文章为个人经验,不做实际用途的,仅供参考,
请玩车的同学放飞自己的思想,这样子更好,别被我的思想限制你们的思维。






路过

鸡蛋

鲜花

握手

雷人

评论 (0 个评论)