|
|
#include "Arith_DetectSmallObj.h"
|
|
|
#include "Arith_ImgOperate.h"
|
|
|
#include <vector>
|
|
|
|
|
|
|
|
|
API_DetectSmallObj * API_DetectSmallObj::Create(SINT32 nWidth, SINT32 nHeight)
|
|
|
{
|
|
|
return new DetectSmallObj(nWidth,nHeight);
|
|
|
}
|
|
|
|
|
|
API_DetectSmallObj * API_DetectSmallObj::Create(SINT32 nWidth, SINT32 nHeight, CENTERRECT mmCenterRect)
|
|
|
{
|
|
|
return new DetectSmallObj(nWidth,nHeight,mmCenterRect);
|
|
|
}
|
|
|
|
|
|
void API_DetectSmallObj::Destroy(API_DetectSmallObj * obj)
|
|
|
{
|
|
|
delete obj;
|
|
|
}
|
|
|
|
|
|
|
|
|
//小目标检测模板1
|
|
|
SINT32 g_DST_nFilter_9_13[DST_KERNAL_SIZE_9_13] =
|
|
|
{
|
|
|
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
|
|
|
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
|
|
|
1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1,
|
|
|
1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1,
|
|
|
1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1,
|
|
|
1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1,
|
|
|
1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1,
|
|
|
1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1,
|
|
|
1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1,
|
|
|
1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1,
|
|
|
1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1,
|
|
|
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
|
|
|
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1
|
|
|
};
|
|
|
|
|
|
//小目标检测模板2
|
|
|
SINT32 g_DST_nFilter_5_9[DST_KERNAL_SIZE_5_9] =
|
|
|
{
|
|
|
1, 1, 1, 1, 1, 1, 1, 1, 1,
|
|
|
1, 1, 1, 1, 1, 1, 1, 1, 1,
|
|
|
1, 1, 0, 0, 0, 0, 0, 1, 1,
|
|
|
1, 1, 0, 0, 0, 0, 0, 1, 1,
|
|
|
1, 1, 0, 0, 0, 0, 0, 1, 1,
|
|
|
1, 1, 0, 0, 0, 0, 0, 1, 1,
|
|
|
1, 1, 0, 0, 0, 0, 0, 1, 1,
|
|
|
1, 1, 1, 1, 1, 1, 1, 1, 1,
|
|
|
1, 1, 1, 1, 1, 1, 1, 1, 1
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
DetectSmallObj::DetectSmallObj(SINT32 nWidth, SINT32 nHeight)
|
|
|
{
|
|
|
CENTERRECT mmCenterRect;
|
|
|
mmCenterRect.cx = nWidth / 2;
|
|
|
mmCenterRect.cy = nHeight / 2;
|
|
|
mmCenterRect.w = nWidth;
|
|
|
mmCenterRect.h = nHeight;
|
|
|
mmCenterRect.s = nWidth * nHeight;
|
|
|
|
|
|
DST_pBlkMaxPoint = NULL;
|
|
|
DST_pBlkPtBeTargetFlag = NULL;
|
|
|
DST_pBlkMaxPntFlag = NULL;
|
|
|
m_FrmObjsCnt = 0;
|
|
|
Init(nWidth, nHeight, mmCenterRect);
|
|
|
}
|
|
|
|
|
|
DetectSmallObj::DetectSmallObj(SINT32 nWidth, SINT32 nHeight, CENTERRECT mmCenterRect)
|
|
|
{
|
|
|
DST_pBlkMaxPoint = NULL;
|
|
|
DST_pBlkPtBeTargetFlag = NULL;
|
|
|
DST_pBlkMaxPntFlag = NULL;
|
|
|
m_FrmObjsCnt = 0;
|
|
|
Init(nWidth, nHeight, mmCenterRect);
|
|
|
}
|
|
|
|
|
|
DetectSmallObj::~DetectSmallObj()
|
|
|
{
|
|
|
DST_ReleaseMemory();
|
|
|
}
|
|
|
|
|
|
bool DetectSmallObj::Init(SINT32 nWidth, SINT32 nHeight, CENTERRECT mmCenterRect)
|
|
|
{
|
|
|
DST_Initialization(nWidth,nHeight, mmCenterRect);
|
|
|
m_FrmObjsCnt = 0;
|
|
|
bEnableSmallDet = true;
|
|
|
|
|
|
return true;
|
|
|
}
|
|
|
|
|
|
int DetectSmallObj::Detect(GD_VIDEO_FRAME_S img, SINT32 nWidth, SINT32 nHeight, CENTERRECT mmCenterRect, GLB_STATUS nStatus)
|
|
|
{
|
|
|
if (!bEnableSmallDet)
|
|
|
{
|
|
|
m_FrmObjsCnt = 0;
|
|
|
return ERR_UNInit;
|
|
|
}
|
|
|
|
|
|
m_DST_stInput.crCenterRect = mmCenterRect;
|
|
|
m_FrmObjsCnt = DST_DetectSmallTarget(img, nWidth, nHeight, nStatus);
|
|
|
return m_FrmObjsCnt;
|
|
|
}
|
|
|
|
|
|
void DetectSmallObj::SetSearchBLK(DST_INPUT inputBLK)
|
|
|
{
|
|
|
m_DST_stInput = inputBLK;
|
|
|
}
|
|
|
|
|
|
void DetectSmallObj::SetCombinDist(SINT32 ndistance)
|
|
|
{
|
|
|
m_DST_stPara.nObjCombineDist = ndistance;
|
|
|
}
|
|
|
|
|
|
TARGET_OBJECT* DetectSmallObj::GetTargetArray()
|
|
|
{
|
|
|
return DST_Target;
|
|
|
}
|
|
|
|
|
|
SINT32 DetectSmallObj::GetTargetNum()
|
|
|
{
|
|
|
return m_FrmObjsCnt;
|
|
|
}
|
|
|
|
|
|
void DetectSmallObj::SetTargetNum(SINT32 num)
|
|
|
{
|
|
|
m_FrmObjsCnt = num;
|
|
|
}
|
|
|
|
|
|
DST_PARAMETERS* DetectSmallObj::GetDstParm()
|
|
|
{
|
|
|
return &m_DST_stPara;
|
|
|
}
|
|
|
|
|
|
void DetectSmallObj::setDstParm(Param_SkyDetect* param)
|
|
|
{
|
|
|
m_DST_stPara.fgdk = param->fSmallDetectGDK;
|
|
|
m_DST_stPara.nDetectGrayType = param->nDetectGrayType;
|
|
|
}
|
|
|
|
|
|
BBOOL DetectSmallObj::getDstDetState()
|
|
|
{
|
|
|
return bEnableSmallDet;
|
|
|
}
|
|
|
|
|
|
void DetectSmallObj::setDstDetState(BBOOL bEnableState)
|
|
|
{
|
|
|
bEnableSmallDet = bEnableState;
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
|
//--函数定义
|
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
|
/**********************************************************
|
|
|
* 函数名称:DST_DetectSmallTarget()
|
|
|
* 功能描述:基于分块极值的小目标检测
|
|
|
* 输入参数:UINT16 *pSrc -- 原始图像
|
|
|
* SINT32 nWidth -- 图像宽度
|
|
|
* SINT32 nHeight -- 图像高度
|
|
|
* 输出参数:无
|
|
|
* 返 回 值:小目标检测个数
|
|
|
* 调用关系:
|
|
|
* 其它说明:无
|
|
|
**********************************************************/
|
|
|
SINT32 DetectSmallObj::DST_DetectSmallTarget(GD_VIDEO_FRAME_S img, SINT32 nWidth, SINT32 nHeight, GLB_STATUS nStatus)
|
|
|
{
|
|
|
//指向DSP数据空间
|
|
|
POINT16S* pBlkMaxPnt = (POINT16S*)DST_pBlkMaxPoint;
|
|
|
TARGET_OBJECT* ptTargetArray = (TARGET_OBJECT*)DST_Target;
|
|
|
SINT32* pBlkPtBeTargetFlag = (SINT32*)DST_pBlkPtBeTargetFlag;
|
|
|
BYTE8* pbBlkMaxPntFlag = (BYTE8*)DST_pBlkMaxPntFlag; //20161130,极值点最大/最小标志
|
|
|
|
|
|
// 未初始化报错
|
|
|
if (!m_DST_bInitialize)
|
|
|
{
|
|
|
return ERR_UNInit;
|
|
|
}
|
|
|
|
|
|
//局部变量
|
|
|
SINT32 nObjsCnt = 0;
|
|
|
|
|
|
//+++++++++++++++++++++++++++++++++++++++++++++++++++++++
|
|
|
//初始化算法输出结果
|
|
|
DST_CleanUpFrameDetectOutput();
|
|
|
|
|
|
//+++++++++++++++++++++++++++++++++++++++++++++++++++++++
|
|
|
//获取检测区域边界
|
|
|
m_DST_stInput.mmCenterRect.minX = m_DST_stInput.crCenterRect.cx - (m_DST_stInput.crCenterRect.w >> 1);
|
|
|
m_DST_stInput.mmCenterRect.minY = m_DST_stInput.crCenterRect.cy - (m_DST_stInput.crCenterRect.h >> 1);
|
|
|
m_DST_stInput.mmCenterRect.maxX = m_DST_stInput.crCenterRect.cx + (m_DST_stInput.crCenterRect.w >> 1);
|
|
|
m_DST_stInput.mmCenterRect.maxY = m_DST_stInput.crCenterRect.cy + (m_DST_stInput.crCenterRect.h >> 1);
|
|
|
|
|
|
//限制检测区域边界
|
|
|
m_DST_stInput.mmCenterRect.minX = MAX(0, MIN(m_DST_stInput.mmCenterRect.minX, nWidth - 1));
|
|
|
m_DST_stInput.mmCenterRect.maxX = MAX(0, MIN(m_DST_stInput.mmCenterRect.maxX, nWidth - 1));
|
|
|
m_DST_stInput.mmCenterRect.minY = MAX(0, MIN(m_DST_stInput.mmCenterRect.minY, nHeight - 1));
|
|
|
m_DST_stInput.mmCenterRect.maxY = MAX(0, MIN(m_DST_stInput.mmCenterRect.maxY, nHeight - 1));
|
|
|
|
|
|
//更新检测区域中心矩形
|
|
|
m_DST_stInput.crCenterRect.cx = (m_DST_stInput.mmCenterRect.minX + m_DST_stInput.mmCenterRect.maxX) >> 1;
|
|
|
m_DST_stInput.crCenterRect.cy = (m_DST_stInput.mmCenterRect.minY + m_DST_stInput.mmCenterRect.maxY) >> 1;
|
|
|
m_DST_stInput.crCenterRect.h = m_DST_stInput.mmCenterRect.maxY - m_DST_stInput.mmCenterRect.minY + 1;
|
|
|
m_DST_stInput.crCenterRect.w = m_DST_stInput.mmCenterRect.maxX - m_DST_stInput.mmCenterRect.minX + 1;
|
|
|
m_DST_stInput.crCenterRect.s = (SINT32)(m_DST_stInput.crCenterRect.h * m_DST_stInput.crCenterRect.w);
|
|
|
|
|
|
// 分块方案不存在,返回0
|
|
|
if(m_DST_stInput.nBlkWidth == 0 || m_DST_stInput.nBlkHeight == 0)
|
|
|
{
|
|
|
return 0;
|
|
|
}
|
|
|
|
|
|
//调整分块大小和分块区域
|
|
|
m_DST_stInput.nBlkNumW = m_DST_stInput.crCenterRect.w / m_DST_stInput.nBlkWidth;
|
|
|
m_DST_stInput.nBlkNumH = m_DST_stInput.crCenterRect.h / m_DST_stInput.nBlkHeight;
|
|
|
m_DST_stInput.nBlkNum = m_DST_stInput.nBlkNumW * m_DST_stInput.nBlkNumH;
|
|
|
if ((m_DST_stInput.nBlkNumW <= 0) || (m_DST_stInput.nBlkNumH <= 0))
|
|
|
{
|
|
|
return 0;
|
|
|
}
|
|
|
|
|
|
//+++++++++++++++++++++++++++++++++++++++++++++++++++++++
|
|
|
//图像分块并返回块极值点
|
|
|
if (nStatus == GLB_STATUS_TRACK)
|
|
|
{
|
|
|
DST_FindExtremum(img, nWidth, nHeight, pBlkMaxPnt, pbBlkMaxPntFlag,
|
|
|
m_DST_stInput.mmCenterRect.minY, m_DST_stInput.mmCenterRect.minX,
|
|
|
m_DST_stInput.nBlkWidth, m_DST_stInput.nBlkHeight,
|
|
|
m_DST_stInput.nBlkNumW, m_DST_stInput.nBlkNumH);
|
|
|
}
|
|
|
else
|
|
|
{// 搜索阶段螺旋输出极值点
|
|
|
DST_FindExtremumSpiral(img, nWidth, nHeight, pBlkMaxPnt, pbBlkMaxPntFlag,
|
|
|
m_DST_stInput.mmCenterRect.minY, m_DST_stInput.mmCenterRect.minX,
|
|
|
m_DST_stInput.nBlkWidth, m_DST_stInput.nBlkHeight,
|
|
|
m_DST_stInput.nBlkNumW, m_DST_stInput.nBlkNumH);
|
|
|
}
|
|
|
|
|
|
//+++++++++++++++++++++++++++++++++++++++++++++++++++++++
|
|
|
//判断极值点是否为目标
|
|
|
// wcw04046 面目标空间留出来
|
|
|
nObjsCnt = DST_DetectFrameTarget(img, nWidth, nHeight,
|
|
|
ptTargetArray, DST_MAX_NUM, pBlkMaxPnt,
|
|
|
m_DST_stInput.nBlkNumW, m_DST_stInput.nBlkNumH, pBlkPtBeTargetFlag);
|
|
|
|
|
|
// 显式输出目标个数
|
|
|
m_DST_stOutput.nFrmObjsCnt = nObjsCnt;
|
|
|
|
|
|
return nObjsCnt;
|
|
|
}
|
|
|
|
|
|
/**********************************************************
|
|
|
* 函数名称:DST_Initialization()
|
|
|
* 功能描述:算法初始化
|
|
|
* 输入参数:无
|
|
|
* 输出参数:无
|
|
|
* 返 回 值:无
|
|
|
* 调用关系:无
|
|
|
* 其它说明:无
|
|
|
**********************************************************/
|
|
|
void DetectSmallObj::DST_Initialization(SINT32 nWidth, SINT32 nHeight, CENTERRECT mmCenterRect)
|
|
|
{
|
|
|
//+++++++++++++++++++++++++++++++++++++++++++++++++++++++
|
|
|
//初始化算法输入
|
|
|
//搜索区域
|
|
|
m_DST_stInput.crCenterRect.cx = (SINT16)(mmCenterRect.cx);
|
|
|
m_DST_stInput.crCenterRect.cy = (SINT16)(mmCenterRect.cy);
|
|
|
m_DST_stInput.crCenterRect.w = mmCenterRect.w;
|
|
|
m_DST_stInput.crCenterRect.h = mmCenterRect.h;
|
|
|
m_DST_stInput.crCenterRect.s = m_DST_stInput.crCenterRect.w * m_DST_stInput.crCenterRect.h;
|
|
|
m_DST_stInput.mmCenterRect.minX = m_DST_stInput.crCenterRect.cx - (m_DST_stInput.crCenterRect.w >> 1);
|
|
|
m_DST_stInput.mmCenterRect.minY = m_DST_stInput.crCenterRect.cy - (m_DST_stInput.crCenterRect.h >> 1);
|
|
|
m_DST_stInput.mmCenterRect.maxX = m_DST_stInput.crCenterRect.cx + (m_DST_stInput.crCenterRect.w >> 1);
|
|
|
m_DST_stInput.mmCenterRect.maxY = m_DST_stInput.crCenterRect.cy + (m_DST_stInput.crCenterRect.h >> 1);
|
|
|
|
|
|
//弱小目标强制搜索
|
|
|
m_DST_stInput.crnSemiSrRect.cx = m_DST_stInput.crCenterRect.cx;
|
|
|
m_DST_stInput.crnSemiSrRect.cy = m_DST_stInput.crCenterRect.cy;
|
|
|
m_DST_stInput.crnSemiSrRect.w = DST_DIMOBJ_SR_RGN_W;
|
|
|
m_DST_stInput.crnSemiSrRect.h = DST_DIMOBJ_SR_RGN_H;
|
|
|
m_DST_stInput.crnSemiSrRect.s = m_DST_stInput.crnSemiSrRect.w * m_DST_stInput.crnSemiSrRect.h;
|
|
|
m_DST_stInput.mmnSemiSrRect.minX = m_DST_stInput.crnSemiSrRect.cx - (m_DST_stInput.crnSemiSrRect.w >> 1);
|
|
|
m_DST_stInput.mmnSemiSrRect.minY = m_DST_stInput.crnSemiSrRect.cy - (m_DST_stInput.crnSemiSrRect.h >> 1);
|
|
|
m_DST_stInput.mmnSemiSrRect.maxX = m_DST_stInput.crnSemiSrRect.cx + (m_DST_stInput.crnSemiSrRect.w >> 1);
|
|
|
m_DST_stInput.mmnSemiSrRect.maxY = m_DST_stInput.crnSemiSrRect.cy + (m_DST_stInput.crnSemiSrRect.h >> 1);
|
|
|
|
|
|
//分块大小
|
|
|
m_DST_stInput.nBlkHeight = 16;
|
|
|
m_DST_stInput.nBlkWidth = 16;
|
|
|
|
|
|
//搜索区域内分块个数
|
|
|
m_DST_stInput.nBlkNumH = m_DST_stInput.crCenterRect.w / m_DST_stInput.nBlkWidth;
|
|
|
m_DST_stInput.nBlkNumW = m_DST_stInput.crCenterRect.h / m_DST_stInput.nBlkHeight;
|
|
|
m_DST_stInput.nBlkNum = m_DST_stInput.nBlkNumH * m_DST_stInput.nBlkNumW;
|
|
|
|
|
|
//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
|
|
|
//初始化算法参数
|
|
|
//算法状态控制(上位机软件界面可调)
|
|
|
//小目标检测参数(上位机软件界面可调)
|
|
|
m_DST_stPara.nObjCombineDist = 9;
|
|
|
m_DST_stPara.fgdk = DST_OBJ_SNR_MIN;
|
|
|
m_DST_stPara.fKernalBGStdMin = DST_Bm_STD_LIMIT_MIN;
|
|
|
m_DST_stPara.fKernalBGStdMax = DST_Bm_STD_LIMIT_MAX;
|
|
|
m_DST_stPara.nObjSizeMin = DST_OBJ_SIZE_MIN;
|
|
|
m_DST_stPara.nObjSizeMax = DST_KERNAL_SIZE_TG * DST_KERNAL_SIZE_TG;
|
|
|
m_DST_stPara.nObjWHRatioMethod = DST_OBJ_WHRATIO_LINEWH;
|
|
|
m_DST_stPara.fObjWHRatioMin = 0.2f;
|
|
|
m_DST_stPara.fObjWHRatioMax = 5.0f;
|
|
|
m_DST_stPara.fObjRectRatioMin = 0.2f;
|
|
|
m_DST_stPara.nBGObjNumThres = 2;
|
|
|
m_DST_stPara.nBTGrayMinThres = 10;
|
|
|
|
|
|
m_DST_stPara.bDimDetecting = false;
|
|
|
m_DST_stPara.bEnableDimDetect = false;
|
|
|
m_DST_stPara.bEnableSecDetect = false;
|
|
|
|
|
|
m_DST_stPara.bSecDetecting = FALSE;
|
|
|
|
|
|
//小目标检测去虚警开关(上位机软件界面可调)
|
|
|
m_DST_stPara.bUseDeFA_VarMin = 1;
|
|
|
m_DST_stPara.bUseDeFA_VarMax = 0;
|
|
|
m_DST_stPara.bUseDeFA_Size = 1;
|
|
|
m_DST_stPara.bUseDeFA_WHRatio = 0;//
|
|
|
m_DST_stPara.bUseDeFA_RectRatio = 0;
|
|
|
m_DST_stPara.bUseDeFA_BGFACnt = 0;
|
|
|
m_DST_stPara.bUseDeFA_BTGrayMin = 1;
|
|
|
m_DST_stPara.bUseDeFA_CenFlag = 0;
|
|
|
m_DST_stPara.bUseDeFA_XYPrj = 0;
|
|
|
|
|
|
//目标检测类型
|
|
|
m_DST_stPara.nDetectGrayType = GLB_OBJ_GRAY_BRIGHT;
|
|
|
|
|
|
// 模板参数
|
|
|
m_DST_stPara.pnFilter = g_DST_nFilter_9_13;
|
|
|
m_DST_stPara.nFilterBGW = DST_KERNAL_SIZE_Bm_13;
|
|
|
m_DST_stPara.nFilterTGW = DST_KERNAL_SIZE_Tm_9;
|
|
|
|
|
|
|
|
|
// 申请内存
|
|
|
DST_MallocMemory(nWidth, nHeight, mmCenterRect);
|
|
|
|
|
|
// 初始化算法输出结果
|
|
|
DST_CleanUpFrameDetectOutput();
|
|
|
|
|
|
// 初始化弱小目标检测结果
|
|
|
DST_CleanUpFrameDimDetectOutput();
|
|
|
|
|
|
m_DST_bInitialize = true;
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/**********************************************************
|
|
|
* 函数名称:DST_CleanUpFrameDetectOutput()
|
|
|
* 功能描述:初始化单帧检测算法输出结果
|
|
|
* 输入参数:无
|
|
|
* 输出参数:无
|
|
|
* 返 回 值:无
|
|
|
* 调用关系:无
|
|
|
* 其它说明:无
|
|
|
**********************************************************/
|
|
|
void DetectSmallObj::DST_CleanUpFrameDetectOutput(void)
|
|
|
{
|
|
|
//小目标检测结果
|
|
|
m_DST_stOutput.nFrmObjsCnt = 0;
|
|
|
m_DST_stOutput.nDimFrmsCnt = 0;
|
|
|
|
|
|
//初始化数据空间
|
|
|
POINT16S* pBlkMaxPnt = (POINT16S*)DST_pBlkMaxPoint;
|
|
|
TARGET_OBJECT* ptTargetArray = (TARGET_OBJECT*)DST_Target;
|
|
|
SINT32* pBlkPtBeTargetFlag = (SINT32*)DST_pBlkPtBeTargetFlag;
|
|
|
BYTE8* pBlkMaxPntFlag = (BYTE8*)DST_pBlkMaxPntFlag;
|
|
|
|
|
|
memset(pBlkMaxPnt, 0, m_DST_stInput.nBlkNum * sizeof(POINT16S) * 2);
|
|
|
memset(ptTargetArray, 0, DST_MAX_NUM * sizeof(TARGET_OBJECT));
|
|
|
memset(pBlkPtBeTargetFlag, 0, m_DST_stInput.nBlkNum * sizeof(SINT32) * 2);
|
|
|
memset(pBlkMaxPntFlag, 0, m_DST_stInput.nBlkNum * sizeof(BYTE8) * 2);
|
|
|
|
|
|
}
|
|
|
/**********************************************************
|
|
|
* 函数名称:DST_CleanUpFrameDimDetectOutput()
|
|
|
* 功能描述:初始化单帧弱小目标检测算法输出结果
|
|
|
* 输入参数:无
|
|
|
* 输出参数:无
|
|
|
* 返 回 值:无
|
|
|
* 调用关系:无
|
|
|
* 其它说明:无
|
|
|
**********************************************************/
|
|
|
void DetectSmallObj::DST_CleanUpFrameDimDetectOutput(void)
|
|
|
{
|
|
|
//弱小目标强制搜索
|
|
|
if (m_DST_stOutput.nDimFrmsCnt <= 0)
|
|
|
{
|
|
|
m_DST_stOutput.pxSrImg = (UINT16*)DST_pxDimSrImg;
|
|
|
memset(m_DST_stOutput.pxSrImg, 0, DST_DIMOBJ_SR_RGN_S * sizeof(UINT16));
|
|
|
}
|
|
|
m_DST_stOutput.snDimSrImgSize.w = m_DST_stInput.crnSemiSrRect.w;
|
|
|
m_DST_stOutput.snDimSrImgSize.h = m_DST_stInput.crnSemiSrRect.h;
|
|
|
m_DST_stOutput.snDimSrImgSize.s = m_DST_stOutput.snDimSrImgSize.w * m_DST_stOutput.snDimSrImgSize.h;
|
|
|
m_DST_stOutput.nDimPriorObjId = -1;
|
|
|
m_DST_stOutput.nFrmDimObjsCnt = 0;
|
|
|
m_DST_stOutput.nDimSmpScale = 1;
|
|
|
|
|
|
//清空弱小目标数组
|
|
|
TARGET_OBJECT* ptDimTarget = (TARGET_OBJECT*)DST_DimTarget;
|
|
|
memset(ptDimTarget, 0, DST_DIMOBJ_BLK_NUM * sizeof(TARGET_OBJECT));
|
|
|
|
|
|
//清空弱小目标检测极值点
|
|
|
POINT16S* pDimBlkMaxPnt = (POINT16S*)DST_pDimBlkMaxPoint;
|
|
|
memset(pDimBlkMaxPnt, 0, DST_DIMOBJ_BLK_NUM * sizeof(POINT16S));
|
|
|
|
|
|
//搜索区域双边滤波
|
|
|
SINT16* pDimBFHighImg = (SINT16*)DST_pDimBFHighImg;
|
|
|
UINT16* pDimBFLowImg = (UINT16*)DST_pDimBFLowImg;
|
|
|
memset(pDimBFHighImg, 0, DST_DIMOBJ_SR_RGN_S * sizeof(SINT16));
|
|
|
memset(pDimBFLowImg, 0, DST_DIMOBJ_SR_RGN_S * sizeof(UINT16));
|
|
|
}
|
|
|
|
|
|
/**********************************************************
|
|
|
* 函数名称:DST_FindBlkExtremum()
|
|
|
* 功能描述:查找块内极值点
|
|
|
* 输入参数:UINT16 *pFrame -- 原始图像
|
|
|
* SINT32 nWidth -- 图像宽度
|
|
|
* SINT32 nHeight -- 图像高度
|
|
|
* SINT32 pBlkStart -- 该分块在原始图像上的起始坐标
|
|
|
* SINT32 nBlkWidth -- 分块宽度
|
|
|
* SINT32 nBlkHeight -- 分块高度
|
|
|
* 输出参数:无
|
|
|
* 返 回 值:POINT16S pPnt -- 块内极值点坐标
|
|
|
* 调用关系:无
|
|
|
* 其它说明:MSSu, 20111115: 函数修改,增加查找块内极小值的功能,
|
|
|
* 对于每个块的极大值和极小值,选两者中与块均值偏差较大的作为返回点。
|
|
|
**********************************************************/
|
|
|
POINT16S DetectSmallObj::DST_FindBlkExtremum(GD_VIDEO_FRAME_S img, SINT32 nWidth, SINT32 nHeight,
|
|
|
SINT32 pBlkStart, SINT32 nBlkWidth, SINT32 nBlkHeight, BYTE8* pbMaxFlag,POINT16S * pSecondMax)
|
|
|
{
|
|
|
SINT32 i, j;
|
|
|
SINT32 nLen = nBlkWidth * nBlkHeight;
|
|
|
UINT16 pGray = 0;
|
|
|
|
|
|
UINT16 pMax = 0;
|
|
|
UINT16 pMax2 = 0;//次极大值
|
|
|
|
|
|
UINT16 pMin = 65535;
|
|
|
UINT16 pMin2 = 65535;//次极小值
|
|
|
|
|
|
|
|
|
SINT32 pMean = 0;
|
|
|
POINT16S pPntMax = { 0 };
|
|
|
POINT16S pPntMax2 = {0};//次极大值点坐标
|
|
|
POINT16S pPntMin = { 0 };
|
|
|
POINT16S pPnt = { 0 };
|
|
|
SINT32 nMaxIndex = 0;
|
|
|
SINT32 nMinIndex = 0;
|
|
|
SINT32 nMaxIndex2 = 0;
|
|
|
SINT32 nMinIndex2 = 0;
|
|
|
|
|
|
SINT32 nIndex = 0;
|
|
|
FLOAT32 fPntMaxBkgMean = 0.0; //20170405,极大值点9*13模板邻域均值
|
|
|
FLOAT32 fPntMinBkgMean = 0.0; //20170405,极小值点9*13模板邻域均值
|
|
|
SINT32 nMaxI = 0;
|
|
|
SINT32 nMaxJ = 0;
|
|
|
|
|
|
UINT16 pDiffThres = m_DST_stPara.nBTGrayMinThres;
|
|
|
|
|
|
//查找块内极值点
|
|
|
for (i = 0; i < nBlkHeight; i++)
|
|
|
{
|
|
|
for (j = 0; j < nBlkWidth; j++)
|
|
|
{
|
|
|
//获取块内每个像素点灰度
|
|
|
nIndex = pBlkStart + j;
|
|
|
if (GD_PIXEL_FORMAT_GRAY_Y8 == img.enPixelFormat)
|
|
|
{
|
|
|
pGray = ((UBYTE8*)img.u64VirAddr[0])[nIndex];
|
|
|
}
|
|
|
else
|
|
|
{
|
|
|
pGray = ((UINT16*)img.u64VirAddr[0])[nIndex];
|
|
|
}
|
|
|
|
|
|
int x = nIndex % nWidth;
|
|
|
int y = nIndex / nWidth;
|
|
|
|
|
|
|
|
|
//if(x == 275 && y == 327)
|
|
|
//{
|
|
|
// int a = 0;
|
|
|
//}
|
|
|
|
|
|
//查找极大值
|
|
|
if (pGray >= pMax)
|
|
|
{
|
|
|
pMax = pGray;
|
|
|
nMaxIndex = nIndex;
|
|
|
nMaxI = i;
|
|
|
nMaxJ = j;
|
|
|
}
|
|
|
//查找极小值
|
|
|
if (pGray <= pMin)
|
|
|
{
|
|
|
pMin = pGray;
|
|
|
nMinIndex = nIndex;
|
|
|
}
|
|
|
|
|
|
//统计块内灰度和
|
|
|
pMean += pGray;
|
|
|
}
|
|
|
//更新下一行的起始坐标
|
|
|
pBlkStart += nWidth;
|
|
|
}
|
|
|
|
|
|
|
|
|
pBlkStart -= nBlkHeight * nWidth;
|
|
|
//查找块内次极值点(除去极大值周边)
|
|
|
for (i = 0; i < nBlkHeight; i++)
|
|
|
{
|
|
|
for (j = 0; j < nBlkWidth; j++)
|
|
|
{
|
|
|
//获取块内每个像素点灰度
|
|
|
nIndex = pBlkStart + j;
|
|
|
if (GD_PIXEL_FORMAT_GRAY_Y8 == img.enPixelFormat)
|
|
|
{
|
|
|
pGray = ((UBYTE8*)img.u64VirAddr[0])[nIndex];
|
|
|
}
|
|
|
else
|
|
|
{
|
|
|
pGray = ((UINT16*)img.u64VirAddr[0])[nIndex];
|
|
|
}
|
|
|
|
|
|
int x = nIndex % nWidth;
|
|
|
int y = nIndex / nWidth;
|
|
|
|
|
|
|
|
|
//if(x == 275 && y == 327)
|
|
|
//{
|
|
|
// int a = 0;
|
|
|
//}
|
|
|
|
|
|
|
|
|
////跳过极大值区域
|
|
|
// if (nIndex > (nMaxIndex - nWidth * g_DST_stPara.nObjCombineDist - nWidth / 2) &&
|
|
|
// nIndex < (nMaxIndex + nWidth * g_DST_stPara.nObjCombineDist + nWidth / 2))
|
|
|
|
|
|
//跳过极大值区域
|
|
|
//if (nIndex >= (nMaxIndex - nWidth * g_DST_stPara.nObjCombineDist - g_DST_stPara.nObjCombineDist / 2) &&
|
|
|
// nIndex <= (nMaxIndex + nWidth * g_DST_stPara.nObjCombineDist + g_DST_stPara.nObjCombineDist / 2))
|
|
|
//
|
|
|
//跳过极大值区域,寻找次极大值
|
|
|
if( (i - nMaxI ) * (i - nMaxI ) + (j - nMaxJ) * (j - nMaxJ ) <m_DST_stPara.nObjCombineDist * m_DST_stPara.nObjCombineDist )
|
|
|
{
|
|
|
continue;
|
|
|
}
|
|
|
|
|
|
|
|
|
//查找次极大值
|
|
|
if (pGray > pMax2)
|
|
|
{
|
|
|
pMax2 = pGray;
|
|
|
nMaxIndex2 = nIndex;
|
|
|
}
|
|
|
|
|
|
}
|
|
|
//更新下一行的其实坐标
|
|
|
pBlkStart += nWidth;
|
|
|
}
|
|
|
|
|
|
|
|
|
//计算块内灰度均值,抛掉极大值
|
|
|
if (nLen <= 1)
|
|
|
{
|
|
|
pMean = pMean;
|
|
|
}
|
|
|
else if (nLen == 2)
|
|
|
{
|
|
|
pMean /= 2;
|
|
|
}
|
|
|
else
|
|
|
{
|
|
|
//pMean -= pMax;
|
|
|
//pMean /= (nLen - 1);
|
|
|
pMean -= (pMax + pMin);
|
|
|
pMean /= (nLen - 2);
|
|
|
}
|
|
|
|
|
|
//抛掉与块均值灰度差异较小的点
|
|
|
//if (ABS(pMax - pMean) < pDiffThres)
|
|
|
//{
|
|
|
// pPnt.x = DST_BLK_MAX_PNT_DELETE_FLAG;
|
|
|
// pPnt.y = DST_BLK_MAX_PNT_DELETE_FLAG;
|
|
|
//}
|
|
|
//else
|
|
|
|
|
|
//MSSu, 20160122: 抛掉平坦块
|
|
|
if ((pMax - pMin) < 2)
|
|
|
{
|
|
|
pPnt.x = DST_BLK_MAX_PNT_DELETE_FLAG;
|
|
|
pPnt.y = DST_BLK_MAX_PNT_DELETE_FLAG;
|
|
|
return pPnt;
|
|
|
}
|
|
|
|
|
|
// 极值点坐标
|
|
|
pPntMax.x = nMaxIndex % nWidth;
|
|
|
pPntMax.y = nMaxIndex / nWidth;
|
|
|
pPntMin.x = nMinIndex % nWidth;
|
|
|
pPntMin.y = nMinIndex / nWidth;
|
|
|
|
|
|
// 次极值点坐标
|
|
|
pPntMax2.x = nMaxIndex2 % nWidth;
|
|
|
pPntMax2.y = nMaxIndex2 / nWidth;
|
|
|
|
|
|
if (GLB_OBJ_GRAY_DARK == m_DST_stPara.nDetectGrayType)
|
|
|
{
|
|
|
pPnt = pPntMin;
|
|
|
*pbMaxFlag = DST_BLK_MIN_PNT;
|
|
|
}
|
|
|
else if (GLB_OBJ_GRAY_BRIGHT == m_DST_stPara.nDetectGrayType)
|
|
|
{
|
|
|
pPnt = pPntMax;
|
|
|
*pbMaxFlag = DST_BLK_MAX_PNT;
|
|
|
if(pPntMax.x == pPntMax2.x && pPntMax.y == pPntMax2.y)
|
|
|
{
|
|
|
pSecondMax->x = -1;
|
|
|
pSecondMax->y = -1;
|
|
|
}
|
|
|
else
|
|
|
{
|
|
|
*pSecondMax = pPntMax2;
|
|
|
}
|
|
|
}
|
|
|
else if (GLB_OBJ_GRAY_ALL == m_DST_stPara.nDetectGrayType)
|
|
|
{
|
|
|
|
|
|
//20170405,分别计算极大值点与极小值点的邻域均值//原先做法是直接与分块均值比较
|
|
|
fPntMaxBkgMean = DST_CalObjBkgMean_UINT16(img, nWidth, nHeight, pPntMax);
|
|
|
fPntMinBkgMean = DST_CalObjBkgMean_UINT16(img, nWidth, nHeight, pPntMin);
|
|
|
|
|
|
//20170405,若邻域范围超出图像边界即均值为负,则直接取分块均值
|
|
|
if (fPntMaxBkgMean < 0 || fPntMinBkgMean < 0)
|
|
|
{
|
|
|
fPntMaxBkgMean = (FLOAT32)pMean;
|
|
|
fPntMinBkgMean = (FLOAT32)pMean;
|
|
|
}
|
|
|
|
|
|
//20170810,wsa,抛掉与块均值灰度差异较小的点
|
|
|
if (ABS(pMax - (UINT16)fPntMaxBkgMean) < pDiffThres && ABS(pMin - (UINT16)fPntMinBkgMean) < pDiffThres)
|
|
|
{
|
|
|
pPnt.x = DST_BLK_MAX_PNT_DELETE_FLAG;
|
|
|
pPnt.y = DST_BLK_MAX_PNT_DELETE_FLAG;
|
|
|
return pPnt;
|
|
|
}
|
|
|
|
|
|
if (ABS(pMax - (UINT16)fPntMaxBkgMean) >= ABS(pMin - (UINT16)fPntMinBkgMean))
|
|
|
{
|
|
|
pPnt = pPntMax;
|
|
|
*pbMaxFlag = DST_BLK_MAX_PNT;
|
|
|
}
|
|
|
else
|
|
|
{
|
|
|
pPnt = pPntMin;
|
|
|
*pbMaxFlag = DST_BLK_MIN_PNT;
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
return pPnt;
|
|
|
}
|
|
|
|
|
|
|
|
|
void DetectSmallObj::DST_MallocMemory(SINT32 nWidth, SINT32 nHeight, CENTERRECT mmCenterRect)
|
|
|
{
|
|
|
DST_ReleaseMemory();
|
|
|
|
|
|
SINT32 DST_BLK_NUM = m_DST_stInput.nBlkNum;
|
|
|
|
|
|
DST_pBlkMaxPoint = new POINT16S[DST_BLK_NUM * 2];//同时处理次极值点
|
|
|
|
|
|
DST_pBlkPtBeTargetFlag = new SINT32[DST_BLK_NUM * 2];
|
|
|
|
|
|
DST_pBlkMaxPntFlag = new BYTE8[DST_BLK_NUM * 2];
|
|
|
|
|
|
}
|
|
|
|
|
|
void DetectSmallObj::DST_ReleaseMemory()
|
|
|
{
|
|
|
if (DST_pBlkMaxPoint)
|
|
|
{
|
|
|
delete[] DST_pBlkMaxPoint;
|
|
|
DST_pBlkMaxPoint = NULL;
|
|
|
}
|
|
|
|
|
|
if (DST_pBlkPtBeTargetFlag)
|
|
|
{
|
|
|
delete[] DST_pBlkPtBeTargetFlag;
|
|
|
DST_pBlkPtBeTargetFlag = NULL;
|
|
|
}
|
|
|
|
|
|
if (DST_pBlkMaxPntFlag)
|
|
|
{
|
|
|
delete[] DST_pBlkMaxPntFlag;
|
|
|
DST_pBlkMaxPntFlag = NULL;
|
|
|
}
|
|
|
}
|
|
|
|
|
|
/**********************************************************
|
|
|
* 函数名称:DST_FindExtremum()
|
|
|
* 功能描述:查找图像中的极值点
|
|
|
* 输入参数:UINT16 *pFrame -- 原始图像
|
|
|
* SINT32 nWidth -- 图像宽度
|
|
|
* SINT32 nHeight -- 图像高度
|
|
|
* SINT32 nSearchAreaT -- 检测区域左上角Y坐标
|
|
|
* SINT32 nSearchAreaL -- 检测区域左上角X坐标
|
|
|
* SINT32 nBlkWidth -- 分块宽度
|
|
|
* SINT32 nBlkHeight -- 分块高度
|
|
|
* SINT32 nBlkNumW -- 行方向分块个数
|
|
|
* SINT32 nBlkNumH -- 列方向分块个数
|
|
|
* 输出参数:POINT16S *pBlkMaxPnt-- 指向分块极值点坐标存储空间地址,BYTE8 *pbBlkMaxPntFlag --极值点类型标记数组
|
|
|
* 返 回 值:无
|
|
|
* 调用关系:DST_FindBlkExtremum(), DST_MergeBlkMaxPoint()
|
|
|
* 其它说明:无
|
|
|
**********************************************************/
|
|
|
void DetectSmallObj::DST_FindExtremum(GD_VIDEO_FRAME_S img, SINT32 nWidth, SINT32 nHeight,
|
|
|
POINT16S* pBlkMaxPnt, BYTE8* pbBlkMaxPntFlag, SINT32 nSearchAreaT, SINT32 nSearchAreaL,
|
|
|
SINT32 nBlkWidth, SINT32 nBlkHeight,
|
|
|
SINT32 nBlkNumW, SINT32 nBlkNumH)
|
|
|
{
|
|
|
SINT32 i, j;
|
|
|
SINT32 pCenterStart, pBlkStart;
|
|
|
SINT32 nRowBlkLine;
|
|
|
SINT32 nRowBlkHSkip;
|
|
|
SINT32 nLine, nIndex;
|
|
|
SINT32 nBlkCnt;
|
|
|
BYTE8 bMaxPntFalg = DST_BLK_MAX_PNT; //20161130,标记极大/极小
|
|
|
POINT16S pBlkSecondMaxPnt = {0};//次极大值
|
|
|
//+++++++++++++++++++++++++++++++++++++++++++++++++++++++
|
|
|
pCenterStart = nSearchAreaT * nWidth + nSearchAreaL;
|
|
|
nRowBlkLine = pCenterStart;
|
|
|
nRowBlkHSkip = nBlkHeight * nWidth;
|
|
|
pBlkStart = nRowBlkLine;
|
|
|
nLine = 0;
|
|
|
nIndex = 0;
|
|
|
nBlkCnt = 0;
|
|
|
|
|
|
for (i = 0; i < nBlkNumH; i++) //DSP移植优化:主频432Mhz 2.4ms
|
|
|
{
|
|
|
for (j = 0; j < nBlkNumW; j++)
|
|
|
{
|
|
|
//计算当前块的坐标
|
|
|
nIndex = 2 * (nLine + j);
|
|
|
|
|
|
//查找块内灰度极大值
|
|
|
pBlkMaxPnt[nIndex] = DST_FindBlkExtremum(img, nWidth, nHeight,
|
|
|
pBlkStart, nBlkWidth, nBlkHeight, &bMaxPntFalg, &pBlkSecondMaxPnt);
|
|
|
|
|
|
// 次极值点
|
|
|
pBlkMaxPnt[nIndex + 1] = pBlkSecondMaxPnt;
|
|
|
|
|
|
//20161130,标记极大/极小
|
|
|
pbBlkMaxPntFlag[nIndex] = bMaxPntFalg;
|
|
|
|
|
|
//更新下一个块的起始坐标
|
|
|
pBlkStart += nBlkWidth;
|
|
|
|
|
|
//防止出错
|
|
|
nBlkCnt++;
|
|
|
if (nBlkCnt >= m_DST_stInput.nBlkNum)
|
|
|
{
|
|
|
break;
|
|
|
}
|
|
|
}
|
|
|
|
|
|
//更新下一行块的行起始坐标
|
|
|
nRowBlkLine += nRowBlkHSkip;
|
|
|
pBlkStart = nRowBlkLine;
|
|
|
|
|
|
//更新下一行块的起始坐标
|
|
|
nLine += nBlkNumW;
|
|
|
|
|
|
//防止出错
|
|
|
if (nBlkCnt >= m_DST_stInput.nBlkNum)
|
|
|
{
|
|
|
break;
|
|
|
}
|
|
|
}
|
|
|
|
|
|
//+++++++++++++++++++++++++++++++++++++++++++++++++
|
|
|
//合并临近的极值点
|
|
|
//MSSu, 20111115: 若m_DST_nDectectMinPnt==TRUE,则为合并临近的极大或极小值
|
|
|
DST_MergeBlkMaxPoint(img, nWidth, nHeight, pBlkMaxPnt, nBlkNumH, nBlkNumW,
|
|
|
m_DST_stPara.nObjCombineDist, pbBlkMaxPntFlag);
|
|
|
}
|
|
|
|
|
|
/**********************************************************
|
|
|
* 函数名称:DST_FindExtremum()
|
|
|
* 功能描述:螺旋查找图像中的极值点
|
|
|
* 输入参数:UINT16 *pFrame -- 原始图像
|
|
|
* SINT32 nWidth -- 图像宽度
|
|
|
* SINT32 nHeight -- 图像高度
|
|
|
* SINT32 nSearchAreaT -- 检测区域左上角Y坐标
|
|
|
* SINT32 nSearchAreaL -- 检测区域左上角X坐标
|
|
|
* SINT32 nBlkWidth -- 分块宽度
|
|
|
* SINT32 nBlkHeight -- 分块高度
|
|
|
* SINT32 nBlkNumW -- 行方向分块个数
|
|
|
* SINT32 nBlkNumH -- 列方向分块个数
|
|
|
* 输出参数:POINT16S *pBlkMaxPnt-- 指向分块极值点坐标存储空间地址,BYTE8 *pbBlkMaxPntFlag --极值点类型标记数组
|
|
|
* 返 回 值:无
|
|
|
* 调用关系:DST_FindBlkExtremum(), DST_MergeBlkMaxPoint()
|
|
|
* 其它说明:无
|
|
|
**********************************************************/
|
|
|
void DetectSmallObj::DST_FindExtremumSpiral(GD_VIDEO_FRAME_S img, SINT32 nWidth, SINT32 nHeight,
|
|
|
POINT16S* pBlkMaxPnt, BYTE8* pbBlkMaxPntFlag, SINT32 nSearchAreaT, SINT32 nSearchAreaL,
|
|
|
SINT32 nBlkWidth, SINT32 nBlkHeight,
|
|
|
SINT32 nBlkNumW, SINT32 nBlkNumH)
|
|
|
{
|
|
|
SINT32 i, j;
|
|
|
SINT32 pCenterStart, pBlkStart;
|
|
|
SINT32 nRowBlkLine;
|
|
|
SINT32 nRowBlkHSkip;
|
|
|
SINT32 nLine, nIndex;
|
|
|
SINT32 nBlkCnt;
|
|
|
BYTE8 bMaxPntFalg = DST_BLK_MAX_PNT; //20161130,标记极大/极小
|
|
|
POINT16S pBlkSecondMaxPnt = { 0 };//次极大值
|
|
|
//+++++++++++++++++++++++++++++++++++++++++++++++++++++++
|
|
|
nRowBlkLine = nSearchAreaT * nWidth + nSearchAreaL;
|
|
|
nRowBlkHSkip = nBlkHeight * nWidth;
|
|
|
pBlkStart = nRowBlkLine;
|
|
|
nLine = 0;
|
|
|
nIndex = 0;
|
|
|
nBlkCnt = 0;
|
|
|
|
|
|
|
|
|
SINT32 r0 = nBlkNumH / 2;
|
|
|
SINT32 c0 = nBlkNumW / 2;
|
|
|
SINT32 R = nBlkNumH;
|
|
|
SINT32 C = nBlkNumW;
|
|
|
std::vector<std::pair<SINT32, SINT32>> around = { { 0, 1 },{ 1, 0 },{ 0, -1 },{ -1, 0 } }; //顺时针方向
|
|
|
SINT32 x = r0, y = c0, num = 1, dir = 0; //{x, y}为当前位置,num为当前查找的数字,dir为当前的方向
|
|
|
SINT32 Left = c0 - 1, Right = c0 + 1, Upper = r0 - 1, Bottom = r0 + 1; //四个方向的边界
|
|
|
while (num <= R * C)
|
|
|
{
|
|
|
if (x >= 0 && x < R && y >= 0 && y < C)
|
|
|
{ //{x, y}位置在矩阵中
|
|
|
//printf("x=%d, y=%d\n", x, y);
|
|
|
//计算当前块的坐标
|
|
|
nIndex = 2 * nBlkCnt;
|
|
|
|
|
|
//查找块内灰度极大值
|
|
|
POINT16S point = DST_FindBlkExtremum(img, nWidth, nHeight,
|
|
|
pBlkStart, nBlkWidth, nBlkHeight, &bMaxPntFalg, &pBlkSecondMaxPnt);
|
|
|
|
|
|
//if (point.x > 0 && point.y > 0)
|
|
|
{
|
|
|
pBlkMaxPnt[nIndex] = point;
|
|
|
// 次极值点
|
|
|
pBlkMaxPnt[nIndex + 1] = pBlkSecondMaxPnt;
|
|
|
|
|
|
//20161130,标记极大/极小
|
|
|
pbBlkMaxPntFlag[nIndex] = bMaxPntFalg;
|
|
|
|
|
|
//更新下一个块的起始坐标
|
|
|
pBlkStart = nBlkWidth * y + x * nRowBlkHSkip;
|
|
|
|
|
|
//防止出错
|
|
|
nBlkCnt++;
|
|
|
if (nBlkCnt >= m_DST_stInput.nBlkNum)
|
|
|
{
|
|
|
break;
|
|
|
}
|
|
|
}
|
|
|
num += 1;
|
|
|
}
|
|
|
if (dir == 0 && y == Right)
|
|
|
{ //向右到右边界
|
|
|
dir += 1; //调转方向向下
|
|
|
Right += 1; //右边界右移
|
|
|
}
|
|
|
else if (dir == 1 && x == Bottom)
|
|
|
{ //向下到底边界
|
|
|
dir += 1;
|
|
|
Bottom += 1; //底边界下移
|
|
|
}
|
|
|
else if (dir == 2 && y == Left)
|
|
|
{ //向左到左边界
|
|
|
dir += 1;
|
|
|
Left--; //左边界左移
|
|
|
}
|
|
|
else if (dir == 3 && x == Upper)
|
|
|
{ //向上到上边界
|
|
|
dir = 0;
|
|
|
Upper--; //上边界上移
|
|
|
}
|
|
|
x += around[dir].first; //下一个节点
|
|
|
y += around[dir].second;
|
|
|
}
|
|
|
|
|
|
//for (i = 0; i < nBlkNumH; i++) //DSP移植优化:主频432Mhz 2.4ms
|
|
|
//{
|
|
|
// for (j = 0; j < nBlkNumW; j++)
|
|
|
// {
|
|
|
// //计算当前块的坐标
|
|
|
// nIndex = 2 * (nBlkNumW * i + j);
|
|
|
|
|
|
// //查找块内灰度极大值
|
|
|
// pBlkMaxPnt[nIndex] = DST_FindBlkExtremum(img, nWidth, nHeight,
|
|
|
// pBlkStart, nBlkWidth, nBlkHeight, &bMaxPntFalg, &pBlkSecondMaxPnt);
|
|
|
|
|
|
// // 次极值点
|
|
|
// pBlkMaxPnt[nIndex + 1] = pBlkSecondMaxPnt;
|
|
|
|
|
|
// //20161130,标记极大/极小
|
|
|
// pbBlkMaxPntFlag[nIndex] = bMaxPntFalg;
|
|
|
|
|
|
// //更新下一个块的起始坐标
|
|
|
// pBlkStart = nBlkWidth * j + i * nRowBlkHSkip;
|
|
|
|
|
|
// //防止出错
|
|
|
// nBlkCnt++;
|
|
|
// if (nBlkCnt >= m_DST_stInput.nBlkNum)
|
|
|
// {
|
|
|
// break;
|
|
|
// }
|
|
|
// }
|
|
|
|
|
|
// ////更新下一行块的起始坐标
|
|
|
// //nLine += nBlkNumW;
|
|
|
|
|
|
// ////防止出错
|
|
|
// //if (nBlkCnt >= m_DST_stInput.nBlkNum)
|
|
|
// //{
|
|
|
// // break;
|
|
|
// //}
|
|
|
//}
|
|
|
|
|
|
|
|
|
|
|
|
//+++++++++++++++++++++++++++++++++++++++++++++++++
|
|
|
//合并临近的极值点
|
|
|
//MSSu, 20111115: 若m_DST_nDectectMinPnt==TRUE,则为合并临近的极大或极小值
|
|
|
DST_MergeBlkMaxPoint(img, nWidth, nHeight, pBlkMaxPnt, nBlkNumH, nBlkNumW,
|
|
|
m_DST_stPara.nObjCombineDist, pbBlkMaxPntFlag);
|
|
|
}
|
|
|
|
|
|
|
|
|
/**********************************************************
|
|
|
* 函数名称:DST_MergeBlkMaxPoint()
|
|
|
* 功能描述:合并临近的极值点
|
|
|
* 输入参数:UINT16 *pFrame -- 输入图像
|
|
|
* SINT32 nWidth -- 图像宽度
|
|
|
* SINT32 nHeight -- 图像高度
|
|
|
* POINT16S *pBlkPnt -- 分块极大值点坐标数组
|
|
|
* SINT32 nPntNumH -- 在列方向上的分块数
|
|
|
* SINT32 nPntNumW -- 在行方向上的分块数
|
|
|
* SINT32 nDist -- 相邻极值点合并的阈值
|
|
|
* 输出参数:无
|
|
|
* 返 回 值:无
|
|
|
* 调用关系:无
|
|
|
* 其它说明:MSSu, 20150608: 增加亮目标、暗目标、亮+暗目标3种情况处理。
|
|
|
**********************************************************/
|
|
|
void DetectSmallObj::DST_MergeBlkMaxPoint(GD_VIDEO_FRAME_S img, SINT32 nWidth, SINT32 nHeight,
|
|
|
POINT16S* pBlkPnt, SINT32 nPntNumH, SINT32 nPntNumW,
|
|
|
SINT32 nDist, BYTE8* pbBlkMaxPntFlag)
|
|
|
{
|
|
|
static SINT32 nX[8] = { -1, 0, 1, -1, 1, -1, 0, 1 };
|
|
|
static SINT32 nY[8] = { -1, -1, -1, 0, 0, 1, 1, 1 };
|
|
|
|
|
|
SINT32 i, k;
|
|
|
POINT16S* pPntA, * pPntB;
|
|
|
UINT16 pPntAValue, pPntBValue;
|
|
|
SINT32 nDistAB;
|
|
|
SINT32 nDistThres;
|
|
|
SINT32 nNearIndex;
|
|
|
SINT32 nPntNum;
|
|
|
SINT32 nMeanAB, nCntAB;
|
|
|
|
|
|
//参数计算
|
|
|
nDistThres = nDist * nDist;
|
|
|
nPntNum = nPntNumH * nPntNumW * 2;
|
|
|
nMeanAB = 0;
|
|
|
nCntAB = 0;
|
|
|
|
|
|
for (i = 0; i < nPntNum; i++)
|
|
|
{
|
|
|
//获取当前极值点A的坐标
|
|
|
pPntA = &pBlkPnt[i];
|
|
|
|
|
|
//若当前极值点A已被删除,则跳过该点,不进行后续处理
|
|
|
if (DST_BLK_MAX_PNT_DELETE_FLAG == pPntA->x
|
|
|
&& DST_BLK_MAX_PNT_DELETE_FLAG == pPntA->y)
|
|
|
{
|
|
|
continue;
|
|
|
}
|
|
|
|
|
|
//遍历周围8个极值点
|
|
|
for (k = 0; k < 8; k++)
|
|
|
{
|
|
|
for (int s = 0; s < 2; s++)
|
|
|
{
|
|
|
//计算临近点B下标
|
|
|
nNearIndex = i + 2 *(nY[k] * nPntNumW + nX[k]) + s;
|
|
|
|
|
|
//防止临近点越界
|
|
|
if ((nNearIndex < 0) || (nNearIndex >= nPntNum)
|
|
|
|| (nNearIndex == i)) //MSSu, 20160409: 宽方向仅1个分块时,邻域点会计算回A点本身,导致A点被删除
|
|
|
{
|
|
|
continue;
|
|
|
}
|
|
|
|
|
|
//// A点可能会在合并中被删掉,需要再判断一次,一个存在很久的bug? by wcw04046 @ 2020/02/20
|
|
|
if (DST_BLK_MAX_PNT_DELETE_FLAG == pPntA->x
|
|
|
&& DST_BLK_MAX_PNT_DELETE_FLAG == pPntA->y)
|
|
|
{
|
|
|
continue;
|
|
|
}
|
|
|
|
|
|
|
|
|
//获取临近点B的坐标
|
|
|
pPntB = &pBlkPnt[nNearIndex];
|
|
|
|
|
|
//若临近点B已被删除,则跳过该点,不进行后续处理
|
|
|
if (DST_BLK_MAX_PNT_DELETE_FLAG == pPntB->x
|
|
|
&& DST_BLK_MAX_PNT_DELETE_FLAG == pPntB->y)
|
|
|
{
|
|
|
continue;
|
|
|
}
|
|
|
|
|
|
//计算A、B点距离
|
|
|
nDistAB = (pPntA->x - pPntB->x) * (pPntA->x - pPntB->x);
|
|
|
nDistAB += (pPntA->y - pPntB->y) * (pPntA->y - pPntB->y);
|
|
|
|
|
|
//若A、B点距离小于阈值,则合并
|
|
|
//MSSu, 20111115: 若m_DST_nDectectMinPnt==TRUE,则两个相邻的极值点中,优先选择极大值点
|
|
|
if (nDistAB < nDistThres && nDistAB != 0)
|
|
|
{
|
|
|
//获取A、B点的亮度
|
|
|
//pPntAValue = pFrame[pPntA->y * nWidth + pPntA->x];
|
|
|
//pPntBValue = pFrame[pPntB->y * nWidth + pPntB->x];
|
|
|
if (GD_PIXEL_FORMAT_GRAY_Y8 == img.enPixelFormat)
|
|
|
{
|
|
|
pPntAValue = ((UBYTE8*)img.u64VirAddr[0])[pPntA->y * nWidth + pPntA->x];
|
|
|
pPntBValue = ((UBYTE8*)img.u64VirAddr[0])[pPntB->y * nWidth + pPntB->x];
|
|
|
}
|
|
|
else
|
|
|
{
|
|
|
pPntAValue = ((UINT16*)img.u64VirAddr[0])[pPntA->y * nWidth + pPntA->x];
|
|
|
pPntBValue = ((UINT16*)img.u64VirAddr[0])[pPntB->y * nWidth + pPntB->x];
|
|
|
}
|
|
|
|
|
|
//检测亮目标
|
|
|
if (GLB_OBJ_GRAY_BRIGHT == m_DST_stPara.nDetectGrayType)
|
|
|
{
|
|
|
if (pPntAValue > pPntBValue)
|
|
|
{
|
|
|
pPntB->x = DST_BLK_MAX_PNT_DELETE_FLAG;
|
|
|
pPntB->y = DST_BLK_MAX_PNT_DELETE_FLAG;
|
|
|
}
|
|
|
else
|
|
|
{
|
|
|
pPntA->x = DST_BLK_MAX_PNT_DELETE_FLAG;
|
|
|
pPntA->y = DST_BLK_MAX_PNT_DELETE_FLAG;
|
|
|
}
|
|
|
}
|
|
|
//检测暗目标
|
|
|
else if (GLB_OBJ_GRAY_DARK == m_DST_stPara.nDetectGrayType)
|
|
|
{
|
|
|
if (pPntAValue < pPntBValue)
|
|
|
{
|
|
|
pPntB->x = DST_BLK_MAX_PNT_DELETE_FLAG;
|
|
|
pPntB->y = DST_BLK_MAX_PNT_DELETE_FLAG;
|
|
|
}
|
|
|
else
|
|
|
{
|
|
|
pPntA->x = DST_BLK_MAX_PNT_DELETE_FLAG;
|
|
|
pPntA->y = DST_BLK_MAX_PNT_DELETE_FLAG;
|
|
|
}
|
|
|
}
|
|
|
//亮暗都检测
|
|
|
else if (GLB_OBJ_GRAY_ALL == m_DST_stPara.nDetectGrayType)
|
|
|
{
|
|
|
//20161130,按大大/大小/小小三种情况处理
|
|
|
if (DST_BLK_MAX_PNT == pbBlkMaxPntFlag[i] && DST_BLK_MAX_PNT == pbBlkMaxPntFlag[nNearIndex])
|
|
|
{
|
|
|
if (pPntAValue >= pPntBValue)
|
|
|
{
|
|
|
pPntB->x = DST_BLK_MAX_PNT_DELETE_FLAG;
|
|
|
pPntB->y = DST_BLK_MAX_PNT_DELETE_FLAG;
|
|
|
}
|
|
|
else
|
|
|
{
|
|
|
pPntA->x = DST_BLK_MAX_PNT_DELETE_FLAG;
|
|
|
pPntA->y = DST_BLK_MAX_PNT_DELETE_FLAG;
|
|
|
}
|
|
|
}
|
|
|
else if (DST_BLK_MIN_PNT == pbBlkMaxPntFlag[i] && DST_BLK_MIN_PNT == pbBlkMaxPntFlag[nNearIndex])
|
|
|
{
|
|
|
if (pPntAValue <= pPntBValue)
|
|
|
{
|
|
|
pPntB->x = DST_BLK_MAX_PNT_DELETE_FLAG;
|
|
|
pPntB->y = DST_BLK_MAX_PNT_DELETE_FLAG;
|
|
|
}
|
|
|
else
|
|
|
{
|
|
|
pPntA->x = DST_BLK_MAX_PNT_DELETE_FLAG;
|
|
|
pPntA->y = DST_BLK_MAX_PNT_DELETE_FLAG;
|
|
|
}
|
|
|
}
|
|
|
else
|
|
|
{
|
|
|
//20170330,极大值点和极小值点不做合并处理
|
|
|
}
|
|
|
|
|
|
}
|
|
|
}
|
|
|
}
|
|
|
}
|
|
|
}
|
|
|
}
|
|
|
|
|
|
/**********************************************************
|
|
|
* 函数名称:DST_DetectExtremumTarget()
|
|
|
* 功能描述:判断当前帧极值点是否为目标
|
|
|
* 输入参数:UINT16 *pFrame -- 原始图像
|
|
|
* SINT32 nWidth -- 图像宽度
|
|
|
* SINT32 nHeight -- 图像高度
|
|
|
* SINT32 nTargetNumMax -- 单帧检测目标的最大个数
|
|
|
* POINT16S *pBlkMaxPnt -- 当前帧极值点数组
|
|
|
* SINT32 nBlkNumW -- 行方向分块个数
|
|
|
* SINT32 nBlkNumH -- 列方向分块个数
|
|
|
* SINT32 *pBlkPtBeTargetFlag -- 极大值点是否为目标的标记
|
|
|
* 输出参数:TARGET_OBJECT *ptTargetArray-- 当前帧目标检测结果数组
|
|
|
* 返 回 值:SINT32 nTargetCnt -- 当前帧检测到的目标个数
|
|
|
* 调用关系:
|
|
|
* 其它说明:无
|
|
|
**********************************************************/
|
|
|
SINT32 DetectSmallObj::DST_DetectFrameTarget(GD_VIDEO_FRAME_S img, SINT32 nWidth, SINT32 nHeight,
|
|
|
TARGET_OBJECT* ptTargetArray, SINT32 nTargetNumMax,
|
|
|
POINT16S* pBlkMaxPnt, SINT32 nBlkNumW, SINT32 nBlkNumH,
|
|
|
SINT32* pBlkPtBeTargetFlag)
|
|
|
{
|
|
|
SINT32 i;
|
|
|
SINT32 nBlkNumCnt;
|
|
|
SINT32 nTargetCnt;
|
|
|
BBOOL bFindTarget;
|
|
|
POINT16S pPnt;
|
|
|
TARGET_OBJECT tTarget;
|
|
|
|
|
|
//初始化
|
|
|
nTargetCnt = 0;
|
|
|
|
|
|
//参数计算
|
|
|
nBlkNumCnt = MIN(nBlkNumW * nBlkNumH, m_DST_stInput.nBlkNum);
|
|
|
|
|
|
//判断极值点是否为目标
|
|
|
for (i = 0; i < nBlkNumCnt * 2; i++)
|
|
|
{
|
|
|
//获取第i个极值点
|
|
|
pPnt = pBlkMaxPnt[i];
|
|
|
|
|
|
//跳过被删除的极值点
|
|
|
if ((DST_BLK_MAX_PNT_DELETE_FLAG == pPnt.x) && (DST_BLK_MAX_PNT_DELETE_FLAG == pPnt.y))
|
|
|
{
|
|
|
continue;
|
|
|
}
|
|
|
|
|
|
|
|
|
//查看此极值点,前面(上面和左边)4个极值点是否已被判断为目标,
|
|
|
//若当前点落在该目标的上下左右边界之内,或者与该目标距离小于阈值,则将当前点删除不处理
|
|
|
//UINT16 pxPntGray = pFrame[pPnt.y * nWidth + pPnt.x];//from S332
|
|
|
UINT16 pxPntGray = 0;//from S332
|
|
|
if (GD_PIXEL_FORMAT_GRAY_Y8 == img.enPixelFormat)
|
|
|
{
|
|
|
pxPntGray = ((UBYTE8*)img.u64VirAddr[0])[pPnt.y * nWidth + pPnt.x];
|
|
|
}
|
|
|
else
|
|
|
{
|
|
|
pxPntGray = ((UINT16*)img.u64VirAddr[0])[pPnt.y * nWidth + pPnt.x];
|
|
|
}
|
|
|
if (DST_JudgeIfBlkPntBelongToTarget(i, nBlkNumH, nBlkNumW, pBlkMaxPnt,
|
|
|
pBlkPtBeTargetFlag, ptTargetArray, m_DST_stPara.nObjCombineDist, pxPntGray))
|
|
|
{
|
|
|
continue;
|
|
|
}
|
|
|
|
|
|
//初始化
|
|
|
memset(&tTarget, 0, sizeof(TARGET_OBJECT));
|
|
|
bFindTarget = false;
|
|
|
|
|
|
|
|
|
//以极值点为中心查找目标
|
|
|
bFindTarget = DST_BlkMaxTargetDetect(img, nWidth, nHeight, pPnt,
|
|
|
m_DST_stPara.pnFilter, m_DST_stPara.nFilterBGW, m_DST_stPara.nFilterTGW,
|
|
|
&tTarget, m_DST_stPara.fgdk);
|
|
|
|
|
|
//若该极值点为目标,则加入当前帧目标数组
|
|
|
if (bFindTarget)
|
|
|
{
|
|
|
//标记为目标,加入当前帧目标数组
|
|
|
tTarget.bObject = true;
|
|
|
// tTarget.unFrmID = m_GLB_stInput.stParaLn.unFrmId;
|
|
|
// 适应目标识别算法的加入,传统检测无法获取目标类型,此处约定目标类别ID置为DT_TARGET_CLS_ID,置信度为1
|
|
|
tTarget.unClsType = DT_TARGET_CLS_ID;
|
|
|
tTarget.fDetConf = 1.0;
|
|
|
tTarget.nObjTypeSrc = ObjSrc::Arith_DST;
|
|
|
|
|
|
ptTargetArray[nTargetCnt] = tTarget;
|
|
|
|
|
|
//标记该极值点处是目标
|
|
|
//Flag大于0,表明该点是目标,且其(Flag-1)表示该目标的编号
|
|
|
pBlkPtBeTargetFlag[i] = nTargetCnt + 1;
|
|
|
|
|
|
//更新当帧目标个数统计
|
|
|
nTargetCnt++;
|
|
|
|
|
|
//若目标个数超过上限,则跳出查找
|
|
|
if (nTargetCnt >= nTargetNumMax)
|
|
|
break;
|
|
|
}
|
|
|
}
|
|
|
|
|
|
return nTargetCnt;
|
|
|
}
|
|
|
|
|
|
#if 0
|
|
|
/**********************************************************
|
|
|
* 函数名称:DST_BlkMaxTargetDetect()
|
|
|
* 功能描述:判断极大值区域是否为目标
|
|
|
* 输入参数:UINT16 *pFrame -- 原始图像
|
|
|
* SINT32 nWidth -- 图像宽度
|
|
|
* SINT32 nHeight -- 图像高度
|
|
|
* POINT16S pPnt -- 极值点坐标
|
|
|
* SINT32 *pnFilter -- 目标背景模板
|
|
|
* SINT32 nFilterBGW -- 目标背景模板 - 背景宽度
|
|
|
* SINT32 nFilterTGW -- 目标背景模板 - 目标宽度
|
|
|
* FLOAT32 fgdk -- 目标SNR阈值
|
|
|
* 输出参数:TARGET_OBJECT *tTarget -- 当前目标结构体
|
|
|
* 返 回 值:1-该极值点是目标,0-该极值点不是目标。
|
|
|
* 调用关系:无
|
|
|
* 其它说明:无
|
|
|
**********************************************************/
|
|
|
BBOOL DetectSmallObj::DST_BlkMaxTargetDetect1(UINT16* pFrame, SINT32 nWidth, SINT32 nHeight, POINT16S pPnt,
|
|
|
SINT32* pnFilter, SINT32 nFilterBGW, SINT32 nFilterTGW,
|
|
|
TARGET_OBJECT* ptTarget, FLOAT32 fgdk)
|
|
|
{
|
|
|
SINT32* pnBlkTargetFlag = (SINT32*)DST_pnBlkTargetFlag;
|
|
|
SINT32 i, j;
|
|
|
BBOOL bIsTarget; //标记该极值点是否为目标
|
|
|
SINT32 nBGRadius, nTGRadius; //背景模板半径、目标模板半径
|
|
|
MINMAXRECT mmTGRect, mmBGRect; //目标、背景窗口边界
|
|
|
SINT32 nBGIndex, nBGFlter; //背景模板下标、背景模板系数
|
|
|
SINT32 nImgIndex; //背景点/邻域点对应的原始图像坐标
|
|
|
SINT32 nBGValue, nBGCnt; //背景点灰度、背景点计数
|
|
|
double dBGMean, dBGStd; //背景均值、方差
|
|
|
double dObjStd, dObjMean; //目标均值、方差
|
|
|
SINT32 nCenterValue; //中心点pPnt的灰度
|
|
|
SINT32 nPntValue; //目标模板内像素的灰度值
|
|
|
FLOAT32 fBGStdOutput; //背景方差 -- 用于显示,没有经过下限限制
|
|
|
|
|
|
BBOOL bTargetPixel; //标记某像素点是否属于目标。用于统计目标大小。
|
|
|
FLOAT32 fgdkCoeff; //gdk下降系数。用于统计目标大小。
|
|
|
|
|
|
SINT32 nObjWH_LineW; //目标宽高比统计 - 每行宽度
|
|
|
SINT32 nObjWH_LineWMax; //目标宽高比统计 - 行宽度的最大值
|
|
|
|
|
|
FLOAT32 fPntgdk; //各点的gdk系数
|
|
|
SINT32 nTGValue; //目标点灰度
|
|
|
SINT32 nCenterValueSumX; //目标点灰度-X坐标乘积累加、目标点灰度-Y坐标乘积累加
|
|
|
SINT32 nCenterValueSumY; //目标点灰度-X坐标乘积累加、目标点灰度-Y坐标乘积累加
|
|
|
|
|
|
SINT32 nValueDiff; //背景点与中心点的灰度差值
|
|
|
SINT32 nValueDiffMin; //背景点与中心点的灰度差的最小值
|
|
|
FLOAT32 fWHRatio; //目标宽高比
|
|
|
FLOAT32 fRectRatio; //目标矩形度
|
|
|
SINT32 nObjCenX, nObjCenY; //目标形心X、Y坐标
|
|
|
|
|
|
FLOAT32 fKernalBGVarMin2; //背景方差下限阈值(可调参数-标准差下限的平方)
|
|
|
FLOAT32 fKernalBGVarMax2; //背景方差上限阈值(可调参数-标准差上限的平方)
|
|
|
|
|
|
SINT32 nBGCntArray[4] = { 0 }; //20180115,记录上下左右邻域背景点个数
|
|
|
DOUBLE64 dBGMeanArray[4] = { 0.0f }; //20180115,记录上下左右邻域背景均值
|
|
|
DOUBLE64 dBGStdArray[4] = { 0.0f }; //20180115,记录上下左右邻域背景标准差
|
|
|
SINT32 nBGOuterRadius = 0; //20180115,回字形的外半径
|
|
|
SINT32 nMaxStdIndex = 0; //20180115,std最大的背景块下标
|
|
|
DOUBLE64 bBGStdMax = -1.0f; //20180115,方差最大的块
|
|
|
|
|
|
//+++++++++++++++++++++++++++++++++++++++++++++++++++++++
|
|
|
//初始化
|
|
|
bIsTarget = false;
|
|
|
nValueDiffMin = (SINT32)1e6;
|
|
|
memset(ptTarget, 0, sizeof(TARGET_OBJECT));
|
|
|
|
|
|
//+++++++++++++++++++++++++++++++++++++++++++++++++++++++
|
|
|
//参数设置
|
|
|
fgdkCoeff = 0.7f;
|
|
|
fKernalBGVarMin2 = m_DST_stPara.fKernalBGStdMin * m_DST_stPara.fKernalBGStdMin;
|
|
|
fKernalBGVarMax2 = m_DST_stPara.fKernalBGStdMax * m_DST_stPara.fKernalBGStdMax;
|
|
|
nBGRadius = (SINT32)(nFilterBGW >> 1);
|
|
|
nTGRadius = (SINT32)(nFilterTGW >> 1);
|
|
|
nBGOuterRadius = nBGRadius - nTGRadius; //20180115,回字形的外半径
|
|
|
|
|
|
//+++++++++++++++++++++++++++++++++++++++++++++++++++++++
|
|
|
//获取中心点灰度值
|
|
|
nCenterValue = pFrame[pPnt.y * nWidth + pPnt.x];
|
|
|
|
|
|
//+++++++++++++++++++++++++++++++++++++++++++++++++++++++
|
|
|
//统计背景均值、方差
|
|
|
//计算背景窗口边界
|
|
|
mmBGRect.minX = pPnt.x - nBGRadius;
|
|
|
mmBGRect.maxX = pPnt.x + nBGRadius;
|
|
|
mmBGRect.minY = pPnt.y - nBGRadius;
|
|
|
mmBGRect.maxY = pPnt.y + nBGRadius;
|
|
|
|
|
|
//防止越界
|
|
|
if (mmBGRect.minX<0 || mmBGRect.maxX>nWidth - 1 || mmBGRect.minY<0 || mmBGRect.maxY>nHeight - 1)
|
|
|
{
|
|
|
return false;
|
|
|
}
|
|
|
|
|
|
//+++++++++++++++++++++++++++++++++++++++++++++++++++++++
|
|
|
//统计背景均值、方差
|
|
|
nBGCnt = 0;
|
|
|
dBGMean = 0;
|
|
|
dBGStd = 0;
|
|
|
dObjStd = 0;
|
|
|
dObjMean = 0;
|
|
|
SINT32 nBGLine = 0;
|
|
|
SINT32 nImgLine = mmBGRect.minY * nWidth + mmBGRect.minX;
|
|
|
|
|
|
//for (i = 0; i < nFilterBGW; i++)
|
|
|
//{
|
|
|
// for (j = 0; j < nFilterBGW; j++)
|
|
|
// {
|
|
|
// nBGIndex = nBGLine + j;
|
|
|
// nImgIndex= nImgLine + j;
|
|
|
// nBGFlter = pnFilter[nBGIndex];
|
|
|
// nBGValue = pFrame[nImgIndex];
|
|
|
|
|
|
// if (1 == nBGFlter)
|
|
|
// {
|
|
|
// //背景灰度及灰度平方累加
|
|
|
// nBGCnt++;
|
|
|
// dBGMean += (double)nBGValue;
|
|
|
// dBGStd += (double)nBGValue * nBGValue;
|
|
|
|
|
|
// //查找背景中与中心点灰度差异最小的点的灰度
|
|
|
// nValueDiff = ABS(nBGValue - nCenterValue);
|
|
|
// if (nValueDiff < nValueDiffMin)
|
|
|
// {
|
|
|
// nValueDiffMin = nValueDiff;
|
|
|
// }
|
|
|
// }
|
|
|
// }
|
|
|
|
|
|
// //更新行起始坐标
|
|
|
// nBGLine += nFilterBGW;
|
|
|
// nImgLine += nWidth;
|
|
|
//}
|
|
|
|
|
|
for (i = 0; i < nFilterBGW; i++)
|
|
|
{
|
|
|
for (j = 0; j < nFilterBGW; j++)
|
|
|
{
|
|
|
nBGIndex = nBGLine + j;
|
|
|
nImgIndex = nImgLine + j;
|
|
|
nBGFlter = pnFilter[nBGIndex];
|
|
|
nBGValue = pFrame[nImgIndex];
|
|
|
|
|
|
if (1 == nBGFlter)
|
|
|
{
|
|
|
//背景灰度及灰度平方累加
|
|
|
//20180115,【屏蔽】采用取4邻域方差最小值的方式,防止背景混入目标点
|
|
|
//按上下左右顺序存邻域背景参数
|
|
|
if (j < nBGOuterRadius)
|
|
|
{
|
|
|
nBGCntArray[0]++;
|
|
|
dBGMeanArray[0] += (double)nBGValue;
|
|
|
dBGStdArray[0] += (double)nBGValue * nBGValue;
|
|
|
}
|
|
|
else if (j >= nFilterTGW + nBGOuterRadius)
|
|
|
{
|
|
|
nBGCntArray[1]++;
|
|
|
dBGMeanArray[1] += (double)nBGValue;
|
|
|
dBGStdArray[1] += (double)nBGValue * nBGValue;
|
|
|
}
|
|
|
else
|
|
|
{
|
|
|
//左邻域
|
|
|
if (i < nBGOuterRadius)
|
|
|
{
|
|
|
nBGCntArray[2]++;
|
|
|
dBGMeanArray[2] += (double)nBGValue;
|
|
|
dBGStdArray[2] += (double)nBGValue * nBGValue;
|
|
|
}
|
|
|
else
|
|
|
{
|
|
|
nBGCntArray[3]++;
|
|
|
dBGMeanArray[3] += (double)nBGValue;
|
|
|
dBGStdArray[3] += (double)nBGValue * nBGValue;
|
|
|
}
|
|
|
}
|
|
|
|
|
|
//查找背景中与中心点灰度差异最小的点的灰度
|
|
|
nValueDiff = ABS(nBGValue - nCenterValue);
|
|
|
if (nValueDiff < nValueDiffMin)
|
|
|
{
|
|
|
nValueDiffMin = nValueDiff;
|
|
|
}
|
|
|
}
|
|
|
}
|
|
|
|
|
|
//更新行起始坐标
|
|
|
nBGLine += nFilterBGW;
|
|
|
nImgLine += nWidth;
|
|
|
}
|
|
|
|
|
|
//20180115,【屏蔽】采用取4邻域方差最小值的方式,防止背景混入目标点
|
|
|
//计算4邻域的均值与方差
|
|
|
for (i = 0; i < 4; i++)
|
|
|
{
|
|
|
nBGCnt += nBGCntArray[i];
|
|
|
dBGMean += dBGMeanArray[i];
|
|
|
dBGStd += dBGStdArray[i];
|
|
|
|
|
|
dBGMeanArray[i] /= nBGCntArray[i];
|
|
|
dBGStdArray[i] /= nBGCntArray[i];
|
|
|
dBGStdArray[i] -= dBGMeanArray[i] * dBGMeanArray[i];
|
|
|
|
|
|
//找到方差最大的块
|
|
|
if (dBGStdArray[i] > bBGStdMax)
|
|
|
{
|
|
|
bBGStdMax = dBGStdArray[i];
|
|
|
nMaxStdIndex = i;
|
|
|
}
|
|
|
}
|
|
|
|
|
|
//抛掉方差最大的块
|
|
|
nBGCnt -= nBGCntArray[nMaxStdIndex];
|
|
|
dBGMean -= (dBGMeanArray[nMaxStdIndex] * nBGCntArray[nMaxStdIndex]);
|
|
|
dBGStd -= (nBGCntArray[nMaxStdIndex] * (dBGStdArray[nMaxStdIndex] + dBGMeanArray[nMaxStdIndex] * dBGMeanArray[nMaxStdIndex]));
|
|
|
|
|
|
dBGMean /= nBGCnt;
|
|
|
dBGStd /= nBGCnt;
|
|
|
dBGStd -= dBGMean * dBGMean;
|
|
|
|
|
|
//保存计算的背景均值及方差
|
|
|
fBGStdOutput = (FLOAT32)dBGStd;
|
|
|
|
|
|
//+++++++++++++++++++++++++++++++++++++++++++++++++++++++
|
|
|
//抛掉方差过大的块
|
|
|
if (m_DST_stPara.bUseDeFA_VarMax //去虚警策略“邻域方差上限限制”的开关
|
|
|
&& dBGStd > fKernalBGVarMax2) //判断邻域方差是否大于上限限制。
|
|
|
return false;
|
|
|
|
|
|
//设置背景方差下限
|
|
|
if (m_DST_stPara.bUseDeFA_VarMin //去虚警策略“邻域方差下限限制”的开关
|
|
|
&& dBGStd < m_DST_stPara.fKernalBGStdMin) //判断邻域方差是否小于下限限制。
|
|
|
{
|
|
|
dBGStd = (double)fKernalBGVarMin2;
|
|
|
}
|
|
|
|
|
|
//+++++++++++++++++++++++++++++++++++++++++++++++++++++++
|
|
|
//gdk不做自适应调节,直接赋给PC机传入的可调参数m_DST_stPara.fgdk
|
|
|
fPntgdk = fgdk;
|
|
|
|
|
|
//+++++++++++++++++++++++++++++++++++++++++++++++++++++++
|
|
|
//目标检测初始化
|
|
|
//计算目标核边界
|
|
|
mmTGRect.minX = pPnt.x - nTGRadius;
|
|
|
mmTGRect.maxX = pPnt.x + nTGRadius;
|
|
|
mmTGRect.minY = pPnt.y - nTGRadius;
|
|
|
mmTGRect.maxY = pPnt.y + nTGRadius;
|
|
|
|
|
|
//初始化
|
|
|
ptTarget->mrnRect.minY = mmTGRect.maxY;
|
|
|
ptTarget->mrnRect.maxY = mmTGRect.minY;
|
|
|
ptTarget->mrnRect.minX = mmTGRect.maxX;
|
|
|
ptTarget->mrnRect.maxX = mmTGRect.minX;
|
|
|
nCenterValueSumX = 0;
|
|
|
nCenterValueSumY = 0;
|
|
|
nTGValue = 0;
|
|
|
|
|
|
//记录目标的类型
|
|
|
ptTarget->nObjTypeGray = (nCenterValue > (SINT32)dBGMean) ? GLB_OBJ_GRAY_BRIGHT : GLB_OBJ_GRAY_DARK;
|
|
|
|
|
|
//MSSu, 20120304:根据系统所要检测的目标类型进行区分
|
|
|
if (GLB_OBJ_GRAY_DARK == m_DST_stPara.nDetectGrayType) //只检测暗目标
|
|
|
{
|
|
|
//MSSu, 20120229: 剔除亮目标。根据夜晚试验气球为暗目标的特性,做出目标类型的限制。
|
|
|
if (GLB_OBJ_GRAY_BRIGHT == ptTarget->nObjTypeGray)
|
|
|
return FALSE;
|
|
|
}
|
|
|
else if (GLB_OBJ_GRAY_BRIGHT == m_DST_stPara.nDetectGrayType) //只检测亮目标
|
|
|
{
|
|
|
//跳过暗目标
|
|
|
if (GLB_OBJ_GRAY_DARK == ptTarget->nObjTypeGray)
|
|
|
return FALSE;
|
|
|
}
|
|
|
//+++++++++++++++++++++++++++++++++++++++++++++++++++++++
|
|
|
//提前计算参数,简化计算
|
|
|
double fPntgdkByStd = fPntgdk * fPntgdk * dBGStd;
|
|
|
|
|
|
//+++++++++++++++++++++++++++++++++++++++++++++++++++++++
|
|
|
//目标检测:基于目标信噪比的检测方法
|
|
|
//首先判断极值点是否为目标
|
|
|
//MSSu, 20111115: 若m_DST_nDectectMinPnt==TRUE,则为判断极大值点或极小值点是否为目标
|
|
|
//若极值点不满足SNR条件,则判断该点是否满足灰度阈值判断的条件
|
|
|
if ((nCenterValue - dBGMean) * (nCenterValue - dBGMean) <= fPntgdkByStd)
|
|
|
{
|
|
|
//标记该点不是目标,直接返回
|
|
|
return false;
|
|
|
}
|
|
|
//若极值点是目标,则统计目标的大小
|
|
|
else
|
|
|
{
|
|
|
//标记该点为目标
|
|
|
bIsTarget = true;
|
|
|
|
|
|
//去虚警:抛掉方差过大的块
|
|
|
if (m_DST_stPara.bUseDeFA_VarMax
|
|
|
&& dBGStd > m_DST_stPara.fKernalBGStdMax)
|
|
|
{
|
|
|
bIsTarget = false;
|
|
|
}
|
|
|
|
|
|
//去虚警:抛掉极值点与背景最小灰度差小于阈值的块
|
|
|
if (m_DST_stPara.bUseDeFA_BTGrayMin
|
|
|
&& nValueDiffMin < m_DST_stPara.nBTGrayMinThres)
|
|
|
{
|
|
|
bIsTarget = false;
|
|
|
}
|
|
|
|
|
|
//若该点不是目标,则跳过剩余计算
|
|
|
if (!bIsTarget)
|
|
|
{
|
|
|
return false;
|
|
|
}
|
|
|
|
|
|
//降低gdk阈值统计目标大小
|
|
|
fPntgdk *= fgdkCoeff;
|
|
|
fPntgdk = MAX(fPntgdk, 4.0f);
|
|
|
|
|
|
//提前计算参数,简化计算
|
|
|
double fPntgdkByStdNew = fPntgdk * fPntgdk * dBGStd;
|
|
|
|
|
|
//搜索目标边界
|
|
|
nObjWH_LineWMax = 0;
|
|
|
SINT32 nLine = (pPnt.y - nTGRadius) * nWidth + pPnt.x - nTGRadius;
|
|
|
//SINT32 nIndex = 0;
|
|
|
SINT32 nFlagLine = 0;
|
|
|
SINT32 nFlagIndex = 0;
|
|
|
for (i = 0; i < nFilterTGW; i++)
|
|
|
{
|
|
|
//初始化每行宽度
|
|
|
nObjWH_LineW = 0;
|
|
|
|
|
|
for (j = 0; j < nFilterTGW; j++)
|
|
|
{
|
|
|
//获取目标区域各点的图像坐标
|
|
|
nImgIndex = nLine + j;
|
|
|
|
|
|
//获取目标区域各点灰度值
|
|
|
nPntValue = pFrame[nImgIndex];
|
|
|
|
|
|
//提前计算参数,简化计算
|
|
|
double dValueDiff = nPntValue - dBGMean;
|
|
|
double dValueDiffSquare = dValueDiff * dValueDiff;
|
|
|
|
|
|
//判断该点是否属于目标点(采用SNR判断方法)
|
|
|
bTargetPixel = false;
|
|
|
if ((i == j && i == nTGRadius)
|
|
|
|| (GLB_OBJ_GRAY_BRIGHT == m_DST_stPara.nDetectGrayType && nPntValue > dBGMean && dValueDiffSquare > fPntgdkByStdNew)
|
|
|
|| (GLB_OBJ_GRAY_DARK == m_DST_stPara.nDetectGrayType && nPntValue < dBGMean && dValueDiffSquare > fPntgdkByStdNew)
|
|
|
|| (GLB_OBJ_GRAY_ALL == m_DST_stPara.nDetectGrayType && dValueDiffSquare > fPntgdkByStdNew))
|
|
|
{
|
|
|
bTargetPixel = true;
|
|
|
}
|
|
|
|
|
|
//查找目标边界,并统计大小
|
|
|
if (bTargetPixel)
|
|
|
{
|
|
|
dObjMean += nPntValue;
|
|
|
dObjStd += nPntValue * nPntValue;
|
|
|
|
|
|
//统计行宽
|
|
|
nObjWH_LineW++;
|
|
|
|
|
|
//查找目标边界
|
|
|
SINT32 nImgX = j + mmTGRect.minX;
|
|
|
SINT32 nImgY = i + mmTGRect.minY;
|
|
|
ptTarget->mrnRect.minY = MIN(ptTarget->mrnRect.minY, nImgY);
|
|
|
ptTarget->mrnRect.maxY = MAX(ptTarget->mrnRect.maxY, nImgY);
|
|
|
ptTarget->mrnRect.minX = MIN(ptTarget->mrnRect.minX, nImgX);
|
|
|
ptTarget->mrnRect.maxX = MAX(ptTarget->mrnRect.maxX, nImgX);
|
|
|
|
|
|
//统计目标质心. MSSu, 20110524
|
|
|
nCenterValueSumX += nImgX * nPntValue;
|
|
|
nCenterValueSumY += nImgY * nPntValue;
|
|
|
nTGValue += nPntValue;
|
|
|
|
|
|
//统计目标大小
|
|
|
ptTarget->unObjPxlsCnt++;
|
|
|
|
|
|
//标记目标区域内目标点
|
|
|
nFlagIndex = nFlagLine + j;
|
|
|
pnBlkTargetFlag[nFlagIndex] = 1;
|
|
|
|
|
|
// 目标极值
|
|
|
ptTarget->pxObjMaxGray = MAX(ptTarget->pxObjMaxGray, nPntValue);
|
|
|
|
|
|
}
|
|
|
}
|
|
|
|
|
|
//查找最大行宽
|
|
|
nObjWH_LineWMax = MAX(nObjWH_LineWMax, nObjWH_LineW);
|
|
|
|
|
|
//更新下一行起始坐标
|
|
|
nLine += nWidth;
|
|
|
nFlagLine += nFilterTGW;
|
|
|
}//end of for (j = 0; j < nKernelSize_TG; j++)...
|
|
|
}//end of else...
|
|
|
|
|
|
if (ptTarget->unObjPxlsCnt > 0)
|
|
|
{
|
|
|
dObjMean /= ptTarget->unObjPxlsCnt;
|
|
|
dObjStd /= ptTarget->unObjPxlsCnt;
|
|
|
dObjStd -= dObjMean * dObjMean;
|
|
|
}
|
|
|
else
|
|
|
{
|
|
|
dObjStd = 0.0;
|
|
|
}
|
|
|
|
|
|
//+++++++++++++++++++++++++++++++++++++++++++++++++++++++
|
|
|
//统计目标信息
|
|
|
if (bIsTarget)
|
|
|
{
|
|
|
//计算统计目标质心
|
|
|
if (0 == nTGValue) //防止出错,例如当阈值设置不恰当时,连目标的极大值点都未统计到目标的大小中
|
|
|
{
|
|
|
ptTarget->pfCenPos.x = (FLOAT32)pPnt.x;
|
|
|
ptTarget->pfCenPos.y = (FLOAT32)pPnt.y;
|
|
|
}
|
|
|
else
|
|
|
{
|
|
|
ptTarget->pfCenPos.x = (FLOAT32)nCenterValueSumX / nTGValue;
|
|
|
ptTarget->pfCenPos.y = (FLOAT32)nCenterValueSumY / nTGValue;
|
|
|
}
|
|
|
|
|
|
//统计目标的灰度(极大值灰度)
|
|
|
ptTarget->pxObjGray = nCenterValue;
|
|
|
|
|
|
//记录目标极大值点坐标
|
|
|
ptTarget->pnMaxPos = pPnt;
|
|
|
|
|
|
//计算目标宽、高、面积
|
|
|
ptTarget->snSize.h = ptTarget->mrnRect.maxY - ptTarget->mrnRect.minY + 1;
|
|
|
ptTarget->snSize.w = ptTarget->mrnRect.maxX - ptTarget->mrnRect.minX + 1;
|
|
|
ptTarget->snSize.s = ptTarget->snSize.h * ptTarget->snSize.w;
|
|
|
|
|
|
//记录背景均值、背景方差、目标背景信噪比
|
|
|
ptTarget->fBGMean = (FLOAT32)dBGMean;
|
|
|
ptTarget->fBGStd = (FLOAT32)sqrt(fBGStdOutput);
|
|
|
ptTarget->fSNR = (FLOAT32)(nCenterValue - dBGMean) / (ptTarget->fBGStd + 0.01f);
|
|
|
|
|
|
//计算目标的伺服方位角、俯仰角
|
|
|
// ptTarget->afAngle.fAz = SERVO_CalcObjAzimuth (pPnt.x, nWidth, m_SERVO_stInput.fAzimuth, m_SERVO_stInput.fResolAz);
|
|
|
// ptTarget->afAngle.fPt = SERVO_CalcObjPitching(pPnt.y, nHeight, m_SERVO_stInput.fPitching, m_SERVO_stInput.fResolPt);
|
|
|
|
|
|
//标记目标类型
|
|
|
ptTarget->nObjTypeSize = GLB_OBJ_SIZE_SMALL;
|
|
|
|
|
|
//标记为目标
|
|
|
bIsTarget = true;
|
|
|
|
|
|
//去虚警:抛掉大小不符合要求的目标
|
|
|
if (m_DST_stPara.bUseDeFA_Size //去虚警策略“目标大小限制”的开关
|
|
|
&& (ptTarget->unObjPxlsCnt < (UINT32)m_DST_stPara.nObjSizeMin
|
|
|
|| ptTarget->unObjPxlsCnt >(UINT32)m_DST_stPara.nObjSizeMax))
|
|
|
{
|
|
|
bIsTarget = false;
|
|
|
}
|
|
|
|
|
|
//去虚警:抛掉长宽比不符合要求的目标
|
|
|
//目标宽高比计算方式2 - 最大行宽度/总高度
|
|
|
if (DST_OBJ_WHRATIO_LINEWH == m_DST_stPara.nObjWHRatioMethod)
|
|
|
{
|
|
|
fWHRatio = (FLOAT32)nObjWH_LineWMax / ptTarget->snSize.h;
|
|
|
}
|
|
|
//目标宽高比计算方式1 - 总宽度/总高度
|
|
|
else
|
|
|
{
|
|
|
fWHRatio = (FLOAT32)(ptTarget->snSize.w) / ptTarget->snSize.h;
|
|
|
}
|
|
|
|
|
|
if (m_DST_stPara.bUseDeFA_WHRatio //去虚警策略“目标宽高比限制”的开关
|
|
|
&& ((fWHRatio < 1 && fWHRatio < m_DST_stPara.fObjWHRatioMin)
|
|
|
|| (fWHRatio > 1 && fWHRatio > m_DST_stPara.fObjWHRatioMax)))
|
|
|
{
|
|
|
bIsTarget = false;
|
|
|
}
|
|
|
|
|
|
//去虚警:抛掉矩形度不符合要求的目标
|
|
|
fRectRatio = (FLOAT32)ptTarget->unObjPxlsCnt / ptTarget->snSize.s;
|
|
|
if (m_DST_stPara.bUseDeFA_RectRatio //去虚警策略“目标矩形度限制”的开关
|
|
|
&& fRectRatio < m_DST_stPara.fObjRectRatioMin)
|
|
|
{
|
|
|
bIsTarget = false;
|
|
|
}
|
|
|
|
|
|
//去虚警:抛掉形心不是目标标记点的目标(形状不规则)
|
|
|
//nObjCenX = (SINT32)((tTarget->mrnRect.minX + tTarget->mrnRect.maxX) / 2.0 + 0.5);
|
|
|
//nObjCenY = (SINT32)((tTarget->mrnRect.minY + tTarget->mrnRect.maxY) / 2.0 + 0.5);
|
|
|
nObjCenX = (ptTarget->mrnRect.minX + ptTarget->mrnRect.maxX) >> 1;
|
|
|
nObjCenY = (ptTarget->mrnRect.minY + ptTarget->mrnRect.maxY) >> 1;
|
|
|
if (m_DST_stPara.bUseDeFA_CenFlag //去虚警策略“形心为目标点”的开关
|
|
|
&& !pnBlkTargetFlag[(nObjCenY - mmTGRect.minY) * nFilterTGW + nObjCenX - mmTGRect.minX])
|
|
|
{
|
|
|
if ((nObjCenX - ptTarget->pfCenPos.x) * (nObjCenX - ptTarget->pfCenPos.x) +
|
|
|
(nObjCenY - ptTarget->pfCenPos.y) * (nObjCenY - ptTarget->pfCenPos.y) > 2.0f)
|
|
|
{
|
|
|
bIsTarget = false;
|
|
|
}
|
|
|
}
|
|
|
}
|
|
|
|
|
|
return bIsTarget;
|
|
|
}
|
|
|
#endif
|
|
|
|
|
|
/**********************************************************
|
|
|
* 函数名称:DST_JudgeIfBlkPntBelongToTarget()
|
|
|
* 功能描述:判断当前极值点是否落在前面已检测到的目标上,或与前面的目标邻近
|
|
|
* 输入参数:SINT32 nPntIndex -- 极值点在数组中的序号
|
|
|
* SINT32 nBlkNumW -- 行方向分块个数
|
|
|
* SINT32 nBlkNumH -- 列方向分块个数
|
|
|
* POINT16S *pBlkMaxPnt -- 当前帧极值点数组
|
|
|
* SINT32 *pBlkPtBeTargetFlag -- 极大值点是否为目标的标记
|
|
|
* TARGET_OBJECT *ptTargetArray-- 当前帧目标检测结果数组
|
|
|
* SINT32 nDistThres -- 极值点合并的距离阈值
|
|
|
* 输出参数:无
|
|
|
* 返 回 值:1-当前极值点被合并,0-当前极值点未被合并
|
|
|
* 调用关系:无
|
|
|
* 其它说明:无
|
|
|
**********************************************************/
|
|
|
BBOOL DetectSmallObj::DST_JudgeIfBlkPntBelongToTarget(SINT32 nPntIndex, SINT32 nBlkNumH, SINT32 nBlkNumW,
|
|
|
POINT16S* pBlkMaxPnt, SINT32* pBlkPtBeTargetFlag,
|
|
|
TARGET_OBJECT* ptTargetArray, SINT32 nDistThres,
|
|
|
UINT16 pxPntGray)
|
|
|
{
|
|
|
SINT32 nX[4] = { -1, 0, 1, -1 };
|
|
|
SINT32 nY[4] = { -1, -1, -1, 0 };
|
|
|
|
|
|
SINT32 k = 0;
|
|
|
POINT16S* pPntA = NULL;
|
|
|
POINT16S* pPntB = NULL;
|
|
|
SINT32 nDistAB = 0;
|
|
|
SINT32 nNearIndex = 0;
|
|
|
SINT32 nDistThres2 = 0;
|
|
|
TARGET_OBJECT* ptTarget = NULL;
|
|
|
|
|
|
//计算参数
|
|
|
nDistThres2 = nDistThres * nDistThres;
|
|
|
|
|
|
//获取当前极值点A的坐标
|
|
|
pPntA = &pBlkMaxPnt[nPntIndex];
|
|
|
|
|
|
for (k = 0; k <= 3; k++)
|
|
|
{
|
|
|
//计算临近点B下标
|
|
|
nNearIndex = nPntIndex + nY[k] * nBlkNumW + nX[k];
|
|
|
|
|
|
//防止临近点越界
|
|
|
if (nNearIndex < 0 || nNearIndex >= nBlkNumH * nBlkNumW)
|
|
|
{
|
|
|
continue;
|
|
|
}
|
|
|
|
|
|
//若该邻域极值点不是目标,则跳过
|
|
|
if (pBlkPtBeTargetFlag[nNearIndex] <= 0)
|
|
|
{
|
|
|
continue;
|
|
|
}
|
|
|
|
|
|
//ptTarget指向该目标信息
|
|
|
ptTarget = &ptTargetArray[pBlkPtBeTargetFlag[nNearIndex] - 1];
|
|
|
|
|
|
//若当前点位于邻域极值目标上,删除该点,返回真
|
|
|
if (pPntA->x >= ptTarget->mrnRect.minX && pPntA->x <= ptTarget->mrnRect.maxX
|
|
|
&& pPntA->y >= ptTarget->mrnRect.minY && pPntA->y <= ptTarget->mrnRect.maxY)
|
|
|
{
|
|
|
if (GLB_OBJ_GRAY_BRIGHT == ptTarget->nObjTypeGray)
|
|
|
{
|
|
|
if (ptTarget->pxObjGray > pxPntGray)
|
|
|
{
|
|
|
pPntA->x = DST_BLK_MAX_PNT_DELETE_FLAG;
|
|
|
pPntA->y = DST_BLK_MAX_PNT_DELETE_FLAG;
|
|
|
return true;
|
|
|
}
|
|
|
}
|
|
|
else
|
|
|
{
|
|
|
if (ptTarget->pxObjGray < pxPntGray)
|
|
|
{
|
|
|
pPntA->x = DST_BLK_MAX_PNT_DELETE_FLAG;
|
|
|
pPntA->y = DST_BLK_MAX_PNT_DELETE_FLAG;
|
|
|
return true;
|
|
|
}
|
|
|
}
|
|
|
}
|
|
|
|
|
|
//获取邻域极值目标的坐标
|
|
|
pPntB = &ptTarget->pnMaxPos;
|
|
|
|
|
|
//计算该点与目标的距离
|
|
|
nDistAB = (pPntA->x - pPntB->x) * (pPntA->x - pPntB->x);
|
|
|
nDistAB += (pPntA->y - pPntB->y) * (pPntA->y - pPntB->y);
|
|
|
|
|
|
//若当前点不在邻域极值目标上,但两者距离小于阈值,也删除该点,返回真
|
|
|
if (nDistAB < nDistThres2)
|
|
|
{
|
|
|
pPntA->x = DST_BLK_MAX_PNT_DELETE_FLAG;
|
|
|
pPntA->y = DST_BLK_MAX_PNT_DELETE_FLAG;
|
|
|
return true;
|
|
|
}
|
|
|
}
|
|
|
|
|
|
return false;
|
|
|
}
|
|
|
|
|
|
/**********************************************************
|
|
|
* 函数名称:DST_CalObjBkgMean_UINT16()
|
|
|
* 功能描述:计算目标背景均值
|
|
|
* 输入参数:UINT16 *pFrame -- 原始图像
|
|
|
* SINT32 nWidth -- 图像宽度
|
|
|
* SINT32 nHeight -- 图像高度
|
|
|
* POINT16S pPnt -- 目标坐标
|
|
|
* 输出参数:FLOAT32 dBGMean -- 目标背景均值信息
|
|
|
* 返 回 值:无
|
|
|
* 调用关系:无
|
|
|
* 其它说明:无
|
|
|
**********************************************************/
|
|
|
FLOAT32 DetectSmallObj::DST_CalObjBkgMean_UINT16(GD_VIDEO_FRAME_S img, SINT32 nWidth, SINT32 nHeight,
|
|
|
POINT16S pPnt)
|
|
|
{
|
|
|
SINT32 i, j;
|
|
|
SINT32 nFilterBGW; //极大值滤波窗口 - 背景核区域大小,目标核区域大小
|
|
|
SINT32 nBGRadius, nTGRadius; //背景模板半径、目标模板半径
|
|
|
SINT32 nBGIndex, nBGFlter; //背景模板下标、背景模板系数
|
|
|
SINT32 nImgIndex; //背景点/邻域点对应的原始图像坐标
|
|
|
SINT32 nBGValue, nBGCnt; //背景点灰度、背景点计数
|
|
|
FLOAT32 dBGMean; //背景均值、方差
|
|
|
SINT32* pnFilter = (SINT32*)g_DST_nFilter_9_13;//目标背景模板
|
|
|
MINMAXRECT mmBGRect; //目标、背景窗口边界
|
|
|
|
|
|
//+++++++++++++++++++++++++++++++++++++++++++++++++++++++
|
|
|
nFilterBGW = DST_KERNAL_SIZE_Bm_13;
|
|
|
nBGRadius = (SINT32)(nFilterBGW >> 1);
|
|
|
nTGRadius = (SINT32)(DST_KERNAL_SIZE_Tm_9 >> 1);
|
|
|
|
|
|
//+++++++++++++++++++++++++++++++++++++++++++++++++++++++
|
|
|
//统计背景均值、方差
|
|
|
//计算背景窗口边界
|
|
|
mmBGRect.minX = pPnt.x - nBGRadius;
|
|
|
mmBGRect.maxX = pPnt.x + nBGRadius;
|
|
|
mmBGRect.minY = pPnt.y - nBGRadius;
|
|
|
mmBGRect.maxY = pPnt.y + nBGRadius;
|
|
|
|
|
|
//防止越界
|
|
|
if (mmBGRect.minX<0 || mmBGRect.maxX>nWidth - 1 || mmBGRect.minY<0 || mmBGRect.maxY>nHeight - 1)
|
|
|
{
|
|
|
return -1.0;
|
|
|
}
|
|
|
|
|
|
//统计背景均值、方差
|
|
|
nBGCnt = 0;
|
|
|
dBGMean = 0;
|
|
|
|
|
|
//小目标检测:在原图上计算背景均值、背景标准差
|
|
|
SINT32 nBGLine = 0;
|
|
|
SINT32 nImgLine = mmBGRect.minY * nWidth + mmBGRect.minX;
|
|
|
for (i = 0; i < nFilterBGW; i++)
|
|
|
{
|
|
|
for (j = 0; j < nFilterBGW; j++)
|
|
|
{
|
|
|
nBGIndex = nBGLine + j;
|
|
|
nImgIndex = nImgLine + j;
|
|
|
nBGFlter = pnFilter[nBGIndex];
|
|
|
if (GD_PIXEL_FORMAT_GRAY_Y8 == img.enPixelFormat)
|
|
|
{
|
|
|
nBGValue = ((UBYTE8*)img.u64VirAddr[0])[nImgIndex];
|
|
|
}
|
|
|
else
|
|
|
{
|
|
|
nBGValue = ((UINT16*)img.u64VirAddr[0])[nImgIndex];
|
|
|
}
|
|
|
if (1 == nBGFlter)
|
|
|
{
|
|
|
//背景灰度及灰度平方累加
|
|
|
nBGCnt++;
|
|
|
dBGMean += (FLOAT32)nBGValue;
|
|
|
}
|
|
|
}
|
|
|
|
|
|
//更新行起始坐标
|
|
|
nBGLine += nFilterBGW;
|
|
|
nImgLine += nWidth;
|
|
|
}
|
|
|
dBGMean /= nBGCnt;
|
|
|
|
|
|
//保存计算的背景均值及方差
|
|
|
return dBGMean;
|
|
|
}
|
|
|
|
|
|
/**********************************************************
|
|
|
* 函数名称:DST_PipeTargetReDetect()
|
|
|
* 功能描述:管道目标二次搜索
|
|
|
* 输入参数:UINT16 *pSrc -- 原始图像
|
|
|
* SINT32 nWidth -- 图像宽度
|
|
|
* SINT32 nHeight -- 图像高度
|
|
|
* POINT32F ptPipeCenPos -- 管道目标在当前帧的中心坐标
|
|
|
* SPEED32F sfPipeSpeed -- 管道目标速度
|
|
|
* MINMAXRECT mrnSrRect -- 搜索区域边界
|
|
|
* FLOAT32 fgdk -- SNR阈值
|
|
|
* TARGET_OBJECT *ptTargetArray-- 当前帧目标检测结果数组
|
|
|
* PIPE *pPipeArray -- 管道数组
|
|
|
* SINT32 *pnFrmObjsCnt -- 单帧检测目标个数
|
|
|
* 输出参数:TARGET_OBJECT *ptTarget -- 二次检测到的目标
|
|
|
* SINT32 *bPipeTargetIndex -- 管道在当前帧查找到的目标
|
|
|
* TARGET_OBJECT *ptTargetArray-- 当前帧目标检测结果数组
|
|
|
* SINT32 *pnFrmObjsCnt -- 单帧检测目标个数
|
|
|
* 返 回 值:1-二次检测找到目标,0-未检测到目标。
|
|
|
* 调用关系:
|
|
|
* 其它说明:在前一帧管道中心区域,重新查找极大或极小值点。
|
|
|
**********************************************************/
|
|
|
BBOOL DetectSmallObj::DST_PipeTargetReDetect(GD_VIDEO_FRAME_S img, SINT32 nWidth, SINT32 nHeight,
|
|
|
POINT32F ptPipeCenPos, SPEED32F sfPipeSpeed,
|
|
|
MINMAXRECT mrnSrRect,
|
|
|
TARGET_OBJECT* ptTarget,
|
|
|
TARGET_OBJECT* ptTargetArray, SINT32* pnFrmObjsCnt)
|
|
|
{
|
|
|
BBOOL bRefoundTarget; //标记管道目标二次搜索是否成功
|
|
|
SINT32 nBlkStart; //管道目标二次搜索时,中心区域的左上角起始坐标
|
|
|
POINT16S pnPipeSearchPoint; //管道目标二次搜索时,中心区域的极值点坐标
|
|
|
SINT32 nFrmObjsCnt; //当前帧目标个数
|
|
|
SINT32 nSrRadiusW; //宽方向搜索半径
|
|
|
SINT32 nSrRadiusH; //高方向搜索半径
|
|
|
|
|
|
//初始化
|
|
|
bRefoundTarget = false;
|
|
|
nFrmObjsCnt = (*pnFrmObjsCnt);
|
|
|
nSrRadiusW = MAX(2, MIN((SINT32)(sfPipeSpeed.vx * 2.0f), DST_PIPE_CENTER_BLK_W / 2));
|
|
|
nSrRadiusH = MAX(2, MIN((SINT32)(sfPipeSpeed.vy * 2.0f), DST_PIPE_CENTER_BLK_H / 2));
|
|
|
POINT16S pBlkSecondMaxPnt = {0};//次极大值
|
|
|
//MSSu, 20150609: 防止越界
|
|
|
MINMAXRECT32S mrnRect;
|
|
|
mrnRect.minX = ptPipeCenPos.x - nSrRadiusW;
|
|
|
mrnRect.maxX = ptPipeCenPos.x + nSrRadiusW;
|
|
|
mrnRect.minY = ptPipeCenPos.y - nSrRadiusH;
|
|
|
mrnRect.maxY = ptPipeCenPos.y + nSrRadiusH;
|
|
|
if ((mrnRect.minX < 0) || (mrnRect.maxX >= nWidth)
|
|
|
|| (mrnRect.minY < 0) || (mrnRect.maxY >= nHeight))
|
|
|
{
|
|
|
return bRefoundTarget;
|
|
|
}
|
|
|
|
|
|
//获取管道中心区域图像起始位置
|
|
|
nBlkStart = mrnRect.minY * nWidth + mrnRect.minX;
|
|
|
|
|
|
//查找块内极值:极大值或极小值
|
|
|
//MSSu, 20111115: 若m_DST_nDectectMinPnt==TRUE,则为查找块内极大或极小值
|
|
|
BYTE8 bMaxPntFalg = DST_BLK_MAX_PNT; //20161130,标记极大/极小
|
|
|
pnPipeSearchPoint = DST_FindBlkExtremum(img, nWidth, nHeight,
|
|
|
nBlkStart, nSrRadiusW * 2 + 1, nSrRadiusH * 2 + 1, &bMaxPntFalg,&pBlkSecondMaxPnt);
|
|
|
|
|
|
//二次检测前,关闭部分去虚警开关(需先保存关闭前的状态)
|
|
|
SINT32 bUseDeFA_VarMax = m_DST_stPara.bUseDeFA_VarMax;
|
|
|
SINT32 bUseDeFA_Size = m_DST_stPara.bUseDeFA_Size;
|
|
|
SINT32 bUseDeFA_BGFACnt = m_DST_stPara.bUseDeFA_BGFACnt;
|
|
|
SINT32 bUseDeFA_BTGrayMin = m_DST_stPara.bUseDeFA_BTGrayMin;
|
|
|
SINT32 bUseDeFA_CenFlag = m_DST_stPara.bUseDeFA_CenFlag;
|
|
|
SINT32 bUseDeFA_XYPrj = m_DST_stPara.bUseDeFA_XYPrj;
|
|
|
m_DST_stPara.bUseDeFA_VarMax = FALSE;
|
|
|
m_DST_stPara.bUseDeFA_Size = FALSE;
|
|
|
m_DST_stPara.bUseDeFA_BGFACnt = FALSE;
|
|
|
m_DST_stPara.bUseDeFA_BTGrayMin = FALSE;
|
|
|
m_DST_stPara.bUseDeFA_CenFlag = FALSE;
|
|
|
m_DST_stPara.bUseDeFA_XYPrj = FALSE;
|
|
|
|
|
|
FLOAT32 fgdk = MAX(m_DST_stPara.fgdk / 2.0f,2.0f);
|
|
|
|
|
|
//若目标超出搜索区域,则不降低阈值再查找,让管道消失
|
|
|
//if (mrnSrRect.minX < pnPipeSearchPoint.x
|
|
|
// && pnPipeSearchPoint.x < mrnSrRect.maxX
|
|
|
// && mrnSrRect.minY < pnPipeSearchPoint.y
|
|
|
// && pnPipeSearchPoint.y < mrnSrRect.maxY)
|
|
|
if (mrnRect.minX < pnPipeSearchPoint.x
|
|
|
&& pnPipeSearchPoint.x < mrnRect.maxX
|
|
|
&& mrnRect.minY < pnPipeSearchPoint.y
|
|
|
&& pnPipeSearchPoint.y < mrnRect.maxY)
|
|
|
{
|
|
|
//若检测到目标,则重置管道待删除标记pPipe->bLost清零
|
|
|
memset(ptTarget, 0, sizeof(TARGET_OBJECT));
|
|
|
bRefoundTarget = DST_BlkMaxTargetDetect(img, nWidth, nHeight, pnPipeSearchPoint,
|
|
|
m_DST_stPara.pnFilter, m_DST_stPara.nFilterBGW, m_DST_stPara.nFilterTGW, ptTarget, fgdk);
|
|
|
ptTarget->nObjTypeSize = GLB_OBJ_SIZE_DIMSMALL;
|
|
|
|
|
|
ptTarget->nObjTypeSrc = ObjSrc::Arith_DIM;//标记为弱目标
|
|
|
}
|
|
|
|
|
|
//if (bRefoundTarget && (ABS(ptTarget->pfCenPos.x - m_GLB_stOutput.crnObjPrediRtLong.cx) > 10
|
|
|
// || ABS(ptTarget->pfCenPos.y - m_GLB_stOutput.crnObjPrediRtLong.cy) > 10))
|
|
|
//{
|
|
|
// bRefoundTarget = false;
|
|
|
//}
|
|
|
|
|
|
//将二次检测到的目标,加入单帧目标数组
|
|
|
if (bRefoundTarget)
|
|
|
{
|
|
|
//标记为目标,加入当前帧目标数组
|
|
|
ptTarget->bObject = true;
|
|
|
// ptTarget->unFrmID = m_GLB_stInput.stParaLn.unFrmId;
|
|
|
//(*bPipeTargetIndex) = nFrmObjsCnt;
|
|
|
memcpy(&ptTargetArray[nFrmObjsCnt], ptTarget, sizeof(TARGET_OBJECT));
|
|
|
nFrmObjsCnt++;
|
|
|
|
|
|
//更新当帧目标个数统计
|
|
|
(*pnFrmObjsCnt) = nFrmObjsCnt;
|
|
|
}
|
|
|
|
|
|
//二次检测后,还原去虚警开关(需先保存关闭前的状态)
|
|
|
m_DST_stPara.bUseDeFA_VarMax = bUseDeFA_VarMax;
|
|
|
m_DST_stPara.bUseDeFA_Size = bUseDeFA_Size;
|
|
|
m_DST_stPara.bUseDeFA_BGFACnt = bUseDeFA_BGFACnt;
|
|
|
m_DST_stPara.bUseDeFA_BTGrayMin = bUseDeFA_BTGrayMin;
|
|
|
m_DST_stPara.bUseDeFA_CenFlag = bUseDeFA_CenFlag;
|
|
|
m_DST_stPara.bUseDeFA_XYPrj = bUseDeFA_XYPrj;
|
|
|
|
|
|
return bRefoundTarget;
|
|
|
}
|
|
|
|
|
|
/**********************************************************
|
|
|
* 函数名称:DST_FindBlkExtremum()
|
|
|
* 功能描述:查找块内极值点
|
|
|
* 输入参数:PIXELTYPE *pFrame -- 原始图像
|
|
|
* SINT32 nWidth -- 图像宽度
|
|
|
* SINT32 nHeight -- 图像高度
|
|
|
* SINT32 pBlkStart -- 该分块在原始图像上的起始坐标
|
|
|
* SINT32 nBlkWidth -- 分块宽度
|
|
|
* SINT32 nBlkHeight -- 分块高度
|
|
|
* 输出参数:无
|
|
|
* 返 回 值:POINT16S pPnt -- 块内极值点坐标
|
|
|
* 调用关系:无
|
|
|
* 其它说明:MSSu, 20111115: 函数修改,增加查找块内极小值的功能,
|
|
|
* 对于每个块的极大值和极小值,选两者中与块均值偏差较大的作为返回点。
|
|
|
**********************************************************/
|
|
|
POINT16S DetectSmallObj::DST_FindBlk4Neighbor(GD_VIDEO_FRAME_S img, SINT32 nWidth, SINT32 nHeight,
|
|
|
SINT32 pBlkStart, SINT32 nBlkWidth, SINT32 nBlkHeight, POINT16S* pSecondMax)
|
|
|
{
|
|
|
SINT32 i, j;
|
|
|
SINT32 nLen = nBlkWidth * nBlkHeight;
|
|
|
UINT16 pGrayGap = 0;
|
|
|
UINT16 pMax = 20; // 起始灰度差阈值,并记录最大的pGrayGap,低于该阈值不作为候选目标
|
|
|
|
|
|
UINT16 pMax2 = 0;
|
|
|
UINT16 pMin = 65535;
|
|
|
SINT32 pMean = 0;
|
|
|
POINT16S pPntMax = { 0 };
|
|
|
POINT16S pPntMax2 = { 0 };
|
|
|
POINT16S pPntMin = { 0 };
|
|
|
POINT16S pPnt = { 0 };
|
|
|
SINT32 nMaxIndex = 0;
|
|
|
SINT32 nMaxIndex2 = 0;
|
|
|
SINT32 nMinIndex = 0;
|
|
|
SINT32 nIndex = 0;
|
|
|
SINT32 nMaxI = 0;
|
|
|
SINT32 nMaxJ = 0;
|
|
|
|
|
|
//查找块内极值点
|
|
|
for (i = 0; i < nBlkHeight; i++)
|
|
|
{
|
|
|
for (j = 0; j < nBlkWidth; j++)
|
|
|
{
|
|
|
//获取块内每个像素点灰度
|
|
|
nIndex = pBlkStart + j;
|
|
|
int nnIndex_left = nIndex - 1;
|
|
|
int nnIndex_right = nIndex + 1;
|
|
|
int nnIndex_top = nIndex - nWidth;
|
|
|
int nnIndex_bottom = nIndex + nWidth;
|
|
|
|
|
|
if (GD_PIXEL_FORMAT_GRAY_Y8 == img.enPixelFormat)
|
|
|
{
|
|
|
UBYTE8 * pFrame = ((UBYTE8*)img.u64VirAddr[0]);
|
|
|
pGrayGap = (pFrame[nIndex] - pFrame[nnIndex_left]) > 0 ? (pFrame[nIndex] - pFrame[nnIndex_left]) : 0 +
|
|
|
(pFrame[nIndex] - pFrame[nnIndex_right]) > 0 ? (pFrame[nIndex] - pFrame[nnIndex_right]) : 0 +
|
|
|
(pFrame[nIndex] - pFrame[nnIndex_top]) > 0 ? (pFrame[nIndex] - pFrame[nnIndex_top]) : 0 +
|
|
|
(pFrame[nIndex] - pFrame[nnIndex_bottom]) > 0 ? (pFrame[nIndex] - pFrame[nnIndex_bottom]) : 0;
|
|
|
}
|
|
|
else
|
|
|
{
|
|
|
UINT16* pFrame = ((UINT16*)img.u64VirAddr[0]);
|
|
|
pGrayGap = (pFrame[nIndex] - pFrame[nnIndex_left]) > 0 ? (pFrame[nIndex] - pFrame[nnIndex_left]) : 0 +
|
|
|
(pFrame[nIndex] - pFrame[nnIndex_right]) > 0 ? (pFrame[nIndex] - pFrame[nnIndex_right]) : 0 +
|
|
|
(pFrame[nIndex] - pFrame[nnIndex_top]) > 0 ? (pFrame[nIndex] - pFrame[nnIndex_top]) : 0 +
|
|
|
(pFrame[nIndex] - pFrame[nnIndex_bottom]) > 0 ? (pFrame[nIndex] - pFrame[nnIndex_bottom]) : 0;
|
|
|
}
|
|
|
//查找极大值
|
|
|
if (pGrayGap > pMax)
|
|
|
{
|
|
|
pMax = pGrayGap;
|
|
|
nMaxIndex = nIndex;
|
|
|
nMaxI = i;
|
|
|
nMaxJ = j;
|
|
|
}
|
|
|
}
|
|
|
//更新下一行的其实坐标
|
|
|
pBlkStart += nWidth;
|
|
|
}
|
|
|
|
|
|
|
|
|
//计算块内灰度均值,抛掉极大值
|
|
|
if (nLen <= 1)
|
|
|
{
|
|
|
pMean = pMean;
|
|
|
}
|
|
|
else if (nLen == 2)
|
|
|
{
|
|
|
pMean /= 2;
|
|
|
}
|
|
|
else
|
|
|
{
|
|
|
//pMean -= pMax;
|
|
|
//pMean /= (nLen - 1);
|
|
|
pMean -= (pMax + pMin);
|
|
|
pMean /= (nLen - 2);
|
|
|
}
|
|
|
|
|
|
//抛掉与块均值灰度差异较小的点
|
|
|
//if (ABS(pMax - pMean) < pDiffThres)
|
|
|
//{
|
|
|
// pPnt.x = DST_BLK_MAX_PNT_DELETE_FLAG;
|
|
|
// pPnt.y = DST_BLK_MAX_PNT_DELETE_FLAG;
|
|
|
//}
|
|
|
//else
|
|
|
|
|
|
pPntMax.x = nMaxIndex % nWidth;
|
|
|
pPntMax.y = nMaxIndex / nWidth;
|
|
|
pPntMax2.x = nMaxIndex2 % nWidth;
|
|
|
pPntMax2.y = nMaxIndex2 / nWidth;
|
|
|
pPntMin.x = nMinIndex % nWidth;
|
|
|
pPntMin.y = nMinIndex / nWidth;
|
|
|
|
|
|
if (GLB_OBJ_GRAY_DARK == m_DST_stPara.nDetectGrayType)
|
|
|
{
|
|
|
pPnt = pPntMin;
|
|
|
}
|
|
|
else if (DST_DETECT_OBJ_TYPE_BRIGHT == m_DST_stPara.nDetectGrayType)
|
|
|
{
|
|
|
pPnt = pPntMax;
|
|
|
if (pPntMax.x == pPntMax2.x && pPntMax.y == pPntMax2.y)
|
|
|
{
|
|
|
pSecondMax->x = -1;
|
|
|
pSecondMax->y = -1;
|
|
|
}
|
|
|
else
|
|
|
{
|
|
|
*pSecondMax = pPntMax2;
|
|
|
}
|
|
|
}
|
|
|
else if (DST_DETECT_OBJ_TYPE_ALL == m_DST_stPara.nDetectGrayType)
|
|
|
{
|
|
|
if (ABS(pMax - pMean) >= ABS(pMin - pMean))
|
|
|
pPnt = pPntMax;
|
|
|
else
|
|
|
pPnt = pPntMin;
|
|
|
}
|
|
|
|
|
|
return pPnt;
|
|
|
}
|
|
|
|
|
|
/**********************************************************
|
|
|
* 函数名称:DST_PipeTargetReDetect()
|
|
|
* 功能描述:管道目标二次搜索
|
|
|
* 输入参数:UINT16 *pSrc -- 原始图像
|
|
|
* SINT32 nWidth -- 图像宽度
|
|
|
* SINT32 nHeight -- 图像高度
|
|
|
* POINT32F ptPipeCenPos -- 管道目标在当前帧的中心坐标
|
|
|
* SPEED32F sfPipeSpeed -- 管道目标速度
|
|
|
* MINMAXRECT mrnSrRect -- 搜索区域边界
|
|
|
* FLOAT32 fgdk -- SNR阈值
|
|
|
* TARGET_OBJECT *ptTargetArray-- 当前帧目标检测结果数组
|
|
|
* PIPE *pPipeArray -- 管道数组
|
|
|
* SINT32 *pnFrmObjsCnt -- 单帧检测目标个数
|
|
|
* 输出参数:TARGET_OBJECT *ptTarget -- 二次检测到的目标
|
|
|
* SINT32 *bPipeTargetIndex -- 管道在当前帧查找到的目标
|
|
|
* TARGET_OBJECT *ptTargetArray-- 当前帧目标检测结果数组
|
|
|
* SINT32 *pnFrmObjsCnt -- 单帧检测目标个数
|
|
|
* 返 回 值:1-二次检测找到目标,0-未检测到目标。
|
|
|
* 调用关系:
|
|
|
* 其它说明:在前一帧管道中心区域,重新查找极大或极小值点。
|
|
|
**********************************************************/
|
|
|
BBOOL DetectSmallObj::DST_PipeTargetRReDetect(GD_VIDEO_FRAME_S img, SINT32 nWidth, SINT32 nHeight,
|
|
|
POINT32F ptPipeCenPos, SPEED32F sfPipeSpeed,
|
|
|
MINMAXRECT mrnSrRect,
|
|
|
TARGET_OBJECT* ptTarget,
|
|
|
TARGET_OBJECT* ptTargetArray, SINT32* pnFrmObjsCnt)
|
|
|
{
|
|
|
BBOOL bRefoundTarget; //标记管道目标二次搜索是否成功
|
|
|
SINT32 nBlkStart; //管道目标二次搜索时,中心区域的左上角起始坐标
|
|
|
POINT16S pnPipeSearchPoint; //管道目标二次搜索时,中心区域的极值点坐标
|
|
|
SINT32 nFrmObjsCnt; //当前帧目标个数
|
|
|
SINT32 nSrRadiusW; //宽方向搜索半径
|
|
|
SINT32 nSrRadiusH; //高方向搜索半径
|
|
|
SINT32 nSrWidth; //宽方向搜索直径
|
|
|
SINT32 nSrHeight; //高方向搜索直径
|
|
|
//初始化
|
|
|
bRefoundTarget = false;
|
|
|
nFrmObjsCnt = (*pnFrmObjsCnt);
|
|
|
nSrRadiusW = mrnSrRect.maxX - mrnSrRect.minX;
|
|
|
nSrRadiusH = mrnSrRect.maxY - mrnSrRect.minY;
|
|
|
POINT16S pBlkSecondMaxPnt = {0};//次极大值
|
|
|
//MSSu, 20150609: 防止越界
|
|
|
MINMAXRECT32S mrnRect;
|
|
|
mrnRect.minX = ptPipeCenPos.x - nSrRadiusW;
|
|
|
mrnRect.maxX = ptPipeCenPos.x + nSrRadiusW;
|
|
|
mrnRect.minY = ptPipeCenPos.y - nSrRadiusH;
|
|
|
mrnRect.maxY = ptPipeCenPos.y + nSrRadiusH;
|
|
|
if ((mrnRect.minX < 0) || (mrnRect.maxX >= nWidth)
|
|
|
|| (mrnRect.minY < 0) || (mrnRect.maxY >= nHeight))
|
|
|
{
|
|
|
return bRefoundTarget;
|
|
|
}
|
|
|
|
|
|
//获取管道中心区域图像起始位置
|
|
|
nBlkStart = mrnRect.minY * nWidth + mrnRect.minX;
|
|
|
nSrWidth = (nSrRadiusW << 1) + 1;
|
|
|
nSrHeight = (nSrRadiusH << 1) + 1;
|
|
|
//查找块内极值:极大值或极小值
|
|
|
//MSSu, 20111115: 若m_DST_nDectectMinPnt==TRUE,则为查找块内极大或极小值
|
|
|
BYTE8 bMaxPntFalg = DST_BLK_MAX_PNT; //20161130,标记极大/极小
|
|
|
//pnPipeSearchPoint = DST_FindBlkExtremum(img, nWidth, nHeight,
|
|
|
// nBlkStart, nSrRadiusW * 2 + 1, nSrRadiusH * 2 + 1, &bMaxPntFalg,&pBlkSecondMaxPnt);
|
|
|
POINT16S pSecondMax;
|
|
|
pnPipeSearchPoint = DST_FindBlk4Neighbor(img, nWidth, nHeight, nBlkStart, nSrWidth, nSrHeight, &pSecondMax);
|
|
|
|
|
|
//三次检测前,关闭部分去虚警开关(需先保存关闭前的状态)
|
|
|
SINT32 bUseDeFA_VarMax = m_DST_stPara.bUseDeFA_VarMax;
|
|
|
SINT32 bUseDeFA_Size = m_DST_stPara.bUseDeFA_Size;
|
|
|
SINT32 bUseDeFA_BGFACnt = m_DST_stPara.bUseDeFA_BGFACnt;
|
|
|
SINT32 bUseDeFA_BTGrayMin = m_DST_stPara.bUseDeFA_BTGrayMin;
|
|
|
SINT32 bUseDeFA_CenFlag = m_DST_stPara.bUseDeFA_CenFlag;
|
|
|
SINT32 bUseDeFA_XYPrj = m_DST_stPara.bUseDeFA_XYPrj;
|
|
|
m_DST_stPara.bUseDeFA_VarMax = FALSE;
|
|
|
m_DST_stPara.bUseDeFA_Size = FALSE;
|
|
|
m_DST_stPara.bUseDeFA_BGFACnt = FALSE;
|
|
|
m_DST_stPara.bUseDeFA_BTGrayMin = FALSE;
|
|
|
m_DST_stPara.bUseDeFA_CenFlag = FALSE;
|
|
|
m_DST_stPara.bUseDeFA_XYPrj = FALSE;
|
|
|
|
|
|
FLOAT32 fgdk = MIN(m_DST_stPara.fgdk / 2.0f, 2.0f);
|
|
|
|
|
|
//若目标超出搜索区域,则不降低阈值再查找,让管道消失
|
|
|
if (mrnRect.minX < pnPipeSearchPoint.x
|
|
|
&& pnPipeSearchPoint.x < mrnRect.maxX
|
|
|
&& mrnRect.minY < pnPipeSearchPoint.y
|
|
|
&& pnPipeSearchPoint.y < mrnRect.maxY)
|
|
|
{
|
|
|
//若检测到目标,则重置管道待删除标记pPipe->bLost清零
|
|
|
memset(ptTarget, 0, sizeof(TARGET_OBJECT));
|
|
|
bRefoundTarget = DST_BlkMaxTargetDetect(img, nWidth, nHeight, pnPipeSearchPoint,
|
|
|
m_DST_stPara.pnFilter, m_DST_stPara.nFilterBGW, m_DST_stPara.nFilterTGW, ptTarget, fgdk);
|
|
|
ptTarget->nObjTypeSize = GLB_OBJ_SIZE_DIMSMALL;
|
|
|
|
|
|
ptTarget->nObjTypeSrc = ObjSrc::Arith_DIM;//标记为弱目标
|
|
|
}
|
|
|
|
|
|
//if (bRefoundTarget && (ABS(ptTarget->pfCenPos.x - m_GLB_stOutput.crnObjPrediRtLong.cx) > 10
|
|
|
// || ABS(ptTarget->pfCenPos.y - m_GLB_stOutput.crnObjPrediRtLong.cy) > 10))
|
|
|
//{
|
|
|
// bRefoundTarget = false;
|
|
|
//}
|
|
|
|
|
|
//将三次检测到的目标,加入单帧目标数组
|
|
|
if (bRefoundTarget)
|
|
|
{
|
|
|
//标记为目标,加入当前帧目标数组
|
|
|
ptTarget->bObject = true;
|
|
|
// ptTarget->unFrmID = m_GLB_stInput.stParaLn.unFrmId;
|
|
|
memcpy(&ptTargetArray[nFrmObjsCnt], ptTarget, sizeof(TARGET_OBJECT));
|
|
|
nFrmObjsCnt++;
|
|
|
|
|
|
//更新当帧目标个数统计
|
|
|
(*pnFrmObjsCnt) = nFrmObjsCnt;
|
|
|
}
|
|
|
|
|
|
//三次检测后,还原去虚警开关(需先保存关闭前的状态)
|
|
|
m_DST_stPara.bUseDeFA_VarMax = bUseDeFA_VarMax;
|
|
|
m_DST_stPara.bUseDeFA_Size = bUseDeFA_Size;
|
|
|
m_DST_stPara.bUseDeFA_BGFACnt = bUseDeFA_BGFACnt;
|
|
|
m_DST_stPara.bUseDeFA_BTGrayMin = bUseDeFA_BTGrayMin;
|
|
|
m_DST_stPara.bUseDeFA_CenFlag = bUseDeFA_CenFlag;
|
|
|
m_DST_stPara.bUseDeFA_XYPrj = bUseDeFA_XYPrj;
|
|
|
|
|
|
return bRefoundTarget;
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
POINT16S * DetectSmallObj::getMaxPoint()
|
|
|
{
|
|
|
return DST_pBlkMaxPoint;
|
|
|
}
|
|
|
|
|
|
|
|
|
/**********************************************************
|
|
|
* 函数名称:DST_CalObjSNR_UINT16()
|
|
|
* 功能描述:计算目标SNR
|
|
|
* 输入参数:UINT16 *pFrame -- 原始图像
|
|
|
* SINT32 nWidth -- 图像宽度
|
|
|
* SINT32 nHeight -- 图像高度
|
|
|
* POINT16S pPnt -- 目标坐标
|
|
|
* 输出参数:OBJECTSNR *objSNR -- 目标SNR信息
|
|
|
* 返 回 值:无
|
|
|
* 调用关系:无
|
|
|
* 其它说明:DSP不移植
|
|
|
**********************************************************/
|
|
|
void DetectSmallObj::DST_CalObjSNR_UINT16(UINT16* pFrame, SINT32 nWidth, SINT32 nHeight,
|
|
|
POINT16S pPnt, OBJECTSNR* objSNR)
|
|
|
{
|
|
|
SINT32 i, j;
|
|
|
SINT32 nFilterBGW; //极大值滤波窗口 - 背景核区域大小,目标核区域大小
|
|
|
SINT32 nBGRadius, nTGRadius; //背景模板半径、目标模板半径
|
|
|
SINT32 nBGIndex, nBGFlter; //背景模板下标、背景模板系数
|
|
|
SINT32 nImgIndex; //背景点/邻域点对应的原始图像坐标
|
|
|
SINT32 nBGValue, nBGCnt; //背景点灰度、背景点计数
|
|
|
double dBGMean, dBGStd; //背景均值、方差
|
|
|
SINT32 nCenterValue; //中心点pPnt的灰度
|
|
|
FLOAT32 fBGStdOutput; //背景方差 -- 用于显示,没有经过下限限制
|
|
|
SINT32* pnFilter = (SINT32*)m_DST_stPara.pnFilter;
|
|
|
MINMAXRECT mmBGRect; //目标、背景窗口边界
|
|
|
|
|
|
//+++++++++++++++++++++++++++++++++++++++++++++++++++++++
|
|
|
//参数设置
|
|
|
nFilterBGW = m_DST_stPara.nFilterBGW;
|
|
|
nBGRadius = (SINT32)(nFilterBGW >> 1);
|
|
|
nTGRadius = (SINT32)(DST_KERNAL_SIZE_Tm_9 >> 1);
|
|
|
|
|
|
//+++++++++++++++++++++++++++++++++++++++++++++++++++++++
|
|
|
//获取中心点灰度值
|
|
|
nCenterValue = pFrame[pPnt.y * nWidth + pPnt.x];
|
|
|
|
|
|
//+++++++++++++++++++++++++++++++++++++++++++++++++++++++
|
|
|
//统计背景均值、方差
|
|
|
//计算背景窗口边界
|
|
|
mmBGRect.minX = pPnt.x - nBGRadius;
|
|
|
mmBGRect.maxX = pPnt.x + nBGRadius;
|
|
|
mmBGRect.minY = pPnt.y - nBGRadius;
|
|
|
mmBGRect.maxY = pPnt.y + nBGRadius;
|
|
|
|
|
|
//防止越界
|
|
|
if (mmBGRect.minX<0 || mmBGRect.maxX>nWidth - 1 || mmBGRect.minY<0 || mmBGRect.maxY>nHeight - 1)
|
|
|
{
|
|
|
memset(objSNR, 0, sizeof(OBJECTSNR));
|
|
|
return;
|
|
|
}
|
|
|
|
|
|
//统计背景均值、方差
|
|
|
nBGCnt = 0;
|
|
|
dBGMean = 0;
|
|
|
dBGStd = 0;
|
|
|
//小目标检测:在原图上计算背景均值、背景标准差
|
|
|
SINT32 nBGLine = 0;
|
|
|
SINT32 nImgLine = mmBGRect.minY * nWidth + mmBGRect.minX;
|
|
|
for (i = 0; i < nFilterBGW; i++)
|
|
|
{
|
|
|
for (j = 0; j < nFilterBGW; j++)
|
|
|
{
|
|
|
nBGIndex = nBGLine + j;
|
|
|
nImgIndex = nImgLine + j;
|
|
|
nBGFlter = pnFilter[nBGIndex];
|
|
|
nBGValue = pFrame[nImgIndex];
|
|
|
|
|
|
if (1 == nBGFlter)
|
|
|
{
|
|
|
//背景灰度及灰度平方累加
|
|
|
nBGCnt++;
|
|
|
dBGMean += (double)nBGValue;
|
|
|
dBGStd += (double)nBGValue * nBGValue;
|
|
|
}
|
|
|
}
|
|
|
|
|
|
//更新行起始坐标
|
|
|
nBGLine += nFilterBGW;
|
|
|
nImgLine += nWidth;
|
|
|
}
|
|
|
dBGMean /= nBGCnt;
|
|
|
dBGStd /= nBGCnt;
|
|
|
dBGStd -= dBGMean * dBGMean;
|
|
|
|
|
|
//保存计算的背景均值及方差
|
|
|
fBGStdOutput = (FLOAT32)dBGStd;
|
|
|
|
|
|
//设置背景方差下限
|
|
|
if (m_DST_stPara.bUseDeFA_VarMin //去虚警策略“邻域方差下限限制”的开关
|
|
|
&& dBGStd < m_DST_stPara.fKernalBGStdMin) //判断邻域方差是否小于下限限制。
|
|
|
{
|
|
|
dBGStd = (double)m_DST_stPara.fKernalBGStdMin * m_DST_stPara.fKernalBGStdMin;
|
|
|
}
|
|
|
|
|
|
//保存目标SNR信息
|
|
|
objSNR->Pnt = pPnt;
|
|
|
objSNR->nTGR = (SINT16)(nTGRadius);
|
|
|
objSNR->nBGR = (SINT16)(nBGRadius);
|
|
|
objSNR->ObjGray = (FLOAT32)nCenterValue;
|
|
|
objSNR->BGMean = (FLOAT32)dBGMean;
|
|
|
objSNR->BGStd = (FLOAT32)sqrt(dBGStd);
|
|
|
objSNR->fSNR = (dBGStd < 0.01) ? 1e6f : (FLOAT32)((nCenterValue - dBGMean) / sqrt(dBGStd));
|
|
|
}
|
|
|
|
|
|
|
|
|
/**********************************************************
|
|
|
* 函数名称:DST_DetectDimTarget_BFilter()
|
|
|
* 功能描述:基于分块极值的弱小目标检测(基于双边滤波的方法)
|
|
|
* 输入参数:UINT16 *pSrc -- 原始图像
|
|
|
* SINT32 nWidth -- 图像宽度
|
|
|
* SINT32 nHeight -- 图像高度
|
|
|
* 输出参数:无
|
|
|
* 返 回 值:ubSuccessFlag跟踪成功标志位
|
|
|
* 调用关系:
|
|
|
* 其它说明:在低频图上计算背景均值,在高频图上计算噪声标准差。
|
|
|
**********************************************************/
|
|
|
UBYTE8 DetectSmallObj::DST_DetectDimTarget_BF(GD_VIDEO_FRAME_S img, SINT32 nWidth, SINT32 nHeight)
|
|
|
{
|
|
|
//指向DSP数据空间
|
|
|
UINT16* pxSrImg = (UINT16*)m_DST_stOutput.pxSrImg;
|
|
|
TARGET_OBJECT* ptDimTargets = (TARGET_OBJECT*)DST_DimTarget;
|
|
|
POINT16S* pDimBlkMaxPnt = (POINT16S*)DST_pDimBlkMaxPoint;
|
|
|
SINT32* pBlkPtBeTargetFlag = (SINT32*)DST_pBlkPtBeTargetFlag;
|
|
|
SINT16* pDimBFHighImg = (SINT16*)DST_pDimBFHighImg; //搜索区域双边滤波高频
|
|
|
UINT16* pDimBFLowImg = (UINT16*)DST_pDimBFLowImg; //搜索区域双边滤波低频
|
|
|
BYTE8* pbBlkMaxPntFlag = (BYTE8*)DST_pBlkMaxPntFlag; //20161130
|
|
|
|
|
|
//局部变量
|
|
|
UBYTE8 ubObjsCnt = 0; //截获区域目标个数
|
|
|
SINT32 nSrRadiusW, nSrRadiusH; //截获区域半径
|
|
|
SIZE32S snImgSize; //截获区域图像尺寸
|
|
|
CENTERRECT crnSrRect; //半自动截获搜索区域中心矩形
|
|
|
MINMAXRECT mmnSrRect; //半自动截获搜索区域边界矩形
|
|
|
SINT32 nBlkWidth, nBlkHeight; //分块宽度、高度
|
|
|
SINT32 nBlkNumW, nBlkNumH; //宽、高方向分块个数
|
|
|
SINT32 nBlkWidthMin; //最小分块宽度
|
|
|
SINT32 nSmpScale = 1; //降采样倍数
|
|
|
MINMAXRECT32S mmnSrSmpRect; //搜索区域边界矩形,MINMAXRECT32S格式
|
|
|
SIZE32S snSmpImgSize; //降采样图像尺寸
|
|
|
|
|
|
//+++++++++++++++++++++++++++++++++++++++++++++++++++++++
|
|
|
//初始化算法输出结果
|
|
|
DST_CleanUpFrameDimDetectOutput();
|
|
|
m_DST_stPara.bDimDetecting = true;
|
|
|
|
|
|
//+++++++++++++++++++++++++++++++++++++++++++++++++++++++
|
|
|
//获取弱小目标搜索区域
|
|
|
//以锁定点位置为中心
|
|
|
crnSrRect.cx = m_DST_stInput.crnSemiSrRect.cx;
|
|
|
crnSrRect.cy = m_DST_stInput.crnSemiSrRect.cy;
|
|
|
|
|
|
//根据参考区域大小调整降采样倍数和大小
|
|
|
if ((m_DST_stInput.crnSemiSrRect.w >> 1) < 33)
|
|
|
{
|
|
|
nSmpScale = 1;
|
|
|
}
|
|
|
else
|
|
|
{
|
|
|
nSmpScale = 2;
|
|
|
}
|
|
|
m_DST_stOutput.nDimSmpScale = nSmpScale;
|
|
|
|
|
|
//以所设置的锁定波门宽高设定半径,并设定上下限
|
|
|
nSrRadiusW = MIN(m_DST_stInput.crnSemiSrRect.w >> 1, DST_DIMOBJ_RADIUS_MAX);
|
|
|
nSrRadiusW = MIN(MAX(nSrRadiusW, DST_DIMOBJ_RADIUS_MIN), DST_DIMOBJ_RADIUS_MAX);
|
|
|
nSrRadiusH = MIN(m_DST_stInput.crnSemiSrRect.h >> 1, DST_DIMOBJ_RADIUS_MAX);
|
|
|
nSrRadiusH = MIN(MAX(nSrRadiusH, DST_DIMOBJ_RADIUS_MIN), DST_DIMOBJ_RADIUS_MAX);
|
|
|
crnSrRect.w = (nSrRadiusW << 1) + 1;
|
|
|
crnSrRect.h = (nSrRadiusH << 1) + 1;
|
|
|
crnSrRect.s = crnSrRect.w * crnSrRect.h;
|
|
|
|
|
|
//计算获取弱小目标搜索区域边界矩形:防越界。
|
|
|
mmnSrRect.minX = MAX(0, MIN(crnSrRect.cx - nSrRadiusW, nWidth - 1));
|
|
|
mmnSrRect.minY = MAX(0, MIN(crnSrRect.cy - nSrRadiusH, nHeight - 1));
|
|
|
mmnSrRect.maxX = MAX(0, MIN(crnSrRect.cx + nSrRadiusW, nWidth - 1));
|
|
|
mmnSrRect.maxY = MAX(0, MIN(crnSrRect.cy + nSrRadiusH, nHeight - 1));
|
|
|
m_DST_stInput.mmnSemiSrRect = mmnSrRect;
|
|
|
mmnSrSmpRect.minX = mmnSrRect.minX;
|
|
|
mmnSrSmpRect.maxX = mmnSrRect.maxX;
|
|
|
mmnSrSmpRect.minY = mmnSrRect.minY;
|
|
|
mmnSrSmpRect.maxY = mmnSrRect.maxY;
|
|
|
|
|
|
//边界限制后,重新更新搜索区域中心矩形
|
|
|
crnSrRect.cx = (mmnSrRect.minX + mmnSrRect.maxX) >> 1;
|
|
|
crnSrRect.cy = (mmnSrRect.minY + mmnSrRect.maxY) >> 1;
|
|
|
crnSrRect.w = mmnSrRect.maxX - mmnSrRect.minX + 1;
|
|
|
crnSrRect.h = mmnSrRect.maxY - mmnSrRect.minY + 1;
|
|
|
crnSrRect.s = crnSrRect.w * crnSrRect.h;
|
|
|
m_DST_stInput.crnSemiSrRect = crnSrRect;
|
|
|
|
|
|
//计算搜索区域图像尺寸
|
|
|
snImgSize.w = crnSrRect.w;
|
|
|
snImgSize.h = crnSrRect.h;
|
|
|
snImgSize.s = snImgSize.w * snImgSize.h;
|
|
|
m_DST_stOutput.snDimSrImgSize = snImgSize;
|
|
|
|
|
|
//计算降采样图像尺寸
|
|
|
if (2 == nSmpScale)
|
|
|
{
|
|
|
snSmpImgSize.w = (crnSrRect.w + 1) / nSmpScale;
|
|
|
snSmpImgSize.h = (crnSrRect.h + 1) / nSmpScale;
|
|
|
snSmpImgSize.s = snSmpImgSize.w * snSmpImgSize.h;
|
|
|
}
|
|
|
else
|
|
|
{
|
|
|
snSmpImgSize.w = crnSrRect.w;
|
|
|
snSmpImgSize.h = crnSrRect.h;
|
|
|
snSmpImgSize.s = snSmpImgSize.w * snSmpImgSize.h;
|
|
|
}
|
|
|
m_DST_stOutput.snDimSrSmpImgSize = snSmpImgSize;
|
|
|
|
|
|
//设置分块大小及分块个数:因强制检测针对的是弱小目标,故分块大小默认设置为4
|
|
|
//20170314,:弱目标检测不调高降采样后的分块大小,以免未被判为极值点
|
|
|
nBlkWidthMin = MAX((SINT32)(sqrt((double)(snImgSize.s) / DST_DIMOBJ_BLK_NUM) + 0.5), 1);
|
|
|
nBlkWidth = MAX(8, nBlkWidthMin);
|
|
|
nBlkWidth = MIN(nBlkWidth, 16);
|
|
|
nBlkHeight = nBlkWidth;
|
|
|
|
|
|
//降采样图像的分块宽高调整为16
|
|
|
if (2 == nSmpScale)
|
|
|
{
|
|
|
nBlkWidth = 16;
|
|
|
nBlkHeight = 16;
|
|
|
}
|
|
|
nBlkNumW = snImgSize.w / nBlkWidth;
|
|
|
nBlkNumH = snImgSize.h / nBlkHeight;
|
|
|
|
|
|
//+++++++++++++++++++++++++++++++++++++++++++++++++++++++
|
|
|
//获取弱小目标检测区域图像或降采样图像
|
|
|
if (2 == nSmpScale)
|
|
|
{
|
|
|
IMGO_GDSGetSubMMRect2DownSample(img, nWidth, nHeight, pxSrImg, mmnSrSmpRect, 0);
|
|
|
}
|
|
|
else
|
|
|
{
|
|
|
IMGO_GDSGetSubMMRect(img, pxSrImg, (SINT16)nWidth, (SINT16)nHeight, mmnSrRect);
|
|
|
}
|
|
|
m_DST_stOutput.nDimFrmsCnt++;
|
|
|
|
|
|
//+++++++++++++++++++++++++++++++++++++++++++++++++++++++
|
|
|
////弱小目标检测算法未开启,则不执行后面的分块检测
|
|
|
//if (!m_GLB_bEanbleDimDetect)
|
|
|
//{
|
|
|
// //20170311:清空正在检测弱小目标的标记,防错
|
|
|
// m_DST_stPara.bDimDetecting = false;
|
|
|
|
|
|
// return ubObjsCnt;
|
|
|
//}
|
|
|
|
|
|
//+++++++++++++++++++++++++++++++++++++++++++++++++++++++
|
|
|
//计算弱小目标检测区域低频图、高频图--双边滤波
|
|
|
DST_BilateralFilterInt(pxSrImg, snSmpImgSize.w, snSmpImgSize.h, pDimBFLowImg, pDimBFHighImg);
|
|
|
|
|
|
//小目标检测
|
|
|
DST_FindExtremum(img, nWidth, nHeight, pDimBlkMaxPnt, pbBlkMaxPntFlag,
|
|
|
mmnSrRect.minY, mmnSrRect.minX, nBlkWidth, nBlkHeight,
|
|
|
nBlkNumW, nBlkNumH);
|
|
|
|
|
|
//判断极大值点是否为目标
|
|
|
ubObjsCnt = DST_DetectFrameTarget(img, nWidth, nHeight,
|
|
|
ptDimTargets, DST_DIMOBJ_BLK_NUM, pDimBlkMaxPnt,
|
|
|
nBlkNumW, nBlkNumH, pBlkPtBeTargetFlag);
|
|
|
|
|
|
//弱小目标检测时,采用恒虚警处理
|
|
|
ubObjsCnt = DST_FixedFADetect(ptDimTargets, ubObjsCnt, DST_DIMOBJ_BLK_NUM);
|
|
|
|
|
|
//更新弱小目标个数
|
|
|
m_DST_stOutput.nFrmDimObjsCnt = ubObjsCnt;
|
|
|
|
|
|
//关闭弱小目标检测
|
|
|
m_DST_stPara.bDimDetecting = false;
|
|
|
|
|
|
return ubObjsCnt;
|
|
|
}
|
|
|
|
|
|
|
|
|
/**********************************************************
|
|
|
* 函数名称:DST_BilateralFilterInt()
|
|
|
* 功能描述:恒虚警算法
|
|
|
* 输入参数:ptTargetArray -- 目标数组
|
|
|
* 输出参数:无
|
|
|
* 返 回 值:ubObjsCnt -- 目标个数
|
|
|
* 调用关系:无
|
|
|
* 其它说明:无
|
|
|
**********************************************************/
|
|
|
SINT32 DetectSmallObj::DST_FixedFADetect(TARGET_OBJECT* ptTargetArray, SINT32 ubObjsCnt, SINT32 nTargetNumMax)
|
|
|
{
|
|
|
SINT32 i;
|
|
|
SINT32 NumSNRMax = 0; //信噪比超过15的目标计数
|
|
|
SINT32 NumSNRLarger = 0; //信噪比超过5且小于15的目标计数
|
|
|
SINT32 NumSNRSmaller = 0; //信噪比不足5的目标计数
|
|
|
|
|
|
//SO_BubbleSort_TargetSNR(ptTargetArray, ubObjsCnt);
|
|
|
|
|
|
for (i = 0; i < ubObjsCnt; i++)
|
|
|
{
|
|
|
TARGET_OBJECT target = ptTargetArray[i];
|
|
|
if (target.bObject && target.fSNR >= 10)
|
|
|
{
|
|
|
NumSNRMax++;
|
|
|
}
|
|
|
else if (target.bObject && target.fSNR >= 5)
|
|
|
{
|
|
|
NumSNRLarger++;
|
|
|
}
|
|
|
else if (target.bObject)
|
|
|
{
|
|
|
NumSNRSmaller++;
|
|
|
}
|
|
|
else
|
|
|
{
|
|
|
//不处理;
|
|
|
}
|
|
|
}
|
|
|
|
|
|
//若SNR≥5的目标个数大于阈值,关闭恒虚警检测
|
|
|
if ((NumSNRLarger >= 2) || (NumSNRMax >= 1))
|
|
|
{
|
|
|
//m_GLB_stPara.nNoTargetFrameCnt = 0;
|
|
|
|
|
|
//20171013,强制提取时
|
|
|
if ((NumSNRLarger + NumSNRMax) > DST_FA_GUIDE_TARGET_NUM)
|
|
|
{
|
|
|
ubObjsCnt = DST_FA_GUIDE_TARGET_NUM;
|
|
|
}
|
|
|
else
|
|
|
{
|
|
|
ubObjsCnt = NumSNRLarger + NumSNRMax;
|
|
|
}
|
|
|
}
|
|
|
else if ((NumSNRLarger + NumSNRSmaller) >= DST_FA_GUIDE_TARGET_NUM)
|
|
|
{
|
|
|
ubObjsCnt = DST_FA_GUIDE_TARGET_NUM;
|
|
|
}
|
|
|
else
|
|
|
{
|
|
|
ubObjsCnt = NumSNRSmaller + NumSNRLarger;
|
|
|
}
|
|
|
|
|
|
//+++++++++++++++++++++++++++++++++++++++++++++++++++++++
|
|
|
//恒虚警算法关闭条件
|
|
|
if (!m_DST_stPara.bDimDetecting)
|
|
|
{
|
|
|
if ((NumSNRLarger >= 1) || (NumSNRMax >= 1))
|
|
|
{
|
|
|
//退出恒虚警帧计数器累加
|
|
|
//m_GLB_nExitFixedFA++;
|
|
|
m_DST_stOutput.nExitFixedFA++;
|
|
|
|
|
|
m_DST_stOutput.nExitFixedFA = MIN(m_DST_stOutput.nExitFixedFA, 65535); //防止数据溢出
|
|
|
}
|
|
|
else
|
|
|
{
|
|
|
//清空退出恒虚警帧计数器
|
|
|
m_DST_stOutput.nExitFixedFA = 0;
|
|
|
}
|
|
|
|
|
|
//20170524,连续5帧满足条件,关闭恒虚警开关
|
|
|
if (m_DST_stOutput.nExitFixedFA >= 5)
|
|
|
{
|
|
|
m_DST_stOutput.nExitFixedFA = 0;
|
|
|
//m_GLB_stPara.bEnableFixedFADetect = false;
|
|
|
//m_GLB_bEanbleDimDetect = false;
|
|
|
}
|
|
|
}
|
|
|
|
|
|
//memset(&ptTargetArray[ubObjsCnt], 0, sizeof(TARGET_OBJECT) * (nTargetNumMax - ubObjsCnt));
|
|
|
|
|
|
return ubObjsCnt;
|
|
|
}
|
|
|
|
|
|
|
|
|
/**********************************************************
|
|
|
* 函数名称:DST_BlkMaxTargetDetect()
|
|
|
* 功能描述:判断极大值区域是否为目标
|
|
|
* 输入参数:UINT16 *pFrame -- 原始图像
|
|
|
* SINT32 nWidth -- 图像宽度
|
|
|
* SINT32 nHeight -- 图像高度
|
|
|
* POINT16S pPnt -- 极值点坐标
|
|
|
* SINT32 *pnFilter -- 目标背景模板
|
|
|
* SINT32 nFilterBGW -- 目标背景模板 - 背景宽度
|
|
|
* SINT32 nFilterTGW -- 目标背景模板 - 目标宽度
|
|
|
* FLOAT32 fgdk -- 目标SNR阈值
|
|
|
* 输出参数:TARGET_OBJECT *tTarget -- 当前目标结构体
|
|
|
* 返 回 值:1-该极值点是目标,0-该极值点不是目标。
|
|
|
* 调用关系:无
|
|
|
* 其它说明:无
|
|
|
**********************************************************/
|
|
|
BBOOL DetectSmallObj::DST_BlkMaxTargetDetect(GD_VIDEO_FRAME_S img, SINT32 nWidth, SINT32 nHeight, POINT16S pPnt,
|
|
|
SINT32* pnFilter, SINT32 nFilterBGW, SINT32 nFilterTGW,
|
|
|
TARGET_OBJECT* ptTarget, FLOAT32 fgdk)
|
|
|
{
|
|
|
//指向数据空间: 标记检测到的目标像素点。0-非目标点,1-目标点。
|
|
|
SINT32* pnBlkTargetFlag = (SINT32*)DST_pnBlkTargetFlag;
|
|
|
|
|
|
SINT32 i, j;
|
|
|
BBOOL bIsTarget = false; //标记该极值点是否为目标
|
|
|
SINT32 nBGRadius = 0; //背景模板半径
|
|
|
SINT32 nTGRadius = 0; //目标模板半径
|
|
|
MINMAXRECT mmTGRect = { 0 }; //目标窗口边界
|
|
|
MINMAXRECT mmBGRect = { 0 }; //背景窗口边界
|
|
|
SINT32 nBGIndex = 0; //背景模板下标
|
|
|
SINT32 nBGFlter = 0; //背景模板系数
|
|
|
SINT32 nImgIndex = 0; //背景点/邻域点对应的原始图像坐标
|
|
|
SINT32 nBGValue = 0; //背景点灰度
|
|
|
SINT32 nBGCnt = 0; //背景点计数
|
|
|
double dBGMean = 0.0f; //背景均值
|
|
|
double dBGStd = 0.0f; //背景方差
|
|
|
SINT32 nCenterValue = 0; //中心点pPnt的灰度
|
|
|
SINT32 nPntValue = 0; //目标模板内像素的灰度值
|
|
|
FLOAT32 fBGStdOutput = 0.0f; //背景方差 -- 用于显示,没有经过下限限制
|
|
|
|
|
|
BBOOL bTargetPixel = false; //标记某像素点是否属于目标。用于统计目标大小。
|
|
|
FLOAT32 fgdkCoeff = 0.0f; //gdk下降系数。用于统计目标大小。
|
|
|
|
|
|
SINT32 nObjWH_LineW = 0; //目标宽高比统计 - 每行宽度
|
|
|
SINT32 nObjWH_LineWMax = 0; //目标宽高比统计 - 行宽度的最大值
|
|
|
|
|
|
FLOAT32 fPntgdk = 0.0f; //各点的gdk系数
|
|
|
SINT32 nTGValue = 0; //目标点灰度
|
|
|
SINT32 nCenterValueSumX = 0; //目标点灰度-X坐标乘积累加、目标点灰度-Y坐标乘积累加
|
|
|
SINT32 nCenterValueSumY = 0; //目标点灰度-X坐标乘积累加、目标点灰度-Y坐标乘积累加
|
|
|
|
|
|
SINT32 nValueDiff = 0; //背景点与中心点的灰度差值
|
|
|
SINT32 nValueDiffMin = 0; //背景点与中心点的灰度差的最小值
|
|
|
FLOAT32 fWHRatio = 0.0f; //目标宽高比
|
|
|
FLOAT32 fRectRatio = 0.0f; //目标矩形度
|
|
|
SINT32 nObjCenX = 0; //目标形心X、Y坐标
|
|
|
SINT32 nObjCenY = 0; //目标形心X、Y坐标
|
|
|
|
|
|
FLOAT32 fKernalBGVarMin2 = 0.0f; //背景方差下限阈值(可调参数-标准差下限的平方)
|
|
|
FLOAT32 fKernalBGVarMax2 = 0.0f; //背景方差上限阈值(可调参数-标准差上限的平方)
|
|
|
|
|
|
SINT32 nDimSmpScale = 1; //弱小检测搜索区域降采样倍数
|
|
|
SIZE32S snDimSrSmpImgSize = { 0 }; //弱小检测搜索区域尺寸:未降采样维持原尺寸,否则为降采样后尺寸
|
|
|
|
|
|
SINT32 nBGCntArray[4] = { 0 }; //20180115,记录上下左右邻域背景点个数
|
|
|
DOUBLE64 dBGMeanArray[4] = { 0.0f }; //20180115,记录上下左右邻域背景均值
|
|
|
DOUBLE64 dBGStdArray[4] = { 0.0f }; //20180115,记录上下左右邻域背景标准差
|
|
|
SINT32 nBGOuterRadius = 0; //20180115,回字形的外半径
|
|
|
SINT32 nMaxStdIndex = 0; //20180115,std最大的背景块下标
|
|
|
DOUBLE64 bBGStdMax = -1.0f; //20180115,方差最大的块
|
|
|
|
|
|
POINT16S pMaxPnt = pPnt; //20180918,极值点坐标
|
|
|
|
|
|
//+++++++++++++++++++++++++++++++++++++++++++++++++++++++
|
|
|
//初始化
|
|
|
bIsTarget = false;
|
|
|
nValueDiffMin = (SINT32)1e6;
|
|
|
memset(ptTarget, 0, sizeof(TARGET_OBJECT));
|
|
|
|
|
|
//+++++++++++++++++++++++++++++++++++++++++++++++++++++++
|
|
|
//参数设置
|
|
|
fgdkCoeff = 0.7f;
|
|
|
fKernalBGVarMin2 = m_DST_stPara.fKernalBGStdMin * m_DST_stPara.fKernalBGStdMin;
|
|
|
fKernalBGVarMax2 = m_DST_stPara.fKernalBGStdMax * m_DST_stPara.fKernalBGStdMax;
|
|
|
nBGRadius = (SINT32)(nFilterBGW >> 1);
|
|
|
nTGRadius = (SINT32)(nFilterTGW >> 1);
|
|
|
nBGOuterRadius = nBGRadius - nTGRadius; //20180115,回字形的外半径
|
|
|
nDimSmpScale = m_DST_stOutput.nDimSmpScale;
|
|
|
snDimSrSmpImgSize.w = (2 == nDimSmpScale) ? (m_DST_stOutput.snDimSrImgSize.w / nDimSmpScale + 1) : m_DST_stOutput.snDimSrImgSize.w;
|
|
|
snDimSrSmpImgSize.h = (2 == nDimSmpScale) ? (m_DST_stOutput.snDimSrImgSize.h / nDimSmpScale + 1) : m_DST_stOutput.snDimSrImgSize.h;
|
|
|
snDimSrSmpImgSize.s = snDimSrSmpImgSize.w * snDimSrSmpImgSize.h;
|
|
|
|
|
|
//+++++++++++++++++++++++++++++++++++++++++++++++++++++++
|
|
|
//获取中心点灰度值
|
|
|
//nCenterValue = pFrame[pPnt.y * nWidth + pPnt.x];
|
|
|
if (GD_PIXEL_FORMAT_GRAY_Y8 == img.enPixelFormat)
|
|
|
{
|
|
|
nCenterValue = ((UBYTE8*)img.u64VirAddr[0])[pPnt.y * nWidth + pPnt.x];
|
|
|
}
|
|
|
else
|
|
|
{
|
|
|
nCenterValue = ((UINT16*)img.u64VirAddr[0])[pPnt.y * nWidth + pPnt.x];
|
|
|
}
|
|
|
|
|
|
//+++++++++++++++++++++++++++++++++++++++++++++++++++++++
|
|
|
//统计背景均值、方差
|
|
|
//计算背景窗口边界
|
|
|
if (m_DST_stPara.bDimDetecting && (m_DST_stOutput.nDimSmpScale > 1))
|
|
|
{
|
|
|
SINT32 nBGRadiusRaw = nBGRadius * m_DST_stOutput.nDimSmpScale;
|
|
|
mmBGRect.minX = pPnt.x - nBGRadiusRaw;
|
|
|
mmBGRect.maxX = pPnt.x + nBGRadiusRaw;
|
|
|
mmBGRect.minY = pPnt.y - nBGRadiusRaw;
|
|
|
mmBGRect.maxY = pPnt.y + nBGRadiusRaw;
|
|
|
}
|
|
|
else
|
|
|
{
|
|
|
mmBGRect.minX = pPnt.x - nBGRadius;
|
|
|
mmBGRect.maxX = pPnt.x + nBGRadius;
|
|
|
mmBGRect.minY = pPnt.y - nBGRadius;
|
|
|
mmBGRect.maxY = pPnt.y + nBGRadius;
|
|
|
}
|
|
|
|
|
|
//防止越界
|
|
|
if (mmBGRect.minX<0 || mmBGRect.maxX>nWidth - 1 || mmBGRect.minY<0 || mmBGRect.maxY>nHeight - 1)
|
|
|
{
|
|
|
return false;
|
|
|
}
|
|
|
|
|
|
//+++++++++++++++++++++++++++++++++++++++++++++++++++++++
|
|
|
//统计背景均值、方差
|
|
|
nBGCnt = 0;
|
|
|
dBGMean = 0;
|
|
|
dBGStd = 0;
|
|
|
SINT32 nDiffMinBkgCnt = 0;
|
|
|
//基于双边滤波的弱目标检测:在低频图上计算背景均值,在高频图上计算背景标准差
|
|
|
if (!m_DST_stPara.bDimDetecting /*|| m_GLB_stPara.bEnableFixedFADetect*/)
|
|
|
{
|
|
|
SINT32 nBGLine = 0;
|
|
|
SINT32 nImgLine = mmBGRect.minY * nWidth + mmBGRect.minX;
|
|
|
for (i = 0; i < nFilterBGW; i++)
|
|
|
{
|
|
|
for (j = 0; j < nFilterBGW; j++)
|
|
|
{
|
|
|
nBGIndex = nBGLine + j;
|
|
|
nImgIndex = nImgLine + j;
|
|
|
nBGFlter = pnFilter[nBGIndex];
|
|
|
//nBGValue = pFrame[nImgIndex];
|
|
|
if (GD_PIXEL_FORMAT_GRAY_Y8 == img.enPixelFormat)
|
|
|
{
|
|
|
nBGValue = ((UBYTE8*)img.u64VirAddr[0])[nImgIndex];
|
|
|
}
|
|
|
else
|
|
|
{
|
|
|
nBGValue = ((UINT16*)img.u64VirAddr[0])[nImgIndex];
|
|
|
}
|
|
|
if (1 == nBGFlter)
|
|
|
{
|
|
|
//按上下左右顺序存邻域背景参数
|
|
|
if (j < nBGOuterRadius)
|
|
|
{
|
|
|
nBGCntArray[0]++;
|
|
|
dBGMeanArray[0] += (double)nBGValue;
|
|
|
dBGStdArray[0] += (double)nBGValue * nBGValue;
|
|
|
}
|
|
|
else if (j >= nFilterTGW + nBGOuterRadius)
|
|
|
{
|
|
|
nBGCntArray[1]++;
|
|
|
dBGMeanArray[1] += (double)nBGValue;
|
|
|
dBGStdArray[1] += (double)nBGValue * nBGValue;
|
|
|
}
|
|
|
else
|
|
|
{
|
|
|
//左邻域
|
|
|
if (i < nBGOuterRadius)
|
|
|
{
|
|
|
nBGCntArray[2]++;
|
|
|
dBGMeanArray[2] += (double)nBGValue;
|
|
|
dBGStdArray[2] += (double)nBGValue * nBGValue;
|
|
|
}
|
|
|
else
|
|
|
{
|
|
|
nBGCntArray[3]++;
|
|
|
dBGMeanArray[3] += (double)nBGValue;
|
|
|
dBGStdArray[3] += (double)nBGValue * nBGValue;
|
|
|
}
|
|
|
}
|
|
|
|
|
|
//查找背景中与中心点灰度差异最小的点的灰度
|
|
|
nValueDiff = ABS(nBGValue - nCenterValue);
|
|
|
if (nValueDiff < nValueDiffMin)
|
|
|
{
|
|
|
nValueDiffMin = nValueDiff;
|
|
|
}
|
|
|
}
|
|
|
}
|
|
|
|
|
|
//更新行起始坐标
|
|
|
nBGLine += nFilterBGW;
|
|
|
nImgLine += nWidth;
|
|
|
}
|
|
|
|
|
|
//计算4邻域的均值与方差
|
|
|
for (i = 0; i < 4; i++)
|
|
|
{
|
|
|
nBGCnt += nBGCntArray[i];
|
|
|
dBGMean += dBGMeanArray[i];
|
|
|
dBGStd += dBGStdArray[i];
|
|
|
|
|
|
dBGMeanArray[i] /= nBGCntArray[i];
|
|
|
dBGStdArray[i] /= nBGCntArray[i];
|
|
|
dBGStdArray[i] -= dBGMeanArray[i] * dBGMeanArray[i];
|
|
|
|
|
|
//找到方差最大的块
|
|
|
if (dBGStdArray[i] > bBGStdMax)
|
|
|
{
|
|
|
bBGStdMax = dBGStdArray[i];
|
|
|
nMaxStdIndex = i;
|
|
|
}
|
|
|
}
|
|
|
|
|
|
//抛掉方差最大的块
|
|
|
nBGCnt -= nBGCntArray[nMaxStdIndex];
|
|
|
dBGMean -= (dBGMeanArray[nMaxStdIndex] * nBGCntArray[nMaxStdIndex]);
|
|
|
dBGStd -= (nBGCntArray[nMaxStdIndex] * (dBGStdArray[nMaxStdIndex] + dBGMeanArray[nMaxStdIndex] * dBGMeanArray[nMaxStdIndex]));
|
|
|
|
|
|
dBGMean /= nBGCnt;
|
|
|
dBGStd /= nBGCnt;
|
|
|
dBGStd -= dBGMean * dBGMean;
|
|
|
}
|
|
|
else
|
|
|
{
|
|
|
//防止越界
|
|
|
if ((mmBGRect.minX < m_DST_stInput.mmnSemiSrRect.minX)
|
|
|
|| (mmBGRect.maxX > m_DST_stInput.mmnSemiSrRect.maxX)
|
|
|
|| (mmBGRect.minY < m_DST_stInput.mmnSemiSrRect.minY)
|
|
|
|| (mmBGRect.maxY > m_DST_stInput.mmnSemiSrRect.maxY))
|
|
|
{
|
|
|
return false;
|
|
|
}
|
|
|
|
|
|
SINT32 nBGLine = 0;
|
|
|
SINT32 nImgLine = ((mmBGRect.minY - m_DST_stInput.mmnSemiSrRect.minY) / nDimSmpScale) * snDimSrSmpImgSize.w
|
|
|
+ (mmBGRect.minX - m_DST_stInput.mmnSemiSrRect.minX) / nDimSmpScale;
|
|
|
SINT32 nBGValueLow = 0;
|
|
|
double dBGMeanLow = 0;
|
|
|
double dBGStdLow = 0;
|
|
|
SINT32 nBGValueHigh = 0;
|
|
|
double dBGMeanHigh = 0;
|
|
|
double dBGStdHigh = 0;
|
|
|
UINT16* pDimBFLowImg = (UINT16*)DST_pDimBFLowImg; //搜索区域双边滤波低频
|
|
|
SINT16* pDimBFHighImg = (SINT16*)DST_pDimBFHighImg; //搜索区域双边滤波高频
|
|
|
for (i = 0; i < nFilterBGW; i++)
|
|
|
{
|
|
|
for (j = 0; j < nFilterBGW; j++)
|
|
|
{
|
|
|
nBGIndex = nBGLine + j;
|
|
|
nImgIndex = nImgLine + j;
|
|
|
nBGFlter = pnFilter[nBGIndex];
|
|
|
nBGValueLow = pDimBFLowImg[nImgIndex];
|
|
|
nBGValueHigh = pDimBFHighImg[nImgIndex];
|
|
|
|
|
|
if (1 == nBGFlter)
|
|
|
{
|
|
|
//背景灰度及灰度平方累加
|
|
|
nBGCnt++;
|
|
|
dBGMeanLow += (double)nBGValueLow;
|
|
|
dBGStdLow += (double)nBGValueLow * nBGValueLow;
|
|
|
dBGMeanHigh += (double)nBGValueHigh;
|
|
|
dBGStdHigh += (double)nBGValueHigh * nBGValueHigh;
|
|
|
|
|
|
//查找背景中与中心点灰度差异最小的点的灰度
|
|
|
nValueDiff = ABS(nBGValueLow - nCenterValue);
|
|
|
// add 新增统计灰度差小于阈值的背景点数
|
|
|
if (nValueDiff < m_DST_stPara.nBTGrayMinThres)
|
|
|
{
|
|
|
nDiffMinBkgCnt++;
|
|
|
}
|
|
|
if (nValueDiff < nValueDiffMin)
|
|
|
{
|
|
|
nValueDiffMin = nValueDiff;
|
|
|
}
|
|
|
}
|
|
|
}
|
|
|
|
|
|
//更新行起始坐标
|
|
|
nBGLine += nFilterBGW;
|
|
|
nImgLine += snDimSrSmpImgSize.w;
|
|
|
}
|
|
|
|
|
|
//低频均值、方差
|
|
|
dBGMeanLow /= nBGCnt;
|
|
|
dBGStdLow /= nBGCnt;
|
|
|
dBGStdLow -= dBGMeanLow * dBGMeanLow;
|
|
|
|
|
|
//高频均值、方差
|
|
|
dBGMeanHigh /= nBGCnt;
|
|
|
dBGStdHigh /= nBGCnt;
|
|
|
dBGStdHigh -= dBGMeanHigh * dBGMeanHigh;
|
|
|
|
|
|
//背景均值、方差
|
|
|
dBGMean = dBGMeanLow;
|
|
|
dBGStd = dBGStdHigh;
|
|
|
}
|
|
|
|
|
|
//保存计算的背景均值及方差
|
|
|
fBGStdOutput = (FLOAT32)dBGStd;
|
|
|
|
|
|
//+++++++++++++++++++++++++++++++++++++++++++++++++++++++
|
|
|
//抛掉方差过大的块
|
|
|
if (m_DST_stPara.bUseDeFA_VarMax //去虚警策略“邻域方差上限限制”的开关
|
|
|
&& dBGStd > fKernalBGVarMax2) //判断邻域方差是否大于上限限制。
|
|
|
return false;
|
|
|
|
|
|
//设置背景方差下限
|
|
|
if (m_DST_stPara.bUseDeFA_VarMin //去虚警策略“邻域方差下限限制”的开关
|
|
|
&& !m_DST_stPara.bDimDetecting
|
|
|
&& !m_DST_stPara.bSecDetecting
|
|
|
&& dBGStd < fKernalBGVarMin2) //背景方差下限修改,20190508
|
|
|
{
|
|
|
dBGStd = (double)fKernalBGVarMin2;
|
|
|
}
|
|
|
|
|
|
//+++++++++++++++++++++++++++++++++++++++++++++++++++++++
|
|
|
//gdk不做自适应调节,直接赋给PC机传入的可调参数m_DST_stPara.fgdk
|
|
|
fPntgdk = fgdk;
|
|
|
|
|
|
//20160409: 基于双边滤波的弱目标检测,提高阈值
|
|
|
//20170311: 针对阿拉善试验对S-200探测距离不足,降低弱目标检测阈值。
|
|
|
if (m_DST_stPara.bDimDetecting)
|
|
|
{
|
|
|
fPntgdk = MAX(2.0f, fgdk - 2.0f);
|
|
|
}
|
|
|
//else if (m_GLB_stPara.bEnableFixedFADetect)
|
|
|
//{
|
|
|
// fPntgdk = MAX(2.0f, fgdk - 5.0f);
|
|
|
//}
|
|
|
else
|
|
|
{
|
|
|
//不处理
|
|
|
}
|
|
|
|
|
|
//+++++++++++++++++++++++++++++++++++++++++++++++++++++++
|
|
|
//目标检测初始化
|
|
|
//计算目标核边界
|
|
|
if (m_DST_stPara.bDimDetecting && (m_DST_stOutput.nDimSmpScale > 1))
|
|
|
{
|
|
|
SINT32 nTGRadiusRaw = nTGRadius * m_DST_stOutput.nDimSmpScale;
|
|
|
mmTGRect.minX = pPnt.x - nTGRadiusRaw;
|
|
|
mmTGRect.maxX = pPnt.x + nTGRadiusRaw;
|
|
|
mmTGRect.minY = pPnt.y - nTGRadiusRaw;
|
|
|
mmTGRect.maxY = pPnt.y + nTGRadiusRaw;
|
|
|
nTGRadius = nTGRadius * m_DST_stOutput.nDimSmpScale;
|
|
|
nFilterTGW = (nTGRadius << 1) + 1;
|
|
|
}
|
|
|
else
|
|
|
{
|
|
|
mmTGRect.minX = pPnt.x - nTGRadius;
|
|
|
mmTGRect.maxX = pPnt.x + nTGRadius;
|
|
|
mmTGRect.minY = pPnt.y - nTGRadius;
|
|
|
mmTGRect.maxY = pPnt.y + nTGRadius;
|
|
|
}
|
|
|
|
|
|
//初始化
|
|
|
ptTarget->mrnRect.minY = mmTGRect.maxY;
|
|
|
ptTarget->mrnRect.maxY = mmTGRect.minY;
|
|
|
ptTarget->mrnRect.minX = mmTGRect.maxX;
|
|
|
ptTarget->mrnRect.maxX = mmTGRect.minX;
|
|
|
nCenterValueSumX = 0;
|
|
|
nCenterValueSumY = 0;
|
|
|
nTGValue = 0;
|
|
|
|
|
|
//记录目标的类型
|
|
|
ptTarget->nObjTypeGray = (nCenterValue < (SINT32)dBGMean) ? GLB_OBJ_GRAY_DARK : GLB_OBJ_GRAY_BRIGHT;
|
|
|
|
|
|
//20120304:根据系统所要检测的目标类型进行区分
|
|
|
if (DST_DETECT_OBJ_TYPE_DARK == m_DST_stPara.nDetectGrayType) //只检测暗目标
|
|
|
{
|
|
|
//20120229: 剔除亮目标。根据夜晚试验气球为暗目标的特性,做出目标类型的限制。
|
|
|
if (GLB_OBJ_GRAY_BRIGHT == ptTarget->nObjTypeGray)
|
|
|
return FALSE;
|
|
|
}
|
|
|
else if (DST_DETECT_OBJ_TYPE_BRIGHT == m_DST_stPara.nDetectGrayType) //只检测亮目标
|
|
|
{
|
|
|
//跳过暗目标
|
|
|
if (GLB_OBJ_GRAY_DARK == ptTarget->nObjTypeGray)
|
|
|
return FALSE;
|
|
|
}
|
|
|
else
|
|
|
{
|
|
|
//不处理
|
|
|
}
|
|
|
//+++++++++++++++++++++++++++++++++++++++++++++++++++++++
|
|
|
//提前计算参数,简化计算
|
|
|
double fPntgdkByStd = fPntgdk * fPntgdk * dBGStd;
|
|
|
|
|
|
//+++++++++++++++++++++++++++++++++++++++++++++++++++++++
|
|
|
//目标检测:基于目标信噪比的检测方法
|
|
|
//首先判断极值点是否为目标
|
|
|
//20111115: 若m_DST_nDectectMinPnt==TRUE,则为判断极大值点或极小值点是否为目标
|
|
|
//若极值点不满足SNR条件,则判断该点是否满足灰度阈值判断的条件
|
|
|
if ((nCenterValue - dBGMean) * (nCenterValue - dBGMean) <= fPntgdkByStd)
|
|
|
{
|
|
|
//标记该点不是目标,直接返回
|
|
|
return false;
|
|
|
}
|
|
|
//若极值点是目标,则统计目标的大小
|
|
|
else
|
|
|
{
|
|
|
//标记该点为目标
|
|
|
bIsTarget = true;
|
|
|
|
|
|
//去虚警:抛掉方差过大的块
|
|
|
if (m_DST_stPara.bUseDeFA_VarMax
|
|
|
&& dBGStd > m_DST_stPara.fKernalBGStdMax)
|
|
|
{
|
|
|
bIsTarget = false;
|
|
|
}
|
|
|
|
|
|
//去虚警:抛掉极值点与背景最小灰度差小于阈值的块
|
|
|
SINT32 nBTGrayMinThres = m_DST_stPara.nBTGrayMinThres;
|
|
|
|
|
|
if (m_DST_stPara.bDimDetecting)
|
|
|
{
|
|
|
nBTGrayMinThres = 3;
|
|
|
m_DST_stPara.bUseDeFA_BTGrayMin = false;
|
|
|
}
|
|
|
|
|
|
|
|
|
if (m_DST_stPara.bUseDeFA_BTGrayMin
|
|
|
&& nValueDiffMin < nBTGrayMinThres
|
|
|
&& nDiffMinBkgCnt > nBGCnt * 0.3)
|
|
|
{
|
|
|
bIsTarget = false;
|
|
|
}
|
|
|
|
|
|
//若该点不是目标,则跳过剩余计算
|
|
|
if (!bIsTarget)
|
|
|
{
|
|
|
return false;
|
|
|
}
|
|
|
|
|
|
//降低gdk阈值统计目标大小
|
|
|
fPntgdk *= fgdkCoeff;
|
|
|
fPntgdk = MAX(fPntgdk, 4.0f);
|
|
|
|
|
|
//20170313,二次检测降低阈值
|
|
|
if (m_DST_stPara.bSecDetecting && m_DST_stPara.bEnableSecDetect)
|
|
|
{
|
|
|
fPntgdk = MAX(fPntgdk, 2.0f);
|
|
|
}
|
|
|
|
|
|
//20160409: 基于双边滤波的弱目标检测,提高阈值
|
|
|
if (m_DST_stPara.bDimDetecting)
|
|
|
{
|
|
|
fPntgdk = (float)(sqrt((nCenterValue - dBGMean) * (nCenterValue - dBGMean) / MAX(dBGStd, 0.01)));
|
|
|
fPntgdk = MAX(5.0f, fPntgdk * 0.9f);
|
|
|
}
|
|
|
|
|
|
//提前计算参数,简化计算
|
|
|
double fPntgdkByStdNew = fPntgdk * fPntgdk * dBGStd;
|
|
|
|
|
|
//搜索目标边界
|
|
|
nObjWH_LineWMax = 0;
|
|
|
SINT32 nLine = (pPnt.y - nTGRadius) * nWidth + pPnt.x - nTGRadius;
|
|
|
SINT32 nFlagLine = 0;
|
|
|
SINT32 nFlagIndex = 0;
|
|
|
for (i = 0; i < nFilterTGW; i++)
|
|
|
{
|
|
|
//初始化每行宽度
|
|
|
nObjWH_LineW = 0;
|
|
|
|
|
|
for (j = 0; j < nFilterTGW; j++)
|
|
|
{
|
|
|
//获取目标区域各点的图像坐标
|
|
|
nImgIndex = nLine + j;
|
|
|
|
|
|
//获取目标区域各点灰度值
|
|
|
//nPntValue = pFrame[nImgIndex];
|
|
|
if (GD_PIXEL_FORMAT_GRAY_Y8 == img.enPixelFormat)
|
|
|
{
|
|
|
nPntValue = ((UBYTE8*)img.u64VirAddr[0])[nImgIndex];
|
|
|
}
|
|
|
else
|
|
|
{
|
|
|
nPntValue = ((UINT16*)img.u64VirAddr[0])[nImgIndex];
|
|
|
}
|
|
|
//提前计算参数,简化计算
|
|
|
double dValueDiff = nPntValue - dBGMean;
|
|
|
double dValueDiffSquare = dValueDiff * dValueDiff;
|
|
|
|
|
|
//判断该点是否属于目标点(采用SNR判断方法)
|
|
|
//20180918,应根据当前点的目标灰度类型判别
|
|
|
bTargetPixel = false;
|
|
|
if ((i == j && i == nTGRadius)
|
|
|
|| (DST_DETECT_OBJ_TYPE_BRIGHT == ptTarget->nObjTypeGray && nPntValue > dBGMean && dValueDiffSquare > fPntgdkByStdNew)
|
|
|
|| (DST_DETECT_OBJ_TYPE_DARK == ptTarget->nObjTypeGray && nPntValue < dBGMean && dValueDiffSquare > fPntgdkByStdNew))
|
|
|
{
|
|
|
bTargetPixel = true;
|
|
|
|
|
|
//20170330,对于弱小目标认为是孤立点,不再遍历邻域区域
|
|
|
if ((m_DST_stPara.bSecDetecting || m_DST_stPara.bDimDetecting)
|
|
|
&& !(i == j && i == nTGRadius))
|
|
|
{
|
|
|
bTargetPixel = false;
|
|
|
}
|
|
|
}
|
|
|
|
|
|
//查找目标边界,并统计大小
|
|
|
if (bTargetPixel)
|
|
|
{
|
|
|
//统计行宽
|
|
|
nObjWH_LineW++;
|
|
|
|
|
|
//查找目标边界
|
|
|
SINT32 nImgX = j + mmTGRect.minX;
|
|
|
SINT32 nImgY = i + mmTGRect.minY;
|
|
|
ptTarget->mrnRect.minY = MIN(ptTarget->mrnRect.minY, nImgY);
|
|
|
ptTarget->mrnRect.maxY = MAX(ptTarget->mrnRect.maxY, nImgY);
|
|
|
ptTarget->mrnRect.minX = MIN(ptTarget->mrnRect.minX, nImgX);
|
|
|
ptTarget->mrnRect.maxX = MAX(ptTarget->mrnRect.maxX, nImgX);
|
|
|
|
|
|
//统计目标质心. 20110524
|
|
|
nCenterValueSumX += nImgX * nPntValue;
|
|
|
nCenterValueSumY += nImgY * nPntValue;
|
|
|
nTGValue += nPntValue;
|
|
|
|
|
|
//统计目标大小
|
|
|
ptTarget->unObjPxlsCnt++;
|
|
|
|
|
|
//标记目标区域内目标点
|
|
|
nFlagIndex = nFlagLine + j;
|
|
|
pnBlkTargetFlag[nFlagIndex] = 1;
|
|
|
//20180918,更新极值点坐标和值
|
|
|
if (GLB_OBJ_GRAY_BRIGHT == ptTarget->nObjTypeGray)
|
|
|
{
|
|
|
//若当前点灰度大于极值点,更新极值点
|
|
|
if (nPntValue > nCenterValue)
|
|
|
{
|
|
|
nCenterValue = nPntValue;
|
|
|
pMaxPnt.x = pPnt.x - nTGRadius + j;
|
|
|
pMaxPnt.y = pPnt.y - nTGRadius + i;
|
|
|
}
|
|
|
}
|
|
|
else
|
|
|
{
|
|
|
//若当前点灰度小于极值点,更新极值点
|
|
|
if (nPntValue < nCenterValue)
|
|
|
{
|
|
|
nCenterValue = nPntValue;
|
|
|
pMaxPnt.x = pPnt.x - nTGRadius + j;
|
|
|
pMaxPnt.y = pPnt.y - nTGRadius + i;
|
|
|
}
|
|
|
}
|
|
|
}
|
|
|
}
|
|
|
|
|
|
//查找最大行宽
|
|
|
nObjWH_LineWMax = MAX(nObjWH_LineWMax, nObjWH_LineW);
|
|
|
|
|
|
//更新下一行起始坐标
|
|
|
nLine += nWidth;
|
|
|
nFlagLine += nFilterTGW;
|
|
|
}//end of for (j = 0; j < nKernelSize_TG; j++)...
|
|
|
}//end of else...
|
|
|
|
|
|
//+++++++++++++++++++++++++++++++++++++++++++++++++++++++
|
|
|
//统计目标信息
|
|
|
if (bIsTarget)
|
|
|
{
|
|
|
//计算统计目标质心
|
|
|
if (0 == nTGValue) //防止出错,例如当阈值设置不恰当时,连目标的极大值点都未统计到目标的大小中
|
|
|
{
|
|
|
//ptTarget->pfCenPos.x = (FLOAT32)pPnt.x;
|
|
|
//ptTarget->pfCenPos.y = (FLOAT32)pPnt.y;
|
|
|
ptTarget->pfCenPos.x = (FLOAT32)pMaxPnt.x;
|
|
|
ptTarget->pfCenPos.y = (FLOAT32)pMaxPnt.y;
|
|
|
}
|
|
|
else
|
|
|
{
|
|
|
ptTarget->pfCenPos.x = (FLOAT32)nCenterValueSumX / nTGValue;
|
|
|
ptTarget->pfCenPos.y = (FLOAT32)nCenterValueSumY / nTGValue;
|
|
|
}
|
|
|
|
|
|
//统计目标的灰度(极大值灰度)
|
|
|
//20180918,取极大值灰度
|
|
|
//ptTarget->pxObjGray = (UINT16)((pFrame[pPnt.y * nWidth + pPnt.x] + pFrame[(pPnt.y + 1) * nWidth + pPnt.x] + pFrame[(pPnt.y ) * nWidth + pPnt.x + 1]
|
|
|
// + pFrame[(pPnt.y - 1) * nWidth + pPnt.x] + pFrame[pPnt.y * nWidth + pPnt.x - 1] ) / 5);
|
|
|
//ptTarget->pxObjGray = (UINT16)(pFrame[pMaxPnt.y * nWidth + pMaxPnt.x]);
|
|
|
//ptTarget->pxObjMaxGray = (UINT16)(pFrame[pMaxPnt.y * nWidth + pMaxPnt.x]); //20200511
|
|
|
if (GD_PIXEL_FORMAT_GRAY_Y8 == img.enPixelFormat)
|
|
|
{
|
|
|
ptTarget->pxObjGray = (((UBYTE8*)img.u64VirAddr[0])[pMaxPnt.y * nWidth + pMaxPnt.x]);
|
|
|
ptTarget->pxObjMaxGray = (((UBYTE8*)img.u64VirAddr[0])[pMaxPnt.y * nWidth + pMaxPnt.x]); //20200511
|
|
|
|
|
|
ptTarget->fGrayNeighbor[0] = (((UBYTE8*)img.u64VirAddr[0])[(pMaxPnt.y - 1) * nWidth + pMaxPnt.x]);
|
|
|
ptTarget->fGrayNeighbor[1] = (((UBYTE8*)img.u64VirAddr[0])[pMaxPnt.y * nWidth + pMaxPnt.x + 1]);
|
|
|
ptTarget->fGrayNeighbor[2] = (((UBYTE8*)img.u64VirAddr[0])[(pMaxPnt.y + 1) * nWidth + pMaxPnt.x]);
|
|
|
ptTarget->fGrayNeighbor[3] = (((UBYTE8*)img.u64VirAddr[0])[pMaxPnt.y * nWidth + pMaxPnt.x - 1]);
|
|
|
}
|
|
|
else
|
|
|
{
|
|
|
ptTarget->pxObjGray = (((UINT16*)img.u64VirAddr[0])[pMaxPnt.y * nWidth + pMaxPnt.x]);
|
|
|
ptTarget->pxObjMaxGray = (((UINT16*)img.u64VirAddr[0])[pMaxPnt.y * nWidth + pMaxPnt.x]); //20200511
|
|
|
|
|
|
ptTarget->fGrayNeighbor[0] = (((UINT16*)img.u64VirAddr[0])[(pMaxPnt.y - 1) * nWidth + pMaxPnt.x]);
|
|
|
ptTarget->fGrayNeighbor[1] = (((UINT16*)img.u64VirAddr[0])[pMaxPnt.y * nWidth + pMaxPnt.x + 1]);
|
|
|
ptTarget->fGrayNeighbor[2] = (((UINT16*)img.u64VirAddr[0])[(pMaxPnt.y + 1) * nWidth + pMaxPnt.x]);
|
|
|
ptTarget->fGrayNeighbor[3] = (((UINT16*)img.u64VirAddr[0])[pMaxPnt.y * nWidth + pMaxPnt.x - 1]);
|
|
|
}
|
|
|
//记录目标极大值点坐标
|
|
|
//ptTarget->pnMaxPos = pPnt;
|
|
|
ptTarget->pnMaxPos = pMaxPnt;
|
|
|
|
|
|
//计算目标宽、高、面积
|
|
|
ptTarget->snSize.h = ptTarget->mrnRect.maxY - ptTarget->mrnRect.minY + 1;
|
|
|
ptTarget->snSize.w = ptTarget->mrnRect.maxX - ptTarget->mrnRect.minX + 1;
|
|
|
ptTarget->snSize.s = ptTarget->snSize.h * ptTarget->snSize.w;
|
|
|
|
|
|
//记录背景均值、背景方差、目标背景信噪比
|
|
|
ptTarget->fBGMean = (FLOAT32)dBGMean;
|
|
|
ptTarget->fBGStd = (FLOAT32)sqrt(fBGStdOutput);
|
|
|
ptTarget->fSNR = (FLOAT32)(nCenterValue - dBGMean) / (ptTarget->fBGStd + 0.01f);
|
|
|
// 适应目标识别算法的加入,传统检测无法获取目标类型,此处约定目标类别ID置为DT_TARGET_CLS_ID,置信度为1
|
|
|
ptTarget->unClsType = DT_TARGET_CLS_ID;
|
|
|
ptTarget->fDetConf = 1.0;
|
|
|
ptTarget->nObjTypeSrc = ObjSrc::Arith_DST;
|
|
|
//标记目标类型
|
|
|
ptTarget->nObjTypeSize = GLB_OBJ_SIZE_SMALL;
|
|
|
|
|
|
//20160409: 标记弱目标
|
|
|
if (m_DST_stPara.bDimDetecting)
|
|
|
{
|
|
|
ptTarget->nObjTypeSize = GLB_OBJ_SIZE_DIMSMALL;
|
|
|
}
|
|
|
|
|
|
//20170311:若当前为弱小目标检测,则抛掉尺寸过大的目标
|
|
|
if (m_DST_stPara.bDimDetecting &&
|
|
|
(ptTarget->unObjPxlsCnt > 4 || ptTarget->snSize.w > 3 || ptTarget->snSize.h > 3))
|
|
|
{
|
|
|
bIsTarget = false;
|
|
|
}
|
|
|
|
|
|
//20210323wl 屏蔽掉不适合本项目
|
|
|
////20170313,对像素点个数小于2的暗目标不检测
|
|
|
////20171223,检测阶段
|
|
|
//if (ptTarget->nObjTypeGray == DST_OBJ_TYPE_DARK
|
|
|
// && ptTarget->unObjPxlsCnt < 4
|
|
|
// /*&& GLB_STATUS_TRACK != m_GLB_stPara.nStatus*/)
|
|
|
//{
|
|
|
// bIsTarget = false;
|
|
|
//}
|
|
|
|
|
|
//去虚警:抛掉大小不符合要求的目标
|
|
|
if (m_DST_stPara.bUseDeFA_Size //去虚警策略“目标大小限制”的开关
|
|
|
&& !m_DST_stPara.bDimDetecting
|
|
|
&& !m_DST_stPara.bSecDetecting
|
|
|
&& (ptTarget->unObjPxlsCnt < (UINT32)m_DST_stPara.nObjSizeMin
|
|
|
|| ptTarget->unObjPxlsCnt >(UINT32)m_DST_stPara.nObjSizeMax))
|
|
|
{
|
|
|
bIsTarget = false;
|
|
|
}
|
|
|
|
|
|
//去虚警:抛掉长宽比不符合要求的目标
|
|
|
//目标宽高比计算方式2 - 最大行宽度/总高度
|
|
|
//if (GLB_STATUS_TRACK == m_GLB_stPara.nStatus)
|
|
|
//{
|
|
|
// m_DST_stPara.nObjWHRatioMethod = DST_OBJ_WHRATIO_TOTALWH;
|
|
|
//}
|
|
|
//else
|
|
|
//{
|
|
|
// m_DST_stPara.nObjWHRatioMethod = DST_OBJ_WHRATIO_LINEWH;
|
|
|
//}
|
|
|
if (DST_OBJ_WHRATIO_LINEWH == m_DST_stPara.nObjWHRatioMethod)
|
|
|
{
|
|
|
fWHRatio = (FLOAT32)nObjWH_LineWMax / ptTarget->snSize.h;
|
|
|
}
|
|
|
//目标宽高比计算方式1 - 总宽度/总高度
|
|
|
else
|
|
|
{
|
|
|
fWHRatio = (FLOAT32)(ptTarget->snSize.w) / ptTarget->snSize.h;
|
|
|
}
|
|
|
|
|
|
if (m_DST_stPara.bUseDeFA_WHRatio //去虚警策略“目标宽高比限制”的开关
|
|
|
&& ((fWHRatio < 1 && fWHRatio < m_DST_stPara.fObjWHRatioMin)
|
|
|
|| (fWHRatio > 1 && fWHRatio > m_DST_stPara.fObjWHRatioMax)))
|
|
|
{
|
|
|
bIsTarget = false;
|
|
|
}
|
|
|
|
|
|
//去虚警:抛掉矩形度不符合要求的目标
|
|
|
fRectRatio = (FLOAT32)ptTarget->unObjPxlsCnt / ptTarget->snSize.s;
|
|
|
if (m_DST_stPara.bUseDeFA_RectRatio //去虚警策略“目标矩形度限制”的开关
|
|
|
&& fRectRatio < m_DST_stPara.fObjRectRatioMin)
|
|
|
{
|
|
|
bIsTarget = false;
|
|
|
}
|
|
|
|
|
|
//去虚警:抛掉形心不是目标标记点的目标(形状不规则)
|
|
|
nObjCenX = (ptTarget->mrnRect.minX + ptTarget->mrnRect.maxX) >> 1;
|
|
|
nObjCenY = (ptTarget->mrnRect.minY + ptTarget->mrnRect.maxY) >> 1;
|
|
|
if (m_DST_stPara.bUseDeFA_CenFlag //去虚警策略“形心为目标点”的开关
|
|
|
&& !pnBlkTargetFlag[(nObjCenY - mmTGRect.minY) * nFilterTGW + nObjCenX - mmTGRect.minX])
|
|
|
{
|
|
|
if (ABS(nObjCenX - ptTarget->pfCenPos.x) > 1 || ABS(nObjCenY - ptTarget->pfCenPos.y) > 1)
|
|
|
{
|
|
|
bIsTarget = false;
|
|
|
}
|
|
|
}
|
|
|
}
|
|
|
|
|
|
return bIsTarget;
|
|
|
}
|
|
|
|
|
|
|
|
|
/**********************************************************
|
|
|
* 函数名称:CalGuassGrayWeightTable()
|
|
|
* 功能描述:计算双边滤波灰度权重表
|
|
|
* 输入参数:UINT16 *pnGrayWeightTable-- 灰度权重表指针
|
|
|
* SINT32 nLen -- 灰度权重表长度
|
|
|
* SINT32 nStd -- 标准差
|
|
|
* 输出参数:UINT16 *pnGrayWeightTable-- 灰度权重表指针
|
|
|
* 返 回 值:无
|
|
|
* 调用关系:无
|
|
|
* 其它说明:无
|
|
|
**********************************************************/
|
|
|
void DetectSmallObj::DST_CalGuassGrayWeightTable(UINT16* pnGrayWeightTable, SINT32 nLen, SINT32 nStd)
|
|
|
{
|
|
|
SINT32 i;
|
|
|
double dArg = 0.0;
|
|
|
for (i = 0; i < nLen; i++)
|
|
|
{
|
|
|
dArg = -(i * i * 1.0) / (2 * nStd * nStd);
|
|
|
pnGrayWeightTable[i] = (UINT16)(exp(dArg) * 4096 + 0.5);
|
|
|
}
|
|
|
}
|
|
|
|
|
|
|
|
|
/**********************************************************
|
|
|
* 函数名称:DST_GetGuassGrayWeightFromTable()
|
|
|
* 功能描述:查表得到局部窗口像素对应的权重值
|
|
|
* 输入参数:UINT16 *pFrame -- 原始图像
|
|
|
* UINT16 *pnTable -- 权重表
|
|
|
* UINT16 *pnGrayWeight -- 局部权重表
|
|
|
* SINT32 nTableLen -- 权重表长度
|
|
|
* SINT32 nWidth -- 图像宽度
|
|
|
* SINT32 nHeight -- 图像高度
|
|
|
* 输出参数:UINT16 *pnGrayWeight -- 局部权重表
|
|
|
* 返 回 值:无
|
|
|
* 调用关系:无
|
|
|
* 其它说明:无
|
|
|
**********************************************************/
|
|
|
void DetectSmallObj::DST_GetGuassGrayWeightFromTable(UINT16* pFrame, UINT16* pnTable,
|
|
|
UINT16* pnGrayWeight, SINT32 nTableLen,
|
|
|
SINT32 nWidth, SINT32 nHeight)
|
|
|
{
|
|
|
SINT32 i;
|
|
|
SINT32 nLen = nWidth * nHeight;
|
|
|
SINT32 nCenterY = (nHeight - 1) / 2;
|
|
|
SINT32 nCenterX = (nWidth - 1) / 2;
|
|
|
SINT32 fCen_data = pFrame[nCenterY * nWidth + nCenterX];
|
|
|
SINT32 nIndex;
|
|
|
|
|
|
for (i = 0; i < nLen; i++)
|
|
|
{
|
|
|
nIndex = abs(pFrame[i] - fCen_data);
|
|
|
nIndex = MIN(nIndex, nTableLen - 1);
|
|
|
pnGrayWeight[i] = (UINT16)(pnTable[nIndex]);
|
|
|
}
|
|
|
}
|
|
|
|
|
|
|
|
|
/**********************************************************
|
|
|
* 函数名称:DST_BilateralFilterInt()
|
|
|
* 功能描述:二维双边滤波(整型)
|
|
|
* 输入参数:UINT16 *pFrame -- 原始图像
|
|
|
* SINT32 nWidth -- 图像宽度
|
|
|
* SINT32 nHeight -- 图像高度
|
|
|
* 输出参数:UINT16 *pnLowImg -- 低频图
|
|
|
* SINT16 *pnHighImg -- 高频图
|
|
|
* 返 回 值:无
|
|
|
* 调用关系:无
|
|
|
* 其它说明:无
|
|
|
**********************************************************/
|
|
|
void DetectSmallObj::DST_BilateralFilterInt(UINT16* pFrame, SINT32 nWidth, SINT32 nHeight,
|
|
|
UINT16* pnLowImg, SINT16* pnHighImg)
|
|
|
{
|
|
|
UINT16* pGrayWeightTable = (UINT16*)DST_pDimBFGrayWeightTable;
|
|
|
|
|
|
SINT32 i, j, m, n;
|
|
|
SINT32 nLen = nWidth * nHeight;
|
|
|
SINT32 nFilterWidth = 3; //滤波窗口宽度
|
|
|
SINT32 nFilterHeight = 3; //滤波窗口高度
|
|
|
SINT32 nFilterHalfW = (SINT32)(nFilterWidth / 2); //滤波窗口半径-宽度
|
|
|
SINT32 nFilterHalfH = (SINT32)(nFilterHeight / 2); //滤波窗口半径-高度
|
|
|
SINT32 nFilterSize = nFilterWidth * nFilterHeight; //滤波窗口总像素个数
|
|
|
SINT32 nGrayStd = 20; //灰度标准差
|
|
|
double dWeight = 0.0; //注意数据位宽
|
|
|
double dSum = 0.0; //注意数据位宽,不能用long
|
|
|
|
|
|
//滤波数据临时空间
|
|
|
UINT16 pnNearGrayWeight[9] = { 0 }; //滤波窗口灰度权重表
|
|
|
UINT16 pnNearImg[9] = { 0 }; //滤波数据临时空间
|
|
|
|
|
|
//+++++++++++++++++++++++++++++++++++++++++++++++++++++++
|
|
|
//计算灰度高斯权值映射表
|
|
|
DST_CalGuassGrayWeightTable(pGrayWeightTable, DST_DIM_BFGWEIGHT_LEN, nGrayStd);
|
|
|
|
|
|
//+++++++++++++++++++++++++++++++++++++++++++++++++++++++
|
|
|
//计算低频图:对每个点进行双边滤波
|
|
|
for (i = 0; i < nHeight; i++)
|
|
|
{
|
|
|
for (j = 0; j < nWidth; j++)
|
|
|
{
|
|
|
SINT32 nCnt = 0;
|
|
|
SINT32 posX = 0;
|
|
|
SINT32 posY = 0;
|
|
|
|
|
|
//遍历该点邻域
|
|
|
for (m = -nFilterHalfH; m <= nFilterHalfH; m++)
|
|
|
{
|
|
|
for (n = -nFilterHalfW; n <= nFilterHalfW; n++)
|
|
|
{
|
|
|
//防止越界
|
|
|
if (m + i < 0 || m + i >= nHeight)
|
|
|
posY = i;
|
|
|
else
|
|
|
posY = m + i;
|
|
|
if (n + j < 0 || n + j >= nWidth)
|
|
|
posX = j;
|
|
|
else
|
|
|
posX = j + n;
|
|
|
|
|
|
//获取邻域像素
|
|
|
pnNearImg[nCnt] = pFrame[posY * nWidth + posX];
|
|
|
nCnt++;
|
|
|
}
|
|
|
}
|
|
|
|
|
|
//查表得到当前的灰度高斯加权系数
|
|
|
DST_GetGuassGrayWeightFromTable(pnNearImg, pGrayWeightTable, pnNearGrayWeight,
|
|
|
DST_DIM_BFGWEIGHT_LEN, nFilterWidth, nFilterHeight);
|
|
|
|
|
|
//计算去噪窗口滤波结果及权重值
|
|
|
dWeight = 0.0;
|
|
|
dSum = 0.0;
|
|
|
for (m = 0; m < nFilterSize; m++)
|
|
|
{
|
|
|
dSum += pnNearImg[m] * pnNearGrayWeight[m];
|
|
|
dWeight += pnNearGrayWeight[m];
|
|
|
}
|
|
|
pnLowImg[i * nWidth + j] = (UINT16)(dSum / dWeight);
|
|
|
}
|
|
|
}
|
|
|
|
|
|
//+++++++++++++++++++++++++++++++++++++++++++++++++++++++
|
|
|
//计算高频图
|
|
|
for (i = 0; i < nLen; i++)
|
|
|
{
|
|
|
pnHighImg[i] = pFrame[i] - pnLowImg[i];
|
|
|
|
|
|
if (pnHighImg[i] > 200)
|
|
|
{
|
|
|
int a = 0;
|
|
|
}
|
|
|
}
|
|
|
}
|
|
|
|