You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

1133 lines
40 KiB

/*********版权所有C2014武汉高德红外股份有限公司***************
* Arith_BkgMonitor.cpp
*
*
* "Arith_BkgMonitor""BKM"
* V2.0
* MSSu
* 2015.03.16
*
* 1
* 2015.04.20
* V2.0
* MSSu
*
* 2
*******************************************************************/
#include "Arith_ImgOperate.h"
#include "Arith_Detector.h"
#include "Arith_BkgMonitor.h"
#include "Arith_TrackSAObj.h"
#include <opencv2/opencv.hpp>
BkgMonitor::BkgMonitor()
{
memset(g_GLB_bObj8BkgStatus, 0, sizeof(BBOOL) * GLB_OBJ_BKG_NUM); //20170227Whao目标跟踪时8邻域方差异常标志
g_GLB_bComplexEnv = FALSE; //20170301连续退出复杂环境帧计数及进入复杂环境标志
g_GLB_bCrossInterference = FALSE; //20170603wsa,场景分析:判断是否有交错目标干扰
g_GLB_bMultiObj = FALSE; //20170301连续多目标帧计数及标志
g_GLB_bMultiObjMerge = FALSE; //20170306多目标合并标志位
g_GLB_bInterferenceMem = FALSE; //20170217Whao干扰进记忆跟踪标志位和干扰方向
g_GLB_bInfrnDirection = GLB_INFRN_DIR_NONE; //20170217Whao干扰进记忆跟踪标志位和干扰方向
g_GLB_nObj8BkgArrayIndex = 0; //20170220Whao目标跟踪时8邻域背景监控均值与方差数据记录的数组当前下标
g_GLB_nObj8BkgFrames = 0; //20170220Whao目标跟踪时8邻域背景监控均值与方差数据记录的总帧数
g_GLB_nExitInfrnMemCnt = 0; //20170302Whao退出干扰进记忆跟踪帧计数
g_GLB_nMultiObjCnt = 0; //20170301连续多目标帧计数及标志
g_GLB_nExitComplexEnv = 0; //20170301连续退出复杂环境帧计数及进入复杂环境标志【DSP-B核移植】
g_GLB_nCrossInterferenceCnt = 0; //20170603wsa,场景分析:交错目标干扰时目标逼近计数器
g_GLB_bObjGrayMean = 0.0; //20170216Whao目标跟踪时目标4邻域均值【DSP-B核移植】
g_GLB_NearEdge = FALSE;
bJudgeBkgMean = FALSE;
//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
//背景监控空间
memset(mrnBkgBlks, 0, 8 * sizeof(MINMAXRECT32S)); //目标跟踪时8邻域框
memset(DSP_GLB_Obj8BkgMeanArray, 0, sizeof(FLOAT32) * GLB_OBJ_BKG_FRM_NUM * GLB_OBJ_BKG_NUM);//目标跟踪时8邻域背景均值数组
memset(DSP_GLB_Obj8BkgStdArray, 0, sizeof(FLOAT32) * GLB_OBJ_BKG_FRM_NUM * GLB_OBJ_BKG_NUM);//目标跟踪时8邻域背景标准差数组
}
BkgMonitor::~BkgMonitor()
{
}
//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
////////////////////////////////////////////////////////////////////////////////
//--函数定义
////////////////////////////////////////////////////////////////////////////////
/**********************************************************
* BKM_BkgMonitor()
* 8
* PIXELTYPE *pFrame
* SINT32 nWidth --
* SINT32 nHeight --
* CENTERRECT crnObjRect --
* SPEED32F AngleSpeed --
* g_GLB_bComplexEnv
* g_GLB_bInterferenceMem
*
*
*
**********************************************************/
/*************************************
* Method: BKM_BkgMonitor()
* Function Description:
* CreateData: 2025/2/18
* Input Param: GD_VIDEO_FRAME_S img --
* Input Param: GLB_INPUT * p_GLB_Input --
* Input Param: GrayType nTrackGrayType --
* Input Param: CENTERRECT crCenterRect --
* Input Param: OBJECTSTATUS * pTrackStatus --
* Output Param:
* Return: void
* Call Relation:
* Other Description:
*************************************/
void BkgMonitor::BKM_BkgMonitor(GD_VIDEO_FRAME_S img, GLB_INPUT* p_GLB_Input, GrayType nTrackGrayType, CENTERRECT crCenterRect, OBJECTSTATUS* pTrackStatus)
{
//20170216监控目标的8邻域区域
MINMAXRECT32S mrnObj; //目标跟踪矩形
OBJECTMONITOR ObjectMONI; //目标场景监控信息
SINT16 nObjOutRadius = 5; //目标扩展半径,防止背景点包含目标点计算得出的均值和标准差有偏差
SINT16 nObjCenterX = 0; //目标中心点X坐标
SINT16 nObjCenterY = 0; //目标中心点Y坐标
SINT16 nObjWidth = 0; //目标中心点X坐标
SINT16 nObjHeight = 0; //目标中心点Y坐标
DOUBLE64 dGrayMean = 0.0f;
SINT16 nCnt = 0;
SINT16 i = 0;
SINT16 j = 0;
SINT16 nBkgWRadius = 0; //目标场景监控半径
SINT16 nBkgHRadius = 0; //目标场景监控半径
CENTERRECT crnObjRect = { 0 };
SINT32 nWidth = img.u32Width;
SINT32 nHeight = img.u32Height;
crnObjRect.cx = (SINT16)pTrackStatus->ptPos.x;
crnObjRect.cy = (SINT16)pTrackStatus->ptPos.y;
crnObjRect.w = MAX((SINT16)pTrackStatus->sfSize.w, 8);
crnObjRect.h = MAX((SINT16)pTrackStatus->sfSize.h, 8);
nBkgWRadius = (SINT16)(MAX(crnObjRect.w * 0.75, (crCenterRect.w - crnObjRect.w) / 2));
nBkgHRadius = (SINT16)(MAX(crnObjRect.h * 0.75, (crCenterRect.h - crnObjRect.h) / 2));
nObjCenterX = crnObjRect.cx;
nObjCenterY = crnObjRect.cy;
nObjWidth = crnObjRect.w;
nObjHeight = crnObjRect.h;
//20171208这样取值对于形状姿态不规律的目标可能取到背景区域
mrnObj.minX = MAX(0, MIN(nObjCenterX - nObjWidth / 2 - nObjOutRadius, nWidth - 1));
mrnObj.maxX = MAX(0, MIN(nObjCenterX + nObjWidth / 2 + nObjOutRadius, nWidth - 1));
mrnObj.minY = MAX(0, MIN(nObjCenterY - nObjHeight / 2 - nObjOutRadius, nHeight - 1));
mrnObj.maxY = MAX(0, MIN(nObjCenterY + nObjHeight / 2 + nObjOutRadius, nHeight - 1));
#if 0
// 计算区域的左上角坐标
int minX = mrnObj.minX;
int minY = mrnObj.minY;
// 计算扣取区域的宽度和高度
int width = nObjWidth;
int height = nObjHeight;
// 计算扣取区域在原始图像中的偏移量
int offset = minY * nWidth + minX;
// 构造 cv::Mat 对象
cv::Mat croppedImage(height, width, CV_8UC1);
for (int i = 0; i < height; ++i)
{
for (int j = 0; j < width; ++j)
{
croppedImage.at<uchar>(i, j) = ((UBYTE8*)img.u64VirAddr[0])[(i + minY)* nWidth + minX + j];
}
}
#endif
// 计算目标区域的均值
for (j = mrnObj.minY; j <= mrnObj.maxY; j++)
{
for (i = mrnObj.minX; i <= mrnObj.maxX; i++)
{
//dGrayMean += pFrame[j * nWidth + i];
if (GD_PIXEL_FORMAT_GRAY_Y8 == img.enPixelFormat)
{
dGrayMean += ((UBYTE8*)img.u64VirAddr[0])[j * nWidth + i];
}
else
{
dGrayMean += ((UINT16*)img.u64VirAddr[0])[j * nWidth + i];
}
nCnt++;
}
}
g_GLB_bObjGrayMean = FLOAT32(dGrayMean / nCnt);
// 对目标8邻域区域进行监控
BKM_CalObjBkgMonitor(img, nWidth, nHeight, mrnObj, nBkgWRadius, nBkgHRadius, &ObjectMONI, nTrackGrayType, pTrackStatus->sfAglSpeed,
(FLOAT32*)DSP_GLB_Obj8BkgMeanArray, (FLOAT32*)DSP_GLB_Obj8BkgStdArray);
//区域场景分析,主要针对过杆
//20170221Whao监控数组大于10以后才进行处理
//20170303Whao仅对低空时判定过杆伺服俯仰角<10°
if ((g_GLB_nObj8BkgFrames > GLB_OBJ_BKG_FRM_NUM - 1) /*&& g_SERVO_stInput.fPitching < GLB_INFRN_PT_THRES*/)
{
BKM_AnalyzeBkg(p_GLB_Input, g_GLB_bObjGrayMean, (FLOAT32*)DSP_GLB_Obj8BkgMeanArray, (FLOAT32*)DSP_GLB_Obj8BkgStdArray, pTrackStatus);
}
else
{
g_GLB_bInterferenceMem = false;
g_GLB_bInfrnDirection = GLB_INFRN_DIR_NONE;
}
}
/**********************************************************
* BKM_CleanUpResult()
*
*
* :
*
*
*
**********************************************************/
void BkgMonitor::BKM_CleanUpResult()
{
//20170220Whao清空场景监控结果
memset(mrnBkgBlks, 0, 8 * sizeof(MINMAXRECT32S));
memset(&DSP_GLB_Obj8BkgMeanArray, 0, GLB_OBJ_BKG_FRM_NUM * GLB_OBJ_BKG_NUM * sizeof(FLOAT32));//目标跟踪时8邻域背景均值数组
memset(&DSP_GLB_Obj8BkgStdArray, 0, GLB_OBJ_BKG_FRM_NUM * GLB_OBJ_BKG_NUM * sizeof(FLOAT32)); //目标跟踪时8邻域背景标准差数组
memset(&g_GLB_bObj8BkgStatus, 0, GLB_OBJ_BKG_NUM * sizeof(BBOOL)); //目标跟踪时8邻域背景监控方差的变化趋势矩阵
g_GLB_nObj8BkgArrayIndex = 0;
g_GLB_nObj8BkgFrames = 0;
g_GLB_bInterferenceMem = false;
g_GLB_nExitInfrnMemCnt = 0;
g_GLB_bInfrnDirection = GLB_INFRN_DIR_NONE;
bJudgeBkgMean = false;
//20170603清空交错干扰标志位和计数器
g_GLB_bCrossInterference = false;
g_GLB_nCrossInterferenceCnt = 0;
//20170301清空多目标计数及标志
g_GLB_nMultiObjCnt = 0;
g_GLB_bMultiObj = false;
//20170306清空多目标合并标志位
g_GLB_bMultiObjMerge = false;
//20170301清空连续退出复杂环境帧计数及进入复杂环境标志
g_GLB_nExitComplexEnv = 0;
g_GLB_bComplexEnv = false;
}
/**********************************************************
* TO_CalObjBkgMonitor()
* 8
* PIXELTYPE *pFrame --
* SINT32 nWidth --
* SINT32 nHeight --
* MINMAXRECT32S mrnObj --
* SINT32 nBkgRadius --
* UBYTE8 nDetectGrayType --
* SPEED32F AngleSpeed --
* OBJECTMONITOR *objSNR --
* FLOAT32 *pdObj8BkgMeanArray-- 8
* FLOAT32 *pdObj8BkgStdArray -- 8
*
*
*
**********************************************************/
void BkgMonitor::BKM_CalObjBkgMonitor(GD_VIDEO_FRAME_S img, SINT32 nWidth, SINT32 nHeight,
MINMAXRECT32S mrnObj, SINT32 nBkgWRadius, SINT32 nBkgHRadius,
OBJECTMONITOR *objSNR, GrayType nDetectGrayType, SPEED32F AngleSpeed,
FLOAT32 *pdObj8BkgMeanArray, FLOAT32 *pdObj8BkgStdArray)
{
SINT32 i, j, k;
SINT32 nBGValue, nBGCnt; //背景点灰度、背景点计数
double dBGMean, dBGStd; //背景均值、方差
MINMAXRECT32S mrnBkg; //背景区域矩形
SINT32 nLineIndex, nIndex;
FLOAT32 fGrayMax, fGrayMin, fGrayMean;
SINT32 nGrayCnt;
SINT32 CenterX, CenterY;
//20170220获取帧间的下标
if (g_GLB_nObj8BkgFrames < GLB_OBJ_BKG_FRM_NUM - 1)
{
g_GLB_nObj8BkgArrayIndex = g_GLB_nObj8BkgFrames;
}
else
{
g_GLB_nObj8BkgArrayIndex = g_GLB_nObj8BkgFrames % GLB_OBJ_BKG_FRM_NUM;
}
//+++++++++++++++++++++++++++++++++++++++++++++++++++++++
//获取目标灰度值极值、均值【重复计算】及其坐标
nLineIndex = mrnObj.minY * nWidth;
CenterX = (mrnObj.minX + mrnObj.maxX) >> 1;
CenterY = (mrnObj.minY + mrnObj.maxY) >> 1;
//objSNR->ObjGray = pFrame[CenterY * nWidth + CenterX];
if (GD_PIXEL_FORMAT_GRAY_Y8 == img.enPixelFormat)
{
objSNR->ObjGray = ((UBYTE8*)img.u64VirAddr[0])[CenterY * nWidth + CenterX];
}
else
{
objSNR->ObjGray = ((UINT16*)img.u64VirAddr[0])[CenterY * nWidth + CenterX];
}
fGrayMax = objSNR->ObjGray;
fGrayMin = objSNR->ObjGray;
fGrayMean = 0.0f;
nGrayCnt = 0;
for (i = mrnObj.minY; i <= mrnObj.maxY; i++)
{
for (j = mrnObj.minX; j <= mrnObj.maxX; j++)
{
nIndex = nLineIndex + j;
//目标灰度均值
//fGrayMean += (FLOAT32)(pFrame[nIndex]);
if (GD_PIXEL_FORMAT_GRAY_Y8 == img.enPixelFormat)
{
fGrayMean += ((UBYTE8*)img.u64VirAddr[0])[nIndex];
}
else
{
fGrayMean += ((UINT16*)img.u64VirAddr[0])[nIndex];
}
nGrayCnt++;
}
nLineIndex += nWidth;
}
if (nGrayCnt > 0)
{
fGrayMean /= nGrayCnt;
}
//根据检测类型,获取目标灰度极值
//亮目标
if (GrayType::BrightTarget == nDetectGrayType)
{
objSNR->ObjGray = fGrayMax;
objSNR->ObjGrayMean = fGrayMean;
}
//暗目标
else if (GrayType::DarkTarget == nDetectGrayType)
{
objSNR->ObjGray = fGrayMin;
objSNR->ObjGrayMean = fGrayMean;
}
//亮暗全检测
else
{
objSNR->ObjGray = fGrayMean;
objSNR->ObjGrayMean = fGrayMean;
}
//+++++++++++++++++++++++++++++++++++++++++++++++++++++++
//统计背景均值、方差划分为0-上、1-右上、2-右、3-右下、4-下、5-左下、6-左、7-左上8个背景区域
//计算背景窗口边界
mrnBkg.minX = MAX(0, MIN(mrnObj.minX - nBkgWRadius, nWidth - 1));
mrnBkg.maxX = MAX(0, MIN(mrnObj.maxX + nBkgWRadius, nWidth - 1));
mrnBkg.minY = MAX(0, MIN(mrnObj.minY - nBkgHRadius, nHeight - 1));
mrnBkg.maxY = MAX(0, MIN(mrnObj.maxY + nBkgHRadius, nHeight - 1));
//20170303【防错】如果目标运动到图像边界则方差数组和均值数组清零
if ((0 == mrnObj.minX) || (0 == mrnObj.minY) || ((nWidth - 1) == mrnObj.maxX) || ((nWidth - 1) == mrnObj.maxY))
{
for (i = 0; i < GLB_OBJ_BKG_NUM; i++)
{
nIndex = g_GLB_nObj8BkgArrayIndex * GLB_OBJ_BKG_NUM + i;
pdObj8BkgMeanArray[nIndex] = 0.0;
pdObj8BkgStdArray[nIndex] = 0.0;
}
}
else
{
//MSSu, 20170607: 以下代码可简化到一个for循环内执行先保存每个每个背景区域的边界矩形数组即可。
//背景区域0-上
mrnBkgBlks[0] = mrnObj;
mrnBkgBlks[0].minY = mrnBkg.minY;
mrnBkgBlks[0].maxY = mrnObj.minY - 1;
//背景区域1-右上
mrnBkgBlks[1] = mrnBkgBlks[0];
mrnBkgBlks[1].minX = mrnObj.maxX + 1;
mrnBkgBlks[1].maxX = mrnBkg.maxX;
//背景区域2-右
mrnBkgBlks[2] = mrnObj;
mrnBkgBlks[2].minX = mrnBkgBlks[1].minX;
mrnBkgBlks[2].maxX = mrnBkgBlks[1].maxX;
//背景区域3-右下
mrnBkgBlks[3] = mrnBkgBlks[2];
mrnBkgBlks[3].minY = mrnObj.maxY + 1;
mrnBkgBlks[3].maxY = mrnBkg.maxY;
//背景区域4-下
mrnBkgBlks[4] = mrnObj;
mrnBkgBlks[4].minY = mrnBkgBlks[3].minY;
mrnBkgBlks[4].maxY = mrnBkgBlks[3].maxY;
//背景区域5-左下
mrnBkgBlks[5] = mrnBkgBlks[4];
mrnBkgBlks[5].minX = mrnBkg.minX;
mrnBkgBlks[5].maxX = mrnObj.minX - 1;
#if 0
// 计算区域的左上角坐标
int minX = mrnBkgBlks[5].minX;
int minY = mrnBkgBlks[5].minY;
// 计算扣取区域的宽度和高度
int width = mrnBkgBlks[5].maxX - mrnBkgBlks[5].minX;
int height = mrnBkgBlks[5].maxY - mrnBkgBlks[5].minY;
// 计算扣取区域在原始图像中的偏移量
int offset = minY * nWidth + minX;
// 构造 cv::Mat 对象
cv::Mat region5(height, width, CV_8UC1);
for (int i = 0; i < height; ++i)
{
for (int j = 0; j < width; ++j)
{
region5.at<uchar>(i, j) = ((UBYTE8*)img.u64VirAddr[0])[(i + minY) * nWidth + minX + j];
}
}
#endif
//背景区域6-左
mrnBkgBlks[6] = mrnObj;
mrnBkgBlks[6].minX = mrnBkgBlks[5].minX;
mrnBkgBlks[6].maxX = mrnBkgBlks[5].maxX;
//背景区域7-左上
mrnBkgBlks[7] = mrnBkgBlks[6];
mrnBkgBlks[7].minY = mrnBkgBlks[0].minY;
mrnBkgBlks[7].maxY = mrnBkgBlks[0].maxY;
//遍历每个背景分块,抛掉最大值、最小值
for (k = 0; k < GLB_OBJ_BKG_NUM; k++)
{
//统计背景均值、方差
double dBlkMin = 1e6;
double dBlkMax = 1e-6;
nBGCnt = 0;
dBGMean = 0;
dBGStd = 0;
nLineIndex = mrnBkgBlks[k].minY * nWidth;
for (i = mrnBkgBlks[k].minY; i <= mrnBkgBlks[k].maxY; i++)
{
for (j = mrnBkgBlks[k].minX; j <= mrnBkgBlks[k].maxX; j++)
{
nIndex = nLineIndex + j;
//nBGValue = pFrame[nIndex];
if (GD_PIXEL_FORMAT_GRAY_Y8 == img.enPixelFormat)
{
nBGValue = ((UBYTE8*)img.u64VirAddr[0])[nIndex];
}
else
{
nBGValue = ((UINT16*)img.u64VirAddr[0])[nIndex];
}
//背景灰度及灰度平方累加
dBGMean += (double)nBGValue;
dBGStd += (double)nBGValue * nBGValue;
nBGCnt++;
dBlkMin = MIN(dBlkMin, nBGValue);
dBlkMax = MAX(dBlkMax, nBGValue);
}
nLineIndex += nWidth;
}
//计算上背景均值、方差
nIndex = g_GLB_nObj8BkgArrayIndex * GLB_OBJ_BKG_NUM + k;
dBGMean -= (dBlkMin + dBlkMax);
dBGStd -= (dBlkMin * dBlkMin + dBlkMax * dBlkMax);
nBGCnt -= 2;
pdObj8BkgMeanArray[nIndex] = FLOAT32( dBGMean / (double)nBGCnt);
pdObj8BkgStdArray[nIndex] = FLOAT32(dBGStd / (double)nBGCnt);
pdObj8BkgStdArray[nIndex] -= pdObj8BkgMeanArray[nIndex] * pdObj8BkgMeanArray[nIndex];
}
}
//20170227更新邻域背景是否异常状态如分割不准确导致的方差异常
BKM_UpdateObjBkgStatus(pdObj8BkgStdArray);
//BKM_UpdateObjBkgMean(pdObj8BkgMeanArray);
//20170220帧数累加
g_GLB_nObj8BkgFrames++;
}
/**********************************************************
* BKM_AnalyzeBkg()
*
* SPEED32F AngleSpeed --
* DOUBLE64 bObjGrayMean --
* DOUBLE64 *pdObj8BkgMeanArray-- 8
* DOUBLE64 *pdObj8BkgStdArray -- 8
*
*
*
*
**********************************************************/
void BkgMonitor::BKM_AnalyzeBkg(GLB_INPUT* p_GLB_Input, FLOAT32 bObjGrayMean,
FLOAT32 *pdObj8BkgMeanArray, FLOAT32 *pdObj8BkgStdArray, OBJECTSTATUS* pTrackStatus)
{
SINT32 i;
SINT16 nValidCnt = 0; //判别有效性计数
BBOOL bJudgeBkgStd = false; //判别背景区域方差可转自动跟踪标志位
SINT32 nStdThreshold = 5000; //2500; //方差预警阈值
SINT32 nIndexCurrFrm = g_GLB_nObj8BkgArrayIndex * GLB_OBJ_BKG_NUM; //10
FLOAT32 fSpeedThresh = 0.0025f; //目标过杆判断速度阈值 20161216141048目标过杆速度为0.029
SPEED32F AngleSpeed = pTrackStatus->sfAglSpeed;
//20170301如果已经判断在过云则不进行过杆判断防止已经在过云过程中进此条件进记忆跟踪
//20170302【屏蔽】过杆优先级更高
if (g_GLB_bComplexEnv)
{
return;
}
// 调整可见光的方差阈值
if (GLB_VIDEO_TYPE::GLB_VIDEO_VL == p_GLB_Input->unVideoSrc)
{
nStdThreshold = 500;
}
// 单帧分左右会受到预测不准确,目标特征的影响
FLOAT32 leftMean = (pdObj8BkgMeanArray[nIndexCurrFrm + 5] + pdObj8BkgMeanArray[nIndexCurrFrm + 6] + pdObj8BkgMeanArray[nIndexCurrFrm + 7]) / 3;
FLOAT32 rightMean = (pdObj8BkgMeanArray[nIndexCurrFrm + 1] + pdObj8BkgMeanArray[nIndexCurrFrm + 2] + pdObj8BkgMeanArray[nIndexCurrFrm + 3]) / 3;
//过杆判断
if (!g_GLB_bInterferenceMem)
{
//20170302水平过杆
if (fabs(AngleSpeed.vx) > fabs(AngleSpeed.vy))
{
//水平过杆方向判断
//20171207过杆判断采用速度阈值防止静止的目标判断为过杆
if(AngleSpeed.vx < -fSpeedThresh)
{
//目标向左运动,判断左侧三个邻域的均值和方差,若左+左上或左+左下的梯度值大于预警阈值
g_GLB_bInfrnDirection = GLB_INFRN_DIR_LEFT;
//判断前方有杆,提前进记忆跟踪
if ((pdObj8BkgStdArray[nIndexCurrFrm + 7] > nStdThreshold
&& pdObj8BkgStdArray[nIndexCurrFrm + 6] > nStdThreshold)
|| (pdObj8BkgStdArray[nIndexCurrFrm + 6] > nStdThreshold
&& pdObj8BkgStdArray[nIndexCurrFrm + 5] > nStdThreshold))
{
//置干扰进记忆跟踪标志为真
g_GLB_bInterferenceMem = true;
}
//单凭借方差在轮廓不清晰的背景,无法准确判断,需要结合背景灰度(默认可见光为暗目标)
if (GLB_VIDEO_TYPE::GLB_VIDEO_VL == p_GLB_Input->unVideoSrc)
{
if (rightMean - leftMean > 20)
{
g_GLB_bInterferenceMem = true;
}
}
else
{
}
}
//else
//20171207过杆判断采用速度阈值防止静止的目标判断为过杆
if (AngleSpeed.vx > fSpeedThresh)
{
//目标向右运动,判断右侧三个邻域的均值和方差,若左+左上或左+左下的梯度值大于预警阈值
g_GLB_bInfrnDirection = GLB_INFRN_DIR_RIGHT;
//判断前方有杆,提前进记忆跟踪
if ((pdObj8BkgStdArray[nIndexCurrFrm + 1] > nStdThreshold
&& pdObj8BkgStdArray[nIndexCurrFrm + 2] > nStdThreshold)
|| (pdObj8BkgStdArray[nIndexCurrFrm + 2] > nStdThreshold
&& pdObj8BkgStdArray[nIndexCurrFrm + 3] > nStdThreshold))
{
//置干扰进记忆跟踪标志为真
g_GLB_bInterferenceMem = true;
}
//单凭借方差在轮廓不清晰的背景,无法准确判断,需要结合背景灰度(默认可见光为暗目标)
if (GLB_VIDEO_TYPE::GLB_VIDEO_VL == p_GLB_Input->unVideoSrc)
{
if (leftMean - rightMean > 20)
{
g_GLB_bInterferenceMem = true;
}
}
else
{
}
}
}
// //不考虑垂直方向过杆,避免云层干扰
// else
// {
// //垂直方向判断
// if (AngleSpeed.vy < 0)
// {
// //目标向下运动,判断下侧三个邻域的均值和方差,若下+左下或下+右下的梯度值大于预警阈值
// //判断下方有杆,提前进记忆跟踪
// if ((pdObj8BkgStdArray[nIndexCurrFrm + 3] > nStdThreshold
// && pdObj8BkgStdArray[nIndexCurrFrm + 4] > nStdThreshold)
// || (pdObj8BkgStdArray[nIndexCurrFrm + 4] > nStdThreshold
// && pdObj8BkgStdArray[nIndexCurrFrm + 5] > nStdThreshold))
// {
// //置干扰进记忆跟踪标志为真
// g_GLB_bInterferenceMem = true;
// g_GLB_bInfrnDirection = GLB_INFRN_DIR_DOWN;
// }
// }
// else
// {
// //目标向上运动,判断下侧三个邻域的均值和方差,若上+左上或上+右上的梯度值大于预警阈值
// //判断上方有杆,提前进记忆跟踪
// if ((pdObj8BkgStdArray[nIndexCurrFrm + 7] > nStdThreshold
// && pdObj8BkgStdArray[nIndexCurrFrm + 0] > nStdThreshold)
// || (pdObj8BkgStdArray[nIndexCurrFrm + 0] > nStdThreshold
// && pdObj8BkgStdArray[nIndexCurrFrm + 1] > nStdThreshold))
// {
// //置干扰进记忆跟踪标志为真
// g_GLB_bInterferenceMem = true;
// g_GLB_bInfrnDirection = GLB_INFRN_DIR_UP;
// }
// }
// }
}
//解除干扰,置干扰进记忆跟踪标志为假
if (g_GLB_bInterferenceMem)
{
////背景区域均值均小于目标均值,【这里考虑的是亮目标过杆】
//for (i = 0; i < GLB_OBJ_BKG_NUM; i++)
//{
// if (bObjGrayMean > pdObj8BkgMeanArray[nIndexCurrFrm + i])
// {
// nValidCnt++;
// }
//}
if (GLB_INFRN_DIR_RIGHT == g_GLB_bInfrnDirection)
{
//水平运动时,目标的上三背景区域方差或者下三背景区域方差均小于阈值,即场景趋于平坦
if ((pdObj8BkgStdArray[nIndexCurrFrm + 0] < nStdThreshold
&& pdObj8BkgStdArray[nIndexCurrFrm + 1] < nStdThreshold)
|| (pdObj8BkgStdArray[nIndexCurrFrm + 4] < nStdThreshold
&& pdObj8BkgStdArray[nIndexCurrFrm + 3] < nStdThreshold))
{
bJudgeBkgStd = true;
}
if (GLB_VIDEO_TYPE::GLB_VIDEO_VL == p_GLB_Input->unVideoSrc)
{
// 暗目标向右出遮挡区域
if (pdObj8BkgMeanArray[nIndexCurrFrm + 7] + 20 < pdObj8BkgMeanArray[nIndexCurrFrm + 1] ||
pdObj8BkgMeanArray[nIndexCurrFrm + 5] + 20 < pdObj8BkgMeanArray[nIndexCurrFrm + 3])
{
bJudgeBkgMean = true;
}
}
else
{
if (pdObj8BkgMeanArray[nIndexCurrFrm + 7] > pdObj8BkgMeanArray[nIndexCurrFrm + 1] + 100 ||
pdObj8BkgMeanArray[nIndexCurrFrm + 5] > pdObj8BkgMeanArray[nIndexCurrFrm + 3] + 100)
{
bJudgeBkgMean = true;
}
}
}
else if (GLB_INFRN_DIR_LEFT == g_GLB_bInfrnDirection)
{
//水平运动时,目标的上三背景区域方差或者下三背景区域方差均小于阈值,即场景趋于平坦
if ((pdObj8BkgStdArray[nIndexCurrFrm + 0] < nStdThreshold
&& pdObj8BkgStdArray[nIndexCurrFrm + 7] < nStdThreshold)
|| (pdObj8BkgStdArray[nIndexCurrFrm + 5] < nStdThreshold
&& pdObj8BkgStdArray[nIndexCurrFrm + 4] < nStdThreshold))
{
bJudgeBkgStd = true;
}
if (GLB_VIDEO_TYPE::GLB_VIDEO_VL == p_GLB_Input->unVideoSrc)
{
if (pdObj8BkgMeanArray[nIndexCurrFrm + 7] > pdObj8BkgMeanArray[nIndexCurrFrm + 1] + 20 ||
pdObj8BkgMeanArray[nIndexCurrFrm + 5] > pdObj8BkgMeanArray[nIndexCurrFrm + 3] + 20)
{
bJudgeBkgMean = true;
}
}
else
{
if (pdObj8BkgMeanArray[nIndexCurrFrm + 7] + 100 < pdObj8BkgMeanArray[nIndexCurrFrm + 1] ||
pdObj8BkgMeanArray[nIndexCurrFrm + 5] + 100 < pdObj8BkgMeanArray[nIndexCurrFrm + 3])
{
bJudgeBkgMean = true;
}
}
}
//20170414暂不判断垂直运动
// else if (GLB_INFRN_DIR_DOWN == g_GLB_bInfrnDirection || GLB_INFRN_DIR_UP == g_GLB_bInfrnDirection)
// {
// //垂直运动时,目标的左三背景区域方差或者右三背景区域方差均小于阈值,即场景趋于平坦
// if ((pdObj8BkgStdArray[nIndexCurrFrm + 5] < nStdThreshold
// && pdObj8BkgStdArray[nIndexCurrFrm + 6] < nStdThreshold
// && pdObj8BkgStdArray[nIndexCurrFrm + 7] < nStdThreshold)
// || (pdObj8BkgStdArray[nIndexCurrFrm + 3] < nStdThreshold
// && pdObj8BkgStdArray[nIndexCurrFrm + 2] < nStdThreshold
// && pdObj8BkgStdArray[nIndexCurrFrm + 1] < nStdThreshold))
// {
// //除了考虑目标左右背景之外,上下背景方差用来区别进入干扰和退出干扰
// if (pdObj8BkgStdArray[nIndexCurrFrm + 0] < nStdThreshold
// && pdObj8BkgStdArray[nIndexCurrFrm + 4] < nStdThreshold)
// {
// bJudgeBkgStd = true;
// }
// }
// }
else
{
//暂不处理
}
//20170914,wsa对20161201_170642_2进行测试发现6400帧过杆时由于面目标偏离预测位置一点点导致计算
//出来的背景(包含真实目标区域)方差并不是很准,不满足方差条件导致无法退出干扰,改进时加入相似度判别
//若均值和方差条件均满足可转自动跟踪情况,置标志位为假
if (bJudgeBkgMean && bJudgeBkgStd || pTrackStatus->unContiLostCnt > p_GLB_Input->unFreq * 3)
{
g_GLB_nExitInfrnMemCnt++;
if (g_GLB_nExitInfrnMemCnt > GLB_EXIT_INFRN_MEM_CNT)
{
g_GLB_bInterferenceMem = false;
bJudgeBkgMean = false;
g_GLB_nExitInfrnMemCnt = 0;
g_GLB_bInfrnDirection = GLB_INFRN_DIR_NONE;
}
}
else
{
g_GLB_nExitInfrnMemCnt = 0;
//g_GLB_bInfrnDirection = GLB_INFRN_DIR_NONE;
}
}
}
/**********************************************************
* BKM_UpdateObjBkgStatus()
*
* FLOAT32 *pdObj8BkgStdArray -- 8
*
*
*
*
**********************************************************/
void BkgMonitor::BKM_UpdateObjBkgStatus(FLOAT32 *pdObj8BkgStdArray)
{
FLOAT32 ardMeanOf8BkgStd[GLB_OBJ_BKG_FRM_NUM] = {0.0}; //方差的均值10帧
SINT32 i, j;
SINT32 nAbnormalCnt = 0; //异常帧计数器
FLOAT32 dBGMean = 0.0; //均值
FLOAT32 dBGValue = 0.0; //当前值
FLOAT32 dAbnormalStdThres = 2000; //超过阈值2000直接视为异常
//20170301如果已经判断在过杆则不进行过杆云判断过杆优先级更高
if (g_GLB_bInterferenceMem)
{
return;
}
//若不满10帧不进行变化趋势计算
if (g_GLB_nObj8BkgFrames < GLB_OBJ_BKG_FRM_NUM - 1)
{
return;
}
//计算最近10帧背景方差的均值
//MSSu, 20170307: 此处重复计算。可在每帧保存背景块方差时,直接计算好
for (j = 0; j < GLB_OBJ_BKG_FRM_NUM; j++)
{
dBGMean = 0.0;
//遍历每帧记录
for (i = 0; i < GLB_OBJ_BKG_NUM; i++)
{
//当前值,求和
dBGValue = pdObj8BkgStdArray[j * GLB_OBJ_BKG_NUM + i];
dBGMean += (FLOAT32)dBGValue;
}
ardMeanOf8BkgStd[j] = dBGMean / GLB_OBJ_BKG_NUM;
}
//分别比较8块邻域和背景方差的差异找出异常背景块
for (i = 0; i < GLB_OBJ_BKG_NUM; i++)
{
nAbnormalCnt = 0;
for (j = 0; j < GLB_OBJ_BKG_FRM_NUM; j++)
{
if (pdObj8BkgStdArray[j * GLB_OBJ_BKG_NUM + i] > 1.5 * ardMeanOf8BkgStd[j])
{
nAbnormalCnt++;
}
}
//10帧的异常帧数超过5帧且大于阈值则认为该背景块异常
if (nAbnormalCnt > 0.5 * GLB_OBJ_BKG_FRM_NUM
|| pdObj8BkgStdArray[g_GLB_nObj8BkgArrayIndex * GLB_OBJ_BKG_NUM + i] > dAbnormalStdThres)
{
g_GLB_bObj8BkgStatus[i] = GLB_OBJ_BKG_STD_ABNORMAL;
}
else
{
g_GLB_bObj8BkgStatus[i] = GLB_OBJ_BKG_STD_NORMAL;
}
}
//// 判断接近强边缘,此时异常块大概率呈现一边倒趋势至少出现连续3个true
//for (SINT32 i = 0; i < GLB_OBJ_BKG_NUM; i++)
//{
// SINT32 BLK1 = i;
// SINT32 BLK2 = (i + 1) % GLB_OBJ_BKG_NUM;
// SINT32 BLK3 = (i + 2) % GLB_OBJ_BKG_NUM;
// if (g_GLB_bObj8BkgStatus[BLK1] + g_GLB_bObj8BkgStatus[BLK2] + g_GLB_bObj8BkgStatus[BLK3] == 3)
// {
// int a = 0;
// }
//}
//20170228若背景环境复杂如鱼鳞状云8邻域区域有一半方差异常不进行合并
SINT16 nAbnormalBlkCnt = 0; //异常背景块计数
//统计异常背景块个数
for (i = 0; i < GLB_OBJ_BKG_NUM; i++)
{
if (g_GLB_bObj8BkgStatus[i])
{
nAbnormalBlkCnt++;
}
}
//更新复杂场景标志位及退出复杂场景帧计数
if (nAbnormalBlkCnt > GLB_OBJ_BKG_NUM / 2 - 1)
{
//退出复杂场景帧数清零
g_GLB_nExitComplexEnv = 0;
//进入复杂场景第一帧,复杂场景标志位置为真
if (!g_GLB_bComplexEnv)
{
g_GLB_bComplexEnv = true;
}
////人工调整一次分割阈值,保证目标与背景的区分度
//if (g_DAT_stPara.nGrayThresMinBright < DAT_GRAY_THRES_MAX)
//{
// g_DAT_stPara.nGrayThresMinBright = (g_DAT_stPara.nGrayThresMinBright + DAT_GRAY_THRES_MAX) / 2;
//}
//if (g_DAT_stPara.nGrayThresMinDark < DAT_GRAY_THRES_MAX)
//{
// g_DAT_stPara.nGrayThresMinDark = (g_DAT_stPara.nGrayThresMinDark + DAT_GRAY_THRES_MAX) / 2;
//}
//if (g_DAT_stPara.nGradThresMin < DAT_GRAD_THRES_MAX)
//{
// g_DAT_stPara.nGradThresMin = (g_DAT_stPara.nGradThresMin + DAT_GRAD_THRES_MAX) / 2;
//}
}
else
{
//累计退出复杂场景帧计数
g_GLB_nExitComplexEnv++;
//若帧计数超过阈值,则异常环境标志位置为假
if (g_GLB_nExitComplexEnv > GLB_EXIT_CMPLX_ENV_CNT && g_GLB_bComplexEnv)
{
g_GLB_bComplexEnv = false;
////人工调整一次分割阈值,保证目标分割的完整性
//if (g_DAT_stPara.nGrayThresMinBright > DAT_GRAY_THRES_MIN)
//{
// g_DAT_stPara.nGrayThresMinBright = DAT_GRAY_THRES_MIN;
//}
//if (g_DAT_stPara.nGrayThresMinDark > DAT_GRAY_THRES_MIN)
//{
// g_DAT_stPara.nGrayThresMinDark = DAT_GRAY_THRES_MIN;
//}
//if (g_DAT_stPara.nGradThresMin > DAT_GRAD_THRES_MIN)
//{
// g_DAT_stPara.nGradThresMin = DAT_GRAD_THRES_MIN;
//}
}
}
}
void BkgMonitor::BKM_UpdateObjBkgMean(FLOAT32* pdObj8BkgMeanArray)
{
FLOAT32 ardMeanOf8BkgGray[GLB_OBJ_BKG_NUM] = { 0.0 }; //灰度的均值8个方向
SINT32 i, j;
SINT32 nAbnormalCnt = 0; //异常帧计数器
FLOAT32 dBGMean = 0.0; //均值
FLOAT32 dBGValue = 0.0; //当前值
FLOAT32 dAbnormalStdThres = 2000; //超过阈值2000直接视为异常
////20170301如果已经判断在过杆则不进行过杆云判断过杆优先级更高
//if (g_GLB_bInterferenceMem)
//{
// return;
//}
//若不满10帧不进行变化趋势计算
if (g_GLB_nObj8BkgFrames < GLB_OBJ_BKG_FRM_NUM - 1)
{
return;
}
//每个块计算连续10帧灰度的均值
for (i = 0; i < GLB_OBJ_BKG_NUM; i++)
{
dBGMean = 0.0;
for (j = 0; j < GLB_OBJ_BKG_FRM_NUM; j++)
{
dBGValue = pdObj8BkgMeanArray[i + j * GLB_OBJ_BKG_FRM_NUM];
dBGMean += (FLOAT32)dBGValue;
}
ardMeanOf8BkgGray[i] = dBGMean / GLB_OBJ_BKG_FRM_NUM;
}
////分别比较8块邻域和背景方差的差异找出异常背景块
//for (i = 0; i < GLB_OBJ_BKG_NUM; i++)
//{
// nAbnormalCnt = 0;
// for (j = 0; j < GLB_OBJ_BKG_FRM_NUM; j++)
// {
// if (pdObj8BkgStdArray[j * GLB_OBJ_BKG_NUM + i] > 1.5 * ardMeanOf8BkgStd[j])
// {
// nAbnormalCnt++;
// }
// }
// //10帧的异常帧数超过5帧且大于阈值则认为该背景块异常
// if (nAbnormalCnt > 0.5 * GLB_OBJ_BKG_FRM_NUM
// || pdObj8BkgStdArray[g_GLB_nObj8BkgArrayIndex * GLB_OBJ_BKG_NUM + i] > dAbnormalStdThres)
// {
// g_GLB_bObj8BkgStatus[i] = GLB_OBJ_BKG_STD_ABNORMAL;
// }
// else
// {
// g_GLB_bObj8BkgStatus[i] = GLB_OBJ_BKG_STD_NORMAL;
// }
//}
////20170228若背景环境复杂如鱼鳞状云8邻域区域有一半方差异常不进行合并
//SINT16 nAbnormalBlkCnt = 0; //异常背景块计数
////统计异常背景块个数
//for (i = 0; i < GLB_OBJ_BKG_NUM; i++)
//{
// if (g_GLB_bObj8BkgStatus[i])
// {
// nAbnormalBlkCnt++;
// }
//}
////更新复杂场景标志位及退出复杂场景帧计数
//if (nAbnormalBlkCnt > GLB_OBJ_BKG_NUM / 2 - 1)
//{
// //退出复杂场景帧数清零
// g_GLB_nExitComplexEnv = 0;
// //进入复杂场景第一帧,复杂场景标志位置为真
// if (!g_GLB_bComplexEnv)
// {
// g_GLB_bComplexEnv = true;
// }
//}
//else
//{
// //累计退出复杂场景帧计数
// g_GLB_nExitComplexEnv++;
// //若帧计数超过阈值,则异常环境标志位置为假
// if (g_GLB_nExitComplexEnv > GLB_EXIT_CMPLX_ENV_CNT && g_GLB_bComplexEnv)
// {
// g_GLB_bComplexEnv = false;
// }
//}
}
/**********************************************************
* BKM_MergeMultiTarget()
*
* TARGET_OBJECT *ptTargetArray--
* SINT32 nObjsCnt --
* TARGET_OBJECT *ptTargetArray--
* nTargetNum --
*
*
**********************************************************/
//SINT16 BKM_MergeMultiTarget(TARGET_OBJECT *ptTargetArray, SINT32 nObjsCnt)
//{
// SINT32 i = 0;
// SINT32 j = 0;
// SINT32 k = 0;
// TARGET_OBJECT *ptOtherTarget = NULL;
// TARGET_OBJECT *ptCurrentTarget = NULL;
// //SINT32 nXDistance = 0;
// //SINT32 nYDistance = 0;
// SINT16 nDist = 0; //两个目标框间的最小距离
// SINT16 nMinDistThres = 2 * g_DAT_stPara.nDSmpScale; //合并的最小距离阈值【DSP移植注意B核g_DAT_stPara.nDSmpScale的赋值】
// SINT32 nDeltetID = 0; //待删除目标下标
//
// //初始化多目标合并标志
// g_GLB_bMultiObjMerge = false;
//
// //仅一个目标或者无最优管道目标直接返回
// if (nObjsCnt < 2)
// {
// return nObjsCnt;
// }
//
// for (i = 0; i < nObjsCnt - 1; i++)
// {
// //候选目标
// ptCurrentTarget = &ptTargetArray[i];
//
// for (j = i + 1; j < nObjsCnt; j++)
// {
// //待合并目标
// ptOtherTarget = &ptTargetArray[j];
//
// //计算两个目标框间的最小距离
// nDist = IMGO_CalcDistOfTwoRect(ptCurrentTarget->mrnRect, ptOtherTarget->mrnRect);
//
// //距离大于阈值不合并
// if (nDist > nMinDistThres)
// {
// continue;
// }
// else
// {
// //更新多目标合并标志位
// g_GLB_bMultiObjMerge = true;
//
// //更新合并后的目标信息,包括目标矩形,中心点坐标,尺寸和像素点个数,【灰度值和目标类型暂未更新】
// ptCurrentTarget->mrnRect.minX = MIN(ptCurrentTarget->mrnRect.minX, ptOtherTarget->mrnRect.minX);
// ptCurrentTarget->mrnRect.minY = MIN(ptCurrentTarget->mrnRect.minY, ptOtherTarget->mrnRect.minY);
// ptCurrentTarget->mrnRect.maxX = MAX(ptCurrentTarget->mrnRect.maxX, ptOtherTarget->mrnRect.maxX);
// ptCurrentTarget->mrnRect.maxY = MAX(ptCurrentTarget->mrnRect.maxY, ptOtherTarget->mrnRect.maxY);
// ptCurrentTarget->pfCenPos.x = (FLOAT32)(ptCurrentTarget->mrnRect.minX + ptCurrentTarget->mrnRect.maxX) / 2.0f;
// ptCurrentTarget->pfCenPos.y = (FLOAT32)(ptCurrentTarget->mrnRect.minY + ptCurrentTarget->mrnRect.maxY) / 2.0f;
// ptCurrentTarget->snSize.w = ptCurrentTarget->mrnRect.maxX - ptCurrentTarget->mrnRect.minX + 1;
// ptCurrentTarget->snSize.h = ptCurrentTarget->mrnRect.maxY - ptCurrentTarget->mrnRect.minY + 1;
// ptCurrentTarget->snSize.s = ptCurrentTarget->snSize.w * ptCurrentTarget->snSize.h;
// ptCurrentTarget->unObjPxlsCnt = ptCurrentTarget->unObjPxlsCnt + ptOtherTarget->unObjPxlsCnt;
//
// //删除被合并的目标
// for (k = j + 1; k < nObjsCnt; k++)
// {
// ptTargetArray[k-1] = ptTargetArray[k];
// }
// memset(&ptTargetArray[nObjsCnt-1], 0, sizeof(TARGET_OBJECT));
// nObjsCnt--;
// i--;
// break;
// }
// }
// }
//
// return nObjsCnt;
//}
//
/**********************************************************
* BKM_MultiObjMonitor()
*
* BYTE8 bTargetIndex --
* TARGET_OBJECT *ptTargetArray--
* SINT32 nObjsCnt --
*
* BBOOL bMultiObj --
*
*
**********************************************************/
//BBOOL BKM_MultiObjMonitor(BYTE8 bTargetIndex, TARGET_OBJECT *ptTargetArray, SINT32 nObjsCnt)
//{
// BBOOL bMultiObj = false;
// SINT32 i = 0;
// SINT32 nNonNeighborObjCnt = 0; //不相邻目标计数器
// TARGET_OBJECT *ptOtherTarget = NULL;
// TARGET_OBJECT *ptPipeTarget = NULL;
// SINT16 nDist = 0; //两个目标框间的最小距离
// SINT16 nMinDistThres = 3; //合并的最小距离阈值
//
// //仅一个目标或者无最优管道目标直接返回
// if (nObjsCnt < 2 || -1 == bTargetIndex)
// {
// //清零帧数并返回
// g_GLB_nMultiObjCnt = 0;
// return bMultiObj;
// }
//
// //候选管道目标
// ptPipeTarget = &ptTargetArray[bTargetIndex];
//
// for (i = 0; i < nObjsCnt; i++)
// {
// //跳过候选目标
// if (i == bTargetIndex)
// {
// continue;
// }
//
// ptOtherTarget = &ptTargetArray[i];
//
// //计算两个目标框间的最小距离
// nDist = IMGO_CalcDistOfTwoRect(ptPipeTarget->mrnRect, ptOtherTarget->mrnRect);
//
// //距离大于阈值不合并
// if (nDist > nMinDistThres)
// {
// nNonNeighborObjCnt++;
// continue;
// }
// else
// {
// //20170302累加多目标帧数这里仅存在距离小于阈值的目标时认为是多目标
// g_GLB_nMultiObjCnt++;
// if (g_GLB_nMultiObjCnt > GLB_MULTI_OBJ_MAX_CNT)
// {
// bMultiObj = true;
// }
// break;
// }
// }
//
// //如果均为不相邻目标,则视为多目标为假,帧数清零
// if (nNonNeighborObjCnt == nObjsCnt - 1)
// {
// g_GLB_nMultiObjCnt = 0;
// }
//
// return bMultiObj;
//}