问题 运动检测


我真的无法理解这一点,所以我希望有人可以给我一点手^^

我正试图通过我的网络摄像头检测C#中的运动。

到目前为止,我已经尝试了多个库(AForge Lib),但失败了,因为我不明白如何使用它。

起初我只是想比较当前帧与最后一帧的像素,但结果却像是完全一样:I

现在,我的网络摄像头每次从网络摄像头运行一个事件“webcam_ImageCaptured”,就像5-10 fps。

但我找不到了 简单 从两个图像中获得差异的方法,或者至少是有效的东西。

有没有人知道我怎么能这么简单(尽可能这样)?


12774
2017-07-13 00:08


起源

“但失败了,因为我不明白如何使用它。”你有没有走过这个: codeproject.com/Articles/10248/Motion-Detection-Algorithms - Fabian Bigler
是的我已经尝试过了,它给了我一个错误。 - Jazerix


答案:


使用您提到的库来使运动检测工作是微不足道的。以下是AForge(2.2.4版)示例。它适用于视频文件,但您可以轻松地将其适应网络摄像头事件。

约翰内斯是对的,但我认为玩这些库可以简化理解基本图像处理的方法。

我的应用程序在一台非常快的SSD机器上以120FPS处理720p视频,在我的开发笔记本电脑上处理大约50FPS。

public static void Main()
{    
    float motionLevel = 0F;
    System.Drawing.Bitmap bitmap = null;
    AForge.Video.FFMPEG.VideoFileReader reader = null;
    AForge.Vision.Motion.MotionDetector motionDetector = null;    

    motionDetector = GetDefaultMotionDetector();

    reader.Open(@"C:\Temp.wmv");

    while (true)
    {
        bitmap = reader.ReadVideoFrame();
        if (bitmap == null) break;

        // motionLevel will indicate the amount of motion as a percentage.
        motionLevel = motionDetector.ProcessFrame(bitmap);

        // You can also access the detected motion blobs as follows:
        // ((AForge.Vision.Motion.BlobCountingObjectsProcessing) motionDetector.Processor).ObjectRectangles [i]...
    }

    reader.Close();
}

// Play around with this function to tweak results.
public static AForge.Vision.Motion.MotionDetector GetDefaultMotionDetector ()
{
    AForge.Vision.Motion.IMotionDetector detector = null;
    AForge.Vision.Motion.IMotionProcessing processor = null;
    AForge.Vision.Motion.MotionDetector motionDetector = null;

    //detector = new AForge.Vision.Motion.TwoFramesDifferenceDetector()
    //{
    //  DifferenceThreshold = 15,
    //  SuppressNoise = true
    //};

    //detector = new AForge.Vision.Motion.CustomFrameDifferenceDetector()
    //{
    //  DifferenceThreshold = 15,
    //  KeepObjectsEdges = true,
    //  SuppressNoise = true
    //};

    detector = new AForge.Vision.Motion.SimpleBackgroundModelingDetector()
    {
        DifferenceThreshold = 10,
        FramesPerBackgroundUpdate = 10,
        KeepObjectsEdges = true,
        MillisecondsPerBackgroundUpdate = 0,
        SuppressNoise = true
    };

    //processor = new AForge.Vision.Motion.GridMotionAreaProcessing()
    //{
    //  HighlightColor = System.Drawing.Color.Red,
    //  HighlightMotionGrid = true,
    //  GridWidth = 100,
    //  GridHeight = 100,
    //  MotionAmountToHighlight = 100F
    //};

    processor = new AForge.Vision.Motion.BlobCountingObjectsProcessing()
    {
        HighlightColor = System.Drawing.Color.Red,
        HighlightMotionRegions = true,
        MinObjectsHeight = 10,
        MinObjectsWidth = 10
    };

    motionDetector = new AForge.Vision.Motion.MotionDetector(detector, processor);

    return (motionDetector);
}

11
2017-07-13 03:20



这实际上给我带来了一些非常好的结果! :)我发现移动相机会让事情变得混乱。但是当它静止不动时,它现在正在完美地检测到运动^^但是,我仍然想知道如何将检测到的区域应用到位图图像,然后才能在窗体上显示。 - Jazerix
这条线 HighlightMotionRegions = true 照顾好这一点。如果您愿意,可以将其关闭并自行渲染自定义叠加层。这些基本算法适用于固定摄像机。移动摄像机使用更复杂的算法。请记住,上面的代码只是突出显示动作。它不跟踪对象。您需要自己编写代码以逐帧关联blob标识。 - Raheel Khan
啊,那真是太棒了。我昨天在街上偷窥它,它运作正常。但我发现它有点过分,特别是当风吹来的时候:我 - Jazerix
尝试使用DifferenceThreshold,SuppressNoise,MinObjectsWidth和MinObjectsWidth来改变灵敏度和对象大小。 - Raheel Khan
不应该行AForge.Video.FFMPEG.VideoFileReader reader = null; be var reader = new AForge.Video.FFMPEG.VideoFileReader(); - 否则你会得到一个空引用异常? - DavidWainwright


运动检测是一个复杂的问题,它需要大量的计算能力。

尽量先限制你想要检测的内容。随着复杂性的增加:您是否想要检测是否有运动?你想检测多少运动?您想要检测图像的哪些区域实际移动吗?

我假设您只是想知道什么时候发生了变化:

  • 相邻的帧减去相邻的帧
  • 计算所有像素差异的所有平方的总和
  • 除以像素数
  • 观看网络摄像头流的编号。它会产生一定的地面噪音,并会在某些东西移动时显着上升。
  • 尽量只限制某个颜色通道,这可能会改善一些事情

1
2017-07-13 00:20