用户
 找回密码
 立即注册

QQ登录

只需一步,快速开始

点击进入授权页面

只需一步,快速开始

  • QQ空间
  • 回复
  • 收藏
  • TA的每日心情
    无聊
    2017-6-24 14:20
  • 签到天数: 3 天

    [LV.2]偶尔看看I

    本帖最后由 190808149 于 2016-12-1 13:00 编辑

    训练Intel Curie内置的神经网络识别简单头部动作。
    用Intel Curie Genduino101开发板内置的General Vision神经网络识别摄像头实时视频中的简单头部动作。点头代表Yes确认。摇头代表No否认。系统显示?号代表暂不能识别输入动作。


    废话少说,先看视频:




    最新源程序请在github上下载:
    1.电脑上运行Processing客户端,负责收集实时视频,处理光流,并将光流向量发送给Intel Curie Genduino 101。程序如下,可直接在processing中运行:
    https://github.com/qq95538/Servo ... aster/OpticalFlow
    2.电脑USB外接Intel Curie Genduino101,负责对光流向量进行训练和识别,可直接在arduino sketch中编译传送给Genduino:
    https://github.com/qq95538/ServoTurnAround/tree/master/CuireNeron
    如您在使用以上代码出现问题,请在论坛回帖与我取得联系。

    详细介绍如下:

    1、神经网络入门
    由IBM公司编著,简单,易懂,权威。
    http://www.arduino.cn/thread-31574-1-1.html
    主要介绍基本的神经网络系统,和反向传播神经网络。

    2、RBF神经网络
    http://www.arduino.cn/thread-31575-1-1.html
    Curie使用的不是反向传播神经网络,而是径向神经网络RBF。

    3、Intel Curie Genduino101内置的NeuroMem神经网络就是RBF神经网络。

    http://www.arduino.cn/thread-31577-1-1.html
    查看NeuroMem官方网站说明书。再次确认该神经网络运行原理。


    4、查看例程,学习使用神经网络的基本方法和关键函数。
    主要是4点:
    (1) 应用神经网络前,先创建一个神经网络对象。
    #include <CurieNeurons.h>
    CurieNeurons hNN;
    (2) 启动神经网络对象。
    hNN.begin();
    (3) 让神经网络反复学习多组向量。
    hNN.learn(vector, sampleNbr*signalNbr, catL);
    (4) 神经网络可以工作了。用识别函数判断未知向量的状态。
    hNN.classify(vector, sampleNbr*signalNbr,&dist, &cat, &nid);

    结合例程,我画出了这个项目的动作识别原理图。

    配图1:Intel Curie内置神经网络识别简单头部动作.png

    5、项目制作过程

    (1)电脑上运行Processing客户端,负责收集实时视频,处理光流,并将光流向量发送给Intel Curie Genduino 101。


    首先在电脑安装Processing开发平台。在https://www.processing.org下载安装最新版本Processing软件。

    然后打开Processing软件,给Processing平台添加OpenCV库。
    文章截图2.png

    选择菜单栏 工具-添加工具。点击鼠标。打开工具管理器。
    文章截图1.png
    选择第一页, Libraries,在下拉菜单中选择OpenV,点击Install安装。(注意,这一步需翻墙)

    安装成功后,就可以使用本文后附的Processing程序代码了。程序代码启动电脑摄像头,分析拍摄的实时录像光流方向,并传递给Intel Curie Genduino 101进行处理。

    (2)电脑USB外接Intel Curie Genduino101,负责对光流向量进行训练和识别,可直接在arduino sketch中编译传送给Genduino。


    要调用Genduino 101的神经元分析光流向量,首先,要安装General Vision NeuroMem神经网络API库。

    在链接处:
    http://www.general-vision.com/download/curieneurons-free-library/
    下载CurieNeuron库zip文件。

    打开arduino sketch,首先确保Intel Curie Genduino 101板块驱动是否已经添加。

    文章截图3.png

    文章截图4.png

    确保sketch的开发板管理器已经安装和正确识别Curie以后,再添加CuireNeuron库。

    文章截图5.png

    然后添加刚才我们下载好的CuireNeuron.zip库文件。

    文章截图6.png

    神经网络API CurieNeuron库添加成功后,就可以使用本文后附的程序代码,调用Curie的神经元功能了。

    下面将代码放入Sketch烧写到Intel Curie Genduino 101开发板:


    IMG_20161130_005212.jpg
    将Genduino 101用USB和电脑连接,并用Sketch烧写固件程序。打开串口查看器,显示“Neurons Initialized.”神经网络初始化完成。即可开始操作。
    IMG_20161130_005130.jpg

    Genduino101充当服务器端,用于处理光流向量。在Genduino固件上,我使用pin 13 LED做指示灯。每接收处理一次向量数据,LED灯就明暗切换一次。方便随时观察Genduino 101运行状态。

    IMG_20161130_012254.jpg
    自己对着笔记本电脑聊天摄像头做点头-摇头测试,向量数据通过Serial串口传输到Genduino101服务器端识别后,返回电脑Processing客户端。显示Yes和No结果。每一个动作的Yes/No识别结果依次向上滚动,逐渐更替缩小。

    IMG_20161130_012318.jpg

    当然,在Genduino识别动作之前,按下A键训练头部动作1,按下S键训练头部动作2,按下其他任意键结束训练。程序进入正常识别状态。
    读者可以稍微更改程序扩展更多的动作。如果您有心得,请回帖与我探讨。


    6、服务端Intel Curie Genduino101程序设计

    [C++] 纯文本查看 复制代码
    /**
     *processing control a 2-4 servos platform 
     *modified by qq95538 
     *
     *my email address is [url=mailto:190808149@qq.com]190808149@qq.com[/url]
     *
     */
    
     #include <CurieNeurons.h>
     CurieNeurons hNN;
    
     int catL = 0;
     int prevcat = 0;
     int dist, cat, nid, nsr, ncount;
     
     const short sampleNbr = 20;
     const short signalNbr = 2;
     byte vector[sampleNbr*signalNbr];
     byte flowX[sampleNbr];
     byte flowY[sampleNbr];
     boolean a = false;
     void setup()   
     {
       pinMode(13, OUTPUT);
       Serial.begin(115200);
       while (!Serial);
       if(hNN.begin()==0){
          Serial.print("neurons initialized");
          hNN.forget(500);
       }
       else{
          Serial.print("error.");
       }
     }
     void loop() 
     {
       while(Serial.available()==0);
       char data=Serial.read();
       for(int i = 0; i < sampleNbr; i++)
       {
           while(Serial.available()==0);
           vector[i*signalNbr]=Serial.read();
       }
       for(int i = 0; i < sampleNbr; i++)
       {
           while(Serial.available()==0);
           vector[i*signalNbr+1]=Serial.read();
       }
       a = !a;
       digitalWrite(13, a);   // turn the LED on (HIGH is the voltage level)
       switch(data)
       {    
           case '%':
               //learn 1
               catL = 1;          
               /*for(int i = 0; i <sampleNbr; i++){
                  Serial.write(vector[i*signalNbr]); 
                  Serial.write(vector[i*signalNbr+1]);
               }*/
               ncount = hNN.learn(vector, sampleNbr*signalNbr, catL);
               Serial.write(ncount);
               Serial.write("#");
               Serial.flush();
               break;
           case '^':
               //learn 1
               catL = 2;          
               /*for(int i = 0; i <sampleNbr; i++){
                  Serial.write(vector[i*signalNbr]); 
                  Serial.write(vector[i*signalNbr+1]);
               }*/
               ncount = hNN.learn(vector, sampleNbr*signalNbr, catL);
               Serial.write(ncount);
               Serial.write("#");
               Serial.flush();
               break;
           case '$':
               // Recognize
               hNN.classify(vector, sampleNbr*signalNbr,&dist, &cat, &nid);
               Serial.write(cat);
               Serial.write("#");
               Serial.flush();
               break;
                          
       }
       
     }
    


    7、客户端Processing程序设计

    [Java] 纯文本查看 复制代码
    import gab.opencv.*;
    import processing.video.*;
    import processing.serial.*;
    Serial port;
    
    OpenCV opencv;
    Capture video;
    byte lastx, lasty;
    byte currentx, currenty;
    byte[] rawVecX;
    byte[] rawVecY;
    int index;
    int count;
    boolean action;
    final int sampleNbr = 20;
    byte state;
    byte[] result;
    int P_result;
    
    void setup() {
      size(640, 240);
    
      result = new byte[3];
      P_result = 0;
      rawVecX = new byte[sampleNbr];
      rawVecY = new byte[sampleNbr];
      lastx = 0;
      lasty = 0;
      count = 0;
      port = new Serial(this, Serial.list()[0], 115200);
      video = new Capture(this, 320, 240);
      opencv = new OpenCV(this, 320, 240);  
      video.start();
    }
    
    void draw() {
      if(keyPressed){
         if (key == 'a' || key == 'A') {
           state = 1;
           println("change state to learning 1");
         } 
         else if (key == 's' || key == 'S') {
           state = 2;
           println("change state to learning 2");;
           
         }
         else{
           state = 3;
           println("change state to classifying");
         }
      }
      background(0);
      opencv.loadImage(video);
      opencv.calculateOpticalFlow();
      image(video, 0, 0);
      translate(video.width,0);
      stroke(255,0,0);
      opencv.drawOpticalFlow();
      PVector aveFlow = opencv.getAverageFlow();
      int flowScale = 50; 
      stroke(255);
      strokeWeight(2);
      
      textSize(50);
      if(result[2] == 1){    
        text("Yes", 10, 230);
      }
      else if(result[2] == 2){
        text("No", 10, 230);  
      }
      else{
        text("?", 10, 230);
      }
      textSize(40);
      if(result[1] == 1){    
        text("Yes", 10, 175);
      }
      else if(result[1] == 2){
        text("No", 10, 175);  
      }
      else{
        text("?", 10, 175);
      }
      textSize(30);
      if(result[0] == 1){    
        text("Yes", 10, 130);
      }
      else if(result[0] == 2){
        text("No", 10, 130);  
      }
      else{
        text("?", 10, 130);
      }
      
      line(video.width/2, video.height/2, video.width/2 + aveFlow.x*flowScale, video.height/2 + aveFlow.y*flowScale);
      
      currentx=byte(map(aveFlow.x, -1, 1, 0, 255));
      currenty=byte(map(aveFlow.y, -1, 1, 0, 255));
      if (action == true){
          if(index < sampleNbr){
              rawVecX[index] = currentx;
              rawVecY[index] = currenty;
              index++;  
          }
          else
          {
              action = false; 
              print("count=");
              println(count); 
              for(int i = 0; i < sampleNbr; i++){
                  print(int(rawVecX[i]));
                  print(",");
              }
              println();
              for(int i = 0; i < sampleNbr; i++){
                  print(int(rawVecY[i]));
                  print(",");
              }
              print("|");
              println(state);
              sendToCurie(state, rawVecX, rawVecY);
              println("accepted");
           }
      }
      else
      {
        if(abs(int(currentx)-int(lastx)) > 30 || abs(int(currenty)-int(lasty)) > 30){
          action = true;
          index = 0;
          count = count + 1;
          println("started");
        }
      }
      lastx = currentx;
      lasty = currenty;
    
    }
    
    void captureEvent(Capture c) {
      c.read();
    }
    
    void sendToCurie(byte LorC, byte[] vecX, byte[] vecY) //send yaw and roll angel to MegaPi to control servos 
    {
       if(LorC == 1){
            port.write('%');        
       }
       else if(LorC == 2){
            port.write('^');
       }
       else{
            port.write('$');
       }
          
      port.write(vecX);
      port.write(vecY);
      
      byte inByte;
      int ct = 0;
      while (port.available() > 0){
          inByte = byte(port.read());
          print(int(inByte));
          if(ct == 0){
            result[0] = result[1];
            result[1] = result[2];
            result[2] = inByte;
          }
          print(">");
          if(inByte == '#'){
              break;
          }
          ct = ct + 1;
      }
    }
    
    












    打赏

    2人打赏

    没有processing库,例如opencv
    heiketiguo 发表于 2016-11-30 23:25
    没有processing库,例如opencv

    您好,OpenCV库需要在Processing中选择 工具-添加工具 选择OpenCV 安装。已更新文章,请查看文章教程添加OpenCV。
    打赏
    Arduino代码有错误,hNN.后面第一个字母要大写
    if(hNN.begin()==0){这句也有问题,不知怎么改?
    as.JPG
    搞定了,Arduino与101库版本过低导致的
    heiketiguo 发表于 2016-12-3 08:03
    搞定了,Arduino与101库版本过低导致的

    嗯,是说怎么这么奇怪?连begin函数都没有找到。
    打赏
    后面的识别不了啊
    有空要试试
    本帖最后由 incarry 于 2017-10-19 10:39 编辑

    网页找不到CuireNeuron.zip ,购买按钮也自动跳转到主页了 还请楼主分享一下
    发新帖
    发表评论
    高级模式  
    您需要登录后才可以回帖 登录 | 立即注册  
    关闭

    推荐主题 上一条 /2 下一条