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:
Have a look at a few different blur operators like:
medianBlur
is good for controlling impulse noise while preserving edges in the image.
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.