#include "processa.h"
#include <QDebug>

Processa::Processa()
{
    NBloks=64;
    Type=PROCESS_NO;
    Reset=NULL;

    set_count(0);
    mat_release();
}

void Processa::mat_release(void)
{
    AccMean.release();
    AccS2.release();
    AccGavd.release();
    frame_old.release();
}

void Processa::set_count(int count)
{
    CountMean=count;
    CountStd=count;
    CountGavd=count;

}

void Processa::set_reset_handle(bool *reset)
{
    Reset=reset;
}

void Processa::set_nbloks(int nbloks)
{
    NBloks=nbloks;
}

void Processa::set_type(int type)
{
    Type=type;
}

cv::Mat Processa::filter(const cv::Mat frame)
{
    if(Reset!=NULL)
    {
        if((*Reset)==true)
        {
            *Reset=false;
            set_count(0);
            mat_release();
        }
    }

    if(Type==PROCESS_NO)    return frame;
    if(Type==PROCESS_MEAN)  return filter_mean(frame);
    if(Type==PROCESS_STD)   return filter_std(frame);
    if(Type==PROCESS_GAVD)  return filter_gavd(frame);
    return frame;
}


/****************************** Private ******************************/
cv::Mat Processa::filter_mean(const cv::Mat frame)
{
    if(Reset!=NULL)
    if(frame.size() != AccMean.size())
    {
        set_count(0);
        mat_release();
    }

    if(CountMean==0)
    {
        AccMean=frame;
        CountMean=CountMean+1;
    }
    else
    {
        AccMean=(CountMean*AccMean+frame)/(CountMean+1.0);

        if(CountMean<=NBloks) CountMean=CountMean+1;
    }

    return AccMean;
}


cv::Mat Processa::filter_std(const cv::Mat frame)
{
    if(Reset!=NULL)
    if(frame.size() != AccS2.size())
    {
        set_count(0);
        mat_release();
    }

    cv::Mat tmp;
    cv::Mat E=filter_mean(frame);

    tmp=(frame-E);

    if(CountStd==0)
    {
        AccS2=tmp.mul(tmp);
        CountStd=CountStd+1;
    }
    else
    {
        AccS2=(CountStd*AccS2+tmp.mul(tmp))/(CountStd+1.0);

        if(CountStd<=NBloks) CountStd=CountStd+1;
    }

    cv::sqrt(AccS2,tmp);

    return tmp;
}


cv::Mat Processa::filter_gavd(const cv::Mat frame)
{
    cv::Mat tmp;

    if(Reset!=NULL)
    if(frame.size() != AccGavd.size())
    {
        set_count(0);
        mat_release();
    }

    if(CountGavd==0)
    {
        AccGavd=frame*0;
        CountGavd=CountGavd+1;
    }
    else
    {
        cv::absdiff(frame,frame_old,tmp);
        AccGavd=((CountGavd-1.0)*AccGavd+tmp)/(CountGavd);

        if(CountGavd<=NBloks) CountGavd=CountGavd+1;
    }

    frame_old=frame;

    return AccGavd;
}
