针对移动机器人的人体目标检测和跟踪系统的实现

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/NK_test/article/details/74127868

预期效果

机器人可以在较为简单的生活环境背景中,实现对单个人体目标的检测和实时跟踪,做出前进、后退、左转和右转等基本操作。

运行环境

  1. Windows7、 Visual Studio 2013
  2. EmguCv2.4.9
  3. 小R科技-51duino WiFi视频智能小车机器人(更换加强版的路由模块)

基本思路

检测:我们要利用智能小车并不优秀的硬件设备来实现对人体目标的检测和实时跟踪,检测部分我们使用人脸来定位人体,虽然这样使得智能小车只能识别并跟踪正面人体,但是由于智能小车视角的原因(视角很低)并且摄像头和路由模块传输速率有限,没办法传输高分辨率的图像,这些外部因素使得我们最终确定使用人脸检测定位人体目标。但是如果硬件允许的话,这个完全可以将人脸替换成人体目标的检测。seetaFace引擎是一个开源项目,它的人脸检测模块较为准确,并且速度很快。

跟踪:跟踪主要是要满足实时跟踪,经过对比粒子滤波、Camshift、KCF算法等的优势和缺点,最终决定选择Camshift算法。Camshift算法基于颜色概率分布图进行选择,所以如果背景颜色和目标颜色很接近的时候会造成一定的干扰。算法的跟踪算法也可以随着目标的大小而变化,这对我们通过智能车摄像头来判断目标物体的运动状态是至关重要的。另外,针对我们的具体需求,对算法进行了优化和改进。

  • 为了减少背景色对目标物体的干扰,我们加入了形态学检测,我们人脸的轮廓长宽比是有一定限制的,在这个比例区间内我们认为跟踪是成功的,一旦跟踪目标的矩形区域长宽比例超过这个阈值,我们先暂时忽略掉这一帧,继续用上一帧更新跟踪窗口。

    仅使用Camshift算法:
    这里写图片描述

    加上形态学检测:
    这里写图片描述

  • 如果接连几帧都超过了阈值,我们就认为跟踪目标已经丢失,便暂时停止跟踪,重新检测定位目标再进行跟踪。(检测部分使用seetaFace的检测模块,平均检测时间为十几ms)

        public ObjectTracking(Image<Bgr, Byte> image, Rectangle ROI)
        {
            // Initialize parameters
            trackbox = new MCvBox2D();
            trackcomp = new MCvConnectedComp();
            hue = new Image<Gray, byte>(image.Width, image.Height);
            hue._EqualizeHist();
            mask = new Image<Gray, byte>(image.Width, image.Height);
            //hist = new DenseHistogram(10, new RangeF(0, 255));
            hist = new DenseHistogram(30, new RangeF(0, 180));
            backproject = new Image<Gray, byte>(image.Width, image.Height);

            // Assign Object's ROI from source image.
            trackingWindow = ROI;

            // Producing Object's hist
            CalObjectHist(image);
        }
        public Rectangle Tracking(Image<Bgr, Byte> image, MainWindow mw)
        {
            UpdateHue(image);

            // Calucate BackProject
            backproject = hist.BackProject(new Image<Gray, Byte>[] { hue });

            // Apply mask
            backproject._And(mask);

            // Tracking windows empty means camshift lost bounding-box last time
            // here we give camshift a new start window from 0,0 (you could change it)
            if (trackingWindow.IsEmpty || trackingWindow.Width==0 || trackingWindow.Height==0)
            {
                trackingWindow = new Rectangle(0, 0, 100, 100);
            }
            CvInvoke.cvCamShift(backproject, trackingWindow,
                new MCvTermCriteria(10, 1), out trackcomp, out trackbox);

            // update tracking window
            int width_ = trackcomp.rect.Width;
            int height_ = trackcomp.rect.Height;

            //形态学约束

            if (height_ >= width_ && (2.5 * width_ - 1.0 * height_ ) > 0.01)
            {
                trackingWindow = trackcomp.rect;
               // retry = 0;
            }
            else
            {
                //trackingWindow = trackcomp.rect;
                  mw.RobotEngine.SendDataInSocket(mw.CMD_Stop, mw.ControlIp, mw.Port);
                  mw.hasSendCom = false;
                  retry++;
                  if (retry>=6)
                  {
                      System.Environment.Exit(0); 
                  }
                  //seetaFace重检测
                  image.Save("0.jpg");
                  Process p = new Process();
                  p.StartInfo.FileName = "HumanDection.exe";
                  p.StartInfo.Arguments = "0.jpg seeta_fd_frontal_v1.0.bin";
                  p.StartInfo.WindowStyle = ProcessWindowStyle.Hidden;
                  p.Start();
                  p.WaitForExit();//关键,等待外部程序退出后才能往下执行

                  FileStream fs = new FileStream("face.txt", FileMode.Open, FileAccess.Read);
                  StreamReader sr = new StreamReader(fs);
                  string s = sr.ReadLine();
                  fs.Close();
                  string[] strs = s.Split(' ');
                  trackingWindow.X = int.Parse(strs[0]);
                  trackingWindow.Y = int.Parse(strs[1]);
                  trackingWindow.Width = int.Parse(strs[2]);
                  trackingWindow.Height = int.Parse(strs[3]);
                  image.Draw(trackingWindow, new Bgr(System.Drawing.Color.Red), 3);//绘制检测框  

            }

            //trackingWindow = trackcomp.rect;

            return trackingWindow;
        }

智能车控制算法

我们接收到的图像分辨率的都是640*480,所以我们画出了下面的矩形框。我们根据跟踪框的大小变化比例设定一个阈值,当矩形框的面积变化比例超过这个阈值时,我们就控制智能小车前进或者后退;当跟踪框的中心点的横坐标处于0~100时,我们进行左转操作,当中心点处于540~640时,进行右转操作。

这里写图片描述

核心算法

  1. 使用seetaFace进行人脸检测定位人体目标
  2. 使用改进的Camshift算法(形态学约束+重检测)进行跟踪
  3. 使用C#编写上位机并进行核心运动控制逻辑的编写

基本流程图如下:
这里写图片描述

运行效果

  • 初始帧检测
  • 直行跟踪
  • 转弯跟踪

源码下载

https://github.com/Tachone/ObjectTracking

猜你喜欢

转载自blog.csdn.net/NK_test/article/details/74127868