📄 morphology.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 + -