target.h

来自「通过使机器人进行简单的图像识别」· C头文件 代码 · 共 279 行

H
279
字号
/********************************************************************
*
* =-----------------------------------------------------------------=
* =                          ____          _________                =
* =                         / _  \         \___  __/                =
* =                        / /_/ /     ____   / /                   =
* =                       /  _   \ ● / _  \ / /                    =
* =                      /  /_/  // // / / // /                     =
* =                      \______//_//_/ /_//_/                      =
* =                                                                 =
* =             Copyright (c) BIN Technology studio,2004            =
* =                           LET'Z BT                              =
* =-----------------------------------------------------------------=
*
*	FileName	: Target.cpp Target.h
*	Description	: 查找目标(那个ex女人的手)
*
*	Author		: 风间苍月(TuQbasic)
*	Email		: tuqbasic@sohu.com
*
*	Create		: 2004.04.23
*	LastChange	: 2004.05.06
*
*	History		: 
********************************************************************/ 
#pragma once
#include "ImageBuffer.h"
#include "Engine\hPackage.h"

typedef struct _sLineArea
{	// x轴与区域的交点
	int iMin;		// 最左端
	int iMax;		// 最右端
}LINEAREA;

typedef struct _tagFloatRect
{
	float		left;
	float		right;
	float		top;
	float		bottom;
}FLOATRECT;

typedef struct _sTargetArea
{
	unsigned int iLineCountX;	// 缓冲横向扫描线数,其实就是高度
	LINEAREA	*pLineX;		// 横向扫描线

	unsigned int iLineCountY;	// 宽度
	LINEAREA	*pLineY;		// 纵向扫描线

	RECT		maxRect;		// 最大包含矩形

	RECT		rect;			// 矩形区域,均值化之后
	FLOATRECT	delta;			// 一次差绝对值,非线性度

	double		distance;		// 大致距离,由位置和面积确定

	_sTargetArea(void)
	{
		pLineX= NULL;
		iLineCountX= 0;

		pLineY= NULL;
		iLineCountY= 0;
	}

	~_sTargetArea(void)
	{
		Free();
	}

	// 清除数据记录
	void Clear(void)
	{
		for (int y= 0; y < iLineCountX; y++)
			pLineX[y].iMin= pLineX[y].iMax= -1;		// 标记为不可用
		for (int x= 0; x < iLineCountY; x++)
			pLineY[x].iMin= pLineY[x].iMax= -1;
		
		maxRect.left= maxRect.right= maxRect.top= maxRect.bottom= 0;
		rect.left= rect.right= rect.top= rect.bottom= 0;
		delta.left= delta.right= delta.top= delta.bottom= 0.;

		distance= 0.;
	}

	void ClearASM(void)
	{
		unsigned int icx= iLineCountX;
		LINEAREA *plx= pLineX;
		__asm
		{
			xor eax, eax;
			mov ebx, icx;
			mov edi, plx;
loop_y:
			mov ecx, eax;
			shl ecx, 3;

			mov dword ptr [edi + ecx], -1;
			mov dword ptr [edi + ecx + 4], -1;

			inc eax;
			cmp eax, ebx;
			jb loop_y;
		}

		unsigned int icy= iLineCountY;
		LINEAREA *ply= pLineY;
		__asm
		{
			xor eax, eax;
			mov ebx, icy;
			mov edi, ply;
loop_x:
			mov ecx, eax;
			shl ecx, 3;

			mov dword ptr [edi + ecx], -1;
			mov dword ptr [edi + ecx + 4], -1;

			inc eax;
			cmp eax, ebx;
			jb loop_x;
		}

		rect.left= rect.right= rect.top= rect.bottom= -1;
		delta.left= delta.right= delta.top= delta.bottom= -1;
	}

	void Alloc(unsigned int wid, unsigned int hei)
	{
		iLineCountX= hei;
		pLineX= new LINEAREA[hei];

		iLineCountY= wid;
		pLineY= new LINEAREA[wid];
	}

	void Free(void)
	{
		iLineCountX= 0;
		if (pLineX) 
		{
			delete[] pLineX;
			pLineX= NULL;
		}
		
		iLineCountY= 0;
		if (pLineY) 
		{
			delete[] pLineY;
			pLineY= NULL;
		}
	}
}TARGETAREA;

typedef struct _sRatioParam
{
	// 最小长宽
	int			MinWidth;
	int			MinHeight;

	// 纵横比
	float		MinHW;
	float		MaxHW;

	// 非线性度
	FLOATRECT	antiLineNear;
	FLOATRECT	antiLineFar;

	// 丢失时间
	int			LostTime;

	// 判断近处的条件
	int			NearS;
	int			NearTop;
	int			NearBottom;
}RATIOPARAM;

class CTarget
{
public:
	CTarget(void);
	~CTarget(void);

	// 
	void LoadRatioParam(LPI_FILEINI pIni)
	{
		m_ratio.MinHW= pIni->getKeyValueDouble("RatioMinHW", "Target");
		m_ratio.MaxHW= pIni->getKeyValueDouble("RatioMaxHW", "Target");

		m_ratio.antiLineNear.top=	pIni->getKeyValueDouble("RatioTop", "TargetNear");
		m_ratio.antiLineNear.bottom=pIni->getKeyValueDouble("RatioBottom", "TargetNear");
		m_ratio.antiLineNear.left=	pIni->getKeyValueDouble("RatioLeft", "TargetNear");
		m_ratio.antiLineNear.right=	pIni->getKeyValueDouble("RatioRight", "TargetNear");

		m_ratio.antiLineFar.top=	pIni->getKeyValueDouble("RatioTop", "TargetFar");
		m_ratio.antiLineFar.bottom=	pIni->getKeyValueDouble("RatioBottom", "TargetFar");
		m_ratio.antiLineFar.left=	pIni->getKeyValueDouble("RatioLeft", "TargetFar");
		m_ratio.antiLineFar.right=	pIni->getKeyValueDouble("RatioRight", "TargetFar");

		m_ratio.MinWidth= pIni->getKeyValueLong("RatioMinWidth", "Target");
		m_ratio.MinHeight= pIni->getKeyValueLong("RatioMinHeight", "Target");

		m_ratio.LostTime= pIni->getKeyValueLong("LostTime", "Target");

		m_ratio.NearS= pIni->getKeyValueLong("NearS", "Target");
		m_ratio.NearTop= pIni->getKeyValueLong("NearTop", "Target");
		m_ratio.NearBottom= pIni->getKeyValueLong("NearBottom", "Target");
	}

	// 分配所需的内存空间
	bool Alloc(unsigned int wid, unsigned int hei);

	// 释放内存
	void Free(void);

	// 查找目标
	bool UpdateTarget(CImageBuffer<unsigned char> *pSrc);

	// 绘制区域轮廓
	void DrawTargetBorder(CImageBuffer<unsigned char> *pDst);
	void DrawTargetBorderASM(CImageBuffer<unsigned char> *pDst);

	// 绘制区域
	void DrawTargetArea(CImageBuffer<unsigned char> *pDst);
	void DrawTargetAreaASM(CImageBuffer<unsigned char> *pDst);
	void DrawTargetRect(CImageBuffer<unsigned char> *pDst);

	// 是否失去方向(丢失目标一定时间)
	bool IsLost(void)
	{
		return ((GetTickCount() - m_lLostTime) > m_ratio.LostTime) ? true : false;
	}

	// 
	void GetTarget(RECT &r) { r= m_pPreTarget->rect;}
protected:
	// 擦除标记的区域
	void ClearArea(CImageBuffer<unsigned char> *pSrc, TARGETAREA *pTarget);
	void ClearAreaASM(CImageBuffer<unsigned char> *pSrc, TARGETAREA *pTarget);

	// 搜寻轮廓并整理记录遍历的点
	void TraceBorder(int x, int y, CImageBuffer<unsigned char> *pSrc, TARGETAREA *pTarget);
	void TraceBorderASM(int x, int y, CImageBuffer<unsigned char> *pSrc, TARGETAREA *pTarget);

	// 去除上部10%
	void ClearTop(TARGETAREA *pTarget);

	// 计算目标的参数,边界的均值及与均值的差累计
	void TraceBlock(TARGETAREA *pTarget);
	void TraceBlockEx(TARGETAREA *pTarget);

	// 计算非线性度
	void TraceLine(TARGETAREA *pTarget, int xpt, int ypt, int top, int bottom, int left, int right);	// 按与均值的差
	void TraceLineEx(TARGETAREA *pTarget, int xpt, int ypt);	// 每点的delta值

	// 测试距离
	void TestDistance(TARGETAREA *pTarget);

	// 初步判断是否为目标
	bool IsTarget(TARGETAREA *pTarget);

	// 比较两个查找出来的疑似目标,更新最优目标
	void CompareBestBlock(void);
	// 当有疑似目标在左右边缘时用该函数比较
	void CompareBestBlockEx(void);

	// 判断一个矩形是否可能在视野边界上
	bool IsOutView(RECT &rect);
private:
	TARGETAREA	*m_pPreTarget;	// 已有对象,存放最优解
	TARGETAREA	*m_pTarget;		// 新查找出的目标
	RATIOPARAM	m_ratio;		// 目标阈值

	long		m_lLostTime;	// 最后一次获取目标的时间
};

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?