У нас была одна и та же задача в одном из наших проектов.
Чтобы получить фоновую модель, мы просто создаем класс BackgroundModel, собираем первые (скажем, 50) кадров и вычисляем средний кадр, чтобы избежать ошибок пикселей в фоновой модели.
Например, если вы получаете 8-битное изображение в оттенках серого (CV_8UC1) с вашей камеры, вы инициализируете модель с помощью CV_16UC1, чтобы избежать отсечения.
cv::Mat model = cv::Mat(HEIGHT, WIDTH, CV_16UC1, cv::Scalar(0));
Теперь, ожидая первых кадров для расчета вашей модели, просто добавьте каждый кадр в модель и посчитайте количество полученных кадров.
void addFrame(cv::Mat frame) {
cv::Mat convertedFrame;
frame.convertTo(convertedFrame, CV_16UC1);
cv::add(convertedFrame, model, model);
if (++learnedFrames >= FRAMES_TO_LEAN) { // FRAMES_TO_LEARN = 50
createMask();
}
}
Функция createMask () вычисляет средний кадр, который мы используем для модели.
void createMask() {
cv::convertScaleAbs(model, mask, 1.0 / learnedFrames);
mask.convertTo(mask, CV_8UC1);
}
Теперь вы просто отправляете все кадры через класс BackgroundModel в функцию subtract (). Если результатом является пустой cv :: Mat, маска все еще вычисляется. В противном случае вы получите вычтенный кадр.
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;
}
Не в последнюю очередь, вы можете использовать
Скалярная сумма (const Mat & mtx)
вычислить сумму пикселей и решить, является ли это рамкой с подсветкой.