test_backgroundsubtractor_gbh.cpp 6.09 KB
Newer Older
1 2 3 4 5 6 7 8 9 10 11 12 13 14
/*
 * BackgroundSubtractorGBH_test.cpp
 *
 *  Created on: Jun 14, 2012
 *      Author: andrewgodbehere
 */

#include "test_precomp.hpp"

using namespace cv;

class CV_BackgroundSubtractorTest : public cvtest::BaseTest
{
public:
15
    CV_BackgroundSubtractorTest();
16
protected:
17
    void run(int);
18 19 20 21 22 23 24 25 26 27 28 29 30 31
};

CV_BackgroundSubtractorTest::CV_BackgroundSubtractorTest()
{
}

/**
 * This test checks the following:
 * (i) BackgroundSubtractorGMG can operate with matrices of various types and sizes
 * (ii) Training mode returns empty fgmask
 * (iii) End of training mode, and anomalous frame yields every pixel detected as FG
 */
void CV_BackgroundSubtractorTest::run(int)
{
32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117
    int code = cvtest::TS::OK;
    RNG& rng = ts->get_rng();
    int type = ((unsigned int)rng)%7;  //!< pick a random type, 0 - 6, defined in types_c.h
    int channels = 1 + ((unsigned int)rng)%4;  //!< random number of channels from 1 to 4.
    int channelsAndType = CV_MAKETYPE(type,channels);
    int width = 2 + ((unsigned int)rng)%98; //!< Mat will be 2 to 100 in width and height
    int height = 2 + ((unsigned int)rng)%98;

    Ptr<BackgroundSubtractorGMG> fgbg =
            Algorithm::create<BackgroundSubtractorGMG>("BackgroundSubtractor.GMG");
    Mat fgmask;

    if (fgbg == NULL)
        CV_Error(CV_StsError,"Failed to create Algorithm\n");

    /**
     * Set a few parameters
     */
    fgbg->set("smoothingRadius",7);
    fgbg->set("decisionThreshold",0.7);
    fgbg->set("initializationFrames",120);

    /**
     * Generate bounds for the values in the matrix for each type
     */
    uchar maxuc = 0, minuc = 0;
    char maxc = 0, minc = 0;
    unsigned int maxui = 0, minui = 0;
    int maxi=0, mini = 0;
    long int maxli = 0, minli = 0;
    float maxf = 0, minf = 0;
    double maxd = 0, mind = 0;

    /**
     * Max value for simulated images picked randomly in upper half of type range
     * Min value for simulated images picked randomly in lower half of type range
     */
    if (type == CV_8U)
    {
        uchar half = UCHAR_MAX/2;
        maxuc = (unsigned char)rng.uniform(half+32, UCHAR_MAX);
        minuc = (unsigned char)rng.uniform(0, half-32);
    }
    else if (type == CV_8S)
    {
        maxc = (char)rng.uniform(32, CHAR_MAX);
        minc = (char)rng.uniform(CHAR_MIN, -32);
    }
    else if (type == CV_16U)
    {
        ushort half = USHRT_MAX/2;
        maxui = (unsigned int)rng.uniform(half+32, USHRT_MAX);
        minui = (unsigned int)rng.uniform(0, half-32);
    }
    else if (type == CV_16S)
    {
        maxi = rng.uniform(32, SHRT_MAX);
        mini = rng.uniform(SHRT_MIN, -32);
    }
    else if (type == CV_32S)
    {
        maxli = rng.uniform(32, INT_MAX);
        minli = rng.uniform(INT_MIN, -32);
    }
    else if (type == CV_32F)
    {
        maxf = rng.uniform(32.0f, FLT_MAX);
        minf = rng.uniform(-FLT_MAX, -32.0f);
    }
    else if (type == CV_64F)
    {
        maxd = rng.uniform(32.0, DBL_MAX);
        mind = rng.uniform(-DBL_MAX, -32.0);
    }

    Mat simImage = Mat::zeros(height, width, channelsAndType);
    const unsigned int numLearningFrames = 120;
    for (unsigned int i = 0; i < numLearningFrames; ++i)
    {
        /**
         * Genrate simulated "image" for any type. Values always confined to upper half of range.
         */
        if (type == CV_8U)
        {
            rng.fill(simImage,RNG::UNIFORM,(unsigned char)(minuc/2+maxuc/2),maxuc);
            if (i == 0)
118
                fgbg->initialize(simImage.size(),minuc,maxuc);
119 120 121 122 123
        }
        else if (type == CV_8S)
        {
            rng.fill(simImage,RNG::UNIFORM,(char)(minc/2+maxc/2),maxc);
            if (i==0)
124
                fgbg->initialize(simImage.size(),minc,maxc);
125 126 127 128 129
        }
        else if (type == CV_16U)
        {
            rng.fill(simImage,RNG::UNIFORM,(unsigned int)(minui/2+maxui/2),maxui);
            if (i==0)
130
                fgbg->initialize(simImage.size(),minui,maxui);
131 132 133 134 135
        }
        else if (type == CV_16S)
        {
            rng.fill(simImage,RNG::UNIFORM,(int)(mini/2+maxi/2),maxi);
            if (i==0)
136
                fgbg->initialize(simImage.size(),mini,maxi);
137 138 139 140 141
        }
        else if (type == CV_32F)
        {
            rng.fill(simImage,RNG::UNIFORM,(float)(minf/2.0+maxf/2.0),maxf);
            if (i==0)
142
                fgbg->initialize(simImage.size(),minf,maxf);
143 144 145 146 147
        }
        else if (type == CV_32S)
        {
            rng.fill(simImage,RNG::UNIFORM,(long int)(minli/2+maxli/2),maxli);
            if (i==0)
148
                fgbg->initialize(simImage.size(),minli,maxli);
149 150 151 152 153
        }
        else if (type == CV_64F)
        {
            rng.fill(simImage,RNG::UNIFORM,(double)(mind/2.0+maxd/2.0),maxd);
            if (i==0)
154
                fgbg->initialize(simImage.size(),mind,maxd);
155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191
        }

        /**
         * Feed simulated images into background subtractor
         */
        (*fgbg)(simImage,fgmask);
        Mat fullbg = Mat::zeros(simImage.rows, simImage.cols, CV_8U);

        //! fgmask should be entirely background during training
        code = cvtest::cmpEps2( ts, fgmask, fullbg, 0, false, "The training foreground mask" );
        if (code < 0)
            ts->set_failed_test_info( code );
    }
    //! generate last image, distinct from training images
    if (type == CV_8U)
        rng.fill(simImage,RNG::UNIFORM,minuc,minuc);
    else if (type == CV_8S)
        rng.fill(simImage,RNG::UNIFORM,minc,minc);
    else if (type == CV_16U)
        rng.fill(simImage,RNG::UNIFORM,minui,minui);
    else if (type == CV_16S)
        rng.fill(simImage,RNG::UNIFORM,mini,mini);
    else if (type == CV_32F)
        rng.fill(simImage,RNG::UNIFORM,minf,minf);
    else if (type == CV_32S)
        rng.fill(simImage,RNG::UNIFORM,minli,minli);
    else if (type == CV_64F)
        rng.fill(simImage,RNG::UNIFORM,mind,mind);

    (*fgbg)(simImage,fgmask);
    //! now fgmask should be entirely foreground
    Mat fullfg = 255*Mat::ones(simImage.rows, simImage.cols, CV_8U);
    code = cvtest::cmpEps2( ts, fgmask, fullfg, 255, false, "The final foreground mask" );
    if (code < 0)
    {
        ts->set_failed_test_info( code );
    }
192 193 194 195

}

TEST(VIDEO_BGSUBGMG, accuracy) { CV_BackgroundSubtractorTest test; test.safe_run(); }