#include "Arith_Detector.h" // 增加标准化算法模块 #include "Arith_CoordModule.h" #include 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 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 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 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 duration1 = 1000 * (end1 - start1); // 计算面目标检测任务的耗时 std::chrono::duration 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 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; }