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.

849 lines
31 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_Detector.h"
// 增加标准化算法模块
#include "Arith_CoordModule.h"
#include <thread>
using std::thread;
Detectors::Detectors(GLB_INPUT* p_GLB_Input, 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];
memset(m_Target_Array, 0, sizeof(TARGET_OBJECT) * DT_TARGET_MAX_NUM);
nSysStatus = GLB_STATUS_SEARCH;//默认状态
memset(&mDetPara, 0, sizeof(Param_SkyDetect));
m_FrmObjsCnt = 0;
// 全局检测器灰度类型初始化
GrayTypeInit(p_GLB_Input);
//Arith_AreaDetThreadInit();
//Arith_SmallDetThreadInit();
}
Detectors::Detectors(GLB_INPUT* p_GLB_Input, 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];
memset(m_Target_Array, 0, sizeof(TARGET_OBJECT) * DT_TARGET_MAX_NUM);
m_FrmObjsCnt = 0;
nSysStatus = GLB_STATUS_SEARCH;//默认状态
memset(&mDetPara, 0, sizeof(Param_SkyDetect));
m_FrmObjsCnt = 0;
// 全局检测器灰度类型初始化
GrayTypeInit(p_GLB_Input);
//Arith_AreaDetThreadInit();
//Arith_SmallDetThreadInit();
}
Detectors::~Detectors()
{
API_DetectSmallObj::Destroy(pDST_Module);
API_DetectAreaObj::Destroy(pDAT_Module);
delete[] m_Target_Array;
//if (g_pAreaDetHandle)
//{
// pDAT_Module_Free = TRUE;
// free(g_pAreaDetHandle);
// g_pAreaDetHandle = NULL;
//}
//if (g_pSmallDetHandle)
//{
// pDST_Module_Free = TRUE;
// free(g_pSmallDetHandle);
// g_pSmallDetHandle = NULL;
//}
}
BBOOL Detectors::GrayTypeInit(GLB_INPUT* p_GLB_Input)
{
// 全局检测器参数指定检测灰度类型
Param_SkyDetect para = GetParam();
if (GLB_VIDEO_TYPE::GLB_VIDEO_VL == p_GLB_Input->unVideoSrc)
{//可见光默认检测暗目标
para.nDetectGrayType = GLB_OBJ_GRAY_DARK;
}
else if (GLB_VIDEO_TYPE::GLB_VIDEO_IR_SW == p_GLB_Input->unVideoSrc ||
GLB_VIDEO_TYPE::GLB_VIDEO_IR_MW == p_GLB_Input->unVideoSrc ||
GLB_VIDEO_TYPE::GLB_VIDEO_IR_LW == p_GLB_Input->unVideoSrc)
{//红外默认检测亮目标
para.nDetectGrayType = GLB_OBJ_GRAY_BRIGHT;
}
else
{//未设置时亮暗目标都检测
para.nDetectGrayType = GLB_OBJ_GRAY_ALL;
}
SetParam(para);
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;
#ifdef USE_THREAD_POOL
std::future<int> res[2];
// 将小目标检测任务提交到线程池
res[0] = m_SA_TPool.commit(
std::bind(&API_DetectSmallObj::Detect, pDST_Module, img, mmCenterRect, GLB_STATUS_SEARCH), "TP-SmallDet"
);
// 将面目标检测任务提交到线程池
res[1] = m_SA_TPool.commit(
std::bind(&API_DetectAreaObj::Detect, pDAT_Module, img, mmCenterRect, 0, GLB_STATUS_SEARCH), "TP-AreaDet"
);
// 等待小目标检测任务完成
int level = LOG_GETLEVEL();
if (ARITH_LOG_LEVEL_DEBUG == level)
{
auto start0 = std::chrono::high_resolution_clock::now(); // 记录小目标检测任务的开始时间
res[0].get();
auto end0 = std::chrono::high_resolution_clock::now(); // 记录小目标检测任务的结束时间
std::chrono::duration<double, std::milli> duration0 = end0 - start0; // 计算小目标检测任务的耗时
LOG_TIME("API_DetectSmallObj Thread Time:{}", std::to_string(duration0.count()));
}
else
{
res[0].get();
}
// 等待面目标检测任务完成
if (ARITH_LOG_LEVEL_DEBUG == level)
{
auto start1 = std::chrono::high_resolution_clock::now(); // 记录面目标检测任务的开始时间
res[1].get();
auto end1 = std::chrono::high_resolution_clock::now(); // 记录面目标检测任务的结束时间
std::chrono::duration<double, std::milli> duration1 = end1 - start1; // 计算面目标检测任务的耗时
LOG_TIME("API_DetectAreaObj Thread Time:{}", std::to_string(duration1.count()));
}
else
{
res[1].get();
}
#else
thread t1;
thread t2;
// 初始化小目标队列
t1 = std::thread(&API_DetectSmallObj::Detect, pDST_Module, img, mmCenterRect, GLB_STATUS_SEARCH);//创建小目标处理线程
t2 = std::thread(&API_DetectAreaObj::Detect, pDAT_Module, img, mmCenterRect, 0, GLB_STATUS_SEARCH);//创建面目标处理线程
//// 检测线程同步,等待线程完成
// 记录小目标检测任务的开始时间
auto start1 = std::chrono::high_resolution_clock::now();
// 等待小目标检测任务完成
t1.join();
// 记录小目标检测任务的结束时间
auto end1 = std::chrono::high_resolution_clock::now();
// 记录面目标检测任务的开始时间
auto start2 = std::chrono::high_resolution_clock::now();
// 等待面目标检测任务完成
t2.join();
// 记录面目标检测任务的结束时间
auto end2 = std::chrono::high_resolution_clock::now();
// 计算小目标检测任务的耗时
std::chrono::duration<double> duration1 = 1000 * (end1 - start1);
// 计算面目标检测任务的耗时
std::chrono::duration<double> duration2 = 1000 * (end2 - start2);
#endif
//Arith_SetAreaDetParam(img, mmCenterRect, GLB_STATUS_SEARCH);
//Arith_SetSmallDetParam(img, mmCenterRect, 0, GLB_STATUS_SEARCH);
//pDST_Module->Detect(img, mmCenterRect, GLB_STATUS_SEARCH);
//pDAT_Module->Detect(img, mmCenterRect, 0, GLB_STATUS_SEARCH);
// 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();
}
//void Detectors::Arith_AreaDetThreadInit()
//{
// g_pAreaDetHandle = (det_thread_info*)malloc(sizeof(det_thread_info));
// if (g_pAreaDetHandle)
// {
// g_pAreaDetHandle->threadFlag = true;
// g_pAreaDetHandle->DetFlag = false;
// std::thread tAreaDetThread(&Detectors::AreaDetThread, this);
// tAreaDetThread.detach();
// }
//}
//
//void Detectors::Arith_SmallDetThreadInit()
//{
// g_pSmallDetHandle = (det_thread_info*)malloc(sizeof(det_thread_info));
// if (g_pSmallDetHandle)
// {
// g_pSmallDetHandle->threadFlag = true;
// g_pSmallDetHandle->DetFlag = false;
// std::thread tSmallDetThread(&Detectors::SmallDetThread, this);
// tSmallDetThread.detach();
// }
//}
//
//void Detectors::AreaDetThread()
//{
// while (!pDAT_Module_Free && g_pAreaDetHandle->threadFlag)
// {
// //std::lock_guard<std::mutex> lock(g_pAreaDetHandle->mutex);
// if (!pDAT_Module_Free && !g_pAreaDetHandle->DetFlag)
// {
//
//#ifdef __linux__
// usleep(10000);
//#elif _WIN32
// Sleep(10);
//#endif
// continue;
// }
// if (!pDAT_Module_Free)
// {
// pDAT_Module->Detect(g_pAreaDetHandle->img, g_pAreaDetHandle->nWidth, g_pAreaDetHandle->nHeight,
// g_pAreaDetHandle->mmCenterRect, g_pAreaDetHandle->nStatus);
// g_pAreaDetHandle->DetFlag = false;
// }
// }
//}
//
//void Detectors::SmallDetThread()
//{
// while (!pDST_Module_Free && g_pSmallDetHandle->threadFlag)
// {
// if (!pDST_Module_Free && !g_pSmallDetHandle->DetFlag)
// {
//
//#ifdef __linux__
// usleep(5000);
//#elif _WIN32
// Sleep(5);
//#endif
// continue;
// }
// if (!pDST_Module_Free)
// {
// pDST_Module->Detect(g_pSmallDetHandle->img, g_pSmallDetHandle->nWidth, g_pSmallDetHandle->nHeight,
// g_pSmallDetHandle->mmCenterRect, g_pSmallDetHandle->nStatus);
// g_pSmallDetHandle->DetFlag = false;
// }
// }
//}
//
//void Detectors::Arith_SetAreaDetParam(GD_VIDEO_FRAME_S img, SINT32 nWidth, SINT32 nHeight, CENTERRECT mmCenterRect, GLB_STATUS nStatus)
//{
// g_pAreaDetHandle->img = img;
// g_pAreaDetHandle->nWidth = nWidth;
// g_pAreaDetHandle->nHeight = nHeight;
// g_pAreaDetHandle->mmCenterRect = mmCenterRect;
// g_pAreaDetHandle->nStatus = nStatus;
// g_pAreaDetHandle->DetFlag = true;
//}
//
//void Detectors::Arith_SetSmallDetParam(GD_VIDEO_FRAME_S img, SINT32 nWidth, SINT32 nHeight, CENTERRECT mmCenterRect, GLB_STATUS nStatus)
//{
// g_pSmallDetHandle->img = img;
// g_pSmallDetHandle->nWidth = nWidth;
// g_pSmallDetHandle->nHeight = nHeight;
// g_pSmallDetHandle->mmCenterRect = mmCenterRect;
// g_pSmallDetHandle->nStatus = nStatus;
// g_pSmallDetHandle->DetFlag = true;
//}
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.nObjSizeMin = pDST_stPara->nObjSizeMin;
para.nObjSizeMax = pDST_stPara->nObjSizeMax;
// 面目标参数查询
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->nObjTypeSrc == pT2->nObjTypeSrc)
{
continue;
}
if (ObjSrc::Arith_AI != pT1->nObjTypeSrc && ObjSrc::Arith_AI != pT2->nObjTypeSrc)
{
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;
}
// 执行合并(优先保留AI识别结果)
for (int k = nDeltetID + 1; k < nObjsCnt; k++)
{
if (ObjSrc::Arith_AI == ptTargetArray[k - 1].nObjTypeSrc)
{
// 来自传统的目标特性
ptTargetArray[k - 1].pxObjGray = ptTargetArray[k].pxObjGray; // 平均像素灰度
ptTargetArray[k - 1].pxObjMaxGray = ptTargetArray[k].pxObjMaxGray; // 像素灰度
ptTargetArray[k - 1].fBGStd = ptTargetArray[k].fBGStd; // 背景方差
ptTargetArray[k - 1].fBGMean = ptTargetArray[k].fBGMean; // 背景均值
ptTargetArray[k - 1].fSNR = ptTargetArray[k].fSNR; // 信噪比
ptTargetArray[k - 1].nObjTypeGray = ptTargetArray[k].nObjTypeGray; // 目标灰度类型
}
else
{
ptTargetArray[k - 1] = ptTargetArray[k];
}
}
memset(&ptTargetArray[nObjsCnt - 1], 0, sizeof(TARGET_OBJECT));
nObjsCnt--;
i--;
break;
}
}
}
return nObjsCnt;
}
SINT32 DetSkyLineFilter(TARGET_OBJECT* ptTargetArray, SINT32 nObjsCnt, GLB_PARAMETERS *p_GLB_stPara)
{
// 如果低于天地线小面检测,后续抑制流程跳过
/*if (p_GLB_stPara->bEnLowSkylieSADet)
{
return 0;
}*/
SINT32 i = 0;
TARGET_OBJECT* pT1 = NULL;
// 循环遍历,基于检测点位置,查找距离最近的两个标定点
for (i = 0; i < nObjsCnt; i++)
{
pT1 = &ptTargetArray[i];
//20170314: 防错,跳过空目标
if (!pT1->bObject)
{
continue;
}
}
// 连接两个点构造的直线
// 判断点相对线的位置
return 0;
}