我有这个代码,基本上在两个帧上进行“哑”背景减法。
void FrameDifferenceBGS::operator()(cv::InputArray _image, cv::OutputArray _fgmask, double learningRate)
{
cv::Mat img_input = _image.getMat();
if(img_input.empty())
return;
_fgmask.create(img_input.size(), CV_8U);
cv::Mat img_foreground = _fgmask.getMat();
if(img_input_prev.empty())
{
img_input.copyTo(img_input_prev);
return;
}
cv::absdiff(img_input_prev, img_input, img_foreground);
if(img_foreground.channels() == 3)
cv::cvtColor(img_foreground, img_foreground, CV_BGR2GRAY);
if(enableThreshold)
cv::threshold(img_foreground, img_foreground, threshold, 255, cv::THRESH_BINARY);
if(showOutput)
cv::imshow("Frame Difference", img_foreground);
img_input.copyTo(img_input_prev);
img_foreground.copyTo(_fgmask);
firstTime = false;
}
如果我最后没有添加img_foreground.copyTo(_fgmask)
,则输出数组不会使用img_foreground
的结果进行更新,在调用此结果时会产生黑色图像。
我做错了什么/应该在这里做什么?
答案 0 :(得分:1)
我再次审核了您的代码。看起来您正在为_fgmask创建新对象。
_fgmask.create(img_input.size(), CV_8U);
我认为这就是你遇到问题的原因。因为这个参数中的引用不同于此语句之后的引用。在调用函数之前,为什么不调用该行。
答案 1 :(得分:1)
修复
_fgmask.create(img_input.size(), CV_8U);
更改为_fgmask.create(img_input.size(), CV_8UC3);
或_fgmask.create(img_input.size(), img_input.type());
为什么
cv::absdiff(img_input_prev, img_input, img_foreground);
每次都在内部重新创建一个新数组。并且它确实更新了img_foreground结构,但是在分配之后,_fgmask中的内存地址数据无法更改,因为标头是按值传递的。
cv::Mat& img_foreground = _fgmask.getMatRef();
看来
我认为......也许使用Mat?
#include "opencv2/opencv.hpp"
using namespace cv;
class FrameDifferenceBGS
{
public:
Mat prev;
Mat diff;
bool enableThreshold;
bool showOutput;
bool firstTime;
uchar threshold;
FrameDifferenceBGS():firstTime(false),enableThreshold(false),showOutput(false),threshold(0)
{
}
void FrameDifferenceBGS::operator()(cv::Mat& _in, cv::Mat &_fg, double _lr)
{
if(_in.empty())
return;
if(prev.empty())
{
prev=_in.clone();
_fg=cv::Mat::zeros(_in.size(),CV_8UC1);
return;
}
cv::absdiff(prev, _in, diff);
if(diff.channels() == 3)
cv::cvtColor(diff, _fg, CV_BGR2GRAY);
else
_fg=diff;
if(enableThreshold)
cv::threshold(_fg, _fg, threshold, 255, cv::THRESH_BINARY);
if(showOutput)
cv::imshow("Frame Difference", _fg);
prev=_in.clone();
firstTime = false;
}
};
int main()
{
VideoCapture cap(0);
FrameDifferenceBGS bgs;
Mat frame,fg;
for(;;)
{
cap >> frame;
bgs(frame,fg,0);
imshow("frame", frame);
imshow("fg", fg);
if(waitKey(1) ==27) exit(0);
}
return 0;
}
#include "opencv2/opencv.hpp"
class FrameDifferenceBGS
{
public:
cv::Mat img_input_prev;
cv::Mat diff;
cv::Mat img_foreground;//put this in class in stead of inside the function
bool enableThreshold;
bool showOutput;
bool firstTime;
uchar threshold;
FrameDifferenceBGS():firstTime(false),enableThreshold(false),showOutput(false),threshold(0)
{
}
void FrameDifferenceBGS::operator()(cv::InputArray _image, cv::OutputArray _fgmask, double learningRate)
{
cv::Mat img_input = _image.getMat();
if(img_input.empty())
return;
if(_fgmask.empty())
_fgmask.create(img_input.size(), CV_8UC1);
if(img_input_prev.empty())
{
img_input.copyTo(img_input_prev);
return;
}
cv::absdiff(img_input_prev, img_input, img_foreground);
if(img_foreground.channels() == 3)
cv::cvtColor(img_foreground, _fgmask, CV_BGR2GRAY);
if(enableThreshold)
cv::threshold(img_foreground, img_foreground, threshold, 255, cv::THRESH_BINARY);
if(showOutput)
cv::imshow("Frame Difference", img_foreground);
img_input.copyTo(img_input_prev);
//img_foreground.copyTo(_fgmask);
firstTime = false;
}
};
int main()
{
cv::VideoCapture cap(0);
FrameDifferenceBGS bgs;
cv::Mat frame,fg;
for(;;)
{
cap >> frame;
bgs(frame,fg,0);
cv::imshow("frame", frame);
cv::imshow("fg", fg);
if(cv::waitKey(1) ==27) exit(0);
}
return 0;
}