0

基本的に2つのフレームで「ダム」バックグラウンド減算を行うこのコードがあります。

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、これが呼び出されたときに黒い画像が表示されます。

私は何を間違っていますか/ここでやるべきですか?

4

2 に答える 2

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();
  • これは、CV_8U が CV_8UC3 と同じではないため、mat.hpp の @ Mat::create() をチェックすると、型の違いにより常に新しい配列が割り当てられるためです。

意見

私は思う...多分代わりにマットを使う?

#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;
}    

編集 2 (変更されたオリジナル)

#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;
}
于 2013-10-02T17:15:51.247 に答える
1

あなたのコードをもう一度見直しました。_fgmask の新しいオブジェクトを作成しているようです。

 _fgmask.create(img_input.size(), CV_8U);

これがあなたが問題を抱えている理由だと思います。このため、引数の参照は、このステートメントの後の参照とは異なります。関数を呼び出す前に行を呼び出してみませんか。

于 2013-10-02T15:50:36.967 に答える