📄 target.cpp
字号:
}
pTarget->maxRect.right= x;
ypt++;
}
}
int idx= (pTarget->maxRect.right + pTarget->maxRect.left) / 2;
top= pTarget->pLineY[idx].iMin;
bottom= pTarget->pLineY[idx].iMax;
pTarget->rect.top= top; pTarget->rect.bottom= bottom + 1;
int left= 0, right= 0, xpt= 0;
bool by= true;
for (int y= 0; y < pTarget->iLineCountX; y++)
{
if (pTarget->pLineX[y].iMin >= 0)
{
if (by)
{
pTarget->maxRect.top= y;
pTarget->maxRect.bottom= y;
by= !by;
}
pTarget->maxRect.bottom= y;
xpt++;
}
}
int idy= (pTarget->maxRect.top + pTarget->maxRect.bottom) / 2;
left= pTarget->pLineX[idy].iMin;
right= pTarget->pLineX[idy].iMax;
pTarget->rect.left= left; pTarget->rect.right= right + 1;
TraceLine(pTarget, xpt, ypt, top, bottom, left, right);
//TraceLineEx(pTarget, xpt, ypt);
TestDistance(pTarget);
}
// 计算目标的参数,边界的均值及与均值的差累计
void CTarget::TraceBlock(TARGETAREA *pTarget)
{
ClearTop(pTarget);
// 计算四条边的均值作为边界
int top= 0, bottom= 0, ypt= 0;
bool bx= true;
for (int x= 0; x < pTarget->iLineCountY; x++)
{
if (pTarget->pLineY[x].iMin >= 0)
{
if (bx)
{
pTarget->maxRect.left= x;
bx= !bx;
}
pTarget->maxRect.right= x;
bottom+= pTarget->pLineY[x].iMax;
top+= pTarget->pLineY[x].iMin;
ypt++;
}
}
if (ypt > 0)
{
bottom/= ypt;
top/= ypt;
}
pTarget->rect.top= top; pTarget->rect.bottom= bottom + 1;
int left= 0, right= 0, xpt= 0;
bool by= true;
for (int y= 0; y < pTarget->iLineCountX; y++)
{
if (pTarget->pLineX[y].iMin >= 0)
{
if (by)
{
pTarget->maxRect.top= y;
by= !by;
}
pTarget->maxRect.bottom= x;
left+= pTarget->pLineX[y].iMin;
right+= pTarget->pLineX[y].iMax;
xpt++;
}
}
if (xpt > 0)
{
left/= xpt;
right/= xpt;
}
pTarget->rect.left= left; pTarget->rect.right= right + 1;
TraceLine(pTarget, xpt, ypt, top, bottom, left, right);
//TraceLineEx(pTarget, xpt, ypt);
TestDistance(pTarget);
}
// 按与均值的差
void CTarget::TraceLine(TARGETAREA *pTarget, int xpt, int ypt, int top, int bottom, int left, int right)
{
RECT delta;
// 计算各边每个点与均值差的绝对值累计值(非线性度)
{
delta.top= delta.bottom= 0;
for (int x= 0; x < pTarget->iLineCountY; x++)
{
if (pTarget->pLineY[x].iMin >= 0)
{
int delt= pTarget->pLineY[x].iMin - top;
if (delt < 0)
delta.top-= delt;
else
delta.top+= delt;
delt= pTarget->pLineY[x].iMax - bottom;
if (delt < 0)
delta.bottom-= delt;
else
delta.bottom+= delt;
}
}
}
if (xpt > 0)
{
pTarget->delta.top= (float)delta.top / (float)xpt;
pTarget->delta.bottom= (float)delta.bottom / (float)xpt;
}
else
{
pTarget->delta.top= 1983610;
pTarget->delta.bottom= 1983610;
}
{
delta.left= delta.right= 0;
for (int y= 0; y < pTarget->iLineCountX; y++)
{
if (pTarget->pLineX[y].iMin >= 0)
{
int delt= pTarget->pLineX[y].iMin - left;
if (delt < 0)
delta.left-= delt;
else
delta.left+= delt;
delt= pTarget->pLineX[y].iMax - right;
if (delt < 0)
delta.right-= delt;
else
delta.right+= delt;
}
}
}
if (ypt > 0)
{
pTarget->delta.left= (float)delta.left / (float) ypt;
pTarget->delta.right= (float)delta.right / (float) ypt;
}
else
{
pTarget->delta.left= 1983610;
pTarget->delta.right= 1983610;
}
}
// 每点的delta值
void CTarget::TraceLineEx(TARGETAREA *pTarget, int xpt, int ypt)
{
RECT delta;
int lastx= -1;
// 计算各边每个点与均值差的绝对值累计值(非线性度)
{
delta.top= delta.bottom= 0;
for (int x= 0; x < pTarget->iLineCountY; x++)
{
if (pTarget->pLineY[x].iMin >= 0)
{
if (lastx >= 0)
{
int delt= pTarget->pLineY[x].iMin - pTarget->pLineY[x - 1].iMin;
if (delt < 0)
delta.top-= delt;
else
delta.top+= delt;
delt= pTarget->pLineY[x].iMax - pTarget->pLineY[x - 1].iMax;
if (delt < 0)
delta.bottom-= delt;
else
delta.bottom+= delt;
}
lastx= x;
}
}
}
if (xpt > 0)
{
pTarget->delta.top= (float)delta.top / (float)xpt;
pTarget->delta.bottom= (float)delta.bottom / (float)xpt;
}
else
{
pTarget->delta.top= 1983610;
pTarget->delta.bottom= 1983610;
}
int lasty= -1;
{
delta.left= delta.right= 0;
for (int y= 0; y < pTarget->iLineCountX; y++)
{
if (pTarget->pLineX[y].iMin >= 0)
{
if (lasty >= 0)
{
int delt= pTarget->pLineX[y].iMin - pTarget->pLineX[y - 1].iMin;
if (delt < 0)
delta.left-= delt;
else
delta.left+= delt;
delt= pTarget->pLineX[y].iMax - pTarget->pLineX[y - 1].iMax;
if (delt < 0)
delta.right-= delt;
else
delta.right+= delt;
}
lasty= y;
}
}
}
if (ypt > 0)
{
pTarget->delta.left= (float)delta.left / (float) ypt;
pTarget->delta.right= (float)delta.right / (float) ypt;
}
else
{
pTarget->delta.left= 1983610;
pTarget->delta.right= 1983610;
}
}
// 判断一个矩形是否可能在视野边界上
bool CTarget::IsOutView(RECT &rect)
{
if ((rect.left <= 2) || (rect.right >= 253))
return true;
else
return false;
}
// 比较两个查找出来的疑似目标,更新最优目标
void CTarget::CompareBestBlock(void)
{
if (IsOutView(m_pTarget->rect) || IsOutView(m_pPreTarget->rect))
{
CompareBestBlockEx();
return;
}
// 如果pTarget比pPreTarget更像目标,则交换指针
int widT= m_pTarget->rect.right - m_pTarget->rect.left;
int heiT= m_pTarget->rect.bottom - m_pTarget->rect.top;
int widP= m_pPreTarget->rect.right - m_pPreTarget->rect.left;
int heiP= m_pPreTarget->rect.bottom - m_pPreTarget->rect.top;
// 优先考虑纵横比,纵横比相差比率较大时决断大者
float rT= (float)heiT / (float)widT;
float rP= (float)heiP / (float)widP;
float rMax= (rT > rP) ? rT : rP;
float rR= fabs(rT - rP) / rMax;
if ( rR > .25)
{
if (rT > rP)
{
TARGETAREA *ptmp= m_pTarget;
m_pTarget= m_pPreTarget;
m_pPreTarget= ptmp;
}
return;
}
// 再考虑大小(面积),大小相差较大时决断大者
int ST= widT * heiT;
int SP= widP * heiP;
int SMax= (ST > SP) ? ST : SP;
float SR= (float)abs(ST - SP) / (float)SMax;
if ( SR > .25)
{
if (ST > SP)
{
TARGETAREA *ptmp= m_pTarget;
m_pTarget= m_pPreTarget;
m_pPreTarget= ptmp;
}
return;
}
// 最后考虑线性度,线性度优者(累计值小)决断
float DT= m_pTarget->delta.left + m_pTarget->delta.right + m_pTarget->delta.top;// + m_pTarget->delta.bottom;
float DP= m_pPreTarget->delta.left + m_pPreTarget->delta.right + m_pPreTarget->delta.top;// + m_pPreTarget->delta.bottom;
if (DT < DP)
{
TARGETAREA *ptmp= m_pTarget;
m_pTarget= m_pPreTarget;
m_pPreTarget= ptmp;
}
}
void CTarget::CompareBestBlockEx(void)
{
// 如果pTarget比pPreTarget更像目标,则交换指针
int widT= m_pTarget->rect.right - m_pTarget->rect.left;
int heiT= m_pTarget->rect.bottom - m_pTarget->rect.top;
int widP= m_pPreTarget->rect.right - m_pPreTarget->rect.left;
int heiP= m_pPreTarget->rect.bottom - m_pPreTarget->rect.top;
// 当有物体在左右边界时,长宽比是不确信的,不应以此为准,但是如果非边界的长宽比高
// 的话立即返回
float rT= (float)heiT / (float)widT;
float rP= (float)heiP / (float)widP;
float rMax= (rT > rP) ? rT : rP;
float rR= fabs(rT - rP) / rMax;
if (rT > rP)
{
if (IsOutView(m_pTarget->rect))
{
TARGETAREA *ptmp= m_pTarget;
m_pTarget= m_pPreTarget;
m_pPreTarget= ptmp;
return;
}
}
else if (IsOutView(m_pPreTarget->rect))
{
return;
}
// 再考虑大小(面积),大小相差较大时决断大者
int ST= widT * heiT;
int SP= widP * heiP;
int SMax= (ST > SP) ? ST : SP;
float SR= (float)abs(ST - SP) / (float)SMax;
if ( SR > .25)
{
if (ST > SP)
{
TARGETAREA *ptmp= m_pTarget;
m_pTarget= m_pPreTarget;
m_pPreTarget= ptmp;
}
return;
}
// 考虑线性度,线性度优者(累计值小)决断,但是不应计算边界的线性度
float DT= m_pTarget->delta.left + m_pTarget->delta.right + m_pTarget->delta.top + m_pTarget->delta.bottom;
float DP= m_pPreTarget->delta.left + m_pPreTarget->delta.right + m_pPreTarget->delta.top + m_pPreTarget->delta.bottom;
if (DT < DP)
{
TARGETAREA *ptmp= m_pTarget;
m_pTarget= m_pPreTarget;
m_pPreTarget= ptmp;
return;
}
}
// 查找目标
bool CTarget::UpdateTarget(CImageBuffer<unsigned char> *pSrc)
{
// 注意先把周围1像素的边框擦除,以免越界错误
// ********************************************************
bool bFirstTarget= true;
unsigned int hei= pSrc->m_height;
unsigned int wid= pSrc->m_width;
for (unsigned int y= 0; y < hei; y++)
{
unsigned char *pc= pSrc->m_pScanLine[y];
for (unsigned int x= 0; x < wid; x++)
{
if (pc[x])
{ // 以该点为起点遍历轮廓
if (bFirstTarget)
{
TraceBorderASM(x, y, pSrc, m_pPreTarget);
TraceBlockEx(m_pPreTarget);
bFirstTarget= !IsTarget(m_pPreTarget);
}
else
{
TraceBorderASM(x, y, pSrc, m_pTarget);
TraceBlockEx(m_pTarget);
if (IsTarget(m_pTarget))
CompareBestBlock();
}
}
}
}
if (bFirstTarget)
{ // 未找到合适的block
m_pPreTarget->ClearASM();
return false;
}
else
{
m_lLostTime= GetTickCount();
return true;
}
}
// 初步判断是否为目标
bool CTarget::IsTarget(TARGETAREA *pTarget)
{
// 由于摄像头有一定的倾角,所以物体中心和大小之间有一定约束,太大的东西应处于下方才对
int wid= pTarget->rect.right - pTarget->rect.left;
int hei= pTarget->rect.bottom - pTarget->rect.top;
if ((wid < m_ratio.MinWidth) || (hei < m_ratio.MinHeight))
return false;
double r= (double)hei / wid;
if (r > m_ratio.MaxHW)
return false;
else if ((r < m_ratio.MinHW) && (pTarget->distance > 0.5))
{
return false;
}
// 判断非线性度
int c= 0;
if (pTarget->distance < 0.5)
{
if (m_ratio.antiLineNear.left < pTarget->delta.left) c++;
if (m_ratio.antiLineNear.right < pTarget->delta.right) c++;
if (m_ratio.antiLineNear.top < pTarget->delta.top) c++;
if (m_ratio.antiLineNear.bottom < pTarget->delta.bottom) c++;
}
else
{
if (m_ratio.antiLineFar.left < pTarget->delta.left) c++;
if (m_ratio.antiLineFar.right < pTarget->delta.right) c++;
if (m_ratio.antiLineFar.top < pTarget->delta.top) c++;
if (m_ratio.antiLineFar.bottom < pTarget->delta.bottom) c++;
}
if (c > 2)
return false;
return true;
}
void CTarget::TestDistance(TARGETAREA *pTarget)
{
int wid= pTarget->rect.right - pTarget->rect.left;
int hei= pTarget->rect.bottom - pTarget->rect.top;
int s= wid * hei;
if ((s > m_ratio.NearS) && (pTarget->rect.top > m_ratio.NearTop) && (pTarget->rect.bottom > m_ratio.NearBottom))
pTarget->distance= 0;
else
pTarget->distance= 100;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -