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

📄 ximage.cpp

📁 通过使机器人进行简单的图像识别
💻 CPP
字号:
#include "StdAfx.h"
#include "ximage.h"

CXImage::CXImage(void)
: m_b555Mode(false)
, m_pAreaIndex(NULL)
, m_pAreaIndex555(NULL)
, m_pArea(NULL)
, m_pAreaBuf(NULL)
{

}

CXImage::~CXImage(void)
{
	EndIncise();
}

// 初始化(分配空间和计算查找表)
// 参数:图像的宽和高,以及分割所需参数
bool CXImage::InitIncise(unsigned int width, unsigned int height, SHSVRGB::INCISECOLOR clr, bool b555Mode)
{
	EndIncise();
	m_b555Mode= b555Mode;
	try
	{
		if (m_b555Mode)
			m_pAreaIndex555= new CAreaIndex555(clr);
		else
			m_pAreaIndex= new CAreaIndex(clr);
		m_pArea= new CImageBuffer<unsigned char>(width, height);
		m_pAreaBuf= new CImageBuffer<unsigned char>(width, height);
		return true;
	}
	catch(...)
	{
		delete m_pAreaIndex; m_pAreaIndex= NULL;
		delete m_pAreaIndex555; m_pAreaIndex555= NULL;
		delete m_pArea; m_pArea= NULL;
		delete m_pAreaBuf; m_pAreaBuf= NULL;
		return false;
	}
}
	
// 释放空间
void CXImage::EndIncise(void)
{
	delete m_pAreaIndex;	m_pAreaIndex= NULL;
	delete m_pAreaIndex555; m_pAreaIndex555= NULL;
	delete m_pArea;			m_pArea= NULL;
	delete m_pAreaBuf;		m_pAreaBuf= NULL;
}

// 颜色切分
void CXImage::InciseImage(LPI_DXSURFACE ps)
{

}

void CXImage::InciseImage(const BITMAPINFOHEADER * const pBMPHdr)
{
	long lPitch= 2 * pBMPHdr->biWidth;
	lPitch+= (4 - lPitch % 4) % 4;

	for (unsigned int y= 0; y < pBMPHdr->biHeight; y++)
	{
		unsigned short *psrc= reinterpret_cast<unsigned short *>(reinterpret_cast<unsigned char *>(const_cast<BITMAPINFOHEADER *>(pBMPHdr)) + sizeof(BITMAPINFOHEADER) + y * lPitch);
		unsigned char *pdst= m_pArea->m_pScanLine[y];
		for (unsigned int x= 0; x < pBMPHdr->biWidth; x++)
		{
			m_pArea->m_pScanLine[y][x]= m_pAreaIndex555->m_Index[psrc[x]];
		}
	}
}

void CXImage::InciseImageASM(const BITMAPINFOHEADER * const pBMPHdr)
{
	long lPitch= 2 * pBMPHdr->biWidth;
	lPitch+= (4 - lPitch % 4) % 4;
	unsigned int wid= pBMPHdr->biWidth;
	unsigned int hei= pBMPHdr->biHeight;
	unsigned char *pindex= m_pAreaIndex555->m_Index;

	for (unsigned int y= 0; y < hei; y++)
	{
		unsigned short *psrc= reinterpret_cast<unsigned short *>(reinterpret_cast<unsigned char *>(const_cast<BITMAPINFOHEADER *>(pBMPHdr)) + sizeof(BITMAPINFOHEADER) + y * lPitch);
		unsigned char *pdst= m_pArea->m_pScanLine[y];

		__asm
		{
			mov esi, psrc;
			mov edi, pdst;
			mov edx, pindex;

			xor eax, eax;
			xor ebx, ebx;
loop_x:
			mov bx, [esi + eax * 2];		// psrc[x] => bx
			mov bl, [edx + ebx];			// m_Index[psrc[x]] => bl;

			mov [edi + eax], bl;		// bl => m_pScanLine[y][x]

			inc eax;
			cmp eax, wid;
			jnz loop_x;
		}
	}
}

 
// 开运算
void CXImage::OperatorOpen(void)
{
	this->DilationASM(m_pArea, m_pAreaBuf);
	this->ErosionASM(m_pAreaBuf, m_pArea);
}

// 闭运算
void CXImage::OperatorClose(void)
{
	this->ErosionASM(m_pArea, m_pAreaBuf);
	this->DilationASM(m_pAreaBuf, m_pArea);
}

// 清除边框
void CXImage::ClearBorder(CImageBuffer<unsigned char>* pSrc)
{
	for (unsigned int y= 0; y < pSrc->m_height; y++)
	{
		pSrc->m_pScanLine[y][0]= 0;
		pSrc->m_pScanLine[y][pSrc->m_width - 1]= 0;
	}
	for (unsigned int x= 0; x < pSrc->m_width; x++)
	{
		pSrc->m_pScanLine[0][x]= 0;
		pSrc->m_pScanLine[pSrc->m_height - 1][x]= 0;
	}
}

void CXImage::ClearBorderASM(CImageBuffer<unsigned char>* pSrc)
{
	unsigned char **psl= pSrc->m_pScanLine;
	unsigned int hei= pSrc->m_height;
	unsigned int wid= pSrc->m_width;

	__asm
	{
		mov eax, 0;

		mov ebx, wid;
		dec ebx;		// wid - 1 => ebx

		mov ecx, hei;

		mov esi, psl;
loop_y:
		mov edi, [esi + eax * 4];		// (unsigned char *)edi = psl[y]
		mov [edi], 0;
		mov [edi + ebx], 0;

		inc eax;
		cmp eax, ecx;
		jnz loop_y;
	}

	__asm
	{
		mov eax, 0;

		mov ebx, hei;
		dec ebx;		// hei - 1 => ebx;

		mov ecx, wid;

		mov esi, psl;
loop_x:
		mov edi, [esi];				// (unsigned char *)edi = psl[0]
		mov [edi + eax], 0;
		
		mov edi, [esi + ebx * 4];	// (unsigned char *)edi = psl[height - 1]
		mov [edi + eax], 0;

		inc eax;
		cmp eax, ecx;
		jnz loop_x;
	}
}

// 膨胀
void CXImage::Dilation(CImageBuffer<unsigned char>* pSrc, CImageBuffer<unsigned char>* pDest)
{
	ClearBorder(pDest);
	for (unsigned int y= 1; y < pSrc->m_height - 1; y++)
	{
		for (unsigned int x= 1; x < pSrc->m_width - 1; x++)
		{
			// 计算空点数目
			int k= pSrc->m_pScanLine[y - 1][x - 1] +
				pSrc->m_pScanLine[y - 1][x] +
				pSrc->m_pScanLine[y - 1][x + 1] +
				pSrc->m_pScanLine[y][x - 1] +
				pSrc->m_pScanLine[y][x + 1] +
				pSrc->m_pScanLine[y + 1][x - 1] +
				pSrc->m_pScanLine[y + 1][x] +
				pSrc->m_pScanLine[y + 1][x + 1];
			k= 8 - k;
			if (k < 4)
				pDest->m_pScanLine[y][x]= 1;
			else
				pDest->m_pScanLine[y][x]= pSrc->m_pScanLine[y][x];

		}
	}
}

void CXImage::DilationASM(CImageBuffer<unsigned char>* pSrc, CImageBuffer<unsigned char>* pDest)
{
	ClearBorderASM(pDest);
	unsigned int hei= pSrc->m_height - 1;
	unsigned int wid= pSrc->m_width - 1;

	for (unsigned int y= 1; y < hei; y++)
	{
		unsigned char *pSrc1= pSrc->m_pScanLine[y - 1];
		unsigned char *pSrc2= pSrc->m_pScanLine[y];
		unsigned char *pSrc3= pSrc->m_pScanLine[y + 1];
		unsigned char *pDst= pDest->m_pScanLine[y];

		__asm
		{
			mov eax, 1;

			mov esi, pSrc1;			// m_pScanLine[y - 1];
			mov edi, pSrc2;			// m_pScanLine[y];
			mov ebx, pSrc3;			// m_pScanLine[y + 1];

			mov ecx, pDst;
loop_x:
			inc ecx;

			dec eax;				// x - 1 => eax;
			mov dl, [esi + eax];	// [y - 1][x - 1];
			add dl, [edi + eax];	// [y][x - 1];
			add dl, [ebx + eax];	// [y + 1][x - 1];

			inc eax;				// x => eax;
			add dl, [esi + eax];	// [y - 1][x];
			add dl, [ebx + eax];	// [y + 1][x];

			mov dh, [edi + eax];	// [y][x] => dh;
			
			inc eax;				// x + 1 => eax;
			add dl, [esi + eax];	// [y - 1][x + 1];
			add dl, [edi + eax];	// [y][x + 1];
			add dl, [ebx + eax];	// [y + 1][x + 1];
			// now none zero point number in dl

			mov [ecx], dh;

			cmp dl, 4;
			jb no_draw;
			mov [ecx], 1;
no_draw:
			cmp eax, wid;
			jnz loop_x;
		}
	}
}

// 腐蚀
void CXImage::Erosion(CImageBuffer<unsigned char>* pSrc, CImageBuffer<unsigned char>* pDest)
{
	ClearBorder(pDest);
	for (unsigned int y= 1; y < pSrc->m_height - 1; y++)
	{
		for (unsigned int x= 1; x < pSrc->m_width - 1; x++)
		{
			// 计算像点数目
			int k= pSrc->m_pScanLine[y - 1][x - 1] +
				pSrc->m_pScanLine[y - 1][x] +
				pSrc->m_pScanLine[y - 1][x + 1] +
				pSrc->m_pScanLine[y][x - 1] +
				pSrc->m_pScanLine[y][x + 1] +
				pSrc->m_pScanLine[y + 1][x - 1] +
				pSrc->m_pScanLine[y + 1][x] +
				pSrc->m_pScanLine[y + 1][x + 1];
			if (k < 4)
				pDest->m_pScanLine[y][x]= 0;
			else
				pDest->m_pScanLine[y][x]= pSrc->m_pScanLine[y][x];
		}
	}
}

void CXImage::ErosionASM(CImageBuffer<unsigned char>* pSrc, CImageBuffer<unsigned char>* pDest)
{
	ClearBorderASM(pDest);
	unsigned int hei= pSrc->m_height - 1;
	unsigned int wid= pSrc->m_width - 1;

	for (unsigned int y= 1; y < hei; y++)
	{
		unsigned char *pSrc1= pSrc->m_pScanLine[y - 1];
		unsigned char *pSrc2= pSrc->m_pScanLine[y];
		unsigned char *pSrc3= pSrc->m_pScanLine[y + 1];
		unsigned char *pDst= pDest->m_pScanLine[y];

		__asm
		{
			mov eax, 1;

			mov esi, pSrc1;			// m_pScanLine[y - 1];
			mov edi, pSrc2;			// m_pScanLine[y];
			mov ebx, pSrc3;			// m_pScanLine[y + 1];

			mov ecx, pDst;
loop_x:
			inc ecx;

			dec eax;				// x - 1 => eax;
			mov dl, [esi + eax];	// [y - 1][x - 1];
			add dl, [edi + eax];	// [y][x - 1];
			add dl, [ebx + eax];	// [y + 1][x - 1];

			inc eax;				// x => eax;
			add dl, [esi + eax];	// [y - 1][x];
			add dl, [ebx + eax];	// [y + 1][x];

			mov dh, [edi + eax];	// [y][x] => dh;
			
			inc eax;				// x + 1 => eax;
			add dl, [esi + eax];	// [y - 1][x + 1];
			add dl, [edi + eax];	// [y][x + 1];
			add dl, [ebx + eax];	// [y + 1][x + 1];
			// now none zero point number in dl

			mov [ecx], 0;

			cmp dl, 4;
			jb no_draw;
			mov [ecx], dh;
no_draw:
			cmp eax, wid;
			jnz loop_x;
		}
	}
}

// 将二值图像转换为DS图像
void CXImage::ConvertOutDS(LPI_DXSURFACE ps)
{
	LPI_BASICGRAPHIC pbg= ps->GetGraphic();
	pbg->BeginPaint();

	for (unsigned int y= 0; y < m_pArea->m_height; y++)
	{
		for (unsigned int x= 0;  x < m_pArea->m_width; x++)
		{
			if (m_pArea->m_pScanLine[y][x])
				pbg->SetPixelV(x, y, 0x00FF0000);
			else
				pbg->SetPixelV(x, y, 0x00000000);
		}
	}

	pbg->EndPaint();
}

void CXImage::ConvertOutDSASM(LPI_DXSURFACE ps)
{
	IMAGEMEMORY img;
	ps->LockImage(&img);
		
	unsigned int hei= m_pArea->m_height;
	unsigned int wid= m_pArea->m_width;

	if (img.bitcount == 16)
	{
		for (unsigned int y= 0; y < hei; y++)
		{
			unsigned char *pSrc= m_pArea->m_pScanLine[y];
			unsigned short *pDst= reinterpret_cast<unsigned short *>(img.pMemory + y * img.lPitch);

			__asm
			{
				mov eax, 0;

				mov esi, pSrc;
				mov edi, pDst;

				mov cx, 0xF800;
				mov dx, 0x0000;
loop_x_16:
				mov [edi], dx;

				mov bl, [esi];
				cmp bl, 0;
				jz nodraw_16;
draw_16:
				mov [edi], cx;
nodraw_16:
				inc esi;
				add edi, 2;

				inc eax;
				cmp eax, wid;
				jnz loop_x_16;
			}

//			for (unsigned int x= 0; x < wid; x++)
//			{
//				if (pSrc[x])
//					(*pDst++)= 0xF800;
//				else
//					(*pDst++)= 0x0000;
//			}
		}
	}
	else if (img.bitcount == 32)
	{	
		for (unsigned int y= 0; y < hei; y++)
		{
			unsigned char *pSrc= m_pArea->m_pScanLine[y];
			unsigned int *pDst= reinterpret_cast<unsigned int *>(img.pMemory + y * img.lPitch);

			__asm
			{
				mov eax, 0;

				mov esi, pSrc;
				mov edi, pDst;

				mov ecx, 0xFFFF0000;
				mov edx, 0x00000000;
loop_x_32:
				mov [edi], edx;

				mov bl, [esi];
				cmp bl, 0;
				jz nodraw_32;
draw_32:
				mov [edi], ecx;
nodraw_32:
				inc esi;
				add edi, 4;

				inc eax;
				cmp eax, wid;
				jnz loop_x_32;
			}
//			for (unsigned int x= 0; x < wid; x++)
//			{
//				if (pSrc[x])
//					(*pDst++)= 0xFFFF0000;
//				else
//					(*pDst++)= 0xFF000000;
//			}
		}
	}

	ps->UnlockImage();
}

// 获取缓冲
CImageBuffer<unsigned char> *CXImage::GetImageBuffer(CImageBuffer<unsigned char> *pDst)
{
	for (unsigned int y= 0; y < m_pArea->m_height; y++)
	{
		for (unsigned int x= 0; x < m_pArea->m_width; x++)
		{
			pDst->m_pScanLine[y][x]= m_pArea->m_pScanLine[y][x];
		}
	}
	return pDst;
}

CImageBuffer<unsigned char> *CXImage::GetImageBufferASM(CImageBuffer<unsigned char> *pDst)
{
	unsigned int hei= m_pArea->m_height;
	unsigned int wid= m_pArea->m_width;

	for (unsigned int y= 0; y < hei; y++)
	{
		memcpy(pDst->m_pScanLine[y], m_pArea->m_pScanLine[y], wid);
	}
	return pDst;
}

⌨️ 快捷键说明

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