EmguCV 中的对象跟踪

发布于 2024-12-25 00:49:15 字数 284 浏览 1 评论 0原文

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

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

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

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

I am building an object tracking program that should track the unknown object. The user must select a region in the live video stream that should be tracked. My project is similar to this video.

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

I have tried a method but it is not robust enough and the tracker moves a lot. So I am starting from scratch again.

Anyone knows a method on how I can come up with the one in the video? I am a newbie in emgucv and as of now I really have no idea where to start again.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

往事随风而去 2025-01-01 00:49:15

该视频建议模板匹配,由于速度的原因,我预计它更有可能是 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 询问,我会尽可能提供帮助。我也会复制并粘贴这个解决方案。


视频中的方法

由于时间有限,我将让您编写大部分代码,但实际上用户使用颜料盒的单击事件来查找图像中对象的设置 eX 和 eY 位置。模板的大小固定,即 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);

现在,由于使用图像的投资回报率,我们可以减慢处理速度,并再次搞乱原始图像的显示,因此最好这样做:

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

我们使用声明,因为这会在我们完成后处理额外的图像数据并释放资源。

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

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

除了 ROI 和模板的矩形之外,这几乎就是它,在图像上绘制大小和位置,如果您有问题,请告诉我,但代码应该随时待命,

干杯,

克里斯

The video suggest template matching which due to speed I expect it's more likely to be a FFT (Fast Fourier Transform) Method, this is fairly easy to implement in EMGU however getting it perfect is hard.


Template Matching

First the template matching method I have made a method that will match an object within an image you feed into it FFT only works on single spectrum images for colour you will have to split the spectrum's and add the results matrices together:

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;
}

The thing most people forget is to pad the array with zeros akin to the size of the template we use zeros as this has no effect on the fft method. We pad the matrix else we don't process the data around the edge properly and we can miss matching items.

The second point and I cant stress how important this is is that the FFT method will at the moment return a match to the objects top left hand corner. result_Matrix.MinMax finds the place in which the object is most likely to have matched. There is a lot that you will need to experiment with so any more problems ask here or EMGU and I'll help when I can. I will copy and paste this solution over as well.


The Method in the Video

Well I will leave you to code most of this as I am stuck for time, but in effect the user uses the click event of a paintbox to find set e.X and e.Y location of an object within the image. The template is of a fixed sized so 100x100

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

He then sets an ROI on the original image around the object this accounts for movement. In our case say we want a buffer (ROI) around the template of 50 pixels. This would equate to an intial ROI of:

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

Now since working with an ROI of an image we can slow down the processing as well as mess up displaying the original image again so it would be much better to do something like this:

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

We use a using statement as this disposes of the extra image data when we've finished and frees up resources.

Now for the trick the ROI is actually controlled by the results from the Detect_object which is why we keep Location as a global variable. Once Location we have matched the template successfully our using statement will look more like:

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

That's pretty much it other than rectangles of the ROI and template, size and location are drawn on the image if you have problems with that let me know but the code should readily be out there,

Cheers,

Chris

魂牵梦绕锁你心扉 2025-01-01 00:49:15

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

希望有帮助!

The video appears to be using something akin to the CAMSHIFT method described by Gary Bradski. Here is the C++ code for the camshift demo application, I know its not C#, but it should hopefully be easily portable to EmguCV. Here is the documentation for the core of the camshift algorithm.

Hope that helps!

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文