运动目标检测 之 GMM背景模型算法
综述
单高斯背景建模是一种基于像素样本统计信息的背景表示方法,它是根据视频中的每个像素在时域上的概率统计信息(均值/方差)来构建各个像素的颜色分布模型,依次来达到背景建模的目的。背景建模完成后,使用统计差分进行目标像素判断以达到对前景目标的检测,同时用目标像素不断更新背景模型以实现对动态背景的建模拟合。
混合高斯背景模型是有限个单高斯分布的加权和,它能描述像素的多峰状态,适用于对光照渐变、树木摇摆等复杂背景进行准确建模。所谓多峰状态就是在同一时间段内,由于场景的复杂性某个像素点存在多个背景状态,比如树木摇摆的某个像素点,在树枝覆盖了这个像素点时它的像素点值(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 __cplusplus
extern "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_DM6467
typedef unsigned long long U64;
#else
typedef unsigned __int64 U64;
#endiftypedef signed char S8;
typedef signed short S16;
typedef signed int S32;
#ifdef CHIP_DM6467
typedef signed long long S64;
#else
typedef 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_DM6467
typedef unsigned long long * PU64;
#else
typedef unsigned __int64 * PU64;
#endiftypedef signed char * PS8;
typedef signed short * PS16;
typedef signed int * PS32;
#ifdef CHIP_DM6467
typedef signed long long * PS64;
#else
typedef signed __int64 * PS64;
#endiftypedef float * PFL;
typedef double * PDB;
typedef void * PVD;/*^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^函数结构体定义^^^^^^^^^^^^^^^^^^^^^^*//*vvvvvvvvvvvvvvvvvvvvvvvvvvvvvv函数结构体定义vvvvvvvvvvvvvvvvvvvvvv*/
#ifdef __cplusplus
}
#endif
#endif
.c文件
#ifdef __cplusplus
extern "C"{
#endif#include "ObjDet_GmmHead.h"/*****************************************************************************函 数 名 : OD_GmmDestroy功能描述 : XXXX输入参数 : INOUT void **pWorkHandl 输出参数 : 无返 回 值 : 调用函数 : 被调函数 : 修改历史 :1.日 期 : 2015年2月23日作 者 : 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_DBGif(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.日 期 : 2015年2月23日作 者 : 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_DBGpstODGmmInnerS->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.日 期 : 2015年2月26日作 者 : 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.日 期 : 2015年2月26日作 者 : 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.日 期 : 2015年2月23日作 者 : 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);}#endifmemset(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;}}}#endifreturn iRetOk;
}#ifdef __cplusplus
}
#endif
运动目标检测 之 GMM背景模型算法相关推荐
- 运动目标检测(GMM、Code Book、Vibe)
运动目标检测(前景背景分离)被认为是视频分析学习的入门基础,分为以像素为特征的方法和以纹理为特征的方法,以纹理为特征的方法主要参考上节所讲的LBP和SILTP,这里我们重点介绍像素方法,像素方法是最常 ...
- 运动目标检测单高斯背景建模
1.运动目标背景建模 背景建模也称为背景估计,其主要目的是根据当前的背景估计,把对序列图像的运动目标检测问题转化为一个二分类问题,将所有像素划分为背景和运动前景两类,进而对分类结果进行后处理,得到最终 ...
- 运动目标检测混合高斯背景建模
1.混合高斯背景建模理论 混合高斯背景建模是基于像素样本统计信息的背景表示方法,利用像素在较长时间内大量样本值的概率密度等统计信息(如模式数量.每个模式的均值和标准差)表示背景,然后使用统计差分(如3 ...
- Matlab实现---基于平均背景法的视频运动目标检测(有背景更新)
目录 实现目标及说明 代码及说明 完整文件获取 实现目标及说明 MATLAB--编程实现基于平均背景法的视频运动目标检测,并且要不断更新背景. 网上找到的很多关于运动目标检测的,多数是用OpenCV或 ...
- 【计算机视觉】运动目标检测算法文献阅读笔记
先前在博客中对常见的运动目标检测算法有写过一篇总结,详情请参考:http://blog.csdn.NET/kezunhai/article/details/8830787.本文是在校期间写的部分阅读笔 ...
- Python与OpenCV(二)——基于背景差分法的运动目标检测程序分析
背景差分法是传统运动目标检测算法中最常用的方法.其基本原理如图所示. 从图中可知,背景差分法是通过建立背景模型,比较当前帧与背景模型对应像素的差异点来检测运动目标的方法. 背景模型的建立主要通过两种方 ...
- 运动目标检测ViBe算法的numpy实现
ViBe算法是一种优秀的运动目标检测,其背景建模是基于像素的邻域来建立,算法的具体原理我就不介绍了,网上可以搜到一大堆.网上提供的实现方法多是遍历图像中每个像素建立背景模型,有用c/c++实现的,也有 ...
- 运动目标检测——研究方向与难点
运动目标检测算法的研究 1 帧间差分法 帧间差分法是用来检测固定摄像头下的运动物体.该方法利用图像序列中相邻帧的像素值之间的相关性,先将图像序列中相邻两帧进行相减,然后对得到差值图像进行阈值判断,进而 ...
- 基于高斯核密度估计的背景建模和改进的五帧帧差法相融合的运动目标检测算法
上篇文章所指定的是对一个不包含动态背景的监控视频进行前景提取,用基于改进的五帧帧差和混合高斯模型相融合的前景提取算法是可以很好实现前景提取的.但本文中要求在包含动态背景的监控视频提取前景目标,虽然上篇 ...
最新文章
- GBDT和GNN结合,结果怎么样?
- uses 子句的写法
- 同余(数论) AcWing算法课
- Android中TextView限制一行显示及其它效果
- CF 1475 F . Unusual Matrix 思维
- java安卓浏览器下载文件,JAVA实现文件下载,浏览器端得到数据没反应解决方案
- Redhat enterprise linux下安装rlwrap工具
- 【c语言】关键字存储类型讲解(auto,extern,static,register,const)
- 又一个脑洞实现了!索尼将推出穿在身上的空调:夏日出门必备
- view绘制流程学习心得
- 马尔科夫决策过程(MDP) : BlackJack (MC-On Policy)
- Java使用数组学习心得
- java正则判断11位手机号码_java-正则表达式判断手机号
- java影院订票系统图形界面,java简单影院订票系统Word版
- 百度快照劫持代码的更新
- 月入3万多的程序员回老家, 被亲戚说不如县城卖手机月入2千的表弟
- CTF-网络信息安全攻防学习平台(脚本关)
- 【数据分析实战】杭州2019年链家在售房源数据分析
- Zxing 预览框不变增加扫描区域,仿微信扫到一半就可以成功
- 关于数据库报错ERROR 2003 (HY000): Can‘t connect to MySQL server on ‘localhost:3306‘ (10061