We had the same task in one of our projects.
To get the base model, we simply create the BackgroundModel class, grab the first (say) 50 frames and calculate the middle frame to avoid pixel errors in the background model.
For example, if you get an 8-bit grayscale image (CV_8UC1) from your camera, you initialize your model CV_16UC1 to avoid cropping.
cv::Mat model = cv::Mat(HEIGHT, WIDTH, CV_16UC1, cv::Scalar(0));
Now, expecting the first frames to be calculated by your model, simply add each frame to the model and count the number of frames received.
void addFrame(cv::Mat frame) { cv::Mat convertedFrame; frame.convertTo(convertedFrame, CV_16UC1); cv::add(convertedFrame, model, model); if (++learnedFrames >= FRAMES_TO_LEAN) {
The createMask () function calculates the middle frame that we use for the model.
void createMask() { cv::convertScaleAbs(model, mask, 1.0 / learnedFrames); mask.convertTo(mask, CV_8UC1); }
Now you just send all the frames through the BackgroundModel class to the subtract () function. If the result is an empty cv :: Mat, the mask is still computed. Otherwise, you get a subtracted frame.
cv::Mat subtract(cv::Mat frame) { cv::Mat result; if (++learnedFrames >= FRAMES_TO_LEAN) { // FRAMES_TO_LEARN = 50 cv::subtract(frame, mask, result); } else { addFrame(frame); } return result; }
Last but not least, you can use the Scalar Sum (const Mat & mtx) to calculate the sum of the pixel and decide whether it will be a frame with a highlight on it.