运动目标检测 之 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.日 期 : 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_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.日 期 : 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_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.日 期 : 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); } #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
- 运动目标检测 之 GMM背景模型算法
- 运动目标检测 之 Vibe背景模型算法
- OpenCV之基于GMM的运动目标检测
- 目标检测之GMM
- OpenCV_基于混合高斯模型GMM的运动目标检测
- OpenCV_基于混合高斯模型GMM的运动目标检测
- OpenCV_基于混合高斯模型GMM的运动目标检测
- OpenCV_基于混合高斯模型GMM的运动目标检测
- OpenCV_基于混合高斯模型GMM的运动目标检测
- OpenCV_基于混合高斯模型GMM的运动目标检测
- 【matlab】运动目标检测之"背景差分算法“(转载)
- 运动目标检测--背景减法
- 运动目标检测--背景减法
- 运动目标检测--背景减法
- 运动目标检测算法
- 运动目标检测算法
- 基于自组织背景减除的运动目标检测算法
- 运动背景下的运动目标检测
- Linux下scp的用法
- [leetCode]155. Min Stack
- j2ee项目中突然出现大批量的路径报错
- laravel对数据库的便捷操作
- 关于数字倒置的函数
- 运动目标检测 之 GMM背景模型算法
- spark for python : linux
- /etc/profile /etc/bashrc ~/.bash_profile ~/.bashrc ~/.bash_logout 说明及区别
- OpenCms多语言内容添加拷贝
- 随软键盘的弹起与隐藏,界面做合理的调整的一种实现(避免软键盘遮挡内容的显示)
- 科目二
- 自己动手,打造自己的事件总线
- 重定向和转发中的路径问题
- OpenCV3.0 Examples学习笔记(3)-cout_mat.cpp