简体   繁体   中英

Frame difference noise?

I'm attempting to detect motion using frame difference. If there is a motion, I will enter another method, if not, I will not enter that method. The problem is when I make frame difference by using either absdiff(), or bitwise_xor(), I get a noisy frame, that is always detected as a motion.

I tried to remove that noise by using erode() and dilate() methods, it decreases the effect of the noise, but still there is noise. How can I remove this noise ?

Part of my current code:

capture >> Frame; // get a new frame from camera

cvtColor(Frame,Frame1,CV_RGB2GRAY);
threshold(Frame1,Frame1,50,255,CV_THRESH_BINARY);

waitKey(500);
capture >> PreFrame;

cvtColor(PreFrame,PreFrame,CV_RGB2GRAY);
threshold(PreFrame,PreFrame,50,255,CV_THRESH_BINARY);

//Result = Frame1 - PreFrame1;
//absdiff(Frame1,PreFrame1,Result);

bitwise_xor(Frame1,PreFrame,Result);
erode(Result,Result,Mat());
dilate(Result,Result,Mat());

imshow("Result",Result);

if (norm(Result,NORM_L1)==0){
    printf(" no change \n")
}
else
{
    // motion detected
}

You can reduce noise a few different ways just applying one of the following techniques right after capturing the frame:

Blurring (averaging within the frame)

Have a look at a few different blur operators like:

  1. blur (fast, but less smooth)
  2. GaussianBlur (slower, but smoother)
  3. medianBlur (reduces impulse noise)

medianBlur is good for controlling impulse noise while preserving edges in the image.

Frame averaging (average different frames)

  1. accumulate
  2. accumulateWeighted

With frame averaging just divide the accumulated result by the number of frames accumulated to get the averaged frame. You probably want a rolling average window of say 5-10 frames to reduce the noise significantly. However, higher window sizes means more motion blurring when objects move in and out of the field of view. This will work best if your camera is motionless.

Hope that helps!

What happens if take the absolute difference of your grayscale images, and then threshold the result to remove small intensity changes? This would allow small variations in pixel intensity frame-to-frame, while still triggering your motion detector if there were any significant changes.

For example:

// Obtain image two images in grayscale
cvtColor(Frame,Frame1,CV_RGB2GRAY);
cvtColor(PreFrame,PreFrame,CV_RGB2GRAY);

// Take the absolute difference, this will be zero for identical
// pixels, and larger for greater differences
absdiff(Frame, PreFrame, Result)

// Threshold to remove small differences
threshold(Result,Result,20,255,CV_THRESH_BINARY);

// Prepare output, using Result as a mask
Mat output = Mat::zeros(Frame.size(), Frame.type());
add(
    Frame,   // Add frame
    0,       // and zero
    output,  // to output
    Result   // Only if result is non-zero
);

Do you have any example input/output images you are able to share?

By thresholding your images before you take the difference, you're multiplying the effect of the noise greatly. Do the subtraction on the grayscale images directly with absdiff instead of bitwise_xor .

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM