📄 target.cpp
字号:
#include "stdafx.h"
#include "Target.h"
#include <math.h>
// 跟踪虫的探测方向
POINT Direction[8]={ {-1, 0}, {-1, -1}, {0, -1}, {1, -1}, {1, 0}, {1, 1}, {0, 1}, {-1, 1}};
CTarget::CTarget(void)
: m_pPreTarget(NULL)
, m_pTarget(NULL)
, m_lLostTime(0)
{
}
CTarget::~CTarget(void)
{
Free();
}
// 分配所需的内存空间
bool CTarget::Alloc(unsigned int wid, unsigned int hei)
{
m_pPreTarget= new TARGETAREA;
m_pTarget= new TARGETAREA;
m_pPreTarget->Alloc(wid, hei);
m_pTarget->Alloc(wid, hei);
return true;
}
// 释放内存
void CTarget::Free(void)
{
if (m_pPreTarget)
{
m_pPreTarget->Free();
delete m_pPreTarget;
m_pPreTarget= NULL;
}
if (m_pTarget)
{
m_pTarget->Free();
delete m_pTarget;
m_pTarget= NULL;
}
}
// 绘制区域轮廓
void CTarget::DrawTargetBorder(CImageBuffer<unsigned char> *pDst)
{
for (int y= 0; y < m_pPreTarget->iLineCountX; y++)
{
int x= m_pPreTarget->pLineX[y].iMin;
if (x >= 0)
{
pDst->m_pScanLine[y][x]= 0x01;
}
x= m_pPreTarget->pLineX[y].iMax;
if (x >= 0)
{
pDst->m_pScanLine[y][x]= 0x01;
}
}
for (int x= 0; x < m_pPreTarget->iLineCountY; x++)
{
int y= m_pPreTarget->pLineY[x].iMin;
if (y >= 0)
{
pDst->m_pScanLine[y][x]= 0x01;
}
y= m_pPreTarget->pLineY[x].iMax;
if (y >= 0)
{
pDst->m_pScanLine[y][x]= 0x01;
}
}
}
void CTarget::DrawTargetBorderASM(CImageBuffer<unsigned char> *pDst)
{
{
unsigned int yMax= m_pPreTarget->iLineCountX;
LINEAREA *pl= m_pPreTarget->pLineX;
unsigned char **ppc= pDst->m_pScanLine;
__asm
{
xor eax, eax;
mov cl, 0x01;
mov esi, pl
mov edi, ppc;
loop_y:
mov ebx, [esi + eax * 8]; // x= min,注意此处8与LINEAREA相关
cmp ebx, 0;
jl no_draw_min_x;
mov edx, [edi + eax * 4]; // edx = pScanLine[y];
mov byte ptr [edx + ebx], cl;
no_draw_min_x:
mov ebx, [esi + eax * 8 + 4]; // x= max;
cmp ebx, 0;
jl no_draw_max_x;
mov byte ptr [edx + ebx], cl; // 当iMin大于0 时iMax才可能大于0,此时edx必为有效值
no_draw_max_x:
inc eax;
cmp eax, yMax;
jb loop_y;
}
}
{
unsigned int xMax= m_pPreTarget->iLineCountY;
LINEAREA *pl= m_pPreTarget->pLineY;
unsigned char **ppc= pDst->m_pScanLine;
__asm
{
xor eax, eax;
mov cl, 0x01;
mov esi, pl;
mov edi, ppc;
loop_x:
mov ebx, [esi + eax * 8]; // y= min;
cmp ebx, 0;
jl no_draw_min_y;
mov edx, [edi + ebx * 4];
mov byte ptr [edx + eax], cl;
no_draw_min_y:
mov ebx, [esi + eax * 8 + 4]; // y= max;
cmp ebx, 0;
jl no_draw_max_y;
mov edx, [edi + ebx * 4];
mov byte ptr [edx + eax], cl;
no_draw_max_y:
inc eax;
cmp eax, xMax;
jb loop_x;
}
}
}
// 绘制区域
void CTarget::DrawTargetArea(CImageBuffer<unsigned char> *pDst)
{
for (int y= 0; y < m_pPreTarget->iLineCountX; y++)
{
int iMin= m_pPreTarget->pLineX[y].iMin;
if (iMin < 0) continue;
int iMax= m_pPreTarget->pLineX[y].iMax;
unsigned char *pc= pDst->m_pScanLine[y];
for (int x= iMin; x <= iMax; x++)
pc[x]= 0x01;
}
}
void CTarget::DrawTargetAreaASM(CImageBuffer<unsigned char> *pDst)
{
int yMax= m_pPreTarget->iLineCountX;
LINEAREA *pl= m_pPreTarget->pLineX;
unsigned char **ppc= pDst->m_pScanLine;
__asm
{
xor eax, eax;
mov esi, pl;
mov edi, ppc;
loop_again_y:
mov ebx, [esi + eax * 8]; // iMin;
cmp ebx, 0;
jl no_draw;
mov ecx, [esi + eax * 8 + 4]; // iMax;
mov edx, [edi + eax * 4]; // pSrc->m_pScanLine[y];
{
loop_again_x:
mov byte ptr[edx + ebx], 0x01;
inc ebx;
cmp ebx, ecx;
jle loop_again_x;
}
no_draw:
inc eax;
cmp eax, yMax;
jl loop_again_y;
}
}
void CTarget::DrawTargetRect(CImageBuffer<unsigned char> *pDst)
{
for (int y= m_pPreTarget->rect.top; y < m_pPreTarget->rect.bottom; y++)
{
for (int x= m_pPreTarget->rect.left; x < m_pPreTarget->rect.right; x++)
{
pDst->m_pScanLine[y][x]= 0x01;
}
}
}
// 擦除标记的区域
void CTarget::ClearArea(CImageBuffer<unsigned char> *pSrc, TARGETAREA *pTarget)
{
for (int y= 0; y < pTarget->iLineCountX; y++)
{
int iMin= pTarget->pLineX[y].iMin;
if (iMin < 0) continue;
int iMax= pTarget->pLineX[y].iMax;
unsigned char *pc= pSrc->m_pScanLine[y];
for (int x= iMin; x <= iMax; x++)
pc[x]= 0;
}
}
void CTarget::ClearAreaASM(CImageBuffer<unsigned char> *pSrc, TARGETAREA *pTarget)
{
int yMax= pTarget->iLineCountX;
LINEAREA *pl= pTarget->pLineX;
unsigned char **ppc= pSrc->m_pScanLine;
__asm
{
xor eax, eax;
mov esi, pl;
mov edi, ppc;
loop_again_y:
mov ebx, [esi + eax * 8]; // iMin;
cmp ebx, 0;
jl no_draw;
mov ecx, [esi + eax * 8 + 4]; // iMax;
mov edx, [edi + eax * 4]; // pSrc->m_pScanLine[y];
{
loop_again_x:
mov byte ptr[edx + ebx], 0;
inc ebx;
cmp ebx, ecx;
jle loop_again_x;
}
no_draw:
inc eax;
cmp eax, yMax;
jl loop_again_y;
}
}
// 搜寻轮廓并整理记录遍历的点
// 参考代码见vb代码"边界跟踪.zip",算法来源遗失
void CTarget::TraceBorder(int x, int y, CImageBuffer<unsigned char> *pSrc, TARGETAREA *pTarget)
{
pTarget->ClearASM();
// 统计周围点数目并找出第一个边界点
int startpos= 0, step= 0;
unsigned int bordercount= 0;
int xnow= 0, ynow= 0;
for (step= 0; step < 8; step++)
{
xnow = x + Direction[step].x;
ynow = y + Direction[step].y;
if (pSrc->m_pScanLine[ynow][xnow])
{
bordercount++;
if (startpos == 0)
startpos= step; // 初始搜索的方向
}
}
if ((bordercount == 8) || (bordercount == 0))
{ // 该点不在轮廓上
pSrc->m_pScanLine[y][x]= 0;
return;
}
int xtry, ytry;
xnow= x, ynow= y;
step= startpos;
do
{
xtry= xnow + Direction[step].x;
ytry= ynow + Direction[step].y;
if (pSrc->m_pScanLine[ytry][xtry])
{ // 找到一个轮廓点,整理数据记录
if (pTarget->pLineX[ytry].iMin < 0)
{ // 第一个点
pTarget->pLineX[ytry].iMin= xtry;
pTarget->pLineX[ytry].iMax= xtry;
}
else
{
if (xtry < pTarget->pLineX[ytry].iMin)
pTarget->pLineX[ytry].iMin= xtry;
else if (xtry > pTarget->pLineX[ytry].iMax)
pTarget->pLineX[ytry].iMax= xtry;
}
if (pTarget->pLineY[xtry].iMin < 0)
{
pTarget->pLineY[xtry].iMin= ytry;
pTarget->pLineY[xtry].iMax= ytry;
}
else
{
if (ytry < pTarget->pLineY[xtry].iMin)
pTarget->pLineY[xtry].iMin= ytry;
else if (ytry > pTarget->pLineY[xtry].iMax)
pTarget->pLineY[xtry].iMax= ytry;
}
step-= 2;
xnow= xtry;
ynow= ytry;
}
else
{ // 若点(xcur, ycur)非轮廓点则顺时针旋转45度
step= step + 1;
}
// 检测step是否越界
if (step >= 8)
step-= 8;
else if (step < 0)
step+= 8;
}while((xnow != x) || (ynow != y));
// 将找到的block区域擦除
ClearAreaASM(pSrc, pTarget);
}
void CTarget::TraceBorderASM(int x, int y, CImageBuffer<unsigned char> *pSrc, TARGETAREA *pTarget)
{
pTarget->ClearASM();
// 统计周围点数目并找出第一个边界点
int startpos= 0, step= 0;
unsigned int bordercount= 0;
int xnow= 0, ynow= 0;
for (step= 0; step < 8; step++)
{
xnow = x + Direction[step].x;
ynow = y + Direction[step].y;
if (pSrc->m_pScanLine[ynow][xnow])
{
bordercount++;
if (startpos == 0)
startpos= step; // 初始搜索的方向
}
}
if ((bordercount == 8) || (bordercount == 0))
{ // 该点不在轮廓上
pSrc->m_pScanLine[y][x]= 0;
return;
}
int xtry, ytry;
xnow= x, ynow= y;
step= startpos;
LINEAREA *plx= pTarget->pLineX;
LINEAREA *ply= pTarget->pLineY;
do
{
xtry= xnow + Direction[step].x;
ytry= ynow + Direction[step].y;
if (pSrc->m_pScanLine[ytry][xtry])
{ // 找到一个轮廓点,整理数据记录
__asm
{
mov ecx, xtry;
mov edx, ytry;
}
__asm
{
mov edi, plx;
mov eax, edx;
shl eax, 3;
mov ebx, [edi + eax]; // pTarget->pLineX[ytry];
cmp ebx, 0;
jge update_collection_x;
// 新纪录
mov [edi + eax], ecx;
mov [edi + eax + 4], ecx;
jmp update_end_x;
update_collection_x:
// 更新纪录
cmp ecx, [edi + eax];
jnb update_nodraw_x_min;
mov [edi + eax], ecx;
jmp update_end_x;
update_nodraw_x_min:
cmp ecx, [edi + eax + 4];
jna update_nodraw_x_max;
mov [edi + eax + 4], ecx;
update_nodraw_x_max:
update_end_x:
}
__asm
{
mov edi, ply;
mov eax, ecx;
shl eax, 3;
mov ebx, [edi + eax]; // pTarget->pLineY[xtry];
cmp ebx, 0;
jge update_colletion_y;
// 新纪录
mov [edi + eax], edx;
mov [edi + eax + 4], edx;
jmp update_end_y;
update_colletion_y:
// 更新纪录
cmp edx, [edi + eax];
jnb update_nodraw_y_min;
mov [edi + eax], edx;
jmp update_end_y;
update_nodraw_y_min:
cmp edx, [edi + eax + 4];
jna update_nodraw_y_max;
mov [edi + eax + 4], edx;
update_nodraw_y_max:
update_end_y:
}
__asm
{
mov xnow, ecx;
mov ynow, edx;
}
step-= 2;
}
else
{ // 若点(xcur, ycur)非轮廓点则顺时针旋转45度
step++;
}
// 检测step是否越界
if (step >= 8)
step-= 8;
else if (step < 0)
step+= 8;
}while((xnow != x) || (ynow != y));
// 将找到的block区域擦除
ClearAreaASM(pSrc, pTarget);
}
// 去除上部
void CTarget::ClearTop(TARGETAREA *pTarget)
{
// 去除上部10%
}
void CTarget::TraceBlockEx(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;
pTarget->maxRect.right= x;
bx= !bx;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -