我的简单背景减法算法不起作用

时间:2014-11-17 21:07:36

标签: c++ opencv

我使用OpenCV 2.4.9,Visual Studio 2013
我开发了一个从后台提取对象的程序。背景显示为黑色,对象显示为原始颜色 我通过笔记本电脑摄像头收到输入。

这是我的程序

#include <iostream>
#include <cstdlib>

#include <opencv2/core/core.hpp>
#include <opencv2/highgui/highgui.hpp>

using namespace std;
using namespace cv;

int main(int argc, char** argv) {

    namedWindow("Background Subtraction");
    VideoCapture capture(0); // Open the default camera
    if (!capture.isOpened())  // Check if we succeeded
        return -1;

    Mat bg_frame;   // Capture 1st frame
    capture >> bg_frame;

    Mat cur_frame;  // Capture current frame

    double threshold = (double)50;
    while (1) {
        // Capture current frame
        capture >> cur_frame;

        // Loop all pixel in image

        for (int i = 0; i < cur_frame.rows; ++i) {
            for (int j = 0; j < cur_frame.cols; ++j) {
                Vec3b bg_RGB_pixel = bg_frame.at<Vec3b>(i, j);
                Vec3b cur_RGB_pixel = cur_frame.at<Vec3b>(i, j);

                double pixel_different = sqrt(  pow(bg_RGB_pixel[0], cur_RGB_pixel[0]) + 
                                                pow(bg_RGB_pixel[1], cur_RGB_pixel[1]) + 
                                                pow(bg_RGB_pixel[2], cur_RGB_pixel[2]) );

                if (pixel_different > threshold) {
                    cur_RGB_pixel[0] = 0;
                    cur_RGB_pixel[1] = 0;
                    cur_RGB_pixel[2] = 0;

                    cur_frame.at<Vec3b>(i, j) = cur_RGB_pixel;
                }
            }
        }
        imshow("Background Subtraction", cur_frame);


        char c = cvWaitKey(10);
        if (c == 27) 
            break;
    }

    return 0;
}

当我运行代码时,我收到此错误。 错误出现在此行

Vec3b bg_RGB_pixel = bg_frame.at<Vec3b>(i, j);

enter image description here

我该如何解决这个问题?

感谢您的所有建议和解决方案。

[编辑]
使用Mat.at(i,j)时异常:std :: bad_alloc; - 已解决
我刚刚发现问题出在我安装在计算机上的AntiVirus软件上。 我必须确认该应用程序可以使用我的网络摄像头,但程序仍然执行,它会收到以下错误,因为它什么也没有捕获。

但现在,我发现我的算法出现了新问题。它不会删除背景。输出只是一个黑屏。

我现在该怎么办?

1 个答案:

答案 0 :(得分:0)

我看到两个问题:

我很确定你没有正确使用pow()。我假设你正在寻找2的幂(bg_RGB_pixel [0] - cur_RGB_pixel [0])等等。在你看来,bg_RGB_pixel的功能是cur_RGB_pixel的功能。

我用更长的形式写了它,因为我认为它更清晰(首先计算差异,然后是权力;见下面的代码)。

另外,我认为你想要pixel_different比阈值更少 - 而不是更多 - 以便将相对于第一个捕获的参考帧不改变的背景归零(除非你想要分割出新的东西)在图像上)。

无论如何 - 这对我有效(仅显示内部,每个图像,循环):

    for (int i = 0; i < cur_frame.rows; ++i) {
        for (int j = 0; j < cur_frame.cols; ++j) {
            Vec3b bg_RGB_pixel = bg_frame.at<Vec3b>(i, j);
            Vec3b cur_RGB_pixel = cur_frame.at<Vec3b>(i, j);

            int diff0 = bg_RGB_pixel[0] - cur_RGB_pixel[0];
            int diff1 = bg_RGB_pixel[1] - cur_RGB_pixel[1];
            int diff2 = bg_RGB_pixel[2] - cur_RGB_pixel[2];

            double pixel_different = sqrt(pow(diff0, 2) + pow(diff1, 2) + pow(diff2, 2));

            if (pixel_different < threshold) {
                cur_RGB_pixel[0] = 0;
                cur_RGB_pixel[1] = 0;
                cur_RGB_pixel[2] = 0;

                cur_frame.at<Vec3b>(i, j) = cur_RGB_pixel;
            }
        }
    }

我将大部分背景分割出来,并且在我开始后出现在相机视野中的项目不会被分割出来(不会变黑)并以原始颜色显示。 在合理范围内...即使是新项目也有一些部分被涂黑了。但是你使用的是非常简单的分割算法,所以这是预期的,结果实际上非常好。

迈克尔