运动目标检测 之 GMM背景模型算法

来源:互联网 发布:铁木辛柯 知乎 编辑:程序博客网 时间:2024/05/21 09:25

综述

单高斯背景建模是一种基于像素样本统计信息的背景表示方法,它是根据视频中的每个像素在时域上的概率统计信息(均值/方差)来构建各个像素的颜色分布模型,依次来达到背景建模的目的。背景建模完成后,使用统计差分进行目标像素判断以达到对前景目标的检测,同时用目标像素不断更新背景模型以实现对动态背景的建模拟合。

混合高斯背景模型是有限个单高斯分布的加权和,它能描述像素的多峰状态,适用于对光照渐变、树木摇摆等复杂背景进行准确建模。所谓多峰状态就是在同一时间段内,由于场景的复杂性某个像素点存在多个背景状态,比如树木摇摆的某个像素点,在树枝覆盖了这个像素点时它的像素点值(R:35,G:45,B:65),在下帧图像中树枝由于风吹没有覆盖这个像素点时它的值为(R:135,G:200,B:35),对这个像素来说它有这两种背景状态,在视频中很多帧图像的时序上来说,这个像素点不停的出现这两种状态,就呈现了一个多峰的背景分布模型。

高斯背景模型中,认为像素之间的颜色信息互不相关,对各像素点的处理都是相互独立的。对于视频图像中的每一个像素点,其值在序列图像中的变化可看作是不断产生像素值的随机过程,即用高斯分布来描述每个像素点的颜色呈现规律(多峰/单峰)。

原理

在混合高斯背景模型维护中,场景中的一个像素值的混合高斯模型我们假设它有K个高斯分布组成,那么在图像中像素j在时刻t取值为 的概率为:

其中表示t时刻像素j的混合高斯模型中第i个高斯分布的权重,满足:
其中
表示 第i个高斯成分的均值
是协方差:,其中是标准差,I是单位矩阵
为高斯概率密度函数:

算法逻辑

1、初始化:取视频第一帧图像中每个像素的值来对各自混合高斯模型中K个单高斯分布的均值赋值,对K个单高斯分布的方差赋值为,对这K个高斯分布权重初始化为

2、在视频流中每帧新图像每个像素值与当前像素的K个单高斯模型逐个进行比较,判断是否与高斯模型的均值的偏差在一定范围内

其中,是标准差的倍数,表示前一时刻,在视频流里就是前一帧

3、如果符合上述公式则这个像素值符合这个单高斯背景要求是某个K个模型中某个单高斯背景点,否则是这个单高斯的前景点

4、如果像素点与某一高斯模式匹配,那么这个高斯模式假设是第i个模式的参数更新如下:


5、如果第二步中没有任何模式匹配,则这个像素对应的K个高斯模式中的最小的被替换,替换的模式的均值为,方差为,权重为

6、跳出模式的遍历循环后,各个模式的权值按如下公式更新,

其中,学习速率,对于匹配的模式不匹配的模式,然后对各模式权重归一化

7、各个模式根据的值降序排列,权重大,标准差小的模式排在前面

8、排序完成后,取前个高斯模型作为整个混合高斯模型的背景分布,要求就是,这个高斯的权重累加起来的和大于一定阈值:

其中:T是人为设定的阈值,k是表示几个高斯模型。

9、结合第3步与第8步,将第3步判断中,如果一个像素相对于第8步中的k个高斯分布来说都是前景点的话,就认为这个像素点是目标检测的目标的一个像素点,将所有这样的像素点组合起来形成前景目标,实现视频目标检测。

算法源码

.h文件

#ifndef OBJDET_INNERHEAD_H#define OBJDET_INNERHEAD_H#ifdef __cplusplusextern "C"{#endif#include "ObjDet_Interface.h"//#define OD_EXE_DSP#ifdef OD_EXE_DSP#else#define OD_VIBE#endif#define IN #define OUT#define INOUT#define OBJ_WH_MIN    32  /*目标宽高最低值*/#define OBJ_WH_MAX    128 /*目标宽高最大值*/#define ALIGN_1(a) ((0 == a % 8) ? (a) : (((a + 8)>>3)<<3))#define ALIGN_2(a) ((0 == a % 16) ? (a) : (((a + 16)>>4)<<4))#define ALIGN_3(a) ((0 == a % 32) ? (a) : (((a + 32)>>5)<<5))#define FLTMAX(a, b) ((a > b) ? (a) : (b))#define FLTMIN(a, b) ((a < b) ? (a) : (b))#define MEDINCHAR(x) (((x) < 0 ? 0 : ((x) > 255 ? 255 : (x))))#define SWAP_VALUE(A, B) {int tmpSwap;tmpSwap=A; A=B; B=tmpSwap;}#define DIFABS(a, b) ((a > b) ? (a - b) : (0))typedef unsigned char          U8;   typedef unsigned short         U16; typedef unsigned int           U32;#ifdef CHIP_DM6467typedef unsigned long long     U64;#elsetypedef unsigned __int64       U64;#endiftypedef signed char            S8;typedef signed short           S16;typedef signed int             S32;#ifdef CHIP_DM6467typedef signed long long       S64;#elsetypedef signed __int64         S64;#endiftypedef float                  FL;typedef double                 DB;typedef void                   VD;typedef unsigned char *         PU8;   typedef unsigned short *        PU16; typedef unsigned int *          PU32;#ifdef CHIP_DM6467typedef unsigned long long *    PU64;#elsetypedef unsigned __int64   *    PU64;#endiftypedef signed char *           PS8;typedef signed short *          PS16;typedef signed int *            PS32;#ifdef CHIP_DM6467typedef signed long long *      PS64;#elsetypedef signed __int64   *      PS64;#endiftypedef float *                 PFL;typedef double *                PDB;typedef void *                  PVD;/*^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^函数结构体定义^^^^^^^^^^^^^^^^^^^^^^*//*vvvvvvvvvvvvvvvvvvvvvvvvvvvvvv函数结构体定义vvvvvvvvvvvvvvvvvvvvvv*/#ifdef __cplusplus}#endif#endif

.c文件

#ifdef __cplusplusextern "C"{#endif#include "ObjDet_GmmHead.h"/***************************************************************************** 函 数 名  : OD_GmmDestroy 功能描述  : XXXX 输入参数  : INOUT void **pWorkHandl   输出参数  : 无 返 回 值  :  调用函数  :  被调函数  :  修改历史      :  1.日    期   : 2015223日    作    者   : TL_ImgFIlter    修改内容   : 新生成函数*****************************************************************************/S32 OD_GmmDestroy(INOUT void **pWorkHandl){    U8 ucModePtrIdx = 0;    GMM_InnerInfoS *pstGmmInnerInfo = NULL;    if(NULL == *pWorkHandl)    {        return OD_RLT_NO;    }    pstGmmInnerInfo = (GMM_InnerInfoS *)(*pWorkHandl);    pstGmmInnerInfo->uiGmmFrmNum = 0;    pstGmmInnerInfo->stGmmAreaPosLTRB.usLftTopPotX = 0;    pstGmmInnerInfo->stGmmAreaPosLTRB.usLftTopPotY = 0;    pstGmmInnerInfo->stGmmAreaPosLTRB.usRgtBtmPotX = 0;    pstGmmInnerInfo->stGmmAreaPosLTRB.usRgtBtmPotY = 0;    pstGmmInnerInfo->usGmmImgWth = 0;    pstGmmInnerInfo->usGmmImgHgt = 0;    pstGmmInnerInfo->usGmmImgStp = 0;    pstGmmInnerInfo->ucGmmImgChn = 0;    if(NULL != pstGmmInnerInfo->pucModeNum)    {        free(pstGmmInnerInfo->pucModeNum);        pstGmmInnerInfo->pucModeNum = NULL;    }    if(NULL != pstGmmInnerInfo->pucRsltImg)    {        free(pstGmmInnerInfo->pucRsltImg);        pstGmmInnerInfo->pucRsltImg = NULL;    }    for(ucModePtrIdx = 0; ucModePtrIdx < GMM_MAX_NUM; ucModePtrIdx++)    {        GMM_PixModeS * pstGrmmPixMode = pstGmmInnerInfo->apstGmmModeImg[ucModePtrIdx];        if(NULL != pstGrmmPixMode)        {            free(pstGrmmPixMode);             pstGrmmPixMode = NULL;        }    }    free(pstGmmInnerInfo);    pstGmmInnerInfo = NULL;    #ifdef GMM_DBG    if(NULL != pstGmmInnerInfo->pstGmmImgDbg)    {        cvReleaseImage(&pstGmmInnerInfo->pstGmmImgDbg);    }    cvDestroyWindow("GMM");    #endif}/***************************************************************************** 函 数 名  : OD_GmmInitInterface 功能描述  : XXXX 输入参数  : IN    OD_AreaPotPosS *pstGmmAreaPos               IN    unsigned int uiImgWth                       IN    unsigned int uiImgHgt                       INOUT void **pWorkHandl               输出参数  : 无 返 回 值  :  调用函数  :  被调函数  :  修改历史      :  1.日    期   : 2015223日    作    者   : TL_ImgFIlter    修改内容   : 新生成函数*****************************************************************************/S32 OD_GmmInitInterface(IN    OD_AreaPotPosS *pstGmmAreaPos,                        IN    unsigned int uiImgWth,                        IN    unsigned int uiImgHgt,                        INOUT void **pWorkHandl){    S32 iRetOk = OD_RLT_OK;    #ifndef OD_EXE_DSP    {        U8 ucModeIdx = 0;        U32 uiGmmModeMemSize = 0;        U16 usAreaGmmLftTopX = pstGmmAreaPos->usLftTopPotX;        U16 usAreaGmmLftTopY = pstGmmAreaPos->usLftTopPotY;        U16 usAreaGmmRgtBtmX = pstGmmAreaPos->usRgtBtmPotX;        U16 usAreaGmmRgtBtmY = pstGmmAreaPos->usRgtBtmPotY;        GMM_InnerInfoS *pstODGmmInnerS = (GMM_InnerInfoS *)(malloc(sizeof(GMM_InnerInfoS)));        if(NULL == pstODGmmInnerS)        {            return OD_RLT_NO;        }        memset(pstODGmmInnerS, 0, sizeof(GMM_InnerInfoS));        usAreaGmmLftTopX = (0 != usAreaGmmLftTopX%2) ? (usAreaGmmLftTopX-1) : (usAreaGmmLftTopX);        usAreaGmmLftTopY = (0 != usAreaGmmLftTopY%2) ? (usAreaGmmLftTopY-1) : (usAreaGmmLftTopY);        usAreaGmmRgtBtmX = (0 != usAreaGmmRgtBtmX%2) ? (usAreaGmmRgtBtmX+1) : (usAreaGmmRgtBtmX);        usAreaGmmRgtBtmY = (0 != usAreaGmmRgtBtmY%2) ? (usAreaGmmRgtBtmY+1) : (usAreaGmmRgtBtmY);        usAreaGmmRgtBtmX = (uiImgWth == usAreaGmmRgtBtmX) ? (usAreaGmmRgtBtmX-2) : (usAreaGmmRgtBtmX);        usAreaGmmRgtBtmY = (uiImgHgt == usAreaGmmRgtBtmY) ? (usAreaGmmRgtBtmY-2) : (usAreaGmmRgtBtmY);         pstODGmmInnerS->stGmmAreaPosLTRB.usLftTopPotX = usAreaGmmLftTopX;        pstODGmmInnerS->stGmmAreaPosLTRB.usLftTopPotY = usAreaGmmLftTopY;        pstODGmmInnerS->stGmmAreaPosLTRB.usRgtBtmPotX = usAreaGmmRgtBtmX;        pstODGmmInnerS->stGmmAreaPosLTRB.usRgtBtmPotY = usAreaGmmRgtBtmY;        /*In Parameter Check*/        pstODGmmInnerS->usGmmImgWth = DIFABS(usAreaGmmRgtBtmX, usAreaGmmLftTopX);        pstODGmmInnerS->usGmmImgHgt = DIFABS(usAreaGmmRgtBtmY, usAreaGmmLftTopY);        pstODGmmInnerS->usGmmImgStp = ALIGN_1(pstODGmmInnerS->usGmmImgWth);        if(pstODGmmInnerS->usGmmImgWth > OD_AREA_WH_MAX ||           pstODGmmInnerS->usGmmImgWth < OD_AREA_WH_MIN ||           pstODGmmInnerS->usGmmImgHgt > OD_AREA_WH_MAX ||           pstODGmmInnerS->usGmmImgHgt < OD_AREA_WH_MIN)        {            printf("GMM_INIT_ERROR_WTH_HGT_WRN:%d %d\n", pstODGmmInnerS->usGmmImgWth, pstODGmmInnerS->usGmmImgHgt);            /*这里有个销毁函数*/            iRetOk = OD_GmmDestroy(pstODGmmInnerS);            if(OD_RLT_NO == iRetOk)            {                return iRetOk;            }            return OD_RLT_NO;        }        pstODGmmInnerS->usGmmWgtThr = 768;    /*设为默认值0.75*1024*/        pstODGmmInnerS->ucGmmImgChn = 3;      /*设为默认值3*/        pstODGmmInnerS->pucModeNum = (PU8)(malloc(pstODGmmInnerS->usGmmImgStp*pstODGmmInnerS->usGmmImgHgt*sizeof(U8)));        if(NULL == pstODGmmInnerS->pucModeNum)        {            return OD_RLT_NO;        }        pstODGmmInnerS->pucRsltImg = (PU8)(malloc(pstODGmmInnerS->usGmmImgStp*pstODGmmInnerS->usGmmImgHgt*sizeof(U8)*pstODGmmInnerS->ucGmmImgChn));        if(NULL == pstODGmmInnerS->pucRsltImg)        {            return OD_RLT_NO;        }        memset(pstODGmmInnerS->pucModeNum, 0, pstODGmmInnerS->usGmmImgStp*pstODGmmInnerS->usGmmImgHgt*sizeof(U8));        memset(pstODGmmInnerS->pucRsltImg, 0, pstODGmmInnerS->usGmmImgStp*pstODGmmInnerS->usGmmImgHgt*sizeof(U8)*pstODGmmInnerS->ucGmmImgChn);        uiGmmModeMemSize = (U32)(pstODGmmInnerS->usGmmImgStp * pstODGmmInnerS->usGmmImgHgt * sizeof(GMM_PixModeS));        for(ucModeIdx = 0; ucModeIdx < GMM_MAX_NUM; ucModeIdx++)        {            GMM_PixModeS * pstGrmmPixMode = (GMM_PixModeS *)(malloc(uiGmmModeMemSize));            if(NULL == pstGrmmPixMode)            {                iRetOk = OD_GmmDestroy(pstODGmmInnerS);                if(OD_RLT_NO == iRetOk)                {                    return iRetOk;                }                return OD_RLT_NO;            }            pstODGmmInnerS->apstGmmModeImg[ucModeIdx] = pstGrmmPixMode;            memset(pstGrmmPixMode, 0, uiGmmModeMemSize);        }              #ifdef GMM_DBG        pstODGmmInnerS->pstGmmImgDbg = cvCreateImage(cvSize(pstODGmmInnerS->usGmmImgStp, pstODGmmInnerS->usGmmImgHgt*4), 8, 3);        if(NULL == pstODGmmInnerS->pstGmmImgDbg)        {            return OD_RLT_NO;           }                #endif        *pWorkHandl = (void *)(pstODGmmInnerS);    }    #else    {        /*暂不处理*/    }    #endif}/***************************************************************************** 函 数 名  : OD_PixModeHandle 功能描述  : XXXX 输入参数  : IN U8 ucRVal                                     IN U8 ucGVal                                     IN U8 ucBVal                                     IN PU8 pucFGFlg                      输出参数  : 无 返 回 值  :  调用函数  :  被调函数  :  修改历史      :  1.日    期   : 2015226日    作    者   : schao    修改内容   : 新生成函数*****************************************************************************/S32 OD_PixModeHandle(IN U8 ucRVal,                     IN U8 ucGVal,                     IN U8 ucBVal,                     IN PU8 pucPixModeNum,                     IN U16 usGmmWgtThr,                     INOUT PU8 pucFGFlg,                     INOUT GMM_PixModeS **ppstGmmPixMode){    S32 iRetOk = OD_RLT_OK;    U8 ucModeIdx = 0;    U8 ucBGFixFlg = GMM_CATCH_N;     /*用来判断是否找到当前点所匹配的模式*/    U8 ucBGFGFlag = GMM_FG_FLG;      /*用来判断当前点是前景点还是背景点*/    U8 ucModeR = 0;    U8 ucModeG = 0;    U8 ucModeB = 0;    U16 usTmpModeWgt = 0;    U16 usTmpModeVar = 0;    S16 sModeUpdSpeed = 256;   /*归一化到[0, 1024]*/    S16 sModeOppSpeed = 768;    S16 sTmpVal = 0;    U8  ucModeNum     = *pucPixModeNum;    U16 usModeBgWgtSum  = 0;    U8  ucModeBgNum     = 0;    GMM_PixModeS stTmpGmmPixMode;    GMM_PixModeS *pstGmmPixMode = NULL;    for(ucModeIdx = 0; ucModeIdx < ucModeNum; ucModeIdx++)    {        pstGmmPixMode = (GMM_PixModeS *)(ppstGmmPixMode[ucModeIdx]);        if(usModeBgWgtSum < usGmmWgtThr)        {            ucModeBgNum++;            usModeBgWgtSum += pstGmmPixMode->usModeWht;        }        else        {            break;           }    }    for(ucModeIdx = 0; ucModeIdx < ucModeNum; ucModeIdx++)    {        pstGmmPixMode = (GMM_PixModeS *)(ppstGmmPixMode[ucModeIdx]);        ucModeR = pstGmmPixMode->ucMValChn0;        ucModeG = pstGmmPixMode->ucMValChn1;        ucModeB = pstGmmPixMode->ucMValChn2;        usTmpModeWgt = pstGmmPixMode->usModeWht;        usTmpModeVar = pstGmmPixMode->usModeVar;        if(GMM_CATCH_N == ucBGFixFlg)        {            S16 sRDiff = (S16)(ucRVal) - (S16)(ucModeR);            S16 sGDiff = (S16)(ucGVal) - (S16)(ucModeG);            S16 sBDiff = (S16)(ucBVal) - (S16)(ucModeB);            U16 usRGBDiffMean = (sRDiff*sRDiff + sGDiff*sGDiff + sBDiff*sBDiff) / 3;            if(usRGBDiffMean < (usTmpModeVar>>1))            {                ucBGFixFlg = GMM_CATCH_Y;   /*找到匹配模型*/                if(ucModeIdx < ucModeBgNum)                {                    ucBGFGFlag = GMM_BG_FLG;                }                sTmpVal = ((S16)(ucModeR) + (sRDiff*sModeUpdSpeed>>10));                ucModeR = (U8)((sTmpVal < 0) ? (0) : ((sTmpVal > 255) ? (255) : (sTmpVal)));                sTmpVal = ((S16)(ucModeG) + (sGDiff*sModeUpdSpeed>>10));                ucModeG = (U8)((sTmpVal < 0) ? (0) : ((sTmpVal > 255) ? (255) : (sTmpVal)));                sTmpVal = ((S16)(ucModeB) + (sBDiff*sModeUpdSpeed>>10));                ucModeB = (U8)((sTmpVal < 0) ? (0) : ((sTmpVal > 255) ? (255) : (sTmpVal)));                usTmpModeWgt = (U16)((sModeOppSpeed*usTmpModeWgt + sModeUpdSpeed + 512)>>10);                sTmpVal = (S16)(usTmpModeVar) + (sModeUpdSpeed*((S32)(usRGBDiffMean) - (S32)(usTmpModeVar))>>10);                usTmpModeVar = (sTmpVal > GMM_VAR_MAX) ? (GMM_VAR_MAX) : ((sTmpVal < GMM_VAR_MIN) ? (GMM_VAR_MIN) : (sTmpVal));                pstGmmPixMode->ucMValChn0 = ucModeR;                pstGmmPixMode->ucMValChn1 = ucModeG;                pstGmmPixMode->ucMValChn2 = ucModeB;                pstGmmPixMode->usModeWht  = usTmpModeWgt;                pstGmmPixMode->usModeVar  = usTmpModeVar;            }            else            {                pstGmmPixMode->usModeWht = ((usTmpModeWgt * sModeOppSpeed + 512)>>10);            }        }        else        {            pstGmmPixMode->usModeWht = ((usTmpModeWgt * sModeOppSpeed + 512)>>10);        }    }    /*如果没有匹配的模型*/    if(GMM_CATCH_N == ucBGFixFlg)    {        U16 usModeWgtSum = 0;        /*如果模型达到最大替换最小*//*如果模型未达则添加新的模型*/        ucModeNum += (GMM_MAX_NUM == ucModeNum) ? (0) : (1);        /*给新的模型赋初值*/        ppstGmmPixMode[ucModeNum-1]->usModeWht = (1 == ucModeNum) ? (1024) : (GMM_INIT_WGT);        ppstGmmPixMode[ucModeNum-1]->ucMValChn0 = ucRVal;        ppstGmmPixMode[ucModeNum-1]->ucMValChn1 = ucGVal;        ppstGmmPixMode[ucModeNum-1]->ucMValChn2 = ucBVal;        ppstGmmPixMode[ucModeNum-1]->usModeVar = GMM_INIT_VAR;        /*将权重重新归一化下*/        for(ucModeIdx = 0; ucModeIdx < ucModeNum; ucModeIdx++)        {            usModeWgtSum += ppstGmmPixMode[ucModeIdx]->usModeWht;        }        for(ucModeIdx = 0; ucModeIdx < ucModeNum; ucModeIdx++)        {            ppstGmmPixMode[ucModeIdx]->usModeWht = (ppstGmmPixMode[ucModeIdx]->usModeWht<<10 + 512)/usModeWgtSum;        }        /*从大到小排序*/        for(ucModeIdx = 0; ucModeIdx < GMM_DIFABS(ucModeNum, 1); ucModeIdx++)        {            U8 ucTmpIdx = 0;            for(ucTmpIdx = ucModeIdx; ucTmpIdx < GMM_DIFABS(ucModeNum, 1); ucTmpIdx++)            {                if(ppstGmmPixMode[ucTmpIdx]->usModeWht < ppstGmmPixMode[ucTmpIdx+1]->usModeWht)                {                    stTmpGmmPixMode                       = *ppstGmmPixMode[ucTmpIdx];                     *ppstGmmPixMode[ucTmpIdx]             = *ppstGmmPixMode[ucTmpIdx+1];                    *ppstGmmPixMode[ucTmpIdx+1]           = stTmpGmmPixMode;                }            }        }    }    else    {                U16 usModeWgtSum = 0;        /*根据权重排序,同时归一化权重*/         for(ucModeIdx = 0; ucModeIdx < ucModeNum; ucModeIdx++)        {            usModeWgtSum += ppstGmmPixMode[ucModeIdx]->usModeWht;        }        for(ucModeIdx = 0; ucModeIdx < ucModeNum; ucModeIdx++)        {            ppstGmmPixMode[ucModeIdx]->usModeWht = (ppstGmmPixMode[ucModeIdx]->usModeWht<<10+512)/usModeWgtSum;        }        for(ucModeIdx = 0; ucModeIdx < GMM_DIFABS(ucModeNum, 1); ucModeIdx++)        {            U8 ucTmpIdx = 0;            for(ucTmpIdx = ucModeIdx; ucTmpIdx < GMM_DIFABS(ucModeNum, 1); ucTmpIdx++)            {                if(ppstGmmPixMode[ucTmpIdx]->usModeWht < ppstGmmPixMode[ucTmpIdx+1]->usModeWht)                {                    stTmpGmmPixMode                       = *ppstGmmPixMode[ucTmpIdx];                     *ppstGmmPixMode[ucTmpIdx]             = *ppstGmmPixMode[ucTmpIdx+1];                    *ppstGmmPixMode[ucTmpIdx+1]           = stTmpGmmPixMode;                }            }        }    }    *pucPixModeNum = ucModeNum;    *pucFGFlg = ucBGFGFlag;    return iRetOk;}/***************************************************************************** 函 数 名  : OD_RGBBgSub 功能描述  : XXXX 输入参数  : pucGmmAllImgRGB               usGmmImgWth                   usGmmImgHgt                   usGmmImgStp                   pucGmmFGMask      输出参数  : 无 返 回 值  :  调用函数  :  被调函数  :  修改历史      :  1.日    期   : 2015226日    作    者   : schao    修改内容   : 新生成函数*****************************************************************************/S32 OD_RGBBgSub(IN PU8 pucInpRGBImg,                IN GMM_PixModeS **ppstGmmPixMode,                IN PU8 pucImgModeNum,                IN U16 usGmmWgtThr,                IN U16 usGmmImgWth,                IN U16 usGmmImgHgt,                IN U16 usGmmImgStp,                OUT PU8 pucGmmFGMask){    S32 iRetOk = OD_RLT_OK;    U8 ucRVal = 0;    U8 ucGVal = 0;    U8 ucBVal = 0;    U8 ucFGFlg = 0;    U16 usYIdx = 0;    U16 usXIdx = 0;    U32 uiRGBTtlYIdx = 0;    U32 uiRGBTtlXIdx = 0;    U32 uiTtlYIdx = 0;    U32 uiTtlXIdx = 0;    GMM_PixModeS *apstGmmPixMode[GMM_MAX_NUM] = {NULL, NULL, NULL, NULL};    PU8 pucPixModeNum = NULL;    if(NULL == pucInpRGBImg || NULL == pucGmmFGMask)    {        return OD_RLT_NO;    }    for(usYIdx = 0; usYIdx < usGmmImgHgt; usYIdx++)    {        uiRGBTtlYIdx = usYIdx * usGmmImgStp * 3;        uiTtlYIdx    = usYIdx * usGmmImgStp;        for(usXIdx = 0; usXIdx < usGmmImgWth; usXIdx++)        {            uiRGBTtlXIdx = uiRGBTtlYIdx + usXIdx+ usXIdx+ usXIdx;            uiTtlXIdx    = uiTtlYIdx + usXIdx;            ucRVal = pucInpRGBImg[uiRGBTtlXIdx];            ucGVal = pucInpRGBImg[uiRGBTtlXIdx+1];            ucBVal = pucInpRGBImg[uiRGBTtlXIdx+2];            apstGmmPixMode[0] = (GMM_PixModeS *)(ppstGmmPixMode[0]) + uiTtlXIdx;            apstGmmPixMode[1] = (GMM_PixModeS *)(ppstGmmPixMode[1]) + uiTtlXIdx;            apstGmmPixMode[2] = (GMM_PixModeS *)(ppstGmmPixMode[2]) + uiTtlXIdx;            apstGmmPixMode[3] = (GMM_PixModeS *)(ppstGmmPixMode[3]) + uiTtlXIdx;            pucPixModeNum  = pucImgModeNum + uiTtlXIdx;            OD_PixModeHandle(ucRVal,                             ucGVal,                             ucBVal,                             pucPixModeNum,                             usGmmWgtThr,                             &ucFGFlg,                             apstGmmPixMode);            if(GMM_FG_FLG == ucFGFlg)            {                pucGmmFGMask[uiRGBTtlXIdx]   = ucRVal;                pucGmmFGMask[uiRGBTtlXIdx+1] = ucGVal;                pucGmmFGMask[uiRGBTtlXIdx+2] = ucBVal;            }        }    }    return iRetOk;}/***************************************************************************** 函 数 名  : OD_GmmWorkInterface 功能描述  : GMM工作接口函数 输入参数  : &pvdObjDetHandle                       pucOri_All_Y                           pucOri_All_UV                          stODTShrMem.pucMem                     stODTShrMem.iMemNotUsed                (unsigned int)(usImgWth)               (unsigned int)(usImgHgt)               (unsigned int)(usImgStp)   输出参数  : 无 返 回 值  :  调用函数  :  被调函数  :  修改历史      :  1.日    期   : 2015223日    作    者   : schao    修改内容   : 新生成函数*****************************************************************************/S32 OD_GmmWorkInterface(IN PVD *pvdWorkHandle,                        IN PU8 pucAllImgY,                        IN PU8 pucAllImgUV,                        IN U32 uiFrmNum,                        IN PU8 pucTmpShrMem,                        IN U32 uiShrMemNotUsed,                        IN U32 uiAllImgWth,                        IN U32 uiAllImgHgt,                        IN U32 uiAllImgStp){    S32 iRetOk = OD_RLT_NO;    PU8 pucImgModeNum = NULL;    PU8 pucRsltImg    = NULL;    U16 usYIdx = 0;    U16 usXIdx = 0;    U16 usGmmImgWth = 0;    U16 usGmmImgHgt = 0;    U16 usGmmImgStp = 0;    U8  ucGmmImgChn = 0;    U16 usGmmWgtThr = 0;    U16 usGmmAreaLftTopX = 0;    U16 usGmmAreaLftTopY = 0;    U16 usGmmAreaRgtBtmX = 0;    U16 usGmmAreaRgtBtmY = 0;    U32 uiOriYTtlIdxY = 0;    U32 uiOriXTtlIdxY = 0;    U32 uiOriYTtlIdxUV = 0;    U32 uiOriXTtlIdxUV = 0;    U32 uiGmmYTtlIdxRGB = 0;    U32 uiGmmXTtlIdxRGB = 0;    PU8 pucGmmAllImgY   = NULL;    PU8 pucGmmAllImgUV  = NULL;    PU8 pucGmmAllImgRGB = NULL;    U32 uiShrMemUsed = 0;    GMM_InnerInfoS * pstGmmInnerInfo = NULL;    GMM_PixModeS   **ppstGmmPixMode  = NULL;    if(NULL == (*pvdWorkHandle))    {        return OD_RLT_NO;    }    pstGmmInnerInfo = (GMM_InnerInfoS *)(*pvdWorkHandle);    pucImgModeNum = pstGmmInnerInfo->pucModeNum;    pucRsltImg    = pstGmmInnerInfo->pucRsltImg;    usGmmWgtThr  = pstGmmInnerInfo->usGmmWgtThr;    usGmmImgWth = pstGmmInnerInfo->usGmmImgWth;    usGmmImgHgt = pstGmmInnerInfo->usGmmImgHgt;    usGmmImgStp = pstGmmInnerInfo->usGmmImgStp;    ucGmmImgChn = pstGmmInnerInfo->ucGmmImgChn;     usGmmAreaLftTopX = pstGmmInnerInfo->stGmmAreaPosLTRB.usLftTopPotX;    usGmmAreaLftTopY = pstGmmInnerInfo->stGmmAreaPosLTRB.usLftTopPotY;    usGmmAreaRgtBtmX = pstGmmInnerInfo->stGmmAreaPosLTRB.usRgtBtmPotX;    usGmmAreaRgtBtmY = pstGmmInnerInfo->stGmmAreaPosLTRB.usRgtBtmPotY;    ppstGmmPixMode = pstGmmInnerInfo->apstGmmModeImg;    if(usGmmImgWth < OD_AREA_WH_MIN ||       usGmmImgWth > OD_AREA_WH_MAX ||       usGmmImgHgt < OD_AREA_WH_MIN ||       usGmmImgHgt > OD_AREA_WH_MAX ||       usGmmImgWth > usGmmImgStp)    {        return  OD_RLT_NO;    }    /*分配共享内存*//*加一个内存是否够的判断*/       pucGmmAllImgRGB = pucTmpShrMem + uiShrMemUsed;    uiShrMemUsed   += (usGmmImgStp * usGmmImgHgt) * sizeof(U8) * 3;    /*YUV转成RGB*/    pucGmmAllImgY  = pucAllImgY + usGmmAreaLftTopY       * uiAllImgStp +   usGmmAreaLftTopX;    pucGmmAllImgUV = pucAllImgUV + (usGmmAreaLftTopY>>1) * uiAllImgStp + ((usGmmAreaLftTopX>>1)<<1);    for(usYIdx = 0; usYIdx < usGmmImgHgt; usYIdx++)    {        uiOriYTtlIdxY   =  usYIdx     *  uiAllImgStp;        uiOriYTtlIdxUV  = (usYIdx>>1) *  uiAllImgStp;        uiGmmYTtlIdxRGB =  usYIdx     * (usGmmImgStp*3);        for(usXIdx = 0; usXIdx < usGmmImgWth; usXIdx++)        {            S32 iTmp1 = 0;            S32 iTmp2 = 0;            S32 iTmp3 = 0;            S32 iRTmp = 0;            S32 iGTmp = 0;            S32 iBTmp = 0;            uiOriXTtlIdxY   =  uiOriYTtlIdxY   +  usXIdx;            uiOriXTtlIdxUV  =  uiOriYTtlIdxUV  + ((usXIdx>>1)<<1);            uiGmmXTtlIdxRGB =  uiGmmYTtlIdxRGB + usXIdx+usXIdx+usXIdx;            /*--------YUV==YCbCr------*/                        //R' = 1.164*(Y’-16) + 1.596*(Cr'-128)            //G' = 1.164*(Y’-16) - 0.813*(Cr'-128) - 0.392*(Cb'-128)            //B' = 1.164*(Y’-16) + 2.017*(Cb'-128)            iTmp1 = (((S32)(pucGmmAllImgY[uiOriXTtlIdxY])- 16) * 1192);            iTmp2 = ((S32)(pucGmmAllImgUV[uiOriXTtlIdxUV])   - 128);            iTmp3 = ((S32)(pucGmmAllImgUV[uiOriXTtlIdxUV+1]) - 128);            iRTmp = abs((iTmp1 + 1634 * iTmp3 + 512)>>10);            iGTmp = abs((iTmp1 - 833  * iTmp3 - 401 * iTmp2 + 512)>>10);            iBTmp = abs((iTmp1 + 2065 * iTmp2 + 512)>>10);            iRTmp = (iRTmp > 255) ? (255) : (iRTmp);            iGTmp = (iGTmp > 255) ? (255) : (iGTmp);            iBTmp = (iBTmp > 255) ? (255) : (iBTmp);            pucGmmAllImgRGB[uiGmmXTtlIdxRGB]   = (U8)(iRTmp);            pucGmmAllImgRGB[uiGmmXTtlIdxRGB+1] = (U8)(iGTmp);            pucGmmAllImgRGB[uiGmmXTtlIdxRGB+2] = (U8)(iBTmp);        }    }        #if 1    {        U16  usYIdx = 0;        U16  usXIdx = 0;        char acPreAll[100] = {0};        char acPreNum[10]  = {0};        unsigned char *pucTmpTmp = NULL;        IplImage  *pImgFrmTmpMerge = cvCreateImage(cvSize(usGmmImgWth, usGmmImgHgt), 8, 3);        for(usYIdx = 0; usYIdx < usGmmImgHgt; usYIdx++)        {               uiGmmYTtlIdxRGB =  usYIdx * (usGmmImgStp*3);            for(usXIdx = 0; usXIdx < usGmmImgWth; usXIdx++)            {                /*--------YUV==YCbCr------*/                            //R' = 1.164*(Y’-16) + 1.596*(Cr'-128)                //G' = 1.164*(Y’-16) - 0.813*(Cr'-128) - 0.392*(Cb'-128)                //B' = 1.164*(Y’-16) + 2.017*(Cb'-128)                //S32 iTmpY = pucTmpTmp[usXIdx];                //S32 iTmpU = 128;                //S32 iTmpV = 128;                //S32 iTmp1 = ((iTmpY- 16)*1192);                //S32 iTmp2 = (iTmpU - 128);                //S32 iTmp3 = (iTmpV - 128);                //S32 iRTmp = ((iTmp1 +  1634*iTmp3 + 512)>>10);                //S32 iGTmp = ((iTmp1 -  833*iTmp3 - 401*iTmp2 + 512)>>10);                //S32 iBTmp = ((iTmp1 +  2065*iTmp2 + 512)>>10);                //iRTmp = (iRTmp < 0) ? (0) : (iRTmp);                //iGTmp = (iGTmp < 0) ? (0) : (iGTmp);                //iBTmp = (iBTmp < 0) ? (0) : (iBTmp);                uiGmmXTtlIdxRGB =  uiGmmYTtlIdxRGB + usXIdx+usXIdx+usXIdx;                pImgFrmTmpMerge->imageData[usYIdx * pImgFrmTmpMerge->widthStep + usXIdx*3]       = pucGmmAllImgRGB[uiGmmXTtlIdxRGB+2];                pImgFrmTmpMerge->imageData[usYIdx * pImgFrmTmpMerge->widthStep + usXIdx * 3 + 1] = pucGmmAllImgRGB[uiGmmXTtlIdxRGB+1];                pImgFrmTmpMerge->imageData[usYIdx * pImgFrmTmpMerge->widthStep + usXIdx * 3 + 2] = pucGmmAllImgRGB[uiGmmXTtlIdxRGB];            }        }        _itoa_s((S32)(uiFrmNum), acPreNum, 10, 10);        strcpy_s(acPreAll, sizeof(acPreAll), "F:\\Subjects_Codes\\练习代码类\\OD\\ODT_ObjDetTrack\\TestVideo\\Ori");        strcat_s(acPreAll, sizeof(acPreAll), acPreNum);        strcat_s(acPreAll, sizeof(acPreAll), ".jpg");        cvSaveImage(acPreAll, pImgFrmTmpMerge, 0);    }    #endif    memset(pucRsltImg, 0, sizeof(U8)*usGmmImgStp*usGmmImgHgt*ucGmmImgChn);    OD_RGBBgSub(pucGmmAllImgRGB,                ppstGmmPixMode,                pucImgModeNum,                usGmmWgtThr,                usGmmImgWth,                usGmmImgHgt,                usGmmImgStp,                pucRsltImg);    #ifdef GMM_DBG    {        int ic = 0;        U16 usYIdx = 0;        U16 usXIdx = 0;        U32 uiYTtlIdx = 0;        U32 uiXTtlIdx = 0;        char acPreAll[100] = {0};        char acPreNum[10]  = {0};        PS8 pcTmp = pstGmmInnerInfo->pstGmmImgDbg->imageData;        for(usYIdx = 0; usYIdx < usGmmImgHgt; usYIdx++)        {            uiYTtlIdx = usYIdx*usGmmImgStp;            for(usXIdx = 0; usXIdx < usGmmImgWth; usXIdx++)            {                uiXTtlIdx = uiYTtlIdx + usXIdx;                pcTmp[usYIdx*pstGmmInnerInfo->pstGmmImgDbg->widthStep+usXIdx*3+2] = ppstGmmPixMode[0][uiXTtlIdx].ucMValChn0;                pcTmp[usYIdx*pstGmmInnerInfo->pstGmmImgDbg->widthStep+usXIdx*3+1] = ppstGmmPixMode[0][uiXTtlIdx].ucMValChn1;                pcTmp[usYIdx*pstGmmInnerInfo->pstGmmImgDbg->widthStep+usXIdx*3+0] = ppstGmmPixMode[0][uiXTtlIdx].ucMValChn2;            }        }        pcTmp = pstGmmInnerInfo->pstGmmImgDbg->imageData+pstGmmInnerInfo->pstGmmImgDbg->widthStep*usGmmImgHgt+0;        for(usYIdx = 0; usYIdx < usGmmImgHgt; usYIdx++)        {            uiYTtlIdx = usYIdx*usGmmImgStp;            for(usXIdx = 0; usXIdx < usGmmImgWth; usXIdx++)            {                uiXTtlIdx = uiYTtlIdx + usXIdx;                pcTmp[usYIdx*pstGmmInnerInfo->pstGmmImgDbg->widthStep+usXIdx*3+2] = ppstGmmPixMode[1][uiXTtlIdx].ucMValChn0;                pcTmp[usYIdx*pstGmmInnerInfo->pstGmmImgDbg->widthStep+usXIdx*3+1] = ppstGmmPixMode[1][uiXTtlIdx].ucMValChn1;                pcTmp[usYIdx*pstGmmInnerInfo->pstGmmImgDbg->widthStep+usXIdx*3+0] = ppstGmmPixMode[1][uiXTtlIdx].ucMValChn2;            }        }        pcTmp = pstGmmInnerInfo->pstGmmImgDbg->imageData+pstGmmInnerInfo->pstGmmImgDbg->widthStep*usGmmImgHgt*2+0;        for(usYIdx = 0; usYIdx < usGmmImgHgt; usYIdx++)        {            uiYTtlIdx = usYIdx*usGmmImgStp;            for(usXIdx = 0; usXIdx < usGmmImgWth; usXIdx++)            {                uiXTtlIdx = uiYTtlIdx + usXIdx;                pcTmp[usYIdx*pstGmmInnerInfo->pstGmmImgDbg->widthStep+usXIdx*3+2] = ppstGmmPixMode[2][uiXTtlIdx].ucMValChn0;                pcTmp[usYIdx*pstGmmInnerInfo->pstGmmImgDbg->widthStep+usXIdx*3+1] = ppstGmmPixMode[2][uiXTtlIdx].ucMValChn1;                pcTmp[usYIdx*pstGmmInnerInfo->pstGmmImgDbg->widthStep+usXIdx*3+0] = ppstGmmPixMode[2][uiXTtlIdx].ucMValChn2;            }        }        pcTmp = pstGmmInnerInfo->pstGmmImgDbg->imageData+pstGmmInnerInfo->pstGmmImgDbg->widthStep*usGmmImgHgt*3+0;        for(usYIdx = 0; usYIdx < usGmmImgHgt; usYIdx++)        {            uiYTtlIdx = usYIdx*usGmmImgStp;            for(usXIdx = 0; usXIdx < usGmmImgWth; usXIdx++)            {                uiXTtlIdx = uiYTtlIdx + usXIdx;                pcTmp[usYIdx*pstGmmInnerInfo->pstGmmImgDbg->widthStep+usXIdx*3+2] = ppstGmmPixMode[3][uiXTtlIdx].ucMValChn0;                pcTmp[usYIdx*pstGmmInnerInfo->pstGmmImgDbg->widthStep+usXIdx*3+1] = ppstGmmPixMode[3][uiXTtlIdx].ucMValChn1;                pcTmp[usYIdx*pstGmmInnerInfo->pstGmmImgDbg->widthStep+usXIdx*3+0] = ppstGmmPixMode[3][uiXTtlIdx].ucMValChn2;            }        }        _itoa_s((S32)(uiFrmNum), acPreNum, 10, 10);        strcpy_s(acPreAll, sizeof(acPreAll), "F:\\Subjects_Codes\\练习代码类\\OD\\ODT_ObjDetTrack\\TestVideo\\Mod");        strcat_s(acPreAll, sizeof(acPreAll), acPreNum);        strcat_s(acPreAll, sizeof(acPreAll), ".jpg");        cvSaveImage(acPreAll, pstGmmInnerInfo->pstGmmImgDbg, 0);        /*显示结果图像*/        cvShowImage("GMM", pstGmmInnerInfo->pstGmmImgDbg);        ic = cvWaitKey(10);        //if(27 == ic){break;}    }    {        U16 usYIdx = 0;        U16 usXIdx = 0;        U32 uiYTtlIdx = 0;        U32 uiXTtlIdx = 0;        char *pcTmp = gpucVibeMaskPtr + guiImgStp*gusLftTopY+gusLftTopX+gusLftTopX+gusLftTopX;        for(usYIdx = 0; usYIdx < usGmmImgHgt; usYIdx++)        {            uiYTtlIdx = usYIdx*usGmmImgStp*3;            for(usXIdx = 0; usXIdx < usGmmImgWth; usXIdx++)            {                               int iRTmp = pucRsltImg[uiYTtlIdx+usXIdx+usXIdx+usXIdx];                int iGTmp = pucRsltImg[uiYTtlIdx+usXIdx+usXIdx+usXIdx+1];                int iBTmp = pucRsltImg[uiYTtlIdx+usXIdx+usXIdx+usXIdx+2];                *(pcTmp + usYIdx*guiImgStp + usXIdx+usXIdx+usXIdx+2) = iRTmp;                *(pcTmp + usYIdx*guiImgStp + usXIdx+usXIdx+usXIdx+1) = iGTmp;                *(pcTmp + usYIdx*guiImgStp + usXIdx+usXIdx+usXIdx+0) = iBTmp;            }        }    }    #endif    return iRetOk;}#ifdef __cplusplus}#endif
0 0
原创粉丝点击