现在的位置: 首页 > 专题 > 机器人 > Robotics Studio > 设计中心 > 文档 > 专题 > 机器人 > 正文

Robotics Studio学习教程:第二十一天——相扑机器人可以看到什么?

2014年05月08日 Robotics Studio, 文档, 机器人 ⁄ 转载:原文链接 ⁄ 共 5253字 ⁄ 字号 暂无评论 ⁄ 阅读 1,274 次
Robotics Studio学习教程

Robotics Studio学习教程

继之前分享的一篇《Robotics Studio学习教程:第二十天——开始动手写相扑机器人》, 我们将继续分享下一篇《Robotics Studio学习教程:第二十一天——相扑机器人可以看到什么?》,让我继续开始我们学习Visual Programming Language,以及使用Robotics Studio学习开发机器人应用的道路吧。

 

[Robotics Studio] Sumo[III] - 揪~竟...相扑机器人看到了啥? -- Day21

 

每次发生了不思议的悬案时, 都是会暂停画面 (或是缩小为子画面),  然后跳出一位盛竹如 : "揪~竟..."

让我们把时间倒回到机器人被推倒之前, 我也很想对机器人问说 "揪~竟...你看到啥?"

就让我们动手把事实真相展露在世人面前...

(其实如果你在程序执行的时候打开 http://localhost:50000/controlpanel , 参照之前的 DSS in WebInterface , 你其实可以看到一些东西, PS : Simulated Webcam 的 Web 接口只支持 IE, 不支持 firefox )

还记得之前的 Microsoft.Ccr.Adapters.WinForms  吗, 有了这东东, 我们随时可以在 Windows 当中开出窗口, 显示我们想要看的东西.

所以先把这个 dll 参考到 mysumo 的项目当中, 接着, 新增一个 WinForm , 就叫 CameraImage 好了,  上面放个 PictureBox , 就用预设的名称 pictureBox1 , 大小至少要超过 176 x 144 (从 Simulated Webcam 偷看来的大小).

clip_image002

在 using 当中加入:

  1. using Microsoft.Robotics.Services.mysumo;
  2. using webcam = Microsoft.Robotics.Services.WebCam.Proxy;
  3. using System.Drawing.Imaging;

然后我们就可以加入一个 UpdateImage 的函式:

  1.  /// <summary>
  2.  /// 更新图像而且画出影像辨识结果
  3.  /// </summary>
  4.  /// <param name="cameraFrame"></param>
  5.  /// <param name="result"></param>
  6.  public void UpdateImage(webcam.QueryFrameResponse cameraFrame, ImageProcessResult result)
  7.  {    
  8.   System.Drawing.Bitmap img = 
  9.   new System.Drawing.Bitmap(cameraFrame.Size.Width, 
  10.                                         cameraFrame.Size.Height,
  11.                                         PixelFormat.Format24bppRgb);
  12.  
  13.   System.Drawing.Imaging.BitmapData bmd = 
  14.   img.LockBits( new System.Drawing.Rectangle(0, 0, img.Width, img.Height),
  15.                     System.Drawing.Imaging.ImageLockMode.WriteOnly,          
  16.                     System.Drawing.Imaging.PixelFormat.Format24bppRgb);
  17.   System.Runtime.InteropServices.Marshal.Copy(cameraFrame.Frame, 0, 
  18.                                                                  bmd.Scan0, 
  19.                                                                  img.Width * img.Height * 3);
  20.   img.UnlockBits(bmd);
  21.   using (Graphics g = Graphics.FromImage(img))
  22.     {
  23.       g.FillRectangle(Brushes.Red, new Rectangle(result.XMean - 10, result.YMean - 10, 20, 20));
  24.      }
  25.   pictureBox1.Image = img;
  26. }

 

这个函式的内容就是把 cameraFrame 所传进来的 data, 转成 bitmap,  然后在上面画一个 20x20 的红色正方形, 标示 ImageProcessResult 的结果,最后再把它设定给 pictureBox1.Image。

对了, 因为这个项目预设会产生 XML 说明文件, 而且又把所有警告视为错误, 所以你必须要将 public 的 class , function, property 都加上批注, 看你是要改项目设定还是加上批注 (提醒你在 class, function, property 的上一行输入 /// , 就会自动加上批注), 都可以解决问题.

接着在 mysumo.cs , 先新增一个 cameraimage property , 如下:

  1. private CameraImage cameraform;

你可以对 CameraImage 右键单击选解析, 会自动帮你加上 using Robotics.mysumo;
然后在 Start() 当中就可以加入 :

  1. WinFormsServicePort.Post(new RunForm(() => cameraform = new CameraImage()));

当然, RunForm 也可以靠自动解析产生 using Microsoft.Ccr.Adapters.WinForms; 最后, 我们就可以修改 ValidateFrameHandler 这个函式, 加入一行就可以, 如下:

  1.   // Ignore old images!
  2.   if (msFrame < 1000.0)
  3.   {
  4.       result = ProcessImage(cameraFrame.Size.Width, 
  5.                                     cameraFrame.Size.Height, 
  6.                                     cameraFrame.Frame);
  7.       WinFormsServicePort.FormInvoke(() => cameraform.UpdateImage(cameraFrame, result));
  8.        // 加這行!
  9.       double msProcessing = DateTime.Now.Subtract(begin).TotalMilliseconds;    
  10.       LogVerbose(LogGroups.Console, string.Format("{0} Frame {1} ms Processed {2} ms"
  11.                        begin, msFrame, msProcessing));
  12.       if (result != null)
  13.      {
  14.           result.TimeStamp = cameraFrame.TimeStamp;
  15.           HandleProcessedImage(result);
  16.       }
  17.       else
  18.       {
  19.           LogVerbose(LogGroups.Console, "Skipping empty camera frame!");
  20.       }
  21.   }

在 ProcessImage 之后, 我们就可以更新画面到 cameraform。

另外提一点, 如果你发生问题, 有可能是一个 bug 造成的, 因为我们加了 WinForm, 会导致该 Dll 多了一个 resource, 而原本的 GetEmbedded() 函式是这样:

  1.   /// <summary>
  2.   /// Find the embedded file with the specified name and return a stream to read its contents
  3.   /// </summary>
  4.   /// <returns></returns>
  5.   private Stream GetEmbeddedFile()
  6.   {
  7.       try
  8.       {
  9.           System.Reflection.Assembly asm = System.Reflection.Assembly.GetExecutingAssembly();
  10.           string[] names = asm.GetManifestResourceNames();
  11.           if(names.Length > 0)
  12.               return asm.GetManifestResourceStream(names[0]);

  13.           return null;
  14.       }
  15.       catch
  16.       {
  17.           return null;
  18.       }
  19.   }

它其实只传回第一个 resource, 但那不一定是 PlayerImage.bmp (有可能是我们加入的 CameraImage form) , 所以建议改为:

  1.   /// <summary>
  2.   /// Find the embedded file with the specified name and return a stream to read its contents
  3.   /// </summary>
  4.   /// <returns></returns>
  5.   private Stream GetEmbeddedFile()
  6.   {
  7.       try
  8.       {               
  9.           System.Reflection.Assembly asm = System.Reflection.Assembly.GetExecutingAssembly();
  10.           List<string> lstnames = new List<string>(asm.GetManifestResourceNames());
  11.          
  12.           string bmpname = lstnames.Find(n => n.EndsWith("playerimage.bmp",
  13.                                                       StringComparison.InvariantCultureIgnoreCase));
  14.           if(bmpname != null)
  15.               return asm.GetManifestResourceStream(bmpname);

  16.           return null;
  17.       }
  18.       catch
  19.       {
  20.           return null;
  21.       }
  22.   }

这样才会找到 playerimage.bmp 这个资源. (其实我比较建议用项目的内容去产生资源文件, 这样 vs2008 都会帮你搞定好存取资源相关的程序, 简单又不会出包...)

欧欧, 还有, 写程序养成归还资源的好习惯, 所以在 DropHandler 当中加入:

  1.   if (cameraform != null)
  2.   {
  3.       WinFormsServicePort.FormInvoke(() =>
  4.       {
  5.           cameraform.Dispose();
  6.           cameraform = null;
  7.       });
  8.   }

这样就可以在机器人被移除的当下, 关掉 cameraform.

最后启动 SimulatedSumoReferee, 加入 mysumo 就可以看到画面啦:

clip_image004

在比赛的过程中, 你就会知道机器人看到啥, 而且还会知道影像辨识最后认定敌人的位置...

最后还是要学盛竹如:

李组长皱了皱眉知道这案情必定不单纯...

难道冥冥之中, mysumo 相扑机器人注定要打赢这场仗?

揪~竟, mysumo 会不会得到最终的胜利呢, 我们下回分晓...

 

让我们继续一下章教程:

《Robotics Studio学习教程:第二十二天——让相扑机器人动起来!》

fgx

分享到:

Wopus问答

×