Monday, April 11, 2011

Detecting change in two consecutive pictures

As a toy project i want to write an application that will take pictures from a web cam and then detect changes in them. I want to detect if someone walked in front of the webcam.

Can you guys, show me some pointers on how can i detect a major change in two consecutive shots?

From stackoverflow
  • Over at Code Project is a nice article explaining a possible solution.

  • Subtract the per pixel lightness values from one image to the other.

    This will give you high values per pixel where something is moved, and low values for where things are the same. Total these values and check to see if it's above a certain threshold number to see if a major change has occured.

    I took a photo of my hand from my laptop to show this:

    alt text

    Paul Tomblin : In natural light, this method generates false positives as the sun moves through the sky, changing light levels and moving shadows.
    idursun : @Paul, I think that wouldn't be much a problem because sun doesn't move suddenly and also a significant light level change is that should be tracked.
    Vladimir Dyuzhev : if sun moves suddenly, we'll have more important things to do O_O
    MSalters : Still is a good first filter, very low false negatives.
    James Burgess : This is pretty much the standard for a low-level filter: subtraction and thresholding. A large number of machine vision systems are built entirely upon this simple filter (and only sometimes, something more complex). Of course, reliable thresholding relies on consistent lighting ;)
  • I would start by scaling down the image to something like 30K to 60K pixels. This not only will speed up calculation, but also get rid of minute irrelevant changes. For instance you don't want to detect a curtain near an open window moved by the wind.

    Next, sum the squared differences of the pixel values. If you want to do it thoroughly, you can do it for R, G and B separately:

    Delta := 0;
    for y := 0 to Im1.Height do begin
      for x := 0 to Im1.Width do begin
        DeltaR := ( Im1[x,y].Red   - Im2[x,y].Red ) ^ 2;
        DeltaG := ( Im1[x,y].Green - Im2[x,y].Green ) ^ 2;
        DeltaB := ( Im1[x,y].Blue  - Im2[x,y].Blue ) ^ 2;
        Delta := Delta + DeltaR + DeltaG + DeltaB;
      end;
    end;
    
    if (Delta > Treshold) then
      Say( 'Hi Bob!' );
    

    (this is just pseudo-code and as code would process rather slowly, google for "scanline" if you want to process all pixels in an image quickly)

    You may want to define the treshold value empirically: walk slowly by the camera, preferably wearing clothes matching the background color and see what delta's you get.
    Skipping frames should increase sensitivity.

0 comments:

Post a Comment