Вычитание фона в OpenCV (C ++) - PullRequest
8 голосов
/ 14 октября 2011

Я хочу реализовать метод усреднения фона.У меня 50 кадров изображений, снятых за одну секунду, и некоторые кадры содержат молнии, которые я хочу извлечь в качестве переднего плана.Кадры снимаются стационарной камерой, а рамки - серыми.Я хочу сделать следующее:

  1. Получить фоновую модель
  2. После этого сравните каждый кадр с фоновой моделью, чтобы определить, есть ли освещение в этом кадре или нет.

Я прочитал некоторые документы о том, как это можно сделать с помощью cvAcc (), но мне сложно понять, как это можно сделать.Буду признателен за фрагмент кода, который поможет мне и ссылки на документы, которые помогут мне понять, как я могу это реализовать.

Заранее благодарю.

1 Ответ

19 голосов
/ 14 октября 2011

У нас была одна и та же задача в одном из наших проектов.

Чтобы получить фоновую модель, мы просто создаем класс 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) вычислить сумму пикселей и решить, является ли это рамкой с подсветкой.

...