0

当我尝试将存储在列表中的 N 个先前帧相加,然后除以 num 帧时,生成的背景模型与预期不符。我可以说是因为我之前在同一视频中尝试过 Matlab 中的算法。

class TemporalMeanFilter {
private:
    int learningCount;
    list<Mat> history;
    int height, width;

    Mat buildModel(){
        if(history.size() == 0)
            return Mat();

        Mat image_avg(height, width, CV_8U, Scalar(0));
        double alpha = (1.0/history.size());

        list<Mat>::iterator it = history.begin();
        cout << "History size: " << history.size() << " Weight per cell: " << alpha << endl;

        while(it != history.end()){
            image_avg += (*it * alpha);
            it++;
        }

        return image_avg;
    }

public:
    TemporalMeanFilter(int height, int width, int learningCount){
        this->learningCount = learningCount;
        this->height = height;
        this->width = width;
    }

    void applyFrameDifference(Mat& frame_diff, Mat& bg_model, Mat& input_frame){
        if(history.size() == learningCount)
            history.pop_front();

        history.push_back(input_frame);

        bg_model = buildModel();
        frame_diff = bg_model - input_frame;
    }
};

//主要是这样的

// ... 从文件中读取视频

TemporalMeanFilter meanFilter(height, width, 50); //background subtraction algorithm
meanFilter.applyFrameDifference(diff_frame, bg_model, curr_frame);

//... 显示在屏幕上... prog 结束

图片:http: //imagegur.com/images/untitled.png

左边是bg_model,中间是curr_frame,右边是输出。

也许是因为对 CV_U8 进行了四舍五入?我尝试更改为 CV_32FC1,但由于某种原因它无法添加两个 CV_32FC1 矩阵,因此程序崩溃了。

任何见解将不胜感激。谢谢!

更多信息:

在课堂内,我现在将平均值保存在 CV_16UC1 Mat 中以防止剪切,连续添加后如何导致错误。

add 函数 / operator + 都将结果类型从 CV_16UC1 更改为 CV8UC1。此错误是由此引起的。任何建议如何要求它保留原始数据类型?(PS:我客气地问了……没用)

background_model += *it;

OpenCV Error: Bad argument (When the input arrays in add/subtract/multiply/divid
e functions have different types, the output array type must be explicitly speci
fied) in unknown function, file C:\buildslave64\win64_amdocl\2_4_PackSlave-win32
-vc11-shared\opencv\modules\core\src\arithm.cpp, line 1313
4

1 回答 1

0

您是对的,几乎可以肯定是通过累积缩放的灰度值得到的舍入误差。不过,它没有理由使用浮点像素崩溃,所以你应该尝试这样的事情:

Mat buildModel()
{
    if (history.size() == 0)
        return Mat();

    Mat image_avg = Mat::zeros(height, width, CV_32FC1);
    double alpha = (1.0 / history.size());

    list<Mat>::iterator it = history.begin();

    while (it != history.end())
    {
        Mat image_temp;
        (*it).convertTo(image_temp, CV_32FC1);
        image_avg += image_temp;
        it++;
    }
    image_avg *= alpha;

    return image_avg;
}

根据您要对结果执行的操作,您可能需要在显示之前对其进行标准化或重新缩放或转换回灰度等。

于 2013-12-25T09:44:56.430 回答