【问题标题】:Object Tracking in EmguCVEmguCV 中的对象跟踪
【发布时间】:2012-01-05 10:22:34
【问题描述】:

我正在构建一个应该跟踪未知对象的对象跟踪程序。用户必须在实时视频流中选择一个应该被跟踪的区域。我的项目类似于这个视频。

http://www.youtube.com/watch?v=G5GLIKIkd6E

我尝试了一种方法,但它不够健壮,并且跟踪器移动很多。所以我又从头开始了。

任何人都知道我如何想出视频中的方法吗?我是 emgucv 的新手,到目前为止我真的不知道从哪里开始。

【问题讨论】:

    标签: c# opencv emgucv template-matching


    【解决方案1】:

    视频建议模板匹配,由于速度的原因,我认为它更有可能是 FFT(快速傅里叶变换)方法,这在 EMGU 中相当容易实现,但很难做到完美。


    模板匹配

    首先,模板匹配方法我创建了一种方法,该方法将匹配您输入其中的图像中的对象 FFT 仅适用于颜色的单光谱图像,您必须拆分光谱并将结果矩阵相加:

    Point Location;
    
    private bool Detect_object(Image<Gray, Byte> Area_Image, Image<Gray, Byte> image_object)
    {
        bool success = false;
    
        //Work out padding array size
        Point dftSize = new Point(Area_Image.Width + (image_object.Width * 2), Area_Image.Height + (image_object.Height * 2));
        //Pad the Array with zeros
        using (Image<Gray, Byte> pad_array = new Image<Gray, Byte>(dftSize.X, dftSize.Y))
        {
            //copy centre
            pad_array.ROI = new Rectangle(image_object.Width, image_object.Height, Area_Image.Width, Area_Image.Height);
            CvInvoke.cvCopy(Area_Image, pad_array, IntPtr.Zero);
    
            pad_array.ROI = (new Rectangle(0, 0, dftSize.X, dftSize.Y));
    
            //Match Template
            using (Image<Gray, float> result_Matrix = pad_array.MatchTemplate(image_object, TM_TYPE.CV_TM_CCOEFF_NORMED))
            {
                Point[] MAX_Loc, Min_Loc;
                double[] min, max;
                //Limit ROI to look for Match
    
                result_Matrix.ROI = new Rectangle(image_object.Width, image_object.Height, Area_Image.Width - image_object.Width, Area_Image.Height - image_object.Height);
    
                result_Matrix.MinMax(out min, out max, out Min_Loc, out MAX_Loc);
    
                Location = new Point((MAX_Loc[0].X), (MAX_Loc[0].Y));
                success = true;
                Results =result_Matrix.Convert<Gray,Double>();
    
            }
        }
        return success;
    }
    

    大多数人忘记的是用零填充数组,类似于我们使用零的模板的大小,因为这对 fft 方法没有影响。我们填充矩阵,否则我们无法正确处理边缘周围的数据,我们可能会错过匹配的项目。

    第二点,我不能强调重要,这是 FFT 方法现在将返回匹配对象左上角。 result_Matrix.MinMax 查找对象最有可能匹配的位置。您需要尝试很多东西,所以如果有更多问题,请在此处或 EMGU 提问,我会尽可能提供帮助。我也会复制并粘贴此解决方案。


    视频中的方法

    好吧,我将让您编写大部分代码,因为我被困住了,但实际上用户使用画框的点击事件来查找图像中对象的设置 e.X 和 e.Y 位置。模板是固定大小的,所以 100x100

    Image<Gray, Byte> template_img = Main_Image.Copy(new Rectangle(x, y, 100, 100);
    

    然后,他在对象周围的原始图像上设置了一个 ROI,这说明了运动。在我们的例子中,我们想要一个围绕 50 像素的模板的缓冲区 (ROI)。这相当于初始投资回报率:

    Main_Image.ROI = new Rectangle(x - 50, y - 50, 200, 200);
    

    现在,由于使用图像的 ROI,我们可以减慢处理速度,并且会再次弄乱原始图像的显示,因此最好执行以下操作:

    using( Image<Gray, Byte> img_ROI = Main_Image.Copy(new Rectangle(x - 50, y - 50, 200, 200))
    {
        Detect_object(img_ROI, template_img)
    }
    

    我们使用 using 语句,因为它会在完成后处理额外的图像数据并释放资源。

    现在,ROI 实际上由 Detect_object 的结果控制,这就是我们将 Location 保留为全局变量的原因。一旦 Location 成功匹配模板,我们的 using 语句将看起来更像:

    using( Image<Gray, Byte> img_ROI = Main_Image.Copy(new Rectangle(Location.X - 50, Location.Y - 50, 200, 200)) 
    {
        ...
    }
    

    除了 ROI 和模板的矩形之外,几乎就是这样

    干杯,

    克里斯

    【讨论】:

    • 我尝试跟踪代码,有点困惑于检测对象中的大多数方法对一个人的作用,以及 bool 成功的工作原理......
    【解决方案2】:

    该视频似乎使用了类似于 Gary Bradski 描述的 CAMSHIFT method 的内容。 Here 是 camshift 演示应用程序的 C++ 代码,我知道它不是 C#,但希望它可以轻松移植到 EmguCV。 Here 是 camshift 算法核心的文档。

    希望有帮助!

    【讨论】:

    • 看Trashlock视频的置顶评论“@Computer22Nerd 嗯,它主要只是模板匹配。除了它绑定到一个小区域而不是在整个图像上进行。基本上绿色框是被跟踪的对象,红框是跟踪区域(模板要测试的区域),当我用鼠标点击时,一个40x40的区域被定义为模板,一个80x80的区域被定义为搜索区域。该系统的关键是模板在每一帧都更新,从而可以跟踪不断变化的对象”
    • @Chris 很高兴知道。肯定有比每帧直接创建蛮力模板更好的方法。演示的方法也容易出现漂移,这在视频中经常出现。我会看看我能不能找到我用来做这种东西的论文,然后把它贴出来。另外,希望您不要认为我对您投了反对票,因为您有一个高质量的答案:)
    • 嘿,如果你这样做了,那很好,但方法和它们的能力之间经常会混淆。我同意是的,当然有更好的方法,但 camshift 本身并不合适,因为(尽管 ROI 最小化)整个手都在移动,即有很多噪音。您需要包括适当的轮廓分析,以在每一帧中找到指尖,以获得更可靠的参考点。对于 EMGU/opencv 中的其他人,这将在背景减法/投影方法和“结构分析和形状描述符”的欢呼声中
    猜你喜欢
    • 1970-01-01
    • 2012-11-17
    • 2011-11-07
    • 1970-01-01
    • 2018-09-01
    • 1970-01-01
    • 2015-12-02
    • 1970-01-01
    • 2012-11-11
    相关资源
    最近更新 更多