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.

2168 lines
82 KiB

This file contains ambiguous Unicode characters!

This file contains ambiguous Unicode characters that may be confused with others in your current locale. If your use case is intentional and legitimate, you can safely ignore this warning. Use the Escape button to highlight these characters.

#include "Arith_TrackSAObj.h"
#include "Arith_CoordModule.h"
#include "Arith_ImgOperate.h"
#include "PIPE/Arith_PIPE_utils.h"
#include "Arith_Detector.h"
#include "Arith_DetectAreaObj.h"
#include "Arith_Bbox.h"
// 定义跟踪器最大检测个数
#define TK_TARGET_MAX_NUM 10
#define GLB_TRACK_SMALL2FACE_CNT 5 //小目标和面目标相互切换数组总长度
#define GLB_TRACK_SMALL2FACE_THRES 3 //小目标和面目标相互切换计数阈值
#define GLB_SMALL2FACE_SIZE_THRES 36 //49//64 //小目标转面目标尺寸上限 qw 20220104
SA_Tracker::SA_Tracker(int nWidth, int nHeight)
{
pDST_Module = API_DetectSmallObj::Create(nWidth, nHeight);
pDAT_Module = API_DetectAreaObj::Create(nWidth, nHeight);
// 最大处理TK_TARGET_MAX_NUM个目标
//m_Target_Array = new TARGET_OBJECT[TK_TARGET_MAX_NUM];
// 将跟踪器的本地队列指向小目标队列,复用内存
m_Target_Array = pDST_Module->GetTargetArray();
m_LockingPipe = nullptr;
m_ObjStatus = { 0 };
m_SizeMode = SizeType::SmallTarget;
m_GrayMode = GrayType::BrightTarget;
m_TSA_Input = { 0 };
m_TSA_Param = { 0 };
m_TSA_output = { 0 };
// 波门影响的检测效果,应该为每个目标设置合适的波门
m_TSA_Param.nPipeRadiusTrack = GLB_PIPE_RADIUS_TRACK; // 小面正常跟踪过程中的波门
m_TSA_Param.nPipeRadiusLost = GLB_PIPE_RADIUS_LOST; // 小面跟踪丢失时的波门
m_TSA_Param.nPipeFOVLostCnt = GLB_MEMORY_FRM_NUM; // 小面目标跟踪默认记忆帧数
m_TSA_Param.nUseAIDetFeq = 25; // 使用AI信息进行修正的频率
g_GLB_MonitorStatus = { 0 };
g_GLB_MonitorStatus.bMonitorVaildFlag = TRUE;
nTrackTargetID = -1;
m_nTargetNum = 0;
m_MatchedTarget = { 0 };
// 跟踪阶段局部区域单帧目标检测结果
m_TSA_output.m_nTargetNum = 0;
m_TSA_output.mTarget_Array = new TARGET_OBJECT[DT_TARGET_MAX_NUM];
//跟踪算法:小目标与面目标相互切换计数
memset(TO_pSmall2Area_Target_counter, 0, GLB_TRACK_SMALL2FACE_CNT * sizeof(UBYTE8));
g_GLB_S2ATagCnt = 0; //小目标和面目标相互切换计数器
}
SA_Tracker::~SA_Tracker()
{
if (pDST_Module)
{
delete pDST_Module;
}
if (pDAT_Module)
{
delete pDAT_Module;
}
pDST_Module = NULL;
pDAT_Module = NULL;
}
// 使用管道初始化小面目标跟踪器,返回成功。
bool SA_Tracker::Init(UINT16* pSrc, SINT32 nWidth, SINT32 nHeight, PIPE* pTrackingPipe, GLB_INPUT* p_GLB_Input)
{
m_LockingPipe = pTrackingPipe;
m_nTargetNum = 0;
// 标记为跟踪管道
m_LockingPipe->bTrackingPipe = true;
SINT32 nEnd = m_LockingPipe->ubEnd;
SINT32 nObjSize = (SINT32)(m_LockingPipe->ObjectFilter.fPxlsCnt);
TARGET_OBJECT* pTrackingTarget = &m_LockingPipe->objHistoryList[nEnd];
// 计算目标尺度类型,决定初始跟踪参数,初始化不允许弱小目标,虚警无法控制
if (nObjSize <= GLB_SMALL2FACE_SIZE_THRES)
{
m_SizeMode = SizeType::SmallTarget;
}
else
{
m_SizeMode = SizeType::AreaTarget;
}
// 计算目标灰度类型
if (pTrackingTarget->nObjTypeGray == GLB_OBJ_GRAY_BRIGHT)
{
m_GrayMode = GrayType::BrightTarget;
}
else if (pTrackingTarget->nObjTypeGray == GLB_OBJ_GRAY_DARK)
{
m_GrayMode = GrayType::DarkTarget;
}
//初始化跟踪输出的目标状态
OBJECTSTATUS* pObjStatus = &m_ObjStatus;
pObjStatus->bObjAssigned = true;
pObjStatus->unTotalCnt = 1;
pObjStatus->unTrackedCnt = 1;
pObjStatus->unContiTrackedCnt = 1;
pObjStatus->unContiLostCnt = 0;
pObjStatus->bObjMiss = false;
//
pObjStatus->ptPosPre.x = m_LockingPipe->ptCurrentPnt.x;
pObjStatus->ptPosPre.y = m_LockingPipe->ptCurrentPnt.y;
pObjStatus->ptPos.x = pObjStatus->ptPosPre.x;
pObjStatus->ptPos.y = pObjStatus->ptPosPre.y;
pObjStatus->ptPosFilter.x = pObjStatus->ptPosPre.x;
pObjStatus->ptPosFilter.y = pObjStatus->ptPosPre.y;
pObjStatus->ptPosBorn = pObjStatus->ptPos;
pObjStatus->sfSize.w = pTrackingTarget->snSize.w;
pObjStatus->sfSize.h = pTrackingTarget->snSize.h;
pObjStatus->sfSize.s = pObjStatus->sfSize.w * pObjStatus->sfSize.h;
pObjStatus->sfSizeBorn = pObjStatus->sfSize;
pObjStatus->fObjPxlsCnt = (FLOAT32)pTrackingTarget->unObjPxlsCnt;
//更新目标速度、角速度、置信度
pObjStatus->sfSpeed.vx = 0.0f;
pObjStatus->sfSpeed.vy = 0.0f;
pObjStatus->sfAglSpeed.vx = 0.0f;
pObjStatus->sfAglSpeed.vy = 0.0f;
pObjStatus->fConfidence = 1.0f;
//更新目标角度
Pole pole = getStablePoleFromImagePos(pTrackingTarget->pfCenPos,
p_GLB_Input->stCamera, p_GLB_Input->servoInfo, p_GLB_Input->afPlatformRPY, p_GLB_Input->setupErr);
pObjStatus->afAngle.fAz = (FLOAT32)pole.beta;
pObjStatus->afAngle.fPt = (FLOAT32)pole.alpha;
pObjStatus->afAngleBorn = pObjStatus->afAngle;
// 表观模型初始化
TO_CleanUpObjFeatures();
TARGET_OBJECT* pLockObj = &pTrackingPipe->objHistoryList[pTrackingPipe->ubEnd];
TO_RecordObjFeatures(pLockObj, p_GLB_Input);
return true;
}
int SA_Tracker::Track(GD_VIDEO_FRAME_S img, SINT32 nWidth, SINT32 nHeight, GLB_INPUT* p_GLB_Input, API_MOT_PIPE* g_GLB_PipeProc)
{
nTrackTargetID = -1;
m_MatchedTarget = { 0 };
//调整搜索区域大小,为分块宽高的整数倍
SetAutoSearchZone(nWidth, nHeight, p_GLB_Input);
// 使用运动模型
FilterMeanNL stMotionMod_mean = m_LockingPipe->stMotionMod_mean;
BBOOL bEnableAreaObjDetect = FALSE;
float fObjAglSpeed = ABS(m_LockingPipe->sfAglSpeed.vx) + ABS(m_LockingPipe->sfAglSpeed.vy);
// 像素数超过面目标检出下限或者速度较快,开启面目标检测算法
if ((m_ObjStatus.fObjPxlsCnt > DAT_TARGET_PXLS_MIN) || (fObjAglSpeed > 0.01f))
{
bEnableAreaObjDetect = true;
}
else
{
bEnableAreaObjDetect = false;
}
// 跟踪阶段,合并距离关键参数
SINT32 nCombinDist = m_TSA_Input.nBlkWidth / 2 + 1;
// 小目标跟踪模式
if (m_SizeMode == SizeType::SmallTarget)
{
// 小目标跟踪模块使用上面计算分块方案
DST_INPUT trackInput = { 0 };
trackInput.crCenterRect = m_TSA_Input.crCenterRect;
trackInput.mmCenterRect = m_TSA_Input.mmCenterRect;
trackInput.nBlkHeight = m_TSA_Input.nBlkHeight;
trackInput.nBlkWidth = m_TSA_Input.nBlkWidth;
trackInput.nBlkNumW = m_TSA_Input.nBlkNumW;
trackInput.nBlkNumH = m_TSA_Input.nBlkNumH;
trackInput.nBlkNum = m_TSA_Input.nBlkNum;
pDST_Module->SetSearchBLK(trackInput);
//查找分块极大值、统计当前帧目标
//MSSu, 20150606: 根据分块大小,修改极值点合并距离
//MSSu, 20150606: 小目标跟踪阶段,根据目标大小设置合并距离阈值
// 跟踪阶段,强制缩小检测器合并距离提升分辨能力
nCombinDist = (MAX(1, m_TSA_Input.nBlkWidth / 2 + 1),9);
pDST_Module->SetCombinDist(nCombinDist);
pDST_Module->Detect(img, nWidth, nHeight, m_TSA_Input.crCenterRect, GLB_STATUS_TRACK);
// 小目标可以开面目标检测
if (bEnableAreaObjDetect)
{
pDAT_Module->Detect(img, nWidth, nHeight, m_TSA_Input.crCenterRect, GLB_STATUS_TRACK);
}
}
// 面目标跟踪模式
if (m_SizeMode == SizeType::AreaTarget)
{
pDAT_Module->Detect(img, nWidth, nHeight, m_TSA_Input.crCenterRect, GLB_STATUS_TRACK);
}
//将面目标检测结果复制到小目标检测结果数组
// m_nTargetNum = pDST_Module->AddTargetArray(pDAT_Module->GetTargetArray(), pDAT_Module->m_FrmObjsCnt);
// //小、面目标合并
// SINT32 nDist = pDST_Module->m_DST_stPara.nObjCombineDist;
// m_nTargetNum = MergeSmallAndAreaTarget(m_Target_Array, pDST_Module->m_FrmObjsCnt, pDAT_Module->m_FrmObjsCnt,nDist,GLB_STATUS_TRACK);
// 将小目标队列拷贝进输出队列
SINT32 nSmallTargetNum = pDST_Module->GetTargetNum();
memcpy(m_Target_Array, pDST_Module->GetTargetArray(), nSmallTargetNum * sizeof(TARGET_OBJECT));
//拷贝面目标检测队列,截断拷贝
SINT32 nCpNum = MIN(DT_TARGET_MAX_NUM - nSmallTargetNum,pDAT_Module->GetTargetNum());
memcpy(&m_Target_Array[nSmallTargetNum], pDAT_Module->GetTargetArray(), nCpNum * sizeof(TARGET_OBJECT));
//小、面目标原地合并
m_nTargetNum = MergeSmallAndAreaTarget(m_Target_Array, nSmallTargetNum, nCpNum, nCombinDist ,GLB_STATUS::GLB_STATUS_TRACK);
// 小面目标检测信息使用后重置,为了提高效率这里只重置个数
pDST_Module->SetTargetNum(0);
pDAT_Module->SetTargetNum(0);
// 执行位移强限制
SINT32 nInvalidTargetCnt = 0; //单帧小目标检测的无效目标,指不满足帧间位移强逻辑的目标
if (m_nTargetNum > 0)
{
//遍历单帧检测到的目标,进行位移强逻辑判断
for (int i = 0; i < m_nTargetNum; i++)
{
OBJECTSTATUS* pObjStatus = &m_ObjStatus;
FLOAT32 fAzSpeed = pObjStatus->sfAglSpeed.vx / p_GLB_Input->stCamera.fAglReso; //目标运动的方位角速度(单位:像素)
FLOAT32 fPtSpeed = pObjStatus->sfAglSpeed.vy / p_GLB_Input->stCamera.fAglReso; //目标运动的方位角速度(单位:像素)
//指向当前目标
TARGET_OBJECT* ptTarget = &m_Target_Array[i];
//20161130用预测位置位置防止伺服或者炮塔突然抖动频繁进入记忆跟踪
//20161201用上一帧位置防止图像平稳过程中因为目标变速用预测位置频繁进记忆跟踪
if ((m_ObjStatus.unContiLostCnt < 50) &&
(ABS(ptTarget->pfCenPos.x - nWidth/2) < 50 && ABS(ptTarget->pfCenPos.y - nHeight / 2) < 50)//目标在视场边缘跟踪时伺服通常比较快,容易跟丢
// 修改防跳动的阈值,管道丢失几帧时也不能跳,原来条件太严,无法解决晃动后丢失被噪点干扰的问题
&& (ABS(ptTarget->pfCenPos.x - stMotionMod_mean.crnObjPrediRtLong.cx) > MAX(ABS(fAzSpeed) * 3, 12)
|| ABS(ptTarget->pfCenPos.y - stMotionMod_mean.crnObjPrediRtLong.cy) > MAX(ABS(fPtSpeed) * 3, 12))
&& (ABS(ptTarget->pfCenPos.x - pObjStatus->ptPos.x) > MAX(ABS(fAzSpeed) * 2, 12)
|| ABS(ptTarget->pfCenPos.y - pObjStatus->ptPos.y) > MAX(ABS(fPtSpeed) * 2, 12)))
{
nInvalidTargetCnt++;
}
}
//若所有目标均不满足强逻辑,清空检测结果
if (nInvalidTargetCnt == m_nTargetNum)
{
memset(m_Target_Array, 0, sizeof(TARGET_OBJECT) * m_nTargetNum);
m_nTargetNum = 0;
}
}
// 对空小目标进入二次检测跟踪
if ((0 == m_nTargetNum)
&& (m_TSA_Param.bEnableSecDetect || m_SizeMode == SizeType::SmallTarget) /*&& (g_GLB_stPara->nWorkScene == GLB_WATCH_SKY)*/)//对空模式下才使用二次检测
{
//MSSu, 20150415: 小目标跟踪管道处理时二次检测gdk阈值下降(但不能低于3),并关闭部分去虚警条件
TARGET_OBJECT tTargetRe = { 0 };
BBOOL bPipeReObjFound = pDST_Module->DST_PipeTargetReDetect(img, nWidth, nHeight,
m_LockingPipe->ptCurrentPnt, m_LockingPipe->sfAglSpeed,
m_TSA_Input.mmCenterRect,
&tTargetRe, m_Target_Array, &m_nTargetNum);
// 还没有检出,执行第三次超级弱小目标检测
if (!bPipeReObjFound)
{
TARGET_OBJECT tTargetSe = { 0 };
BBOOL bPipeSeObjFound = pDST_Module->DST_PipeTargetRReDetect(img, nWidth, nHeight,
m_LockingPipe->ptCurrentPnt, m_LockingPipe->sfAglSpeed,
m_TSA_Input.mmCenterRect,
&tTargetSe, m_Target_Array, &m_nTargetNum);
//int a = 0;
}
}
// 补全目标信息,如帧编号、角度、检测时间等.
for (int i = 0; i < m_nTargetNum; i++)
{
TARGET_OBJECT* ptTarget = &m_Target_Array[i];
// 帧编号
ptTarget->unFrmID = p_GLB_Input->unFrmId;
// 计算目标的方位角、俯仰角
//// 转惯性系
Pole poletmp = getStablePoleFromImagePos(ptTarget->pfCenPos, p_GLB_Input->stCamera, p_GLB_Input->servoInfo, p_GLB_Input->afPlatformRPY, p_GLB_Input->setupErr);
// 目标角度赋值为大地坐标系
ptTarget->afAngle.fAz = (FLOAT32)poletmp.beta;
ptTarget->afAngle.fPt = (FLOAT32)poletmp.alpha;
}
PIPE* m_PipeArray = g_GLB_PipeProc->getPipeArray();
SINT32 nRealPipeNum = g_GLB_PipeProc->PIPE_GetAlarmNum();
SINT32 m_nMaxPipeNum = g_GLB_PipeProc->PIPE_GetMaxPipeNum();
if (GLB_VIDEO_TYPE::GLB_VIDEO_VL == p_GLB_Input->unVideoSrc)
{
// 第一次查找:在波门范围查找全图管道目标
nTrackTargetID = FindMatchPipe(nWidth, nHeight, m_LockingPipe, m_PipeArray, nRealPipeNum, m_nMaxPipeNum,
&m_TSA_Param, p_GLB_Input->stCamera.fAglReso);
// 将搜索到的匹配目标输出到跟踪器使用AI识别进行匹配关联对识别结果的同步性要求较高
if (nTrackTargetID != -1)
{
memcpy(&m_MatchedTarget, &m_PipeArray[nTrackTargetID].objHistoryList[m_PipeArray[nTrackTargetID].ubEnd], sizeof(TARGET_OBJECT));
}
else
{
// 第二次查找:在波门范围查找区域小面检测目标
nTrackTargetID = FindMatchTarget(m_LockingPipe, m_Target_Array, m_nTargetNum, m_TSA_Param.nPipeRadiusTrack, p_GLB_Input->stCamera.fAglReso);
if (-1 != nTrackTargetID)
{
memcpy(&m_MatchedTarget, &m_Target_Array[nTrackTargetID], sizeof(TARGET_OBJECT));
}
else
{
memset(&m_MatchedTarget, 0, sizeof(TARGET_OBJECT));
}
}
}
else
{
// 第一次查找:在波门范围查找区域小面检测目标
nTrackTargetID = FindMatchTarget(m_LockingPipe, m_Target_Array, m_nTargetNum, m_TSA_Param.nPipeRadiusTrack, p_GLB_Input->stCamera.fAglReso);
if (nTrackTargetID != -1)
{
memcpy(&m_MatchedTarget, &m_Target_Array[nTrackTargetID], sizeof(TARGET_OBJECT));
}
else
{
// 第二次查找:在波门范围查找全图管道目标
// 将搜索到的匹配目标输出到跟踪器使用AI识别进行匹配关联对识别结果的同步性要求较高
nTrackTargetID = FindMatchPipe(nWidth, nHeight, m_LockingPipe, m_PipeArray, nRealPipeNum, m_nMaxPipeNum,
&m_TSA_Param, p_GLB_Input->stCamera.fAglReso);
if (-1 != nTrackTargetID)
{
memcpy(&m_MatchedTarget, &m_PipeArray[nTrackTargetID].objHistoryList[m_PipeArray[nTrackTargetID].ubEnd], sizeof(TARGET_OBJECT));
}
else
{
memset(&m_MatchedTarget, 0, sizeof(TARGET_OBJECT));
}
}
}
// 将匹配目标的特征更新到跟踪器
UpdateObject2Tracker(nWidth, nHeight, &m_MatchedTarget, p_GLB_Input);
// 局部区域的单帧检测结果拷贝到输出
m_TSA_output.m_nTargetNum = m_nTargetNum;
memcpy(m_TSA_output.mTarget_Array, m_Target_Array, sizeof(TARGET_OBJECT)* m_nTargetNum);
// 跟踪器局部的检测器结果清空
memset(m_Target_Array, 0, sizeof(TARGET_OBJECT) * m_nTargetNum);
m_nTargetNum = 0;
return 0;
}
RECT32S SA_Tracker::getTrackRect()
{
RECT32S bbox = { 0 };
bbox.x = SINT32(m_ObjStatus.ptPos.x - m_ObjStatus.sfSize.w / 2);
bbox.y = SINT32(m_ObjStatus.ptPos.y - m_ObjStatus.sfSize.h / 2);
bbox.w = (SINT32)m_ObjStatus.sfSize.w;
bbox.h = (SINT32)m_ObjStatus.sfSize.h;
return bbox;
}
SINT32 SA_Tracker::getInterfereAreaTargteNum(RECT32S bbox)
{
SINT32 nNum = 0;
SINT32 nX = bbox.x + bbox.w / 2;
SINT32 nY = bbox.y + bbox.h / 2;
for (size_t i = 0; i < pDAT_Module->GetTargetNum(); i++)
{
TARGET_OBJECT* pObj = &pDAT_Module->GetTargetArray()[i];
if (ABS(pObj->pfCenPos.x - nX) < MAX(50, bbox.w * 3) &&
ABS(pObj->pfCenPos.x - nY) < MAX(50, bbox.h * 3))
{
nNum++;
}
}
return nNum;
}
API_DetectSmallObj* SA_Tracker::getDSTmodule()
{
return pDST_Module;
}
void SA_Tracker::SetAutoSearchZone(SINT32 nWidth, SINT32 nHeight, GLB_INPUT* p_GLB_Input)
{
#if 1
SINT32 nEnd = 0; //所跟踪管道的当前目标数组队列末尾
SINT32 nPreStep = 1; //管道队列中最后一次保存的目标,与当前帧的帧间隔
POINT32F ptPrePoint = { 0,0 };//所跟踪管道的上一帧中心坐标
CENTERRECT crCenterRect; //搜索区域中心矩形
MINMAXRECT mmCenterRect; //搜索区域四角矩形
SINT32 nPipeRadiusTrack = m_TSA_Param.nPipeRadiusTrack;
SINT32 nPipeRadiusLost = m_TSA_Param.nPipeRadiusLost;
POINT32F PipeCurrentPnt = { 0 };//跟踪管道当前帧位置预测
PIPE* pPipe = m_LockingPipe;
//上一帧跟踪结果
OBJECTSTATUS* pObjStatus = &this->m_ObjStatus;
//根据目标速度预测目标在当前帧的坐标位置
nEnd = m_LockingPipe->ubEnd;
// 取长时预测点作为管道当前位置预测
pPipe->ptCurrentPnt.x = pPipe->stMotionMod_mean.crnObjPrediRtLong.cx;
pPipe->ptCurrentPnt.y = pPipe->stMotionMod_mean.crnObjPrediRtLong.cy;
//判断管道目标是否超出视场
//if (IMGO_IsPoint16SOutImg(nWidth, nHeight, pPipe->ptCurrentPnt))
if(IMGO_IsPoint32FOutImg(nWidth, nHeight, pPipe->ptCurrentPnt))
{
pPipe->bInsideFOV = false;
memset(&m_TSA_Input.crCenterRect, 0, sizeof(CENTERRECT));
memset(&m_TSA_Input.mmCenterRect, 0, sizeof(MINMAXRECT));
m_TSA_Input.nBlkWidth = 0;
m_TSA_Input.nBlkHeight = 0;
m_TSA_Input.nBlkNumW = 0;
m_TSA_Input.nBlkNumH = 0;
m_TSA_Input.nBlkNum = 0;
return;
}
//+++++++++++++++++++++++++++++++++++++++++++++++++++++++
//获取目标大小,调整分块大小
//N = 1 : 16, W = fix((N + 1) / 2) * 4
//N = 1 2 3 4 5 6 7 8
//W = 4 4 8 8 12 12 16 16
//N = 1 : 16, W = fix((N + 2) / 3) * 3
//N = 1 2 3 4 5 6 7 8
//W = 4 4 4 8 8 8 12 12
SINT32 nObjW = (SINT32)pPipe->ObjectFilter.sfSize.w;
SINT32 nObjH = (SINT32)pPipe->ObjectFilter.sfSize.h;
SINT32 nObjSize = MAX(nObjW, nObjH);
SINT32 nBlkWidth = MAX(4, ((nObjSize + 2) / 3) * 4);
SINT32 nBlkHeight = nBlkWidth;
//+++++++++++++++++++++++++++++++++++++++++++++++++++++++
//获取目标等效像方速度
FLOAT32 fObjVx = FLOAT32(fabs(pPipe->sfAglSpeed.vx) / p_GLB_Input->stCamera.fAglReso);
FLOAT32 fObjVy = FLOAT32(fabs(pPipe->sfAglSpeed.vy) / p_GLB_Input->stCamera.fAglReso);
FLOAT32 fObjSpeed = (FLOAT32)(sqrt((double)(fObjVx * fObjVx + fObjVy * fObjVy)) + 0.5f);
//更新管道半径
//20150416: 管道半径取管道速度的1.5~2倍但以可调参数为下限
SIZE32S snPipeRadius;
if (pPipe->bLost)
{
snPipeRadius.w = MIN((SINT32)(fObjVx * pPipe->unLostCnt), nPipeRadiusLost);
snPipeRadius.h = MIN((SINT32)(fObjVy * pPipe->unLostCnt), nPipeRadiusLost);
snPipeRadius.w = MAX(snPipeRadius.w, nPipeRadiusTrack);
snPipeRadius.h = MAX(snPipeRadius.h, nPipeRadiusTrack);
}
else
{
snPipeRadius.w = MAX((SINT32)(fObjVx * 2), nPipeRadiusTrack);
snPipeRadius.h = MAX((SINT32)(fObjVy * 2), nPipeRadiusTrack);
}
//+++++++++++++++++++++++++++++++++++++++++++++++++++++++
//根据管道半径,修正分块大小:
//保证nBlkNumW<=20, nBlkNumH<=16防止分块极值点坐标溢出及保证计算量
SIZE32S snPipeRange;
snPipeRange.w = snPipeRadius.w * 2 + 1;
snPipeRange.h = snPipeRadius.h * 2 + 1;
snPipeRange.s = snPipeRange.w * snPipeRange.h;
auto DST_BLK_NUM = nWidth/16 * nHeight/16;
SINT32 nBlkWidthMin = MAX((SINT32)(sqrt(((double)snPipeRange.s) / DST_BLK_NUM) + 2), 2);
nBlkWidth = MAX(nBlkWidthMin, MIN(nBlkWidth, 16));
nBlkHeight = nBlkWidth;
//+++++++++++++++++++++++++++++++++++++++++++++++++++++++
//根据目标大小及速度,调整管道半径和分块大小
//20150416: 管道半径取管道速度的1.5~2倍但以可调参数为下限
//20150514: 预测时扩大管道半径
if (pPipe->bLost)
{
m_TSA_Param.nPipeRadius = (SINT32)(fObjSpeed * pPipe->unLostCnt);
}
else
{
m_TSA_Param.nPipeRadius = (SINT32)(fObjSpeed * 2.0f);
}
m_TSA_Param.nPipeRadius = MAX(nPipeRadiusTrack, MIN(m_TSA_Param.nPipeRadius, nPipeRadiusLost));
m_TSA_Input.nBlkWidth = nBlkWidth;
m_TSA_Input.nBlkHeight = nBlkHeight;
m_TSA_Param.nObjCombineDist = (nBlkWidth >> 1);
//+++++++++++++++++++++++++++++++++++++++++++++++++++++++
//计算搜索区域中心矩形
snPipeRange.w = (snPipeRange.w + nBlkWidth - 1) / nBlkWidth * nBlkWidth;
snPipeRange.h = (snPipeRange.h + nBlkHeight - 1) / nBlkHeight * nBlkHeight;
snPipeRadius.w = snPipeRange.w >> 1;
snPipeRadius.h = snPipeRange.h >> 1;
//+++++++++++++++++++++++++++++++++++++++++++++++++++++++
//计算搜索区域左、右、上、下边界
mmCenterRect.minX = pPipe->ptCurrentPnt.x - snPipeRadius.w;
mmCenterRect.maxX = pPipe->ptCurrentPnt.x + snPipeRadius.w - 1;
mmCenterRect.minY = pPipe->ptCurrentPnt.y - snPipeRadius.h;
mmCenterRect.maxY = pPipe->ptCurrentPnt.y + snPipeRadius.h - 1;
//20150513: 利用长短轨迹预测位置,调整当前帧目标预测位置
//if (g_GLB_stOutput.bObjPredictAbnormal && g_GLB_stPara.bEnableServoTrackPredi)
//{
// //计算长短轨迹预测位置外接矩形
// MINMAXRECT32S mrnObjTrackNear, mrnObjTrackLong, mrnObjTrackNLOuter;
// mrnObjTrackNear = g_GLB_stOutput.mrnObjPrediRtNear;
// mrnObjTrackLong = g_GLB_stOutput.mrnObjPrediRtLong;
// mrnObjTrackNLOuter.minX = MIN(mrnObjTrackNear.minX, mrnObjTrackLong.minX);
// mrnObjTrackNLOuter.maxX = MAX(mrnObjTrackNear.maxX, mrnObjTrackLong.maxX);
// mrnObjTrackNLOuter.minY = MIN(mrnObjTrackNear.minY, mrnObjTrackLong.minY);
// mrnObjTrackNLOuter.maxY = MAX(mrnObjTrackNear.maxY, mrnObjTrackLong.maxY);
// //更新搜索区域矩形
// mmCenterRect.minX = MIN(mmCenterRect.minX, mrnObjTrackNLOuter.minX);
// mmCenterRect.maxX = MAX(mmCenterRect.maxX, mrnObjTrackNLOuter.maxX);
// mmCenterRect.minY = MIN(mmCenterRect.minY, mrnObjTrackNLOuter.minY);
// mmCenterRect.maxY = MAX(mmCenterRect.maxY, mrnObjTrackNLOuter.maxY);
// //更新分块大小
// snPipeRange.w = mmCenterRect.maxX - mmCenterRect.minX + 1;
// snPipeRange.h = mmCenterRect.maxY - mmCenterRect.minY + 1;
// snPipeRange.s = snPipeRange.w * snPipeRange.h;
// nBlkWidthMin = MAX((SINT32)(sqrt(((double)snPipeRange.s) / DST_BLK_NUM) + 2), 2);
// nBlkWidth = MAX(nBlkWidthMin, MIN(nBlkWidth, DST_BLK_SIZE_W_16));
// nBlkHeight = nBlkWidth;
// g_TST_stInput.nBlkWidth = nBlkWidth;
// g_TST_stInput.nBlkHeight = nBlkHeight;
// g_TST_stInput.nObjCombineDist = (nBlkWidth >> 1) + 1;
//}
//搜索区域边界限制,防止超出图像边界
mmCenterRect.minX = MAX(0, MIN(mmCenterRect.minX, nWidth - 1));
mmCenterRect.maxX = MAX(0, MIN(mmCenterRect.maxX, nWidth - 1));
mmCenterRect.minY = MAX(0, MIN(mmCenterRect.minY, nHeight - 1));
mmCenterRect.maxY = MAX(0, MIN(mmCenterRect.maxY, nHeight - 1));
m_TSA_Input.mmCenterRect = mmCenterRect;
//20180123根据搜索区域大小更新分块大小避免搜索区域小时分块数量少极值点过少
snPipeRange.w = mmCenterRect.maxX - mmCenterRect.minX + 1;
snPipeRange.h = mmCenterRect.maxY - mmCenterRect.minY + 1;
snPipeRange.s = snPipeRange.w * snPipeRange.h;
nBlkWidth = MAX((SINT32)(sqrt(((double)snPipeRange.s) / DST_BLK_NUM) + 2), 2);
nBlkWidth = MAX(2, MIN(nBlkWidth, 16));
nBlkHeight = nBlkWidth;
m_TSA_Input.nBlkWidth = nBlkWidth;
m_TSA_Input.nBlkHeight = nBlkHeight;
m_TSA_Param.nObjCombineDist = (nBlkWidth >> 1) + 1;
//计算搜索区域中心矩形
crCenterRect.cx = (mmCenterRect.minX + mmCenterRect.maxX) >> 1;
crCenterRect.cy = (mmCenterRect.minY + mmCenterRect.maxY) >> 1;
crCenterRect.w = mmCenterRect.maxX - mmCenterRect.minX + 1;
crCenterRect.h = mmCenterRect.maxY - mmCenterRect.minY + 1;
crCenterRect.w = MIN(crCenterRect.w, 480);
crCenterRect.h = MIN(crCenterRect.h, 480);
crCenterRect.s = crCenterRect.w * crCenterRect.h;
m_TSA_Input.crCenterRect = crCenterRect;
//+++++++++++++++++++++++++++++++++++++++++++++++++++++++
//计算分块个数 //20150424: 目标较小但记忆跟踪
m_TSA_Input.nBlkNumH = m_TSA_Input.crCenterRect.h / m_TSA_Input.nBlkHeight;
m_TSA_Input.nBlkNumW = m_TSA_Input.crCenterRect.w / m_TSA_Input.nBlkWidth;
m_TSA_Input.nBlkNum = m_TSA_Input.nBlkNumH * m_TSA_Input.nBlkNumW;
#endif
}
void SA_Tracker::SetTrackModeAuto()
{
// 更新目标尺度类型
//BBOOL bEnableAreaObjDetect = false; //单独定义面目标检测开关
//if ((g_GLB_stOutput.ObjectStatus.fObjPxlsCnt > DAT_TARGET_PXLS_MIN)
// || (fObjAglSpeed > 0.01f))
//{
// bEnableAreaObjDetect = true;
//}
//else
//{
// bEnableAreaObjDetect = false;
//}
// 更新目标灰度类型
}
FLOAT32 pdf(FLOAT32 fmean, FLOAT32 fstd, FLOAT32 x)
{
FLOAT32 f = FLOAT32(exp(-(x - fmean) * (x - fmean) / (2 * fstd * fstd)));
return f;
}
#if 1
// 表观相似度计算
FLOAT32 SA_Tracker::Similarity_Apparent(PIPE* pPipe, TARGET_OBJECT* ptTarget)
{
FLOAT32 fSimilarity = 0.0f;
// 取跟踪特性监控
MonitorStatus* Monitor = &g_GLB_MonitorStatus;
if (ptTarget->nObjTypeSrc == ObjSrc::Arith_DST || ptTarget->nObjTypeSrc == ObjSrc::Arith_DAT)
{
// 融合权重,跟踪前期无先验,使用手工权值
if (m_SizeMode == AreaTarget)
{
Monitor->fGrayWeight = 0.4f; //灰度权重
Monitor->fPxlsWeight = 0.3f;//尺寸权重
Monitor->fWHRWeight = 0.3f;//宽高比权重
Monitor->fSNRWeight = 0.0f;//信噪比权重
Monitor->fBKGMeanWeight = 0.0f;//背景特征权重
}
else
{
Monitor->fGrayWeight = 0.3f; //灰度权重
Monitor->fPxlsWeight = 0.2f;//尺寸权重
Monitor->fWHRWeight = 0.0f;//宽高比权重
Monitor->fSNRWeight = 0.3f;//信噪比权重
Monitor->fBKGMeanWeight = 0.2f;//背景特征权重
}
}
else
{
Monitor->fPxlsWeight = 0.5f;//尺寸权重
Monitor->fWHRWeight = 0.5f;//宽高比权重
//Monitor->fConfWeight = 0.2;//置信度权重
}
//// 稳跟后根据波动情况自适应权重
//if (Monitor->bMonitorVaildFlag)
//{
// FLOAT32 fGrayVariation = Monitor->TargetGray_sta.fMean / (Monitor->TargetGray_sta.fStd);
// FLOAT32 fWHRatioVariation = Monitor->TargetWHRatio_sta.fMean / Monitor->TargetWHRatio_sta.fStd;
// FLOAT32 fPxlsVariation = Monitor->TargetPxls_sta.fMean / Monitor->TargetPxls_sta.fStd;
// FLOAT32 fSNRVariation = Monitor->TargetSNR_sta.fMean / Monitor->TargetSNR_sta.fStd;
// FLOAT32 fBKGVariation = Monitor->TargetBKGMean_sta.fMean / Monitor->TargetBKGMean_sta.fStd;
// FLOAT32 VariationSum = fGrayVariation + fWHRatioVariation + fPxlsVariation + fSNRVariation + fBKGVariation;
// // 权值计算
// FLOAT32 fGrayWeight = fGrayVariation / VariationSum;
// FLOAT32 fWHRatioWeight = fWHRatioVariation / VariationSum;
// FLOAT32 fPxlsWeight = fPxlsVariation / VariationSum;
// FLOAT32 fSNRWeight = fSNRVariation / VariationSum;
// FLOAT32 fBKGWeight = fBKGVariation / VariationSum;
// // 保存当前帧权值
// Monitor->fGrayWeight = fGrayWeight;
// Monitor->fWHRWeight = fWHRatioWeight;
// Monitor->fPxlsWeight = fPxlsWeight;
// Monitor->fSNRWeight = fSNRWeight;//信噪比权重
// Monitor->fBKGMeanWeight = fBKGWeight;//背景特征权重
//}
//FLOAT32 all = Monitor->fGrayWeight + Monitor->fSNRWeight + Monitor->fBKGMeanWeight + Monitor->fWHRWeight + Monitor->fPxlsWeight;
// 开始计算相似度
if (ptTarget->nObjTypeSrc == ObjSrc::Arith_DST || ptTarget->nObjTypeSrc == ObjSrc::Arith_DAT)
{
FLOAT32 fStd_fixGrayModel = MAX(Monitor->TargetGray_sta.fMax - Monitor->TargetGray_sta.fMin, 300.0f) / 3;
FLOAT32 fPdf_gray = pdf(Monitor->TargetGray_sta.fMean, fStd_fixGrayModel, ptTarget->pxObjGray);
FLOAT32 fStd_fixWHModel = MAX(Monitor->TargetWHRatio_sta.fMax - Monitor->TargetWHRatio_sta.fMin, 1.0f) / 3;//小目标宽高比不稳定给1的跳动值
FLOAT32 fPdf_WH = pdf(Monitor->TargetWHRatio_sta.fMean, fStd_fixWHModel, ptTarget->snSize.w * 1.0f / ptTarget->snSize.h);
FLOAT32 fStd_fixPxlModel = MAX(Monitor->TargetPxls_sta.fMax - Monitor->TargetPxls_sta.fMin, Monitor->TargetPxls_sta.fMean * 0.3f) / 3.0f;
FLOAT32 fPdf_Pxl = pdf(Monitor->TargetPxls_sta.fMean, fStd_fixPxlModel, (FLOAT32)ptTarget->unObjPxlsCnt);
FLOAT32 fStd_fixSNRModel = MAX(Monitor->TargetSNR_sta.fMax - Monitor->TargetSNR_sta.fMin, Monitor->TargetSNR_sta.fMean * 0.5f) / 3.0f;
FLOAT32 fPdf_Snr = pdf(Monitor->TargetSNR_sta.fMean, fStd_fixSNRModel, ptTarget->fSNR);
FLOAT32 fStd_fixBKGMeanModel = MAX(Monitor->TargetBKGMean_sta.fMax - Monitor->TargetBKGMean_sta.fMin, 100.0f) / 3.0f;
FLOAT32 fPdf_BKGMean = pdf(Monitor->TargetBKGMean_sta.fMean, fStd_fixSNRModel, ptTarget->fBGMean);
fSimilarity = fPdf_gray * Monitor->fGrayWeight + fPdf_WH * Monitor->fWHRWeight +
fPdf_Pxl * Monitor->fPxlsWeight + fPdf_Snr * Monitor->fSNRWeight + fPdf_BKGMean * Monitor->fBKGMeanWeight;
}
else
{
FLOAT32 fStd_fixWHModel = MAX(Monitor->TargetWHRatio_sta.fMax - Monitor->TargetWHRatio_sta.fMin, 1.0f) / 3;//小目标宽高比不稳定给1的跳动值
FLOAT32 fPdf_WH = pdf(Monitor->TargetWHRatio_sta.fMean, fStd_fixWHModel, ptTarget->snSize.w * 1.0f / ptTarget->snSize.h);
FLOAT32 fStd_fixPxlModel = MAX(Monitor->TargetPxls_sta.fMax - Monitor->TargetPxls_sta.fMin, Monitor->TargetPxls_sta.fMean * 0.3f) / 3.0f;
FLOAT32 fPdf_Pxl = pdf(Monitor->TargetPxls_sta.fMean, fStd_fixPxlModel, (FLOAT32)ptTarget->unObjPxlsCnt);
FLOAT32 fStd_fixConfModel = MAX(Monitor->TargetConfRatio_sta.fMax - Monitor->TargetConfRatio_sta.fMin, 1.0f) / 3;
fSimilarity = fPdf_WH * Monitor->fWHRWeight + fPdf_Pxl * Monitor->fPxlsWeight;
}
return fSimilarity;
}
// 方向余弦相似度
FLOAT32 SA_Tracker::cos_sim(POINT32F v1, POINT32F v2)
{
FLOAT32 fcosSim = FLOAT32((v1.x * v2.x + v1.y * v2.y) / sqrt((v1.x * v1.x + v1.y * v1.y) * (v2.x * v2.x + v2.y * v2.y)));
return (fcosSim + 1) / 2.0f;
}
// 运动相似度
FLOAT32 SA_Tracker::Similarity_Move(PIPE* pPipe, TARGET_OBJECT* ptTarget, FLOAT32 fAglReso)
{
// 当前帧预测位置
POINT32F predictPos = pPipe->ptCurrentPnt;
// 目标大小
SINT32 nTargetSize = SINT32(pPipe->ObjectFilter.sfSize.w * pPipe->ObjectFilter.sfSize.h);
// 位置惩罚区间,根据目标大小和速度,类似波门取值方法
// 长时速度
SPEED32F fSpeedLong;
SPEED32F fAglSpeedLong = pPipe->sfAglSpeed;
fSpeedLong.vx = fAglSpeedLong.vx / fAglReso;
fSpeedLong.vy = fAglSpeedLong.vy / fAglReso;
// 考虑到测量误差误差在一定小范围内得分一致为1
//POINT16S ptLong = m_LockingPipe->ptCurrentPnt_Long;
//POINT16S ptNear = m_LockingPipe->ptCurrentPnt_Near;
//SINT32 nPipeRadiusTrack = m_TSA_Param.nPipeRadiusTrack;
SINT32 nPipeRadiusLost = m_TSA_Param.nPipeRadiusLost;
SIZE16S padSize = { 0 };
padSize.w = MAX(ABS(fSpeedLong.vx * 3) + pPipe->objHistoryList[pPipe->ubEnd].snSize.w, 8);
padSize.h = MAX(ABS(fSpeedLong.vy * 3) + pPipe->objHistoryList[pPipe->ubEnd].snSize.h, 8);
SINT32 nPipeRadiusTrack = 10 + MAX(pPipe->ObjectFilter.sfSize.w, pPipe->ObjectFilter.sfSize.h);
if (pPipe->bLost)
{
padSize.w = MIN(MAX(nPipeRadiusTrack, ABS(fSpeedLong.vx * pPipe->unLostCnt * 0.5)), nPipeRadiusLost);
padSize.h = MIN(MAX(nPipeRadiusTrack, ABS(fSpeedLong.vy * pPipe->unLostCnt * 0.5)), nPipeRadiusLost);
}
FLOAT32 pX = ABS(ptTarget->pfCenPos.x - predictPos.x);
FLOAT32 pY = ABS(ptTarget->pfCenPos.y - predictPos.y);
FLOAT32 pDistScore = 1 - MIN(1, sqrt(pX * pX + pY * pY) / MAX(padSize.w, padSize.h));
//if (pPipe->bLost)
//{
// padSize.w = nPipeRadiusTrack;
// padSize.h = nPipeRadiusTrack;
//}
//else
//{
// padSize.w = SINT16(MAX(fSpeedLong.vx * 5, MAX(sqrt(nTargetSize) * 3, nPipeRadiusTrack * 0.3)));
// padSize.h = SINT16(MAX(fSpeedLong.vy * 5, MAX(sqrt(nTargetSize) * 3, nPipeRadiusTrack * 0.3)));
//}
//// 计算距离得分
//FLOAT32 pX = MIN(1, (ABS(ptTarget->pfCenPos.x - predictPos.x) * 2 / padSize.w));
//FLOAT32 pY = MIN(1, (ABS(ptTarget->pfCenPos.y - predictPos.y) * 2 / padSize.h));
//// 误差经验值修正:8个像素内包含测量误差以及行车抖动误差加入误差容忍系数提高得分平滑性。
//if (ABS(ptTarget->pfCenPos.x - ptNear.x) < 8)
//{
// pX *= 0.2f;
//}
//if (ABS(ptTarget->pfCenPos.y - ptNear.y) < 8)
//{
// pY *= 0.2f;
//}
//// 位置综合得分
//FLOAT32 pDistScore = (1 - pX) * (1 - pY);
// 计算方向得分,以长时滤波器为准
// 目标运动不明显,直接取位置得分
if (ABS(fSpeedLong.vx) < 0.1 && ABS(fSpeedLong.vy) < 0.1)
{
return pDistScore;
}
POINT32F v1 = { 0 }; POINT32F v2 = { 0 };
v1.x = fSpeedLong.vx;
v1.y = fSpeedLong.vy;
SINT32 nStep = MIN(pPipe->unExistCnt, GLB_PIPE_DEPTH_MAX);
SINT32 nFirstPos = (pPipe->ubEnd - nStep + 1 + GLB_PIPE_DEPTH_MAX) % GLB_PIPE_DEPTH_MAX;
ANGLE32F firsAgl = pPipe->objHistoryList[nFirstPos].afAngle;
v2.x = (ptTarget->afAngle.fAz - firsAgl.fAz) / fAglReso;
v2.y = (ptTarget->afAngle.fPt - firsAgl.fPt) / fAglReso;
FLOAT32 pDirScore = cos_sim(v1, v2);
// 经验修正如果有一个速度矢量模差异过大表明方向相似度极低反之如果都很小则不需要计算cossim
FLOAT32 norm_v2 = ABS(v2.x) + ABS(v2.y);
FLOAT32 norm_v1 = ABS(v1.x) + ABS(v1.y);
if (norm_v1 < 1 && norm_v2 < 1)
{
pDirScore = 1;
}
// 速度方向得分与位置得分加权,其中位置得分更具有代表性
FLOAT32 score = pDirScore * 0.3f + pDistScore * 0.7f;
return score;
}
// 基于特征加权融合的相似度计算,提取最优跟踪目标
SINT32 SA_Tracker::FindMatchTarget(PIPE* pPipe, TARGET_OBJECT* ptTargetArray, SINT32 nFrmObjsCnt, SINT32 nPipeRadius, FLOAT32 fAglReso)
{
//局部变量
FLOAT32 fSim = 0.0f; //目标相似度
FLOAT32 fSimMax = -1.0f;//目标相似度最大值
FLOAT32 fSimThres = 0.7f; //相似度阈值
SINT32 nFrmsStep = 1; //帧间隔
TARGET_OBJECT* ptTarget = NULL; //极大值点的临时目标
BYTE8 nSimTargetId = -1; //与管道差异最小的目标编号
TARGET_OBJECT* ptTargetTempA = NULL;//临时目标A
TARGET_OBJECT* ptTargetTempB = NULL;//临时目标B
FLOAT32 fMoveModelWeight = 0.5;//运动模型权值
FLOAT32 fApparentModelWeight = 0.5;//表观模型权值
FLOAT32 fSScaleChangeLowThres = 0.1; // 小目标尺寸变小阈值
FLOAT32 fSScaleChangeHighThres = 12.f; // 小目标尺寸变大阈值
FLOAT32 fAScaleChangeLowThres = 0.25; // 面目标尺寸变小阈值
FLOAT32 fAScaleChangeHighThres = 4.f; // 面目标尺寸变大阈值
SINT32 nPredictDiffThresX = 8; // 与预测位置像素差阈值
SINT32 nPredictDiffThresY = 8; // 与预测位置像素差阈值
SINT32 nLastDiffThresX = 6; // 与上一帧的像素差阈值
SINT32 nLastDiffThresY = 6; // 与上一帧的像素差阈值
FLOAT32 fMoveThres = 0.5f; //运动相似度阈值
FLOAT32 fMoveSim_Target = 0.f; //候选目标运动相似度
pPipe->unSimTargetNum = 0; //清空相似目标个数
//若当前帧目标个数为0则直接返回查找失败标志(差异度最小目标管道编号为-1)
if (0 == nFrmObjsCnt)
{
return -1;
}
// 小目标主要使用位置信息
if (SizeType::SmallTarget == m_SizeMode)
{
fMoveModelWeight = 0.7f;
fApparentModelWeight = 0.3f;
fMoveThres = 0.7f;
}
// +++++++++++++++++++++++++++++++++++++++++++++++++++++
//若长短轨迹预测异常,则直接取距离搜索区域中心最近的目标
if (m_LockingPipe->stMotionMod_mean.bObjPredictAbnormal
&& m_LockingPipe->unLostCnt > 2)
{
fMoveModelWeight = 1.0;
fApparentModelWeight = 0.0;
}
// 使用运动模型
FilterMeanNL stMotionMod_mean = m_LockingPipe->stMotionMod_mean;
//锁定后的50帧优先使用位置信息降低锁定后立即丢失
//if(g_GLB_stOutput.ObjectStatus.unTotalCnt < 50)
//{
// fMoveModelWeight = 1.0;
// fApparentModelWeight = 0.0;
//}
//统计所有当前帧目标与管道目标的灰度、与中心距离、信噪比差异
for (int i = 0; i < nFrmObjsCnt; i++)
{
ptTarget = &ptTargetArray[i];
if (!ptTarget->bObject)
{
continue;
}
// 计算表观相似度
FLOAT32 fAppSim = Similarity_Apparent(pPipe, ptTarget);
// 计算运动相似度
FLOAT32 fMoveSim = Similarity_Move(pPipe, ptTarget, fAglReso);
if (Arith_DIM == ptTarget->nObjTypeSrc && fMoveSim<0.9)
{
continue;
}
fSim = fAppSim * fApparentModelWeight + fMoveSim * fMoveModelWeight;
ptTarget->fMatchConf = fSim;
SINT32 nDSmpScale = pDAT_Module->GetDatParm()->nDSmpScale;
//LSBAO, 20160705: 若尺寸宽高方向同时变化超过2个像素或者宽高单方向变化超过3个像素则认为目标大小突变 -- 丢失超过1S不判断
if (((ABS(ptTarget->snSize.h - pPipe->ObjectFilter.sfSize.h) > 2 * nDSmpScale && ABS(ptTarget->snSize.w - pPipe->ObjectFilter.sfSize.w) > 2 * nDSmpScale) ||
ABS(ptTarget->snSize.h - pPipe->ObjectFilter.sfSize.h) > 3 * nDSmpScale ||
ABS(ptTarget->snSize.w - pPipe->ObjectFilter.sfSize.w) > 3 * nDSmpScale) && m_LockingPipe->unLostCnt< GLB_FRM_FREQ)
{
continue;
}
if (fSim > fSimThres && fMoveSim > fMoveThres)
{
pPipe->unSimTargetNum++;
}
if (fSim > fSimMax)
{
fSimMax = fSim;
nSimTargetId = i;
fMoveSim_Target = fMoveSim;
}
}
if (pPipe->unSimTargetNum > 1)
{
pPipe->blookout = TRUE;
}
// 单一目标条件判断:当只有一个目标时,关闭大部分条件尽力跟踪,比较符合人眼规律。
// 由于跟踪时谨慎合并目标很容易导致临界目标被DST和DAT同时检出这样其实是一个目标但数量上不满足单一目标条件
BBOOL bSingleTarget = (nFrmObjsCnt == 1);
if (nFrmObjsCnt == 2)
{
TARGET_OBJECT* ptTarget1 = &ptTargetArray[0];
TARGET_OBJECT* ptTarget2 = &ptTargetArray[1];
if (ABS(ptTarget1->pfCenPos.x - ptTarget2->pfCenPos.x) <= 3 &&
ABS(ptTarget1->pfCenPos.y - ptTarget2->pfCenPos.y) <= 3)
{
bSingleTarget = TRUE;
}
}
// 阈值调整
if (pPipe->unLostCnt < 20)
{
fSScaleChangeLowThres = 0.3;
fSScaleChangeHighThres = 3.f;
fAScaleChangeLowThres = 0.5;
fAScaleChangeHighThres = 2.0;
nLastDiffThresX = 6;
nLastDiffThresY = 6;
nPredictDiffThresX = 8;
nPredictDiffThresY = 8;
}
else if (pPipe->unLostCnt < 50)
{
fSScaleChangeLowThres = 0.2;
fSScaleChangeHighThres = 5.f;
fAScaleChangeLowThres = 0.33;
fAScaleChangeHighThres = 3.0;
nLastDiffThresX = 10;
nLastDiffThresY = 10;
nPredictDiffThresX = 12;
nPredictDiffThresY = 12;
}
else if (pPipe->unLostCnt < 100)
{
fSScaleChangeLowThres = 0.15;
fSScaleChangeHighThres = 8.f;
fAScaleChangeLowThres = 0.33;
fAScaleChangeHighThres = 3.0;
nLastDiffThresX = 15;
nLastDiffThresY = 15;
nPredictDiffThresX = 18;
nPredictDiffThresY = 18;
}
else
{
fSScaleChangeLowThres = 0.1;
fSScaleChangeHighThres = 12.f;
fAScaleChangeLowThres = 0.25;
fAScaleChangeHighThres = 4.0;
nLastDiffThresX = 15;
nLastDiffThresY = 15;
nPredictDiffThresX = 18;
nPredictDiffThresY = 18;
}
SINT32 nEnd = pPipe->ubEnd;
// 防跳变// by wcw04046 @ 2020/06/22
if (nSimTargetId != -1 && m_ObjStatus.unContiLostCnt < 200)
{
ptTarget = &pPipe->objHistoryList[nEnd];
FLOAT32 fSizeChange = 0.0f;
FLOAT32 fPixChange = 0.0f;
fSizeChange = (FLOAT32)(ptTargetArray[nSimTargetId].snSize.s) / MAX(ptTarget->snSize.s, 0.001f);
fPixChange = (FLOAT32)(ptTargetArray[nSimTargetId].unObjPxlsCnt) / MAX(ptTarget->unObjPxlsCnt, 0.001f);
// 大于DAT_TARGET_MIN的目标可能是临界目标
if (ptTargetArray[nSimTargetId].unObjPxlsCnt < 6
|| ptTarget->unObjPxlsCnt < 6)
{
if (fSScaleChangeHighThres < fPixChange || fSScaleChangeLowThres > fPixChange)
{
fSimMax = -1;
}
}
else if (fSScaleChangeHighThres < fSizeChange || fSScaleChangeLowThres > fSizeChange)
{
fSimMax = -1;
}
else
{
}
// 目标运动距离强逻辑
ptTarget = &ptTargetArray[nSimTargetId];
//CENTERRECT* pcrnSrRect = &g_GLB_stOutput.crnObjPrediRtLong;
//CENTERRECT* pcrnSrRect = &g_GLB_stOutput.crnObjPrediRtNear;
// 用预测位置和上一帧的位置,防止跟踪跳转到错误的目标
if (nSimTargetId != -1)
{
FLOAT32 fAzSpeed = m_ObjStatus.sfAglSpeed.vx / fAglReso;
FLOAT32 fPtSpeed = m_ObjStatus.sfAglSpeed.vy / fAglReso;
//// 没得选了
//if (m_ObjStatus.unContiLostCnt >= 3 && bSingleTarget)
//{
// nPredictDiffThresX = MAX(70, nPipeRadius * 2);
// nPredictDiffThresY = MAX(70, nPipeRadius * 2);
// nLastDiffThresX = nPipeRadius * 2;//波门范围直接取
// nLastDiffThresY = nPipeRadius * 2;//波门范围直接取
//}
nPredictDiffThresX = MAX(ptTarget->snSize.w / 2, nPredictDiffThresX);
nPredictDiffThresY = MAX(ptTarget->snSize.h / 2, nPredictDiffThresY);
nLastDiffThresX = MAX(ptTarget->snSize.w / 2, nLastDiffThresX);
nLastDiffThresY = MAX(ptTarget->snSize.h / 2, nLastDiffThresY);
//if (g_GLB_stPara->nWorkScene == GLB_WATCH_SKY)
//{
// nPredictDiffThres = 70;
// nLastDiffThres = 15;
//}
//if (g_GLB_stPara->nWorkScene == GLB_WATCH_GROUND)
//{
// nPredictDiffThres = 5;
// nLastDiffThres = 5;
//}
if ((ABS(ptTarget->pfCenPos.x - stMotionMod_mean.crnObjPrediRtLong.cx) > MAX(ABS(fAzSpeed) * 2, nPredictDiffThresX)
|| ABS(ptTarget->pfCenPos.y - stMotionMod_mean.crnObjPrediRtLong.cy) > MAX(ABS(fPtSpeed) * 2, nPredictDiffThresY))
&& (ABS(ptTarget->pfCenPos.x - m_ObjStatus.ptPos.x) > MAX(ABS(fAzSpeed) * 2, nLastDiffThresX)
|| ABS(ptTarget->pfCenPos.y - m_ObjStatus.ptPos.y) > MAX(ABS(fPtSpeed) * 2, nLastDiffThresY)))
{
fSimMax = -1;
}
}
}
//+++++++++++++++++++++++++++++++++++++++++++++++++++++++
// 跟踪阈值动态调整
FLOAT32 fThres = fSimThres;
FLOAT32 ContiLostThres = 1.f - MIN(float(m_ObjStatus.unContiLostCnt) / GLB_FRM_FREQ * 2.0f, 0.5); //丢失帧比例
if (bSingleTarget)
{
fThres = fSimThres * ContiLostThres * 0.5;//降低底线的跟踪
fMoveThres = fMoveThres * ContiLostThres * 0.5;
}
else
{
fThres = fSimThres * ContiLostThres;
fMoveThres = fMoveThres * ContiLostThres;
// 跟踪前10帧防掉
if (m_ObjStatus.unTotalCnt < 10)
{
fThres = fSimThres * 0.1f; //没有底线的跟踪
}
}
if (pPipe->blookout)
{
fThres = 0.8 * ContiLostThres;
fMoveThres = 0.8 * 1.f - ContiLostThres;
}
//若最大相似度不满足阈值,则认为未查找到管道目标,返回-1
if (fSimMax < fThres ||(SmallTarget == m_SizeMode && fMoveSim_Target < fMoveThres))
{
nSimTargetId = -1;
}
if (-1 != nSimTargetId)
{
//记录管道目标跟踪相似度
pPipe->fConfidence = fSimMax;
pPipe->blookout = FALSE;
}
else
{
pPipe->fConfidence = -1;
}
return nSimTargetId;
}
// 基于特征加权融合的相似度计算,提取最优跟踪目标
SINT32 SA_Tracker::FindMatchPipe(SINT32 nWidth, SINT32 nHeight, PIPE* pLockingPipe, PIPE* m_PipeArray, SINT32 nRealPipeNum,
SINT32 nMaxPipeNum, TSA_Parameters* pTSA_Param, FLOAT32 fAglReso)
{
//局部变量
FLOAT32 fSim = 0.0f; //目标相似度
FLOAT32 fSimMax = -1.0f;//目标相似度最大值
FLOAT32 fSimThres = 0.5f; //相似度阈值
SINT32 nFrmsStep = 1; //帧间隔
TARGET_OBJECT* ptLockingTarget = NULL; // 主目标管道指向的目标
TARGET_OBJECT *pCandidateTarget = NULL; //管道数组指向的目标
BYTE8 nSimTargetId = -1; //与管道差异最小的目标编号
SINT32 nFrmObjsCnt = 0; // 管道框在关联区域内目标计数
FLOAT32 fMoveModelWeight = 0.7;//运动模型权值
FLOAT32 fApparentModelWeight = 0.3;//表观模型权值
FLOAT32 fSScaleChangeLowThres = 0.1; // 小目标尺寸变小阈值
FLOAT32 fSScaleChangeHighThres = 12.f; // 小目标尺寸变大阈值
FLOAT32 fAScaleChangeLowThres = 0.25; // 面目标尺寸变小阈值
FLOAT32 fAScaleChangeHighThres = 4.f; // 面目标尺寸变大阈值
SINT32 nPipeRadius = pTSA_Param->nPipeRadiusTrack; // 管道关联范围
FilterMeanNL stMotionMod_mean = m_LockingPipe->stMotionMod_mean;
//若当前帧目标个数为0则直接返回查找失败标志(差异度最小目标管道编号为-1)
if (0 == nRealPipeNum)
{
return -1;
}
//基于频率控制AI识别使用
if (pTSA_Param->nUseAIDetFeq > 0)
{
pTSA_Param->nUseAIDetFeq -= 1;
return -1;
}
else
{
pTSA_Param->nUseAIDetFeq = 25;
}
// +++++++++++++++++++++++++++++++++++++++++++++++++++++
//若长短轨迹预测异常,则直接取距离搜索区域中心最近的目标
if (stMotionMod_mean.bObjPredictAbnormal
&& m_LockingPipe->unLostCnt > 2)
{
fMoveModelWeight = 1.0;
fApparentModelWeight = 0.0;
}
//锁定后的50帧优先使用位置信息降低锁定后立即丢失
//if(g_GLB_stOutput.ObjectStatus.unTotalCnt < 50)
//{
// fMoveModelWeight = 1.0;
// fApparentModelWeight = 0.0;
//}
RECT32S LockingPipeBox, newLockingPipeBox;
LockingPipeBox.x = pLockingPipe->objHistoryList[pLockingPipe->ubEnd].pfCenPos.x - nPipeRadius;
LockingPipeBox.y = pLockingPipe->objHistoryList[pLockingPipe->ubEnd].pfCenPos.y - nPipeRadius;
LockingPipeBox.w = nPipeRadius;
LockingPipeBox.h = nPipeRadius;
limitInBounder(nWidth, nHeight, LockingPipeBox, &newLockingPipeBox);
//统计所有当前帧目标与管道目标的灰度、与中心距离、信噪比差异
for (int i = 0; i < nMaxPipeNum; i++)
{
//指向第i个管道
PIPE* pPipe = &m_PipeArray[i];
//跳过空管道
if (!pPipe->bOccupy)
{
continue;
}
// 跳过跟踪管道处理
if (pPipe->bTrackingPipe)
{
continue;
}
// 跳过丢失管道
if (pPipe->bLost)
{
continue;
}
// 计算IOU,统计目标个数
RECT32S PipeBox, newPipeBox;
PipeBox.w = nPipeRadius;
PipeBox.h = nPipeRadius;
PipeBox.x = pPipe->objHistoryList[pPipe->ubEnd].pfCenPos.x - nPipeRadius;
PipeBox.y = pPipe->objHistoryList[pPipe->ubEnd].pfCenPos.y - nPipeRadius;
limitInBounder(nWidth, nHeight, PipeBox, &newPipeBox);
FLOAT32 targerIOU = IoUA32S(&newLockingPipeBox, &newPipeBox);
if (targerIOU > 0.1)
{
nFrmObjsCnt += 1;
}
pCandidateTarget = &pPipe->objHistoryList[pPipe->ubEnd];
// 计算表观相似度
FLOAT32 fAppSim = Similarity_Apparent(pLockingPipe, pCandidateTarget);
// 计算运动相似度
FLOAT32 fMoveSim = Similarity_Move(pLockingPipe, pCandidateTarget, fAglReso);
fSim = fAppSim * fApparentModelWeight + fMoveSim * fMoveModelWeight;
pCandidateTarget->fMatchConf = fSim;
// 获得降采样倍数
SINT32 nDSmpScale = pDAT_Module->GetDatParm()->nDSmpScale;
//LSBAO, 20160705: 若尺寸宽高方向同时变化超过2个像素或者宽高单方向变化超过5个像素则认为目标大小突变
if (ABS(pCandidateTarget->snSize.h - pLockingPipe->ObjectFilter.sfSize.h) > 5 * nDSmpScale ||
ABS(pCandidateTarget->snSize.w - pLockingPipe->ObjectFilter.sfSize.w) > 5 * nDSmpScale)
{
continue;
}
if (fSim > fSimMax)
{
fSimMax = fSim;
nSimTargetId = i;
}
}
// 单一目标条件判断:当只有一个目标时,关闭大部分条件尽力跟踪,比较符合人眼规律。
// 由于跟踪时谨慎合并目标很容易导致临界目标被DST和DAT同时检出这样其实是一个目标但数量上不满足单一目标条件
BBOOL bSingleTarget = (nFrmObjsCnt == 1);
//if (nFrmObjsCnt == 2)
//{
// TARGET_OBJECT* ptTarget1 = &ptTargetArray[0];
// TARGET_OBJECT* ptTarget2 = &ptTargetArray[1];
// if (ABS(ptTarget1->pfCenPos.x - ptTarget2->pfCenPos.x) <= 3 &&
// ABS(ptTarget1->pfCenPos.y - ptTarget2->pfCenPos.y) <= 3)
// {
// bSingleTarget = TRUE;
// }
//}
// 防跳变// by wcw04046 @ 2020/06/22
if (nSimTargetId != -1)
{
pCandidateTarget = &m_PipeArray[nSimTargetId].objHistoryList[m_PipeArray[nSimTargetId].ubEnd];
if (m_ObjStatus.unContiLostCnt < 100)
{
ptLockingTarget = &pLockingPipe->objHistoryList[pLockingPipe->ubEnd];
FLOAT32 fSizeChange = 0.0f;
FLOAT32 fPixChange = 0.0f;
fSizeChange = (FLOAT32)(pCandidateTarget->snSize.s) / MAX(ptLockingTarget->snSize.s, 0.001f);
fPixChange = (FLOAT32)(pCandidateTarget->unObjPxlsCnt) / MAX(ptLockingTarget->unObjPxlsCnt, 0.001f);
// 大于DAT_TARGET_MIN的目标可能是临界目标
if (pCandidateTarget->unObjPxlsCnt < 6 || ptLockingTarget->unObjPxlsCnt < 6)
{
if (12 < fPixChange || 0.1 > fPixChange)
{
fSimMax = -1;
}
}
else if (12 < fSizeChange || 0.1 > fSizeChange)
{
fSimMax = -1;
}
else
{
}
}
// 目标运动距离强逻辑
//ptTarget = &ptTargetArray[nSimTargetId];
//CENTERRECT* pcrnSrRect = &g_GLB_stOutput.crnObjPrediRtLong;
//CENTERRECT* pcrnSrRect = &g_GLB_stOutput.crnObjPrediRtNear;
// 用预测位置和上一帧的位置,防止跟踪跳转到错误的目标
FLOAT32 fAzSpeed = m_ObjStatus.sfAglSpeed.vx / fAglReso;
FLOAT32 fPtSpeed = m_ObjStatus.sfAglSpeed.vy / fAglReso;
SINT32 nPredictDiffThresX = 16; // 与预测位置像素差阈值
SINT32 nPredictDiffThresY = 16; // 与预测位置像素差阈值
SINT32 nLastDiffThresX = 10; // 与上一帧的像素差阈值
SINT32 nLastDiffThresY = 10; // 与上一帧的像素差阈值
// 没得选了
if (m_ObjStatus.unContiLostCnt >= 3 && bSingleTarget)
{
nPredictDiffThresX = MAX(70, nPipeRadius * 2);
nPredictDiffThresY = MAX(70, nPipeRadius * 2);
nLastDiffThresX = nPipeRadius * 2;//波门范围直接取
nLastDiffThresY = nPipeRadius * 2;//波门范围直接取
}
nPredictDiffThresX = MAX(pCandidateTarget->snSize.w / 2, nPredictDiffThresX);
nPredictDiffThresY = MAX(pCandidateTarget->snSize.h / 2, nPredictDiffThresY);
nLastDiffThresX = MAX(pCandidateTarget->snSize.w / 2, nLastDiffThresX);
nLastDiffThresY = MAX(pCandidateTarget->snSize.h / 2, nLastDiffThresY);
//if (g_GLB_stPara->nWorkScene == GLB_WATCH_SKY)
//{
// nPredictDiffThres = 70;
// nLastDiffThres = 15;
//}
//if (g_GLB_stPara->nWorkScene == GLB_WATCH_GROUND)
//{
// nPredictDiffThres = 5;
// nLastDiffThres = 5;
//}
// 限定AI识别在图像中心位置缓解AI识别结果帧同步问题
BBOOL st1 = ABS(pCandidateTarget->pfCenPos.x - nWidth / 2) < 50 && ABS(pCandidateTarget->pfCenPos.y - nHeight / 2) < 50;
if (FALSE == st1)
{
fSimMax = -1;
}
// 距离限定强逻辑,避免错误关联
if ((ABS(pCandidateTarget->pfCenPos.x - stMotionMod_mean.crnObjPrediRtLong.cx) > MAX(ABS(fAzSpeed) * 2, nPredictDiffThresX)
|| ABS(pCandidateTarget->pfCenPos.y - stMotionMod_mean.crnObjPrediRtLong.cy) > MAX(ABS(fPtSpeed) * 2, nPredictDiffThresY))
&& (ABS(pCandidateTarget->pfCenPos.x - m_ObjStatus.ptPos.x) > MAX(ABS(fAzSpeed) * 2, nLastDiffThresX)
|| ABS(pCandidateTarget->pfCenPos.y - m_ObjStatus.ptPos.y) > MAX(ABS(fPtSpeed) * 2, nLastDiffThresY)))
{
fSimMax = -1;
}
}
//+++++++++++++++++++++++++++++++++++++++++++++++++++++++
//记录管道目标跟踪相似度
pLockingPipe->fConfidence = fSimMax;
// 跟踪阈值动态调整
FLOAT32 fThres = fSimThres;
if (bSingleTarget)
{
fThres = 0.1f;//没有底线的跟踪
// 超过10帧丢失降低阈值搜索
if (m_ObjStatus.unContiLostCnt >= 10)
{
fThres = 0.1f;
}
}
else
{
// 超过10帧丢失降低阈值搜索
if (m_ObjStatus.unContiLostCnt >= 10)
{
fThres = fSimThres * 0.5f;
}
// 丢失超过10帧直接取位置相似度高的目标
// 跟踪前10帧防掉
if (m_ObjStatus.unTotalCnt < 10)
{
fThres = fSimThres * 0.5f;
}
}
//若最大相似度不满足阈值,则认为未查找到管道目标,返回-1
if (fSimMax < fThres)
{
nSimTargetId = -1;
}
if (-1 != nSimTargetId)
{
//记录管道目标跟踪相似度
pLockingPipe->fConfidence = fSimMax;
pLockingPipe->blookout = FALSE;
} else
{
pLockingPipe->fConfidence = -1;
}
return nSimTargetId;
}
void SA_Tracker::TO_RecordObjFeatures(TARGET_OBJECT* ptTargetMonitor, GLB_INPUT* p_GLB_Input)
{
// 如果SA跟踪器没有在当前帧找到目标则不更新目标特征
if (ptTargetMonitor->bObject == FALSE)
{
return;
}
//// 管道丢失,不进行统计
//// 管道更新来源不是检测算法,也不能更新
//// 注意:当前框架下,所有跟踪算法结果包含手动起批都可以刷新管道
if (ptTargetMonitor->nObjTypeSrc != ObjSrc::Arith_DST && ptTargetMonitor->nObjTypeSrc != ObjSrc::Arith_DAT)
{
return;
}
SINT32 nIndex = g_GLB_MonitorStatus.MonitorCnts % FEA_LENS;
// 灰度值
g_GLB_MonitorStatus.TargetGray[nIndex] = ptTargetMonitor->pxObjGray;
// 宽高比
g_GLB_MonitorStatus.TargetWHRatio[nIndex] = ptTargetMonitor->snSize.w / (ptTargetMonitor->snSize.h + 0.1f);
// 实际像素数
g_GLB_MonitorStatus.TargetPxls[nIndex] = (FLOAT32)ptTargetMonitor->unObjPxlsCnt;
// 信噪比
g_GLB_MonitorStatus.TargetSNR[nIndex] = ptTargetMonitor->fSNR;
// 背景均值
g_GLB_MonitorStatus.TargetBKGMean[nIndex] = ptTargetMonitor->fBGMean;
//记录数组更新帧编号
g_GLB_MonitorStatus.unLastUpdateFrm = p_GLB_Input->unFrmId;
g_GLB_MonitorStatus.MonitorCnts++;//记录+1
// 统计目标管道特性
TO_StatisticsObjFeatures();
//20180917如果监控帧数超过阈值且当前帧监控数组有更新,标记监控数据有效
if (g_GLB_MonitorStatus.MonitorCnts > GLB_MONITOR_VALID_CNT)
{
g_GLB_MonitorStatus.bMonitorVaildFlag = true;//监控有效
}
}
void SA_Tracker::TO_CleanUpObjFeatures()
{
//return;
// 仅在跟踪器初始化时调用,信息保留到下一次跟踪初始化,或者因超时而清空
memset(&g_GLB_MonitorStatus, 0, sizeof(MonitorStatus));
}
void SA_Tracker::Reset(OBJECTSTATUS* pObjStatus, BBOOL bUpdateMod, GD_VIDEO_FRAME_S img, SINT32 nWidth, SINT32 nHeight, GLB_INPUT* g_GLB_stInput)
{
//memcpy(&m_ObjStatus, pObjStatus, sizeof(OBJECTSTATUS));
//+++++++++++++++++++++++++++++++++++++++++++++++++++++++
//重置目标位置、尺寸、速度、角度、角速度
m_ObjStatus.ptPos = pObjStatus->ptPos;
m_ObjStatus.ptPosFilter = pObjStatus->ptPosFilter;
m_ObjStatus.sfSize = pObjStatus->sfSize;
m_ObjStatus.sfSpeed = pObjStatus->sfSpeed;
m_ObjStatus.afAngle = pObjStatus->afAngle;
m_ObjStatus.sfAglSpeed = pObjStatus->sfAglSpeed;
m_ObjStatus.fConfidence = pObjStatus->fConfidence;
//重置目标管道
m_LockingPipe->ObjectFilter.pfCenPos = pObjStatus->ptPos;
m_LockingPipe->ObjectFilter.sfSize = pObjStatus->sfSize;
//20161124Whao重置目标管道的像素点个数因为找管道最优目标时会进行像素点个数的强逻辑判断
m_LockingPipe->ObjectFilter.fPxlsCnt = pObjStatus->fObjPxlsCnt;
if (bUpdateMod)
{
memset(&g_GLB_MonitorStatus, 0, sizeof(MonitorStatus));
// 检测目标
CENTERRECT roi = { 0 };
roi.cx = SINT16(pObjStatus->ptPos.x);
roi.cy = SINT16(pObjStatus->ptPos.y);
roi.w = SINT16(MAX(pObjStatus->sfSize.w * 3, 80));
roi.h = SINT16(MAX(pObjStatus->sfSize.h * 3, 80));
SINT32 nDAT_Num = pDAT_Module->Detect(img, nWidth, nHeight, roi, GLB_STATUS_TRACK);
TARGET_OBJECT tmp_target = { 0 };
if (nDAT_Num > 0)
{
tmp_target = pDAT_Module->GetTargetArray()[0];
}
else
{
RECT32S bbox = { 0 };
bbox.x = SINT32(pObjStatus->ptPos.x - pObjStatus->sfSize.w / 2);
bbox.y = SINT32(pObjStatus->ptPos.y - pObjStatus->sfSize.h / 2);
bbox.w = SINT32(pObjStatus->sfSize.w);
bbox.h = SINT32(pObjStatus->sfSize.h);
tmp_target = CreateNewTarget(img, nWidth, nHeight, bbox, g_GLB_stInput->unFrmId);
}
// 初始化模型
if (1)
{
SINT32 nIndex = g_GLB_MonitorStatus.MonitorCnts % FEA_LENS;
// 灰度值
g_GLB_MonitorStatus.TargetGray[nIndex] = tmp_target.pxObjGray;
// 宽高比
g_GLB_MonitorStatus.TargetWHRatio[nIndex] = tmp_target.snSize.w / (tmp_target.snSize.h + 0.1f);
// 实际像素数
g_GLB_MonitorStatus.TargetPxls[nIndex] = (FLOAT32)tmp_target.unObjPxlsCnt;
// 信噪比
g_GLB_MonitorStatus.TargetSNR[nIndex] = tmp_target.fSNR;
// 背景均值
g_GLB_MonitorStatus.TargetBKGMean[nIndex] = tmp_target.fBGMean;
//记录数组更新帧编号
g_GLB_MonitorStatus.unLastUpdateFrm = g_GLB_stInput->unFrmId;
g_GLB_MonitorStatus.MonitorCnts++;//记录+1
// 统计目标管道特性
TO_StatisticsObjFeatures();
}
}
}
void SA_Tracker::TO_StatisticsObjFeatures()
{
SINT32 nEnd = (g_GLB_MonitorStatus.MonitorCnts - 1) % FEA_LENS;
SINT32 nCount = MIN(FEA_LENS, g_GLB_MonitorStatus.MonitorCnts);
//灰度监控
TO_CalcStdOfArray(g_GLB_MonitorStatus.TargetGray, FEA_LENS, nEnd, nCount, &g_GLB_MonitorStatus.TargetGray_sta);
//像素点个数监控
TO_CalcStdOfArray(g_GLB_MonitorStatus.TargetPxls, FEA_LENS, nEnd, nCount, &g_GLB_MonitorStatus.TargetPxls_sta);
// 宽高比监控
TO_CalcStdOfArray(g_GLB_MonitorStatus.TargetWHRatio, FEA_LENS, nEnd, nCount, &g_GLB_MonitorStatus.TargetWHRatio_sta);
// 信噪比
TO_CalcStdOfArray(g_GLB_MonitorStatus.TargetSNR, FEA_LENS, nEnd, nCount, &g_GLB_MonitorStatus.TargetSNR_sta);
// 背景均值
TO_CalcStdOfArray(g_GLB_MonitorStatus.TargetBKGMean, FEA_LENS, nEnd, nCount, &g_GLB_MonitorStatus.TargetBKGMean_sta);
}
//20180305统计数组的标准差
void SA_Tracker::TO_CalcStdOfArray(FLOAT32* pfArray, SINT32 nTotalLen, SINT32 nEnd,
SINT32 nCountLen, PIPE_FEATURE_FLUC* pstPipeFeature)
{
//统计极值、均值、方差
FLOAT32 fMinValue = 1e6;
FLOAT32 fMaxValue = -1e6;
DOUBLE64 dMean = 0.0f;
DOUBLE64 dVariance = 0.0f; //方差
SINT32 i = 0;
FLOAT32 fValue = 0.0f;
//FLOAT32 fStd = 0.0f; //标准差
SINT32 nIndex = 0; //数组下标
FLOAT32 fNormalizedArray[GLB_MONITOR_VALID_CNT] = { 0 }; //归一化后的数组
//FLOAT32 fRange = 0.0f; //数组值域范围
//防错,如果统计长度大于总数组长度,则直接返回-1异常
if (nCountLen > GLB_MONITOR_VALID_CNT)
{
return;
}
for (i = 0; i < nCountLen; i++)
{
nIndex = (nEnd - i + nTotalLen) % nTotalLen;
fValue = pfArray[nIndex];
//有效值存入归一化数组
fNormalizedArray[i] = fValue;
//最大最小值统计
fMinValue = MIN(fMinValue, fValue);
fMaxValue = MAX(fMaxValue, fValue);
}
//归一化数组并统计均值和方差累加
for (i = 0; i < nCountLen; i++)
{
fValue = fNormalizedArray[i];
//背景灰度及灰度平方累加
dMean += (DOUBLE64)fValue;
dVariance += (DOUBLE64)fValue * fValue;
}
//计算均值、方差
dMean = dMean / (DOUBLE64)(MAX(nCountLen, 1));
dVariance = dVariance / (DOUBLE64)(MAX(nCountLen, 1));
dVariance -= dMean * dMean;
pstPipeFeature->fMean = (FLOAT32)dMean;
pstPipeFeature->fStd = (FLOAT32)sqrt(dVariance);
pstPipeFeature->fMin = fMinValue;
pstPipeFeature->fMax = fMaxValue;
return;
}
/**********************************************************
* 函数名称UpdateObject2Tracker()
* 功能描述:更新目标跟踪器中目标信息
* 输入参数PIPE *pPipe -- 跟踪目标管道
* SINT32 nWidth -- 图像宽度
* SINT32 nHeight -- 图像高度
* 输出参数:无
* 返 回 值:无
* 调用关系:无
* 其它说明:无
**********************************************************/
void SA_Tracker::UpdateObject2Tracker(SINT32 nWidth, SINT32 nHeight,TARGET_OBJECT* pTarget, GLB_INPUT* p_GLB_Input)
{
OBJECTSTATUS* pObjStatus = &this->m_ObjStatus;
// 更新帧编号
pObjStatus->unFrmId = p_GLB_Input->unFrmId;
//更新目标计数器
pObjStatus->unTotalCnt++;
// 未找到目标
if (!pTarget->bObject)
{
pObjStatus->unContiTrackedCnt = 0;
pObjStatus->unContiLostCnt++;
//仅使用长时预测更新目标位置
pObjStatus->ptPosPre = pObjStatus->ptPos;
pObjStatus->ptPos.x = m_LockingPipe->stMotionMod_mean.crnObjPrediRtLong.cx;
pObjStatus->ptPos.y = m_LockingPipe->stMotionMod_mean.crnObjPrediRtLong.cy;
pObjStatus->ptPosFilter = pObjStatus->ptPos;
// 其他特征均不更新
}
else
{
pObjStatus->unTrackedCnt++;
pObjStatus->unContiTrackedCnt++;
pObjStatus->unContiLostCnt = 0;
//特征更新
pObjStatus->ptPosPre = pObjStatus->ptPos;
pObjStatus->ptPos = pTarget->pfCenPos;
pObjStatus->sfSize.w = pTarget->snSize.w;
pObjStatus->sfSize.h = pTarget->snSize.h;
pObjStatus->sfSize.s = pObjStatus->sfSize.w * pObjStatus->sfSize.h;
pObjStatus->fObjPxlsCnt = pTarget->unObjPxlsCnt;
// 滤波值
pObjStatus->ptPosFilter.x = pObjStatus->ptPosFilter.x * 0.4 + pObjStatus->ptPos.x * 0.6;//位置在图像系滤波
pObjStatus->ptPosFilter.y = pObjStatus->ptPosFilter.y * 0.4 + pObjStatus->ptPos.y * 0.6;//位置在图像系滤波
pObjStatus->sfSizeFilter.w = pObjStatus->sfSizeFilter.w * 0.4 + pObjStatus->sfSize.w * 0.6;
pObjStatus->sfSizeFilter.h = pObjStatus->sfSizeFilter.h * 0.4 + pObjStatus->sfSize.h * 0.6;
pObjStatus->sfSizeFilter.s = pObjStatus->sfSizeFilter.s * 0.4 + pObjStatus->sfSize.s * 0.6;
//更新目标置信度为目标匹配度
pObjStatus->fConfidence = pTarget->fMatchConf;
// 跟踪器目标来源
pObjStatus->nObjTypeSrc = pTarget->nObjTypeSrc;
pObjStatus->bObjMiss = false;
}
//20170915,优化,非射击期间出视场解锁
//20200401增加边缘检测需求出视场边界由10改为1调用IMGO_IsPoint16SOutImg原IMGO_IsPoint32FOutImg
POINT16S pntTempPos = { 0 };
pntTempPos.x = (SINT16)pObjStatus->ptPos.x;
pntTempPos.y = (SINT16)pObjStatus->ptPos.y;
BBOOL bInsideFOV = !IMGO_IsPoint16SOutImg(nWidth, nHeight, pntTempPos);
if (bInsideFOV)
{
m_LockingPipe->unContinueOutFOVCnt = 0;
}
else
{
m_LockingPipe->unContinueOutFOVCnt++;
}
//若预测帧数超出阈值,或管道目标超出视场,则标记目标丢失
//更改单帧超出视场为多帧超出视场
if ((pObjStatus->unContiLostCnt > (UINT32)(m_TSA_Param.nPipeFOVLostCnt))
|| (m_LockingPipe->unContinueOutFOVCnt>10))
//|| (!bInsideFOV /*&& !g_GLB_stPara.bSetMemoryTrack*/))
{
pObjStatus->bObjMiss = true;
}
////更新目标速度
//pObjStatus->sfSpeed.vx = pPipe->sfSpeed.vx;
//pObjStatus->sfSpeed.vy = pPipe->sfSpeed.vy;
ANGLE32F afAglPre = pObjStatus->afAngle;
Pole targetPole = getStablePoleFromImagePos(pObjStatus->ptPos,
p_GLB_Input->stCamera, p_GLB_Input->servoInfo,
p_GLB_Input->afPlatformRPY, p_GLB_Input->setupErr);
pObjStatus->afAngle.fAz = (FLOAT32)targetPole.beta;
pObjStatus->afAngle.fPt = (FLOAT32)targetPole.alpha;
//更新目标角速度,直接从管道取ab滤波器的速度
//pObjStatus->sfAglSpeed.vx = m_LockingPipe->stMotionMod.m_pdx;
//pObjStatus->sfAglSpeed.vy = m_LockingPipe->stMotionMod.m_pdy;
//长短时轨迹的速度
pObjStatus->sfAglSpeed.vx = m_LockingPipe->sfAglSpeed.vx;
pObjStatus->sfAglSpeed.vy = m_LockingPipe->sfAglSpeed.vy;
//更新目标置信度
pObjStatus->fConfidence = m_LockingPipe->fConfidence;
//+++++++++++++++++++++++++++++++++++++++++++++++++++++++
////20150608: 更新目标最大最小值,用于弱小目标跟踪
//PIXELTYPE pxObjGray = (PIXELTYPE)(pPipe->ObjectFilter.fGray);
//g_TST_stOutput.pxObjGrayMin = MIN(pxObjGray, g_TST_stOutput.pxObjGrayMin);
//g_TST_stOutput.pxObjGrayMax = MAX(pxObjGray, g_TST_stOutput.pxObjGrayMax);
}
//// 基于特征加权融合的相似度计算,提取最优跟踪管道
//SINT32 SA_Tracker::ReFindMatchPipe(PIPE* pPipe, PIPE* ptPipeArray, SINT32 nFrmObjsCnt, SINT32 nPipeRadius, GLB_INPUT* p_GLB_Input, SINT32 nMaxPipeNum)
//{
// //局部变量
// FLOAT32 fSim = 0.0f; //目标相似度
// FLOAT32 fSimMax = 0.5f;//目标相似度最大值
// FLOAT32 fSim_M = -1.0f;//最相似目标运动相似度
// FLOAT32 fSim_A = -1.0f;//最相似目标表观相似度
// FLOAT32 fSimThres = 0.6f; //相似度阈值
// FLOAT32 fSimThresMove = 0.7f; //运动相似度阈值
// FLOAT32 fSimThresApparent = 0.6f; //表观相似度阈值
// SINT32 nFrmsStep = 1; //帧间隔
// TARGET_OBJECT* ptTarget = NULL; //极大值点的临时目标
// BYTE8 nSimTargetId = -1; //与管道差异最小的目标编号
// TARGET_OBJECT* ptTargetTempA = NULL;//临时目标A
// TARGET_OBJECT* ptTargetTempB = NULL;//临时目标B
//
// FLOAT32 fMoveModelWeight = 0.5;//运动模型权值
// FLOAT32 fApparentModelWeight = 0.5;//表观模型权值
// FLOAT32 fAglReso = p_GLB_Input->stCamera.fAglReso;
// PIPE* Pipe_Temp = NULL;//临时管道
// TARGET_OBJECT* ptTarget_Temp = NULL; //临时目标
// // 小目标主要使用位置信息
// if (SizeType::SmallTarget == m_SizeMode)
// {
// fMoveModelWeight = 0.8;
// fApparentModelWeight = 0.2;
// fSimThresMove = 0.8f; //运动相似度阈值
// fSimThresApparent = 0.5f; //表观相似度阈值
// }
// //累计重捕次数
// if (pPipe->blookout)
// {
// pPipe->nMatchpipe++;
// }
// //计算所有当前帧管道与跟踪相似度
// for (int i = 0; i < nMaxPipeNum; i++)
// {
// Pipe_Temp = &ptPipeArray[i];
// //跳过空管道,丢失外推,非目标管道,干扰管道
// if (Pipe_Temp->nPipeID == pPipe->nPipeID || !Pipe_Temp->bOccupy || Pipe_Temp->bLost || !Pipe_Temp->bTarget ||
// (Pipe_Temp->bJammPipe[pPipe->nPipeID] &&
// ABS(Pipe_Temp->ptCurrentPnt.x - pPipe->ptCurrentPnt.x) + ABS(Pipe_Temp->ptCurrentPnt.y - pPipe->ptCurrentPnt.y) < 3))
// {
// continue;
// }
// ptTarget_Temp = &Pipe_Temp->objHistoryList[Pipe_Temp->ubEnd];
// FLOAT32 fAppSim = Similarity_Apparent(pPipe, ptTarget_Temp);
// // 计算运动相似度
// FLOAT32 fMoveSim = Similarity_Move(pPipe, Pipe_Temp, p_GLB_Input);
// fSim = fAppSim * fApparentModelWeight + fMoveSim * fMoveModelWeight;
// if (fMoveSim < 0.2)
// {
// fSim = -1; //因为遍历全局管道,当运动毫无相似性,不允许重捕
// continue;
// }
// if (m_LockingPipe->nMatchpipe > GLB_FRM_FREQ * 3 && m_LockingPipe->nPipeType == 2)
// {
// fSim = MAX(fAppSim, fSim); //面目标长时间未重捕,且存在表观相似目标,允许取消运动特性判断
// }
// if (m_LockingPipe->nMatchpipe > GLB_FRM_FREQ * 3 && m_LockingPipe->nPipeType != 2)
// {
// fSim = MAX(fMoveSim, fSim); //小目标长时间未重捕,且存在运动相似目标,允许取消表观特性判断
// }
// ptTarget_Temp->fMatchConf = fSim;
// //LSBAO, 20160705: 若尺寸宽高方向同时变化超过4个像素或者宽高单方向变化超过6个像素则认为目标大小突变
// /*if (SizeType::SmallTarget == m_SizeMode)
// {
// if (ABS(Pipe_Temp->ObjectFilter.sfSize.s - pPipe->ObjectFilter.sfSize.s) > 16)
// {
// continue;
// }
// }*/
// if (fSim > fSimMax)
// {
// fSimMax = fSim;
// fSim_M = fMoveSim;
// fSim_A = fAppSim;
// nSimTargetId = i;
// }
// }
//
// SINT32 nEnd = pPipe->ubEnd;
// // 防跳变// by wcw04046 @ 2020/06/22
// if (nSimTargetId != -1 && m_ObjStatus.unContiLostCnt < 100)
// {
// TARGET_OBJECT* ptTarget = &pPipe->objHistoryList[nEnd];
// Pipe_Temp = &ptPipeArray[nSimTargetId];
// ptTarget_Temp = &(Pipe_Temp->objHistoryList[Pipe_Temp->ubEnd]);
// FLOAT32 fSizeChange = 0.0f;
// FLOAT32 fPixChange = 0.0f;
//
// fSizeChange = (FLOAT32)(ptTarget_Temp->snSize.s) / MAX(ptTarget->snSize.s, 0.001f);
// fPixChange = (FLOAT32)(ptTarget_Temp->unObjPxlsCnt) / MAX(ptTarget->unObjPxlsCnt, 0.001f);
// // 用预测位置和上一帧的位置,防止跟踪跳转到错误的目标
//
// FLOAT32 fAzSpeed = m_ObjStatus.sfAglSpeed.vx / fAglReso;
// FLOAT32 fPtSpeed = m_ObjStatus.sfAglSpeed.vy / fAglReso;
//
// SINT32 nPredictDiffThres = 16; // 与预测位置像素差阈值
// SINT32 nLastDiffThres = 10; // 与上一帧的像素差阈值
//
// if (fSimMax > fSimThres && 1 == nFrmObjsCnt) //尽力跟踪
// {
// nPredictDiffThres = nPipeRadius * 2;
// nLastDiffThres = nPipeRadius * 2;
// }
// if ((ABS(ptTarget_Temp->pfCenPos.x - pPipe->ptCurrentPnt_Long.x) > MAX(ABS(fAzSpeed), nPredictDiffThres)
// || ABS(ptTarget_Temp->pfCenPos.y - pPipe->ptCurrentPnt_Long.y) > MAX(ABS(fPtSpeed), nPredictDiffThres))
// && (ABS(ptTarget_Temp->pfCenPos.x - pPipe->ptCurrentPnt_Near.x) > MAX(ABS(fAzSpeed), nLastDiffThres)
// || ABS(ptTarget_Temp->pfCenPos.y - pPipe->ptCurrentPnt_Near.y) > MAX(ABS(fPtSpeed), nLastDiffThres)))
// {
// fSimMax = -1;
// }
//
// }
// if (nSimTargetId == -1)
// {
// //记录管道目标跟踪相似度
// pPipe->fConfidence = -1.f;
// Pipe_Temp->fConfidence = -1.f;
// return nSimTargetId;
// }
// //+++++++++++++++++++++++++++++++++++++++++++++++++++++++
// //记录管道目标跟踪相似度
// pPipe->fConfidence = fSimMax;
// Pipe_Temp->fConfidence = fSimMax;
// // 跟踪阈值动态调整
// FLOAT32 fThres = fSimThres;
// FLOAT32 fAppaThres = fSimThresApparent;
// FLOAT32 fMoveThres = fSimThresMove;
// FLOAT32 ContiLostThres = MIN(float(m_ObjStatus.unContiLostCnt) / 2000.0, 0.5);
// if (LOST_COVER == m_ObjStatus.nLostReason || m_LockingPipe->blookout)
// {
// fSimThres = 0.7;
// fThres = 0.7;
// }
// // 超过10帧丢失降低阈值搜索
// if (m_ObjStatus.unContiLostCnt >= 10)
// {
// fThres = MAX(fSimThres * (1 - ContiLostThres), 0.5);
// fMoveThres = MAX(fSimThresMove * (1 - ContiLostThres), fSimThres);
// fAppaThres = MAX(fSimThresApparent * (1 - ContiLostThres), 0.5);
// }
// // 跟踪前10帧防掉
// if (m_ObjStatus.unTotalCnt < 20)
// {
// fThres = fSimThres * 0.5;
// fMoveThres = 0.6;
// fAppaThres = 0.5;
// }
// if (1 == nFrmObjsCnt && LOST_COVER != m_ObjStatus.nLostReason) //尽力跟踪
// {
// fThres = fSimThres * 0.8;
// fAppaThres = fSimThresApparent * 0.8;
// }
// //若最大相似度不满足阈值,则认为未查找到管道目标,返回-1
// if (fSimMax < fThres || (fSim_A < fAppaThres && fSim_M < fMoveThres))
// {
// nSimTargetId = -1;
// }
//
//
// return nSimTargetId;
//}
//// 更新匹配目标,重置滤波信息,并删除匹配管道
//void SA_Tracker::ReElectionPipe(PIPE* pPipe)
//{
// memcpy(&m_MatchedTarget, &pPipe->objHistoryList[pPipe->ubEnd], sizeof(TARGET_OBJECT));
// memcpy(&m_LockingPipe->ObjectFilter, &pPipe->ObjectFilter, sizeof(OBJECT_FILTER));
// //memcpy(&m_LockingPipe->stMotionMod, &pPipe->stMotionMod, sizeof(FilterNL));
// //TO_CleanUpObjFeatures();
// memset(pPipe, 0, sizeof(PIPE));
//}
//
//// 管道运动相似度
//FLOAT32 SA_Tracker::Similarity_Move(PIPE* pLockPipe, PIPE* pPipeTemp, GLB_INPUT* p_GLB_Input)
//{
// FLOAT32 fAglReso = p_GLB_Input->stCamera.fAglReso;
// // 当前帧预测位置
// POINT32F predictPos = { pLockPipe->ptCurrentPnt.x , pLockPipe->ptCurrentPnt.y };
//
// // 目标大小
// SINT32 nTargetSize = pLockPipe->ObjectFilter.sfSize.w * pLockPipe->ObjectFilter.sfSize.h;
//
// // 位置惩罚区间,根据目标大小和速度,类似波门取值方法
// TARGET_OBJECT* ptTarget = &pPipeTemp->objHistoryList[pPipeTemp->ubEnd];
// // 长时速度
// SPEED32F fSpeedLong;
// SPEED32F fAglSpeedLong = pLockPipe->sfAglSpeed;
// fSpeedLong.vx = fAglSpeedLong.vx / fAglReso;
// fSpeedLong.vy = fAglSpeedLong.vy / fAglReso;
//
// SIZE16S padSize = { 0 };
// padSize.w = MAX(ABS(fSpeedLong.vx * 3) + pLockPipe->objHistoryList[pLockPipe->ubEnd].snSize.w, 8);
// padSize.h = MAX(ABS(fSpeedLong.vy * 3) + pLockPipe->objHistoryList[pLockPipe->ubEnd].snSize.h, 8);
//
// SINT32 nPipeRadiusTrack = 10 + MAX(pLockPipe->ObjectFilter.sfSize.w, pLockPipe->ObjectFilter.sfSize.h);
// //padSize.w = MAX(ABS(fSpeedLong.vx * 3), 8);
// //padSize.h = MAX(ABS(fSpeedLong.vy * 3), 8);
//
// ////SINT32 nPipeRadiusTrack = m_TSA_Param.nPipeRadiusTrack;
// //SINT32 nPipeRadiusTrack = 2 * (1 + float(pLockPipe->unLostCnt) / 10.0) + 8;
// SINT32 nPipeRadiusLost = m_TSA_Param.nPipeRadiusLost;
//
// if (pLockPipe->bLost)
// {
// padSize.w = MIN(MAX(nPipeRadiusTrack, ABS(fSpeedLong.vx * pLockPipe->unLostCnt * 0.5)), nPipeRadiusLost);
// padSize.h = MIN(MAX(nPipeRadiusTrack, ABS(fSpeedLong.vy * pLockPipe->unLostCnt * 0.5)), nPipeRadiusLost);
// }
// FLOAT32 pX = ABS(ptTarget->pfCenPos.x - predictPos.x);
// FLOAT32 pY = ABS(ptTarget->pfCenPos.y - predictPos.y);
// FLOAT32 pDistScore = 1 - MIN(1, sqrt(pX * pX + pY * pY) / MAX(padSize.w, padSize.h));
// // 计算方向得分,以长时滤波器为准
// // 目标运动不明显,直接取位置得分
// if (ABS(fSpeedLong.vx) < 0.01 && ABS(fSpeedLong.vy) < 0.01 || pDistScore < 0.2)
// {
// return pDistScore;
// }
//
// POINT32F v1 = { 0 }; POINT32F v2 = { 0 };
// v1.x = fSpeedLong.vx;
// v1.y = fSpeedLong.vy;
// v2.x = pPipeTemp->sfAglSpeed.vx / fAglReso;
// v2.y = pPipeTemp->sfAglSpeed.vy / fAglReso;
// FLOAT32 pDirScore = cos_sim(v1, v2);
//
// // 速度方向得分与位置得分加权,其中速度得分更具有代表性
// FLOAT32 score = pDirScore * 0.7 + pDistScore * 0.3;
//
// return score;
//}
//
///**********************************************************
//* 函数名称UpdateObject2Tracker()
//* 功能描述:更新目标跟踪器中目标信息
//* 输入参数PIPE *pPipe -- 跟踪目标管道
//* SINT32 nWidth -- 图像宽度
//* SINT32 nHeight -- 图像高度
//* 输出参数:无
//* 返 回 值:无
//* 调用关系:无
//* 其它说明:无
//**********************************************************/
//void SA_Tracker::UpdatePipe2Tracker(SINT32 nWidth, SINT32 nHeight, PIPE* pPipe, GLB_INPUT* p_GLB_Input)
//{
// OBJECTSTATUS* pObjStatus = &this->m_ObjStatus;
// //更新目标计数器
// pObjStatus->unTotalCnt++;
// TARGET_OBJECT* pTarget = &pPipe->objHistoryList[pPipe->ubEnd];
// pObjStatus->nLostReason = LOST_NONE;
// // 未找到目标
// if (!pTarget->bObject && pObjStatus->unContiLostCnt > GLB_PIPE_UNFOUND_CNT)
// {
// pObjStatus->nLostReason = LOST_UNFIND;
// }
// // 跟踪目标交错
// if (m_LockingPipe->blookout)
// {
// pObjStatus->nLostReason = LOST_CROSS;
// }
// if (m_LockingPipe->nMatchpipe > GLB_FRM_FREQ * 5)
// {
// pObjStatus->nLostReason = LOST_UNFIND; //长时间未重捕成功,回退至单目标重捕
// }
// //跟踪器进记忆
// if (!pTarget->bObject)
// {
// pObjStatus->unContiTrackedCnt = 0;
// pObjStatus->unContiLostCnt++;
// //20150608: 记忆跟踪时,根据目标角度值,更新目标坐标位置
// ANGLE32F afMemoryAngle = { 0.0 };
// POINT32F ptMemoryPos = { m_LockingPipe->ptStopPnt.x, m_LockingPipe->ptStopPnt.y };
//
//
// //使用预测更新目标位置
// pObjStatus->ptPosPre = pObjStatus->ptPos;
// pObjStatus->ptPos.x = m_LockingPipe->ptCurrentPnt.x;
// pObjStatus->ptPos.y = m_LockingPipe->ptCurrentPnt.y;
// afMemoryAngle.fAz = m_LockingPipe->afCurrentAgl.fAz;
// afMemoryAngle.fPt = m_LockingPipe->afCurrentAgl.fPt;
// // 稳定系到图像坐标系
// Pole targetCarNUEPole;
// targetCarNUEPole.alpha = afMemoryAngle.fPt;
// targetCarNUEPole.beta = afMemoryAngle.fAz;
// targetCarNUEPole.distance = m_LockingPipe->afCurrentAgl.Dr;
// ptMemoryPos = getImagePosFromStablePole(targetCarNUEPole, p_GLB_Input->stCamera, p_GLB_Input->servoInfo, p_GLB_Input->afPlatformRPY, p_GLB_Input->setupErr);
//
// pObjStatus->ptPosFilter.x = m_LockingPipe->ptCurrentPnt_Long.x;//记忆状态滤波轨迹取长时坐标
// pObjStatus->ptPosFilter.y = m_LockingPipe->ptCurrentPnt_Long.y;//记忆状态滤波轨迹取长时坐标
// // 记忆期间目标置信度强制置为0.01
// pObjStatus->fConfidence = 0.01;
// } else
// {
// m_LockingPipe->nMatchpipe = 0; //重置重捕次数
//
// pObjStatus->unTrackedCnt++;
// pObjStatus->unContiTrackedCnt++;
// pObjStatus->unContiLostCnt = 0;
//
// //目标尺寸,滤波
// pObjStatus->sfSize.w = 0.6 * pObjStatus->sfSize.w + 0.4 * pTarget->snSize.w;
// pObjStatus->sfSize.h = 0.6 * pObjStatus->sfSize.h + 0.4 * pTarget->snSize.h;
// pObjStatus->sfSize.s = pObjStatus->sfSize.w * pObjStatus->sfSize.h;
// pObjStatus->fObjPxlsCnt = 0.6 * pObjStatus->fObjPxlsCnt + 0.4 * pTarget->unObjPxlsCnt;
//
// //更新目标位置
// pObjStatus->ptPosPre = pObjStatus->ptPos;
// pObjStatus->ptPos = pTarget->pfCenPos;
// pObjStatus->ptPosFilter = pObjStatus->ptPos;
//
// //更新目标置信度为目标匹配度
// pObjStatus->fConfidence = pTarget->fMatchConf;
//
// // 跟踪器目标来源
// pObjStatus->nObjTypeSrc = pTarget->nObjTypeSrc;
//
// pObjStatus->bObjMiss = false;
//
// ReElectionPipe(pPipe);
// }
// POINT16S pntTempPos = { 0 };
// pntTempPos.x = (SINT16)pObjStatus->ptPos.x;
// pntTempPos.y = (SINT16)pObjStatus->ptPos.y;
// BBOOL bInsideFOV = !IMGO_IsPoint16SOutImg(nWidth, nHeight, pntTempPos);
//
// //若预测帧数超出阈值,或管道目标超出视场,则标记目标丢失
// if ((pObjStatus->unContiLostCnt > (UINT32)(m_TSA_Param.nPipeFOVLostCnt)))
// //|| (!bInsideFOV /*&& !g_GLB_stPara.bSetMemoryTrack*/))
// {
// pObjStatus->bObjMiss = true;
// }
//
// ANGLE32F afAglPre = pObjStatus->afAngle;
//
// Pole targetPole = getStablePoleFromImagePos(pObjStatus->ptPos,
// p_GLB_Input->stCamera, p_GLB_Input->servoInfo,
// p_GLB_Input->afPlatformRPY, p_GLB_Input->setupErr);
// pObjStatus->afAngle.fAz = targetPole.beta;
// pObjStatus->afAngle.fPt = targetPole.alpha;
//
// //更新目标角速度,直接从管道取
// pObjStatus->sfAglSpeed = m_LockingPipe->sfAglSpeed;
//}
#endif