EmguCV:使用光流在运动物体上绘制轮廓?

Posted

技术标签:

【中文标题】EmguCV:使用光流在运动物体上绘制轮廓?【英文标题】:EmguCV: Draw contour on object in Motion using Optical Flow? 【发布时间】:2015-08-25 00:03:31 【问题描述】:

我想在 C# 中进行运动检测(使用 EmguCV 3.0)来移除运动中或前景中的对象以绘制叠加层。

这是我使用 Kinect 完成的示例测试(因为它是深度相机)

如何开始使用 EmguCV 3.0?

我尝试了许多不起作用的后台删除代码 OpticalFlow 似乎是一个好的开始,但在 EmguCV 3.0 中没有示例 如果我找到最大的斑点,如何找到它的轮廓?

有人可以帮我开始吗?

编辑:2015 年 6 月 17 日

在 EmguCV3.0.0 RC 中,我在包和文档中看不到 OpticalFlow: http://www.emgu.com/wiki/files/3.0.0-rc1/document/html/b72c032d-59ae-c36f-5e00-12f8d621dfb8.htm

只有:DenseOpticalFlow、OpticalFlowDualTVL1 ???

这是一个 AbsDiff 代码:

var grayFrame = frame.Convert<Gray, Byte>();
var motionFrame = grayFrame.AbsDiff(backFrame)
                           .ThresholdBinary(new Gray(20), new Gray(255))
                           .Erode(2) 
                           .Dilate(2);

结果:

我不知道如何让运动变成白色?

这是 Blob 代码:

Image<Bgr, Byte> smoothedFrame = new Image<Bgr, byte>(frame.Size);
CvInvoke.GaussianBlur(frame, smoothedFrame, new Size(3, 3), 1); //filter out noises

Mat forgroundMask = new Mat();
fgDetector.Apply(smoothedFrame, forgroundMask);

CvBlobs blobs = new CvBlobs();
blobDetector.Detect(forgroundMask.ToImage<Gray, byte>(), blobs);
blobs.FilterByArea(400, int.MaxValue);
blobTracker.Update(blobs, 1.0, 0, 1);

foreach (var pair in blobs) 
  CvBlob b = pair.Value;
  CvInvoke.Rectangle(frame, b.BoundingBox, new MCvScalar(255.0, 255.0, 255.0), 2);

结果:

为什么会有这么多误报?

这是 MOG2 代码:

forgroundDetector.Apply(frame, forgroundMask);
motionHistory.Update(forgroundMask);
var motionMask = GetMotionMask();
Image<Bgr, Byte> motionImage = new Image<Bgr, byte>(motionMask.Size);
CvInvoke.InsertChannel(motionMask, motionImage, 0);

Rectangle[] rects;
using (VectorOfRect boundingRect = new VectorOfRect()) 
  motionHistory.GetMotionComponents(segMask, boundingRect);
  rects = boundingRect.ToArray();


foreach (Rectangle comp in rects)  ...

结果:

如果我选择最大的区域,我怎样才能得到对象的轮廓?

【问题讨论】:

【参考方案1】:

首先,我可以给你一些示例光流代码。

oldImagenewImage 成为保存前一帧和当前帧的变量。在我的代码中,它的类型是 Image&lt;Gray, Byte&gt;

// prep containers for x and y vectors
Image<Gray, float> velx = new Image<Gray, float>(newImage.Size);
Image<Gray, float> vely = new Image<Gray, float>(newImage.Size);

// use the Horn and Schunck dense optical flow algorithm.
OpticalFlow.HS(oldImage, newImage, true, velx, vely, 0.1d, new MCvTermCriteria(100));

// color each pixel
Image<Hsv, Byte> coloredMotion = new Image<Hsv, Byte>(newImage.Size);
for (int i = 0; i < coloredMotion.Width; i++)

    for (int j = 0; j < coloredMotion.Height; j++)
    
        // Pull the relevant intensities from the velx and vely matrices
        double velxHere = velx[j, i].Intensity;
        double velyHere = vely[j, i].Intensity;

        // Determine the color (i.e, the angle)
        double degrees = Math.Atan(velyHere / velxHere) / Math.PI * 90 + 45;
        if (velxHere < 0)
        
            degrees += 90;
        
        coloredMotion.Data[j, i, 0] = (Byte) degrees;
        coloredMotion.Data[j, i, 1] = 255;

        // Determine the intensity (i.e, the distance)
        double intensity = Math.Sqrt(velxHere * velxHere + velyHere * velyHere) * 10;
        coloredMotion.Data[j, i, 2] = (intensity > 255) ? 255 : intensity;
    

// coloredMotion is now an image that shows intensity of motion by lightness
// and direction by color.

关于如何去除前景的更大问题:

如果我有办法获得静态背景图片,那是最好的开始。然后,通过AbsDiff method 检测前景,并使用Erode 和Dilate 或Gaussian 对图像进行平滑处理,然后使用斑点检测。

对于简单的前景检测,我发现光流处理过多(最大 8fps),而 AbsDiff 方法同样准确,但对帧速率没有影响。

关于轮廓,如果你只是想找到大小、位置和其他时刻,那么上面 AbsDiff 教程中的 blob 检测似乎就足够了,它使用了Image.FindContours(...)

如果没有,我将开始查看 this tutorial 中使用的 CvBlobDetector 类。有一个内置的 DrawBlob 函数可能会派上用场。

【讨论】:

谢谢,EmguCV 3 中似乎没有 OpticalFlow?只有 DenseOpticalFlow 吗?我错了吗? 我在背景/前景上尝试了 AbsDiff(似乎是最好的),但我无法获得运动中的干净物体。我尝试了 Blob 检测器,但它完全搞砸了,它检测到了太多东西。我也尝试过人体检测,但它不适用于部分人体 还有OpticalFlow.LK(...),使用 Lukas-Kanade 算法对关键点进行操作并以这种方式测量光流。它比密集光流更快,但要求对象具有良好的关键点,并且您没有得到明显的区域。另外,除了 AbsDiff 之外,您还使用什么代码? 我用示例代码编辑我的文章。我还链接了 3.0.0-rc 的文档我找不到 OpticalFlow 对象

以上是关于EmguCV:使用光流在运动物体上绘制轮廓?的主要内容,如果未能解决你的问题,请参考以下文章

图像处理openCV光流法追踪运动物体

目标跟踪基于matlab光流法运动视频跟踪含Matlab源码 1357期

目标跟踪基于matlab光流法运动视频跟踪含Matlab源码 1357期

光流法

光流(Optical flow)-视频分析基础概念

有没有办法在不知道深度 Z 的情况下从现实世界物体的运动中找到光流速度?