|
|
#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(¶); // 小目标检测参数设置
|
|
|
|
|
|
pDAT_Module->setDatDetState(para.bEnableDetcetAreaTarget); // 面目标检测开关设置
|
|
|
pDAT_Module->setDatParm(¶); // 面目标检测参数设置
|
|
|
}
|
|
|
|
|
|
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;
|
|
|
}
|
|
|
|