0

我正在尝试使用 OpenCV 的 CodeBook 方法来减去背景。到目前为止一切都很好,但我不确定是否可以在一段时间后更新移动物体的码本,比如 5 分钟,我需要更新码本,之后我会得到很多移动的物体。如何确保 5 分钟后我有需要更新的背景?

感谢您的提示!

4

1 回答 1

2

据说 kim 的算法有一个缓存层,我没有深入研究 opencv 实现,不知道如何有一个适用于曝光问题的可行版本。

笔记

  • opencv 书(我还没读过)应该有你需要的信息,如果它在那里的话
  • 这只是 1 个频道,不在 yuv 中,虽然它可以扩展
  • 需要更多的速度/测试工作(你当然可以在编译器中打开优化)
  • 背景减法是一个流行词。尝试“更改检测”

bgfg_cb.h

#ifndef __bgfg_cb_h__
#define __bgfg_cb_h__


//http://citeseerx.ist.psu.edu/viewdoc/download?doi=10.1.1.148.9778&rep=rep1&type=pdf
#include "opencv2/core/core.hpp"
#include "opencv2/imgproc/imgproc.hpp"
#include "opencv2/highgui/highgui.hpp"
#include <iostream>
#include <time.h>
using namespace cv;
using namespace std;


struct codeword {
    float min;
    float max; 
    float f;
    float l;
    int first;
    int last;
    bool isStale;
};
extern int alpha ;
extern float beta ;
extern int Tdel ,Tadd , Th;


void initializeCodebook(int w,int h);
void update_cb(Mat& frame);
void fg_cb(Mat& frame,Mat& fg);
#endif

bgfg_cb.cpp

#include "opencv2/core/core.hpp"
#include "opencv2/imgproc/imgproc.hpp"
#include "opencv2/highgui/highgui.hpp"
#include <iostream>
#include <time.h>
#include "bgfg_cb.h"
using namespace cv;
using namespace std;

vector<codeword> **cbMain;
vector<codeword> **cbCache;
int t=0;
int alpha = 10;//knob
float beta =1;
int Tdel = 200,Tadd = 150,  Th= 200;//knobs

void initializeCodebook(int w,int h)
{
    cbMain = new vector<codeword>*[w];
    for(int i = 0; i < w; ++i)
        cbMain[i] = new vector<codeword>[h];

    cbCache = new vector<codeword>*[w];
    for(int i = 0; i < w; ++i)
        cbCache[i] = new vector<codeword>[h];
}

void update_cb(Mat& frame)
{
    if(t>10) return;
    for(int i=0;i<frame.rows;i++)
    {
        for(int j=0;j<frame.cols;j++)
        {
            int pix =  frame.at<uchar>(i,j);
            vector<codeword>& cm =cbMain[i][j];         
            bool found = false;
            for(int k=0;k<cm.size();k++)
            {
                if(cm[k].min<=pix && pix<=cm[k].max && !found)
                {
                    found=true;
                    cm[k].min = ((pix-alpha)+(cm[k].f*cm[k].min))/(cm[k].f+1);
                    cm[k].max = ((pix+alpha)+(cm[k].f*cm[k].max))/(cm[k].f+1);
                    cm[k].l=0;
                    cm[k].last=t;
                    cm[k].f++;
                }else
                {
                    cm[k].l++;
                }
            }
            if(!found)
            {
                codeword n={};
                n.min=max(0,pix-alpha);
                n.max=min(255,pix+alpha);
                n.f=1;
                n.l=0;
                n.first=t;
                n.last=t;
                cm.push_back(n);
            }
        }
    }
    t++;
}

void fg_cb(Mat& frame,Mat& fg)
{
    fg=Mat::zeros(frame.size(),CV_8UC1);
    if(cbMain==0) initializeCodebook(frame.rows,frame.cols);
    if(t<10)
    {
        update_cb(frame);
        return;
    }

    for(int i=0;i<frame.rows;i++)
    {
        for(int j=0;j<frame.cols;j++)
        {
            int pix = frame.at<uchar>(i,j);
            vector<codeword>& cm = cbMain[i][j];    
            bool found = false;
            for(int k=0;k<cm.size();k++)
            {
                if(cm[k].min<=pix && pix<=cm[k].max && !found)
                {
                    cm[k].min = ((1-beta)*(pix-alpha)) + (beta*cm[k].min);
                    cm[k].max = ((1-beta)*(pix+alpha)) + (beta*cm[k].max);
                    cm[k].l=0;
                    cm[k].first=t;
                    cm[k].f++;
                    found=true;
                }else
                {
                    cm[k].l++;
                }
            }
            cm.erase( remove_if(cm.begin(), cm.end(), [](codeword& c) { return c.l>=Tdel;} ), cm.end() );
            fg.at<uchar>(i,j) = found?0:255;
            if(found) continue;
            found = false;
            vector<codeword>& cc = cbCache[i][j];   
            for(int k=0;k<cc.size();k++)
            {
                if(cc[k].min<=pix && pix<=cc[k].max && !found)
                {
                    cc[k].min = ((1-beta)*(pix-alpha)) + (beta*cc[k].min);
                    cc[k].max = ((1-beta)*(pix+alpha)) + (beta*cc[k].max);
                    cc[k].l=0;
                    cc[k].first=t;
                    cc[k].f++;
                    found=true;
                }else
                {
                    cc[k].l++;
                }
            }

            if(!found)
            {
                codeword n={};
                n.min=max(0,pix-alpha);
                n.max=min(255,pix+alpha);
                n.f=1;
                n.l=0;
                n.first=t;
                n.last=t;   
                cc.push_back(n);
            }

            cc.erase( remove_if(cc.begin(), cc.end(), [](codeword& c) { return c.l>=Th;} ), cc.end() );
            for(vector<codeword>::iterator it=cc.begin();it!=cc.end();it++)
            {
                if(it->f>Tadd)
                {
                    cm.push_back(*it);
                }
            }

            cc.erase( remove_if(cc.begin(), cc.end(), [](codeword& c) { return c.f>Tadd;} ), cc.end() );
        }
    }
}

主文件

#include "opencv2/core/core.hpp"
#include "opencv2/imgproc/imgproc.hpp"
#include "opencv2/highgui/highgui.hpp"
#include "bgfg_cb.h"
#include <iostream>
using namespace cv;
using namespace std;
void proc()
{
    Mat frame,fg,gray;
    VideoCapture cap("C:/Downloads/S2_L1.tar/S2_L1/Crowd_PETS09/S2/L1/Time_12-34/View_001/frame_%04d.jpg");
    cap >> frame;
    initializeCodebook(frame.rows,frame.cols);
    for(;;)
    {
        cap>>frame; 
        cvtColor(frame,gray,CV_BGR2GRAY);
        fg_cb(gray,fg);
        Mat cc;
        imshow("fg",fg);
        waitKey(1);
    }
}

int main(int argc, char ** argv)
{
    proc(); 
    cin.ignore(1);
    return 0;
}
于 2013-02-24T14:30:01.033 回答