Motion Detection
Asked Answered
A

2

11

I really cannot get my head around this, so I hope that someone can give me a little hand ^^

I'm trying to detect motion in C# via my webcam.

So far I've tried multiple libraries (AForge Lib), but failed because I did not understand how to use it.

At first I just wanted to compare the pixels from the current frame with the last one, but that turned out to work like utter s**t :I

Right now, my webcam runs an event "webcam_ImageCaptured" every time the picture from the webcam, which is like 5-10 fps.

But I cannot find a simple way to get the difference from the two images, or at least something that works decent.

Has anybody got an idea on how I could do this rather simple (as possible as that is)?

Anis answered 13/7, 2013 at 0:8 Comment(2)
"but failed because I did not understand how to use it." => have you walked through this: codeproject.com/Articles/10248/Motion-Detection-AlgorithmsMetre
Yes I have already tried that, and it's giving me an error.Anis
E
12

Getting motion detection to work using the libraries you mention is trivial. Following is an AForge (version 2.2.4) example. It works on a video file but you can easily adapt it to the webcam event.

Johannes' is right but I think playing around with these libraries eases the way to understanding basic image processing.

My application processes 720p video at 120FPS on a very fast machine with SSDs and around 50FPS on my development laptop.

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

    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);
}
Extinct answered 13/7, 2013 at 3:20 Comment(6)
This actually got me some really good results! :) I found that moving the camera would mess things up though. But when it's standing still it is now detecting movement perfectly ^^ However, I was still wondering on how you apply the detected areas to the bitmap image before it is shown on the form.Anis
The line HighlightMotionRegions = true takes care of that. You can turn it off and render custom overlays yourself if you like. These basic algorithms are meant to work with stationary cameras. Moving cameras use far more complex algorithms. Please keep in mind that the code above simply highlights motion. It does NOT track objects. You will need to write code yourself to associate blob identity frame-to-frame.Extinct
ah, that's wondeful. I had it spying in the street yesterday, and it worked ok. But i found that it was a little oversenitive, espiecally when the wind was blowing :IAnis
Try playing with the DifferenceThreshold, SuppressNoise, MinObjectsWidth and MinObjectsWidth to vary sensitivity and object sizes.Extinct
I'll play around with it. Thanks Raheel, you've been great! :DAnis
Shouldn't the line AForge.Video.FFMPEG.VideoFileReader reader = null; be var reader = new AForge.Video.FFMPEG.VideoFileReader(); - otherwise you'll get a null ref exception?Pebrook
E
1

Motion detection is a complex matter, and it requires a lot of computing power.

Try to limit what you want to detect first. With increasing complexity: Do your want to detect whether there is motion or not? Do you want to detect how much motion? Do you want to detect which areas of the image are actually moving?

I assume you just want to know when something changed:

  • subtract adjacent frames from each other
  • calc the sum of all squares of all pixel differences
  • divide by number of pixels
  • watch the number for your webcam stream. It will have a certain ground noise and will significantly go up when something moves.
  • try to limit to a certain color channel only, this may improve things
Evertor answered 13/7, 2013 at 0:20 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.