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.

598 lines
23 KiB

#include "Arith_Detector.h"
// 增加标准化算法模块
#include "Arith_CoordModule.h"
#include <thread>
using std::thread;
Detectors::Detectors(SINT32 nWidth, SINT32 nHeight, CENTERRECT mmCenterRect)
{
pDST_Module = API_DetectSmallObj::Create(nWidth, nHeight, mmCenterRect);
pDAT_Module = API_DetectAreaObj::Create(nWidth, nHeight, mmCenterRect);
// 最大处理DT_TARGET_MAX_NUM个目标
m_Target_Array = new TARGET_OBJECT[DT_TARGET_MAX_NUM];
nSysStatus = GLB_STATUS_SEARCH;//默认状态
}
Detectors::Detectors(SINT32 nWidth, SINT32 nHeight)
{
pDST_Module = API_DetectSmallObj::Create(nWidth, nHeight);
pDAT_Module = API_DetectAreaObj::Create(nWidth, nHeight);
// 最大处理DT_TARGET_MAX_NUM个目标
m_Target_Array = new TARGET_OBJECT[DT_TARGET_MAX_NUM];
m_FrmObjsCnt = 0;
nSysStatus = GLB_STATUS_SEARCH;//默认状态
}
Detectors::~Detectors()
{
API_DetectSmallObj::Destroy(pDST_Module);
API_DetectAreaObj::Destroy(pDAT_Module);
delete m_Target_Array;
}
BBOOL Detectors::Init(SINT32 nWidth, SINT32 nHeight, CENTERRECT mmCenterRect)
{
pDST_Module = API_DetectSmallObj::Create(nWidth, nHeight, mmCenterRect);
pDAT_Module = API_DetectAreaObj::Create(nWidth, nHeight, mmCenterRect);
// 最大处理DT_TARGET_MAX_NUM个目标
m_Target_Array = new TARGET_OBJECT[DT_TARGET_MAX_NUM];
nSysStatus = GLB_STATUS_SEARCH;//默认状态
m_FrmObjsCnt = 0;
// 检测器参数初始化
mDetPara.bEnableDetcetSmallTarget = true;
mDetPara.bEnableDetcetAreaTarget = true;
mDetPara.bEnableDetcetDimTarget = false;
mDetPara.fSmallDetectGDK = 7.0; //适配3315,避免小目标过多
return TRUE;
}
void Detectors::ClearTargetsArray()
{
if(m_Target_Array)
{
memset(m_Target_Array,0,sizeof(TARGET_OBJECT) * DT_TARGET_MAX_NUM);
}
}
SINT32 Detectors::Detect(GD_VIDEO_FRAME_S img, CENTERRECT mmCenterRect)
{
// 类型检查
if (img.enPixelFormat != GD_PIXEL_FORMAT_GRAY_Y16 && GD_PIXEL_FORMAT_GRAY_Y8 != img.enPixelFormat)
{
ClearTargetsArray();
return 0;
}
//UINT16* pSrc = (UINT16*)img.u64VirAddr[0];
SINT32 nWidth = img.u32Width;
SINT32 nHeight = img.u32Height;
thread t1;
thread t2;
// 初始化小目标队列
t1 = std::thread(&API_DetectSmallObj::Detect, pDST_Module, img, nWidth, nHeight, mmCenterRect, GLB_STATUS_SEARCH);//创建小目标处理线程
t2 = std::thread(&API_DetectAreaObj::Detect, pDAT_Module, img, nWidth, nHeight, mmCenterRect, GLB_STATUS_SEARCH);//创建面目标处理线程
//// 检测线程同步
t1.join();
t2.join();
// cv::Mat src(nHeight,nWidth,CV_8UC1);
// UINT16* pY16 = (UINT16*)pSrc;
// for (size_t i = 0; i < nHeight * nWidth; i++)
// {
// src.data[i] = pY16[i];
// }
// cv::imshow("src",src);
// cv::waitKey(1);
// 将小目标队列拷贝进输出队列
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_FrmObjsCnt = MergeSmallAndAreaTarget(m_Target_Array, nSmallTargetNum, nCpNum, 9 ,GLB_STATUS::GLB_STATUS_SEARCH);
return m_FrmObjsCnt;
}
SINT32 Detectors::Detect(GD_VIDEO_FRAME_S img)
{
CENTERRECT mmCenterRect = { SINT16(img.u32Width / 2),SINT16(img.u32Height / 2),SINT16(img.u32Width) ,SINT16(img.u32Height) };
return Detect(img, mmCenterRect);
}
POINT16S* Detectors::GetDST_MaxPoint()
{
return pDST_Module->getMaxPoint();
}
SINT32 Detectors::ImportExternTargets(TARGET_OBJECT* pTargetList, SINT32 nNum)
{
// 清空输出队列
memset(m_Target_Array, 0, sizeof(TARGET_OBJECT) * DT_TARGET_MAX_NUM);
// 外部目标复制到输出队列
memcpy(m_Target_Array, pTargetList, nNum * sizeof(TARGET_OBJECT));
m_FrmObjsCnt = nNum;
return nNum;
}
void Detectors::SetParam(Param_SkyDetect para)
{
pDST_Module->setDstDetState(para.bEnableDetcetSmallTarget); // 小目标检测开关设置
pDST_Module->setDstParm(&para); // 小目标检测参数设置
pDAT_Module->setDatDetState(para.bEnableDetcetAreaTarget); // 面目标检测开关设置
pDAT_Module->setDatParm(&para); // 面目标检测参数设置
}
Param_SkyDetect Detectors::GetParam()
{
Param_SkyDetect para = { 0 };
// 小目标参数查询
para.bEnableDetcetSmallTarget = pDST_Module->getDstDetState();
DST_PARAMETERS* pDST_stPara = pDST_Module->GetDstParm();
para.fSmallDetectGDK = pDST_stPara->fgdk;
para.fDimGdk = pDST_stPara->fDimGdk;
para.nDetectGrayType = pDST_stPara->nDetectGrayType;
// 面目标参数查询
para.bEnableDetcetAreaTarget = pDAT_Module->getDatDetState();
DAT_PARAMETERS* pDAT_stPara = pDAT_Module->GetDatParm();
para.nGrayThresMinBright = pDAT_stPara->nGrayThresMinBright;
para.nGrayThresMinDark = pDAT_stPara->nGrayThresMinDark;
para.fAreaDetectGradDiffThre = pDAT_stPara->nGradThresMin;
para.nDSmpScale = pDAT_stPara->nDSmpScale;
//if (pDAT_stPara->nDetectGrayType != para.nDetectGrayType)
//{
// spdlog::warn("{:08d}Small and area det nGrayType is not same.", 12);
//}
return para;
}
TARGET_OBJECT* Detectors::GetTargetArray()
{
return m_Target_Array;
}
void Detectors::RemoveLabelTarget(RECT32S box)
{
int Disthre = MAX((box.w + box.h), 7);
int cx = box.x + box.w / 2;
int cy = box.y + box.h / 2;
for (size_t i = 0; i < m_FrmObjsCnt; i++)
{
TARGET_OBJECT* tTarget = &m_Target_Array[i];
Disthre = MIN(20, Disthre);
// 基于中心点距离
if (ABS(tTarget->pfCenPos.x - cx) + ABS(tTarget->pfCenPos.y - cy) < Disthre)
{
tTarget->bObject = false;
continue;
}
}
}
/**********************************************************
* SO_MergeSmallAndAreaTarget()
*
* UINT16 *pSrc --
* SINT32 nWidth --
* SINT32 nHeight --
* TARGET_OBJECT *ptTargetArray--
* SINT32 nSmallObjsCnt --
* SINT32 nAreaObjsCnt --
* TARGET_OBJECT *ptTargetArray--
* nTargetNum --
*
* nSmallObjsCnt+nAreaObjsCnt
**********************************************************/
SINT16 MergeSmallAndAreaTarget(TARGET_OBJECT *ptTargetArray, SINT32 nSmallObjsCnt, SINT32 nAreaObjsCnt, SINT32 nCombineDist, GLB_STATUS nSysStatus)
{
SINT32 i = 0;
SINT32 j = 0;
SINT32 k = 0;
TARGET_OBJECT *ptSmallTarget = NULL;
TARGET_OBJECT *ptAreaTarget = NULL;
SINT32 nXDistance = 0;
SINT32 nYDistance = 0;
SINT32 nObjsCnt = (nSmallObjsCnt + nAreaObjsCnt);
SINT32 nMaxPntsDis = 0; //20181205小目标极值点距离绝对值
SINT32 nObjCombineDist = 0;
if (GLB_STATUS_TRACK != nSysStatus)
{
nObjCombineDist = MAX(nCombineDist, 20);//合并阈值保护
}
else
{
nObjCombineDist = nCombineDist;
}
//20170905目标个数为0直接返回
//20170303跟踪且复杂场景下不合并否则导致合并后影响最优管道目标判断尤其在穿云时小目标跟踪稳定合并后相似度反而不如云干扰
//if (nObjsCnt < 1 || g_GLB_bComplexEnv)
//20180926跟踪期间不合并容易导致真实小目标被合并算法进记忆
//20181205考虑跟踪期间的小小目标合并
if (nObjsCnt == 0 /*|| GLB_STATUS_TRACK == nSysStatus*/)
{
return nObjsCnt;
}
//20171206全遍历防止漏合并
for (i = 0; i < nObjsCnt; i++)
{
ptAreaTarget = &ptTargetArray[i];
//20170314: 防错,跳过空目标
if (!ptAreaTarget->bObject)
{
continue;
}
//20171206全遍历防止漏合并
for (j = 0; j < nObjsCnt; j++)
{
if (i == j)
{
continue;
}
ptSmallTarget = &ptTargetArray[j];
//20170314: 防错,跳过空目标
if (!ptSmallTarget->bObject)
{
continue;
}
//20161112仅合并灰度类型相同的目标
if (ptAreaTarget->nObjTypeGray == ptSmallTarget->nObjTypeGray)
{
//20140905: 若两个目标的矩形框有交集,也合并
SINT32 nCombineDist = 1;
BBOOL bBoxClose = true;
if ((ptAreaTarget->mrnRect.minX < ptSmallTarget->mrnRect.minX && ptAreaTarget->mrnRect.maxX < ptSmallTarget->mrnRect.minX - nCombineDist)
|| (ptAreaTarget->mrnRect.maxX > ptSmallTarget->mrnRect.maxX && ptAreaTarget->mrnRect.minX > ptSmallTarget->mrnRect.maxX + nCombineDist)
|| (ptAreaTarget->mrnRect.minY < ptSmallTarget->mrnRect.minY && ptAreaTarget->mrnRect.maxY < ptSmallTarget->mrnRect.minY - nCombineDist)
|| (ptAreaTarget->mrnRect.maxY > ptSmallTarget->mrnRect.maxY && ptAreaTarget->mrnRect.minY > ptSmallTarget->mrnRect.maxY + nCombineDist))
{
bBoxClose = false;
}
else
{
bBoxClose = true;
}
//计算面目标与小目标之间的距离
nXDistance = ABS((SINT32)(ptAreaTarget->pfCenPos.x - ptSmallTarget->pfCenPos.x));
nYDistance = ABS((SINT32)(ptAreaTarget->pfCenPos.y - ptSmallTarget->pfCenPos.y));
BBOOL bDistClose = false;
if (nXDistance < nObjCombineDist
&& nYDistance < nObjCombineDist)
{
bDistClose = true;
}
//矩形交叠或距离过近,则合并,取大者
if (bBoxClose || bDistClose)
{
//20161209如果两个目标极值点与中心点均很近则合并至面目标
SINT32 nDeltetID = i;
FLOAT32 fCenPntDistAB = 0.0f;
SINT32 nMaxPntDistAB = 0;
SINT32 nThres = nObjCombineDist * nObjCombineDist;
//计算A、B点中心点和极值点距离
fCenPntDistAB = (ptAreaTarget->pfCenPos.x - ptSmallTarget->pfCenPos.x) * (ptAreaTarget->pfCenPos.x - ptSmallTarget->pfCenPos.x);
fCenPntDistAB += (ptAreaTarget->pfCenPos.y - ptSmallTarget->pfCenPos.y) * (ptAreaTarget->pfCenPos.y - ptSmallTarget->pfCenPos.y);
nMaxPntDistAB = (ptAreaTarget->pnMaxPos.x - ptSmallTarget->pnMaxPos.x) * (ptAreaTarget->pnMaxPos.x - ptSmallTarget->pnMaxPos.x);
nMaxPntDistAB += (ptAreaTarget->pnMaxPos.y - ptSmallTarget->pnMaxPos.y) * (ptAreaTarget->pnMaxPos.y - ptSmallTarget->pnMaxPos.y);
if (fCenPntDistAB < nThres && nMaxPntDistAB < nThres)
{
SINT32 nSizeDiffW = ptSmallTarget->snSize.w - ptAreaTarget->snSize.w;
SINT32 nSizeDiffH = ptSmallTarget->snSize.h - ptAreaTarget->snSize.h;
if (fCenPntDistAB < 3 && ABS(nSizeDiffW) < 3 && ABS(nSizeDiffH) < 3)
{
nDeltetID = j;//重复目标
}
else
{
//20170221若小目标的宽或高大于7才合并为了小目标逼近过程中平滑过渡到面目标防止跟踪局部
if (ptSmallTarget->nObjTypeSize > GLB_OBJ_SIZE_SMALL)
{
//20181206仅在搜索阶段合并
if (GLB_STATUS_TRACK != nSysStatus || ((GLB_STATUS_TRACK == nSysStatus)
&& ptAreaTarget->nObjTypeSize == GLB_OBJ_SIZE_SMALL
&& (ptAreaTarget->snSize.w > 7 || ptAreaTarget->snSize.h > 7)))
//if (GLB_STATUS_SEARCH == nSysStatus)
{
memcpy(ptAreaTarget, ptSmallTarget, sizeof(TARGET_OBJECT));
ptAreaTarget->nObjTypeSize = GLB_OBJ_SIZE_MIDDLE; //更新目标类型:临界目标
nDeltetID = j;
//20170326更新合并标志
//20181206仅在搜索阶段合并
//if (GLB_STATUS_TRACK == nSysStatus)
//{
// g_GLB_bMergeSmallAndArea = true;
//}
}
else
{
//20170311否则不合并
continue;
}
}
else if (ptAreaTarget->nObjTypeSize > GLB_OBJ_SIZE_SMALL)
{
//20181206仅在搜索阶段合并
if (GLB_STATUS_SEARCH == nSysStatus ||
(GLB_STATUS_TRACK == nSysStatus
&& ptSmallTarget->nObjTypeSize == GLB_OBJ_SIZE_SMALL
&& (ptSmallTarget->snSize.w > 7 || ptSmallTarget->snSize.h > 7)))
//if (GLB_STATUS_SEARCH == nSysStatus)
{
memcpy(ptSmallTarget, ptAreaTarget, sizeof(TARGET_OBJECT));
ptSmallTarget->nObjTypeSize = GLB_OBJ_SIZE_MIDDLE; //更新目标类型:临界目标
nDeltetID = i;
//20170326更新合并标志
//20181206仅在搜索阶段合并
//if (GLB_STATUS_TRACK == nSysStatus)
//{
// g_GLB_bMergeSmallAndArea = true;
//}
}
else
{
//20170311否则不合并
continue;
}
}
else
{
//20181205考虑小小目标合并
nMaxPntsDis = ABS(ptSmallTarget->pnMaxPos.x - ptAreaTarget->pnMaxPos.x) +
ABS(ptSmallTarget->pnMaxPos.y - ptAreaTarget->pnMaxPos.y);
//20181206仅考虑简单背景的情况防止目标和云等背景合并
if (/*!g_GLB_bComplexEnv && */GLB_STATUS_TRACK == nSysStatus && nMaxPntsDis < 2)
{
if (ptSmallTarget->unObjPxlsCnt > ptAreaTarget->unObjPxlsCnt)
{
memcpy(ptAreaTarget, ptSmallTarget, sizeof(TARGET_OBJECT));
nDeltetID = j;
}
else
{
memcpy(ptSmallTarget, ptAreaTarget, sizeof(TARGET_OBJECT));
nDeltetID = i;
}
}
// 增加小小目标合并的情况,因为加入了双极值点的算法,前端没有能力处理极值点不接近而目标框接近的情况。
else if (/*!g_GLB_bComplexEnv && */GLB_STATUS_TRACK != nSysStatus && nMaxPntsDis < 9)
{
memcpy(ptSmallTarget, ptAreaTarget, sizeof(TARGET_OBJECT));
nDeltetID = i;
}
else
{
continue;
}
//跳过,不合并
//continue;
}
}
for (k = nDeltetID + 1; k < nObjsCnt; k++)
{
ptTargetArray[k - 1] = ptTargetArray[k];
}
memset(&ptTargetArray[nObjsCnt - 1], 0, sizeof(TARGET_OBJECT));
nObjsCnt--;
i--;
break;
}
else
{
//暂不处理
} //end of "if (fCenPntDistAB < nThres && nMaxPntDistAB < nThres)"
} //end of "if (bBoxClose || bDistClose)"
} //end of "if (ptAreaTarget->nObjTypeGray == ptSmallTarget->nObjTypeGray)"
} //end of "for (j = i + 1; j < nObjsCnt; j++)"
} // end of "for (i = 0; i < nObjsCnt - 1; i++)"
return nObjsCnt;
}
/**********************************************************
* Sort_TargetArray(SINT32 nObjsNum)
*
* SINT32 nObjsNum --
DetectCenterX -- X
DetectCenterY -- Y
*
*
*
*
**********************************************************/
void Sort_TargetArray(TARGET_OBJECT* ptTargetArray,SINT32 nObjsNum, FLOAT32 DetectCenterX, FLOAT32 DetectCenterY)
{
FLOAT32 DistA = 0.0;
FLOAT32 DistB = 0.0;
TARGET_OBJECT ptTargetArrayTemp;
for (int i = 0; i < nObjsNum - 1; i++)
{
for (int j = i; j < nObjsNum; j++)
{
//根据各个目标检测结果与检测中心点的距离进行排序
DistA = (ptTargetArray[i].pfCenPos.x - DetectCenterX) * (ptTargetArray[i].pfCenPos.x - DetectCenterX)
+ (ptTargetArray[i].pfCenPos.y - DetectCenterY) * (ptTargetArray[i].pfCenPos.y - DetectCenterY);
DistB = (ptTargetArray[j].pfCenPos.x - DetectCenterX) * (ptTargetArray[j].pfCenPos.x - DetectCenterX)
+ (ptTargetArray[j].pfCenPos.y - DetectCenterY) * (ptTargetArray[j].pfCenPos.y - DetectCenterY);
if (DistA > DistB)
{
ptTargetArrayTemp = ptTargetArray[i];
memcpy(&ptTargetArray[i], &ptTargetArray[j], sizeof(TARGET_OBJECT));
memcpy(&ptTargetArray[j], &ptTargetArrayTemp, sizeof(TARGET_OBJECT));
}
}
}
}
SINT32 MergeAIAndSATarget(TARGET_OBJECT* ptTargetArray,SINT32 nObjsCnt)
{
if(nObjsCnt == 0)
{
return nObjsCnt;
}
SINT32 i = 0;
SINT32 j = 0;
SINT32 k = 0;
SINT32 nXDistance = 0;
SINT32 nYDistance = 0;
TARGET_OBJECT* pT1 = NULL;
TARGET_OBJECT* pT2 = NULL;
SINT32 nObjCombineDist = 5;
//20171206全遍历防止漏合并
for (i = 0; i < nObjsCnt; i++)
{
pT1 = &ptTargetArray[i];
//20170314: 防错,跳过空目标
if (!pT1->bObject)
{
continue;
}
//20171206全遍历防止漏合并
for (j = 0; j < nObjsCnt; j++)
{
if (i == j)
{
continue;
}
pT2 = &ptTargetArray[j];
//20170314: 防错,跳过空目标
if (!pT2->bObject)
{
continue;
}
//仅合并传统算法目标与AI目标
if(pT1->unClsType == pT2->unClsType)
{
continue;
}
//20140905: 若两个目标的矩形框有交集,也合并
SINT32 nCombineDist = 1;
BBOOL bBoxClose = true;
if ((pT2->mrnRect.minX < pT1->mrnRect.minX && pT2->mrnRect.maxX < pT1->mrnRect.minX - nCombineDist)
|| (pT2->mrnRect.maxX > pT1->mrnRect.maxX && pT2->mrnRect.minX > pT1->mrnRect.maxX + nCombineDist)
|| (pT2->mrnRect.minY < pT1->mrnRect.minY && pT2->mrnRect.maxY < pT1->mrnRect.minY - nCombineDist)
|| (pT2->mrnRect.maxY > pT1->mrnRect.maxY && pT2->mrnRect.minY > pT1->mrnRect.maxY + nCombineDist))
{
bBoxClose = false;
}
else
{
bBoxClose = true;
}
//计算面目标与小目标之间的距离
nXDistance = ABS((SINT32)(pT2->pfCenPos.x - pT1->pfCenPos.x));
nYDistance = ABS((SINT32)(pT2->pfCenPos.y - pT1->pfCenPos.y));
BBOOL bDistClose = false;
if (nXDistance < nObjCombineDist
&& nYDistance < nObjCombineDist)
{
bDistClose = true;
}
//矩形交叠或距离过近,则合并,取大者
if (bBoxClose || bDistClose)
{
//20161209如果两个目标极值点与中心点均很近则合并至面目标
SINT32 nDeltetID = i;
FLOAT32 fCenPntDistAB = 0.0f;
SINT32 nMaxPntDistAB = 0;
SINT32 nThres = nObjCombineDist * nObjCombineDist;
//计算A、B点中心点距离
fCenPntDistAB = (pT2->pfCenPos.x - pT1->pfCenPos.x) * (pT2->pfCenPos.x - pT1->pfCenPos.x);
fCenPntDistAB += (pT2->pfCenPos.y - pT1->pfCenPos.y) * (pT2->pfCenPos.y - pT1->pfCenPos.y);
if (fCenPntDistAB < nThres)
{
nDeltetID = i;
}
// 执行合并
for (int k = nDeltetID + 1; k < nObjsCnt; k++)
{
ptTargetArray[k - 1] = ptTargetArray[k];
}
memset(&ptTargetArray[nObjsCnt - 1], 0, sizeof(TARGET_OBJECT));
nObjsCnt--;
i--;
break;
}
}
}
return nObjsCnt;
}