⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 target.cpp

📁 通过使机器人进行简单的图像识别
💻 CPP
📖 第 1 页 / 共 2 页
字号:
#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 + -