当我尝试总结存储在列表中的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);
// ...在屏幕上显示...编程结束
图像: http://imagegur.com/images/untitled.png
左边是bg_model,中间是curr_frame,右边是输出。
也许是因为CV_U8完成了四舍五入?我尝试更改为CV_32FC1,但程序崩溃了,因为由于某种原因它无法添加两个CV_32FC1矩阵。
非常感谢任何见解。谢谢!
更多信息:
在课堂上,我现在将平均值保留在CV_16UC1 Mat中以防止剪辑,连续添加后如何导致错误。
add function / 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
答案 0 :(得分: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;
}
根据您对结果的处理方式,您可能需要对其进行标准化或重新缩放,或在显示之前转换回灰度等。