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

📄 morphology.cpp

📁 LOG滤波器提取边缘;用形态学方法提取骨架线;由明暗度提取外形信息;
💻 CPP
字号:
// Morphology.cpp: implementation of the CMorphology class.
//
//////////////////////////////////////////////////////////////////////

#include "stdafx.h"
#include "log.h"
#include "Morphology.h"

#ifdef _DEBUG
#undef THIS_FILE
static char THIS_FILE[]=__FILE__;
#define new DEBUG_NEW
#endif

//////////////////////////////////////////////////////////////////////
// Construction/Destruction
//////////////////////////////////////////////////////////////////////

CMorphology::CMorphology()
{
	m_pSE=NULL;
	m_nSEWidth=0;
	
}

CMorphology::~CMorphology()
{
	if(m_pSE)
		delete[] m_pSE;
	
}

bool CMorphology::Dilate(BYTE* pSrcBuf,BYTE* pDestBuf,int nSEType,int nWidth,int nHeight,BYTE* pSEType,int nSEWidth)
{
	BYTE* pDest;
	//>>若输出阵列为空,则输出结果到输入阵列
	if(pDestBuf==NULL)
		pDest=pSrcBuf;
	else
		pDest=pDestBuf;
	//<<
	
	//>>设置结构元素
	if(nSEType>STRUCTURE_ELEMENT&&nSEType<STRUCTURE_ELEMENT_END)
		SetSE(nSEType);
	else if(pSEType!=NULL)
		SetSE(0,pSEType,nSEWidth);
	else
		TRACE("没有默认的或给定的结构元素\n");
	//<<

	bool bOK;
	BYTE* pTempBuf=new BYTE[nWidth*nHeight];
	::memcpy(pTempBuf,pSrcBuf,nWidth*nHeight);

/*	for(int i=m_nSEWidth/2;i<nHeight-m_nSEWidth/2;i++)
		for(int j=m_nSEWidth/2;j<nWidth-m_nSEWidth/2;j++)
		{
			bOK=false;
			//BYTE Temp=pTempBuf[i*nWidth+j];
			for(int ii=0;ii<m_nSEWidth;ii++)
			{
				for(int jj=0;jj<m_nSEWidth;jj++)
				{
					/*if(m_pSE[ii*m_nSEWidth+jj]!=0)
						if(Temp>pTempBuf[(i+ii-m_nSEWidth/2)*nWidth+(j+jj-m_nSEWidth/2)])
							Temp=pTempBuf[(i+ii-m_nSEWidth/2)*nWidth+(j+jj-m_nSEWidth/2)];
					*
					if(m_pSE[ii*m_nSEWidth+jj])
					{
						if(COLOR_BLACK==0)
							bOK=bOK||(!pTempBuf[(i+ii-m_nSEWidth/2)*nWidth+(j+jj-m_nSEWidth/2)]);
						else
							bOK=bOK||(pTempBuf[(i+ii-m_nSEWidth/2)*nWidth+(j+jj-m_nSEWidth/2)]);

					}
				}
				if(bOK)
					pDest[i*nWidth+j]=COLOR_BLACK;	//黑色
				else
					pDest[i*nWidth+j]=COLOR_WHITE;
			}
			
		}
*/
	::memset(pDest,COLOR_WHITE,nWidth*nHeight);
	for(int i=m_nSEWidth/2;i<nHeight-m_nSEWidth/2;i++)
		for(int j=m_nSEWidth/2;j<nWidth-m_nSEWidth/2;j++)
		{
			if(pTempBuf[i*nWidth+j]==COLOR_BLACK)
			{
				for(int ii=0;ii<m_nSEWidth;ii++)
					for(int jj=0;jj<m_nSEWidth;jj++)
					{
						if(m_pSE[ii*m_nSEWidth+jj])
						{
							pDest[(i+ii-m_nSEWidth/2)*nWidth+(j+jj-m_nSEWidth/2)]=COLOR_BLACK;				
						}
					}
			}
		}
	delete[] pTempBuf;	
	return true;
}

bool CMorphology::Erode(BYTE* pSrcBuf,BYTE* pDestBuf,int nSEType,int nWidth,int nHeight,BYTE* pSEType,int nSEWidth)
{
	BYTE* pDest;
	//>>若输出阵列为空,则输出结果到输入阵列
	if(pDestBuf==NULL)
		pDest=pSrcBuf;
	else
		pDest=pDestBuf;
	//<<
	
	//>>设置结构元素
	if(nSEType>STRUCTURE_ELEMENT&&nSEType<STRUCTURE_ELEMENT_END)
		SetSE(nSEType);
	else if(pSEType!=NULL)
		SetSE(0,pSEType,nSEWidth);
	else
		TRACE("没有默认的或给定的结构元素\n");
	//<<

	bool bOK;
	BYTE* pTempBuf=new BYTE[nWidth*nHeight];
	::memcpy(pTempBuf,pSrcBuf,nWidth*nHeight);

	for(int i=0;i<nHeight-m_nSEWidth/2;i++)
		for(int j=0;j<nWidth-m_nSEWidth/2;j++)
		{
		/*BYTE Temp=pTempBuf[i*nWidth+j];
		for(int ii=0;ii<m_nSEWidth;ii++)
		{
		for(int jj=0;jj<m_nSEWidth;jj++)
		{
		if(m_pSE[ii*m_nSEWidth+jj]>=1)
		if(Temp<pTempBuf[(i+ii-m_nSEWidth/2)*nWidth+(j+jj-m_nSEWidth/2)])
		Temp=pTempBuf[(i+ii-m_nSEWidth/2)*nWidth+(j+jj-m_nSEWidth/2)];
		}
		}
		pDest[i*nWidth+j]=Temp;
			*/
			bOK=true;
			for(int ii=0;(ii<m_nSEWidth-m_nSEWidth/2)&&bOK;ii++)
			{
				for(int jj=0;(jj<m_nSEWidth-m_nSEWidth/2)&&bOK;jj++)
				{
					if(!bOK)break;
					if(m_pSE[ii*m_nSEWidth+jj])
					{
						if((i+ii-m_nSEWidth/2)*nWidth+(j+jj-m_nSEWidth/2)>=0)
						{
							if(COLOR_BLACK==0)
								bOK=bOK&&(!pTempBuf[(i+ii-m_nSEWidth/2)*nWidth+(j+jj-m_nSEWidth/2)]);
							else
								bOK=bOK&&(pTempBuf[(i+ii-m_nSEWidth/2)*nWidth+(j+jj-m_nSEWidth/2)]);
						}
					}
				}
				if(bOK)
					pDest[i*nWidth+j]=COLOR_BLACK;
				else
					pDest[i*nWidth+j]=COLOR_WHITE;
			}
		}
			/*@@int ii=0;
			while((ii<m_nSEWidth)&&bOK)
			{
				int jj=0;
				while((jj<m_nSEWidth)&&bOK)
				{
					if(m_pSE[ii*m_nSEWidth+jj]==1)
					{
						if((i+ii-m_nSEWidth/2)*nWidth+(j+jj-m_nSEWidth/2)>=0)
						{
							if(COLOR_BLACK==0)
								bOK=bOK&&(!pTempBuf[(i+ii-m_nSEWidth/2)*nWidth+(j+jj-m_nSEWidth/2)]);
							else
								bOK=bOK&&(pTempBuf[(i+ii-m_nSEWidth/2)*nWidth+(j+jj-m_nSEWidth/2)]);

						}
					}
					jj++;
				}
				ii++;
			}
				if(bOK)
					pDest[i*nWidth+j]=COLOR_BLACK;
				else
					pDest[i*nWidth+j]=COLOR_WHITE;
	
			
		}*/
	delete[] pTempBuf;	
	return true;
}

bool CMorphology::Skeletonizing(BYTE *pBuf, int nSEType, int nWidth, int nHeight)
{
	SetSE(nSEType);
	
	BYTE* pTempBuf=new BYTE[nWidth*nHeight];	//临时数组
	
	BYTE* pTempBufSrc=new BYTE[nWidth*nHeight];	//临时源数组
	::memcpy(pTempBufSrc,pBuf,nWidth*nHeight);
	
	BYTE* pTempBufb=new BYTE[nWidth*nHeight];	//临时数组清0
	::memset(pTempBufb,0,nWidth*nHeight);
	
	BYTE* pTempBufc=new BYTE[nWidth*nHeight];	//临时数组清0
	::memset(pTempBufc,0,nWidth*nHeight);
	
	bool bContinue=true,bBlack=true;
	int i,j;
	while(bBlack)
	{
		bBlack=false;
		Erode(pTempBufSrc,pTempBufb,nSEType,nWidth,nHeight);

		for(i=0;(i<nHeight)&&bContinue;i++)
			for(j=0;(j<nWidth)&&bContinue;j++)
			{
				if(pTempBufb[i*nWidth+j]==COLOR_BLACK)//黑色
				{
					bBlack=true;	//要做到pTempBufb没有黑色为止
					Dilate(pTempBufb,pTempBufc,nSEType,nWidth,nHeight);

					//XOR(pTempBufSrc,pTempBufc,pTempBufSrc,nWidth,nHeight);

					//pTempBufSrc[ii*nWidth+jj]=(~pTempBufc[ii*nWidth+jj])^(~pTempBufSrc[ii*nWidth+jj]);
							//因为黑色是0,不是255,所以加上~
					//pBuf[ii*nWidth+jj]=(~pTempBufSrc[ii*nWidth+jj])|(~pBuf[ii*nWidth+jj]);
					//OR(pTempBufSrc,pBuf,pBuf,nWidth,nHeight);


						{for(int ii=0;ii<nHeight;ii++)
						for(int jj=0;jj<nWidth;jj++)
						{
							pTempBufSrc[ii*nWidth+jj]=(~pTempBufc[ii*nWidth+jj])^(~pTempBufSrc[ii*nWidth+jj]);
							//因为黑色是0,不是255,所以加上~
						}
					}
					for(int ii=0;ii<nHeight;ii++)
						for(int jj=0;jj<nWidth;jj++)
						{
							pBuf[ii*nWidth+jj]=(~pTempBufSrc[ii*nWidth+jj])|(~pBuf[ii*nWidth+jj]);
						}
					::memcpy(pTempBufSrc,pTempBufb,nWidth*nHeight);
					bContinue=false;
				}
				
			}
		bContinue=true;
	}

	OR(pBuf,pTempBufSrc,pBuf,nWidth,nHeight);

	delete[] pTempBuf;
	delete[] pTempBufSrc;
	delete[] pTempBufb;
	delete[] pTempBufc;
	return true;
}

void CMorphology::SetSE(const int nDefSEType,BYTE* pSEType,int nSEWidth)
{
	if(m_pSE)
	{
		delete[] m_pSE;
	}
	
	//>>没有默认的结构元素,用给定的数组设置结构元素
	if(nDefSEType==0)
	{
		if(nSEWidth>0)
			m_nSEWidth=nSEWidth;
		else
			TRACE("结构元素宽度nWidth出错\n");
		m_pSE=new BYTE[nSEWidth*nSEWidth];
		::memcpy(m_pSE,pSEType,nSEWidth*nSEWidth);
		return;
	}
	//<<

	//>>有默认的结构元素
	switch(nDefSEType)
	{
	case SE_SQUARE:
		{
			m_nSEWidth=3;
			m_pSE=new BYTE[9];
			BYTE btTemp[9]={
					1,1,1,
					1,1,1,
					1,1,1};
				::memcpy(m_pSE,&btTemp,9);
		}
		break;
	case SE_RHOMBUS:
		{
			m_nSEWidth=3;
			m_pSE=new BYTE[9];
			BYTE btTemp[9]={
					0,1,0,
					1,1,1,
					0,1,0};
				::memcpy(m_pSE,&btTemp,9);
		}
		break;

	default:
		TRACE("没有该默认的结构元素\n");
	}
	//<<
	return;
	
}

bool CMorphology::Open(BYTE* pSrcBuf,BYTE* pDestBuf,int nSEType,int nWidth,int nHeight,BYTE* pSEType,int nSEWidth)
{
	Dilate(pSrcBuf,pDestBuf,nSEType,nWidth,nHeight,pSEType,nSEWidth);
	Erode(pSrcBuf,pDestBuf,nSEType,nWidth,nHeight,pSEType,nSEWidth);

	return true;
}

bool CMorphology::Skeleton(BYTE *pBuf, int nSEType, int nWidth, int nHeight)
{
	/*BYTE* pTempBuf1=new BYTE[nWidth*nHeight];
	BYTE* pTempBuf2=new BYTE[nWidth*nHeight];
	BYTE* pTempBuf3=new BYTE[nWidth*nHeight];
	//::memcpy(pTempBuf,pBuf);
	BYTE SE_D1[9]={0,0,3,0,1,1,3,1,3};
	BYTE SE_D2[9]={3,0,0,1,1,0,3,1,3};
	BYTE SE_D3[9]={3,1,3,1,1,0,3,0,0};
	BYTE SE_D4[9]={3,1,3,0,1,1,0,0,3};

	BYTE SE_K1[9]={3,0,3,1,1,1,3,1,3};
	BYTE SE_K2[9]={3,1,3,1,1,0,3,1,3};
	BYTE SE_K3[9]={3,1,3,1,1,1,3,0,3};
	BYTE SE_K4[9]={3,1,3,0,1,1,3,1,3};

	Open(pBuf,pTempBuf1,0,nWidth,nHeight,(BYTE*)SE_D1,3);
	Open(pBuf,pTempBuf2,0,nWidth,nHeight,(BYTE*)SE_D2,3);
	Open(pBuf,pTempBuf3,0,nWidth,nHeight,(BYTE*)SE_K1,3);
	AND(pTempBuf1,pTempBuf2,pBuf,nWidth,nHeight);
	AND(pBuf,pTempBuf3,pBuf,nWidth,nHeight);

	Open(pBuf,pTempBuf1,0,nWidth,nHeight,(BYTE*)SE_D2,3);
	Open(pBuf,pTempBuf2,0,nWidth,nHeight,(BYTE*)SE_D3,3);
	Open(pBuf,pTempBuf3,0,nWidth,nHeight,(BYTE*)SE_K2,3);
	AND(pTempBuf1,pTempBuf2,pBuf,nWidth,nHeight);
	AND(pBuf,pTempBuf3,pBuf,nWidth,nHeight);

	Open(pBuf,pTempBuf1,0,nWidth,nHeight,(BYTE*)SE_D3,3);
	Open(pBuf,pTempBuf2,0,nWidth,nHeight,(BYTE*)SE_D4,3);
	Open(pBuf,pTempBuf3,0,nWidth,nHeight,(BYTE*)SE_K3,3);
	AND(pTempBuf1,pTempBuf2,pBuf,nWidth,nHeight);
	AND(pBuf,pTempBuf3,pBuf,nWidth,nHeight);

	Open(pBuf,pTempBuf1,0,nWidth,nHeight,(BYTE*)SE_D4,3);
	Open(pBuf,pTempBuf2,0,nWidth,nHeight,(BYTE*)SE_D1,3);
	Open(pBuf,pTempBuf3,0,nWidth,nHeight,(BYTE*)SE_K4,3);
	AND(pTempBuf1,pTempBuf2,pBuf,nWidth,nHeight);
	AND(pBuf,pTempBuf3,pBuf,nWidth,nHeight);

	delete[] pTempBuf1;
	delete[] pTempBuf2;
	delete[] pTempBuf3;
	return true;
	*/
	SetSE(nSEType);
	
	BYTE* pTempBufa=new BYTE[nWidth*nHeight];	//临时数组清0
	::memset(pTempBufa,0,nWidth*nHeight);
	
	BYTE* pTempBufb=new BYTE[nWidth*nHeight];	//临时数组清0
	::memset(pTempBufb,0,nWidth*nHeight);
	
	BYTE** pBufSK=new BYTE*[m_nSEWidth];	//临时数组清0
	int j;
	for(j=0;j<m_nSEWidth;j++)
	{
		pBufSK[j]=new BYTE[nWidth*nHeight];
		::memset(pBufSK[j],0,nWidth*nHeight);
	}

	int nCount=0,i=0;
	while(nCount<m_nSEWidth)
	{
		nCount++;
		i=0;
		while(i++<nCount)
		{
			Erode(pBuf,pTempBufa,nSEType,nWidth,nHeight);
			::memcpy(pTempBufb,pTempBufa,nWidth*nHeight);
		}
		Open(pTempBufb,pTempBufb,nSEType,nWidth,nHeight);
		XOR(pTempBufa,pTempBufb,pBufSK[nCount-1],nWidth,nHeight);
	}
	for(j=0;j<m_nSEWidth-1;j++)
	{
		OR(pBufSK[j],pBufSK[j+1],pBufSK[j+1],nWidth,nHeight);
	}
	::memcpy(pBuf,pBufSK[j],nWidth*nHeight);
	
	delete[] pTempBufa;
	delete[] pTempBufb;
	for(j=0;j<m_nSEWidth;j++)
	{
		delete[] pBufSK[j];
	}	
	delete[] pBufSK;

	return true;
}

void CMorphology::AND(BYTE *pSrcBuf1, BYTE *pSrcBuf2, BYTE *pDestBuf, int nWidth, int nHeight)
{
	BYTE* pDest;
	//>>若输出阵列为空,则输出结果到输入阵列
	if(pDestBuf==NULL)
		pDest=pSrcBuf2;
	else
		pDest=pDestBuf;
	//<<
	for(int i=0;i<nHeight;i++)
		for(int j=0;j<nWidth;j++)
		{
			if((pSrcBuf1[i*nWidth+j]==COLOR_BLACK)&&(pSrcBuf2[i*nWidth+j]==COLOR_BLACK))
				pDest[i*nWidth+j]=COLOR_BLACK;
			else
				pDest[i*nWidth+j]=COLOR_WHITE;

		}
}

void CMorphology::OR(BYTE *pSrcBuf1, BYTE *pSrcBuf2, BYTE *pDestBuf, int nWidth, int nHeight)
{
	BYTE* pDest;
	//>>若输出阵列为空,则输出结果到输入阵列
	if(pDestBuf==NULL)
		pDest=pSrcBuf2;
	else
		pDest=pDestBuf;
	//<<
	for(int i=0;i<nHeight;i++)
		for(int j=0;j<nWidth;j++)
		{
			if((pSrcBuf1[i*nWidth+j]==COLOR_BLACK) ||(pSrcBuf2[i*nWidth+j]==COLOR_BLACK))
				pDest[i*nWidth+j]=COLOR_BLACK;
			else
				pDest[i*nWidth+j]=COLOR_WHITE;
			//pDest[i*nWidth+j]=(~pSrcBuf1[i*nWidth+j])|(~pSrcBuf2[i*nWidth+j]);
		}
}

void CMorphology::XOR(BYTE *pSrcBuf1, BYTE *pSrcBuf2, BYTE *pDestBuf, int nWidth, int nHeight)
{
	BYTE* pDest;
	//>>若输出阵列为空,则输出结果到输入阵列
	if(pDestBuf==NULL)
		pDest=pSrcBuf2;
	else
		pDest=pDestBuf;
	//<<
	for(int i=0;i<nHeight;i++)
		for(int j=0;j<nWidth;j++)
		{
			if((pSrcBuf1[i*nWidth+j]==COLOR_BLACK)&&(pSrcBuf2[i*nWidth+j]==COLOR_WHITE))
				pDest[i*nWidth+j]=COLOR_BLACK;
			else if((pSrcBuf1[i*nWidth+j]==COLOR_WHITE)&&(pSrcBuf2[i*nWidth+j]==COLOR_BLACK))
				pDest[i*nWidth+j]=COLOR_BLACK;
			else
				pDest[i*nWidth+j]=COLOR_WHITE;
			
			//pDest[i*nWidth+j]=(~pSrcBuf1[i*nWidth+j])^(~pSrcBuf2[i*nWidth+j]);
		}
}

bool CMorphology::Thinning(BYTE *pBuf, int nWidth, int nHeight)
{
	static int erasetable[256]={
								0,0,1,1,0,0,1,1,
								1,1,0,1,1,1,0,1,
								1,1,0,0,1,1,1,1,
								0,0,0,0,0,0,0,1,
								
								0,0,1,1,0,0,1,1,
								1,1,0,1,1,1,0,1,
								1,1,0,0,1,1,1,1,
								0,0,0,0,0,0,0,1,
								
								1,1,0,0,1,1,0,0,
								0,0,0,0,0,0,0,0,
								0,0,0,0,0,0,0,0,
								0,0,0,0,0,0,0,0,
								
								1,1,0,0,1,1,0,0,
								1,1,0,1,1,1,0,1,
								0,0,0,0,0,0,0,0,
								0,0,0,0,0,0,0,0,

								0,0,1,1,0,0,1,1,
								1,1,0,1,1,1,0,1,
								1,1,0,0,1,1,1,1,
								0,0,0,0,0,0,0,1,
								
								0,0,1,1,0,0,1,1,
								1,1,0,1,1,1,0,1,
								1,1,0,0,1,1,1,1,
								0,0,0,0,0,0,0,0,
								
								1,1,0,0,1,1,0,0,
								0,0,0,0,0,0,0,0,
								1,1,0,0,1,1,1,1,
								0,0,0,0,0,0,0,0,

								1,1,0,0,1,1,0,0,
								1,1,0,1,1,1,0,0,
								1,1,0,0,1,1,1,0,
								1,1,0,0,1,0,0,0
						  };

	BYTE n,e,s,w,ne,se,nw,sw;
	bool Finished=FALSE;
    while(!Finished){
    	Finished=TRUE;
		for (int y=1;y<nHeight-1;y++){ 
			//lpPtr=(char *)lpImgData+(BufSize-LineBytes-y*LineBytes);
			//lpTempPtr=(char *)lpTempImgData+(BufSize-LineBytes-y*LineBytes);
			int x=1; 
			while(x<nWidth-1){
				if(pBuf[y*nWidth+x]==COLOR_BLACK){
					w=pBuf[y*nWidth+x-1];
					e=pBuf[y*nWidth+x+1];
					if( (w==COLOR_WHITE)|| (e==COLOR_WHITE)){
						nw=pBuf[y*nWidth+nWidth+x-1];
						n=pBuf[y*nWidth+nWidth+x];
						ne=pBuf[y*nWidth+nWidth+x+1];
						sw=pBuf[y*nWidth-nWidth+x-1];
						s=pBuf[y*nWidth-nWidth+x];
						se=pBuf[y*nWidth+nWidth+x+1];
						int num=nw/255+n/255*2+ne/255*4+w/255*8+e/255*16+sw/255*32+s/255*64+se/255*128;
						if(erasetable[num]==1){
							pBuf[y*nWidth+x]=(BYTE)255;
							//*(lpTempPtr+x)=(BYTE)255;
							Finished=FALSE;
							x++;
						}
					}
				}
				x++;
			}
		}
	
		for (int x=1;x<nWidth-1;x++){ 
			int y=1;
			while(y<nHeight-1){
				//lpPtr=(char *)lpImgData+(BufSize-LineBytes-y*LineBytes);
				//lpTempPtr=(char *)lpTempImgData+(BufSize-LineBytes-y*LineBytes);
				if(pBuf[y*nWidth+x]==0){
					n=pBuf[y*nWidth+nWidth+x];
					s=pBuf[y*nWidth-nWidth+x];
					if( (n==255)|| (s==255)){
						nw=pBuf[y*nWidth+nWidth+x-1];
						ne=pBuf[y*nWidth+nWidth+x+1];
						w=pBuf[y*nWidth+x-1];
						e=pBuf[y*nWidth+x+1];
						sw=pBuf[y*nWidth-nWidth+x-1];
						se=pBuf[y*nWidth-nWidth+x+1];
						int num=nw/255+n/255*2+ne/255*4+w/255*8+e/255*16+sw/255*32+s/255*64+se/255*128;
						if(erasetable[num]==1){
							//*(lpPtr+x)=(BYTE)255;
							//*(lpTempPtr+x)=(BYTE)255;
							pBuf[y*nWidth+x]=255;
							Finished=FALSE;
							y++;
						}
					}
				}
				y++;
			}
		} 
	}

	return true;
}

⌨️ 快捷键说明

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