運動目標檢測 之 GMM背景模型演算法
綜述
單高斯背景建模是一種基於畫素樣本統計資訊的背景表示方法,它是根據視訊中的每個畫素在時域上的概率統計資訊(均值/方差)來構建各個畫素的顏色分佈模型,依次來達到背景建模的目的。背景建模完成後,使用統計差分進行目標畫素判斷以達到對前景目標的檢測,同時用目標畫素不斷更新背景模型以實現對動態背景的建模擬合。
混合高斯背景模型是有限個單高斯分佈的加權和,它能描述畫素的多峰狀態,適用於對光照漸變、樹木搖擺等複雜背景進行準確建模。所謂多峰狀態就是在同一時間段內,由於場景的複雜性某個畫素點存在多個背景狀態,比如樹木搖擺的某個畫素點,在樹枝覆蓋了這個畫素點時它的畫素點值(R:35,G:45,B:65),在下幀影象中樹枝由於風吹沒有覆蓋這個畫素點時它的值為(R:135,G:200,B:35),對這個畫素來說它有這兩種背景狀態,在視訊中很多幀影象的時序上來說,這個畫素點不停的出現這兩種狀態,就呈現了一個多峰的背景分佈模型。
高斯背景模型中,認為畫素之間的顏色資訊互不相關,對各畫素點的處理都是相互獨立的。對於視訊影象中的每一個畫素點,其值在序列影象中的變化可看作是不斷產生畫素值的隨機過程,即用高斯分佈來描述每個畫素點的顏色呈現規律(多峰/單峰)。
原理
在混合高斯背景模型維護中,場景中的一個畫素值的混合高斯模型我們假設它有K個高斯分佈組成,那麼在影象中畫素j在時刻t取值為 的概率為:
其中表示t時刻畫素j的混合高斯模型中第i個高斯分佈的權重,滿足:
其中
表示 第i個高斯成分的均值
是協方差:,其中是標準差,I是單位矩陣
為高斯概率密度函式:
演算法邏輯
1、初始化:取視訊第一幀影象中每個畫素的值來對各自混合高斯模型中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;
#endif
typedef signed char S8;
typedef signed short S16;
typedef signed int S32;
#ifdef CHIP_DM6467
typedef signed long long S64;
#else
typedef signed __int64 S64;
#endif
typedef 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;
#endif
typedef signed char * PS8;
typedef signed short * PS16;
typedef signed int * PS32;
#ifdef CHIP_DM6467
typedef signed long long * PS64;
#else
typedef signed __int64 * PS64;
#endif
typedef 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_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->imageDa