📄 segmentationbyprojection.cpp
字号:
// SegmentationByProjection.cpp: implementation of the CSegmentationByProjection class.
//
//////////////////////////////////////////////////////////////////////
#include "stdafx.h"
#include "SegmentationByProjection.h"
#include "math.h"
#define ROUND(X) (((X)-int(X))>0.5?int(X)+1:int(X))
#ifdef _DEBUG
#undef THIS_FILE
static char THIS_FILE[]=__FILE__;
#define new DEBUG_NEW
#endif
//////////////////////////////////////////////////////////////////////
// Construction/Destruction
//////////////////////////////////////////////////////////////////////
CSegmentationByProjection::CSegmentationByProjection()
{
}
CSegmentationByProjection::~CSegmentationByProjection()
{
}
BOOL CSegmentationByProjection::Segment(CList<CImage,CImage &> &ImgOutList,CImage &ImgVLP,CRect rcVLP,CImage &ImgOrg,BOOL &m_bBlack,BOOL IsEnter)
{
CImage imTwoOrg;
CImage imTwoQuZao;
ImgVLP.imGraytoTwo(imTwoOrg,m_bBlack);
CList<CRect,CRect> ListRect;
imTwoQuZao = imTwoOrg;
imTwoQuZao.imLTquzao(ListRect);
double dA[2];
double dB[2];
//先通过连通字符求得倾斜角
//要是连同不行就用跳变
if (imTwoQuZao.GetABByLianTong(dA,dB))
{
}
else
{
ImgVLP.GetABByTioaBian(dA,dB);
}
// ImgVLP.GetABByTioaBian(dA,dB);
int nLongType = 0;//等于0为正常;等于1为太长;等于-1为太短;
CImage imRctTwoOrg;
CImage imRctTwoQuZao;
CImage imRctVLP;
ImgVLP.RectifyAB(imRctVLP,dA,dB,m_bBlack?255:0,rcVLP.TopLeft(),&ImgOrg);
imTwoOrg.RectifyAB(imRctTwoOrg,dA,dB,m_bBlack?255:0,rcVLP.TopLeft(),NULL,FALSE);
imTwoQuZao.RectifyAB(imRctTwoQuZao,dA,dB,m_bBlack?255:0,rcVLP.TopLeft(),NULL,FALSE);
if (imRctVLP.GetWidth()>imRctVLP.GetHeight()*6)
{
nLongType = 1;
// AfxMessageBox("太长");
}
if (imRctVLP.GetWidth()<imRctVLP.GetHeight()*4)
{
nLongType = -1;
// AfxMessageBox("太短");
}
//去掉左右边界
CImage imCutTwoOrg;
CImage imCutTwoQuZao = imRctVLP;
CImage imCutVLP;
CImage ImgOut;
// ImgVLP.ShowImg();
int nLR[2];
CImage ImgTemp2 = ImgVLP;
ImgVLP.CutLRByTiaoBian(nLR,m_bBlack,imRctVLP.GetHeight());
imRctVLP.CutFromImg(ImgVLP,CRect(nLR[0],0,nLR[1],imRctVLP.GetHeight()));
imRctTwoQuZao.CutFromImg(ImgOut,CRect(nLR[0],0,nLR[1],imRctTwoQuZao.GetHeight()));
// ImgOut.ShowImg();
int m_nWidth = ImgVLP.GetWidth();
int m_nHeight = ImgVLP.GetHeight();
/*
BOOL bHaveLiangTong = TRUE;
if (!bHaveLiangTong)
{
if (!CutExact(ImgOut,ImgOut1)) //细定位,输出为黑字白底
{
return FALSE;
}
}*/
//ImgVLP.ShowImg();
// int nLRT[2];
return GetExactText(ImgOutList,ImgOut,ImgVLP,ImgTemp2,m_bBlack,nLR); //传入灰度图象
//return FALSE;
}
BOOL CSegmentationByProjection::CutExact(CImage &ImgOut, CImage &ImgIn)
{
int m_nWidth = ImgIn.GetWidth();
int m_nHeight = ImgIn.GetHeight();
CImage ImgTemp;
CRect rcReal;
int *nX = new int[m_nWidth];
int *nTiaoBianY = new int[m_nHeight];
memset(nTiaoBianY,0,sizeof(int)*m_nHeight);
memset(nX,0,sizeof(int)*m_nWidth);
//先去左右边界
int i;
rcReal.left = 0;
rcReal.right = m_nWidth;
rcReal.top = 0;
rcReal.bottom = m_nHeight;
//黑点个数,垂直方向
for (i=0;i<m_nWidth;i++)
{
for (int j=0;j<m_nHeight;j++)
{
if(ImgIn.m_pR[j*m_nWidth+i]==0)
{
nX[i]++;
}
}
}
for (i=0;i<m_nWidth/5;i++)
{
if(nX[i]>0.80*m_nHeight && nX[i+1]<0.2*m_nHeight)
{
continue;
}
else
{
rcReal.left = i;
break;
}
}
//去掉上下边界
//跳变个数,水平方向
for(i=0;i<m_nHeight;i++)
{
for(int j=0;j<m_nWidth-1;j++)
{
if (ImgIn.m_pR[i*m_nWidth+j]!=ImgIn.m_pR[i*m_nWidth+1+j])
{
nTiaoBianY[i]++;
}
}
}
// TRACE(GetIntToString(nTiaoBianY,m_nHeight));
rcReal.top = m_nHeight/2;
for(i=m_nHeight/2;i>=0;i--)
{
if (nTiaoBianY[i]<10)
{
rcReal.top = i+1;
break;
}
}
rcReal.top = i<=0?0:rcReal.top;
for(i=m_nHeight/2;i<m_nHeight;i++)
{
if (nTiaoBianY[i]<10)
{
rcReal.bottom = i;
break;
}
}
rcReal.bottom = i>=m_nHeight?m_nHeight:rcReal.bottom;
// TRACE(GetIntToString(nTiaoBianY,m_nHeight));
if (rcReal.top>=rcReal.bottom)
{
delete []nTiaoBianY;
return FALSE;
}
delete []nX;
delete []nTiaoBianY;
return ImgIn.CutFromImg(ImgOut,rcReal);
}
BOOL CSegmentationByProjection::GetExactText(CList<CImage,CImage&> &ImgList,CImage &ImgIn,CImage &RImgGray,CImage &ImgGray,BOOL m_bBlack,int nLR[2])
{
// ImgIn.ShowImg();
int i,j;
ImgList.RemoveAll();
int nCalWidth[10];
memset(nCalWidth,0,10*sizeof(int));
CImage ImgOut,ImgOut1;
int m_nWidth = ImgIn.GetWidth();
ImgOut1 = ImgIn;
CImage ImgOutLianTong;
CList<int,int> ListNum;
CList<CRect,CRect> ListRect;
ImgOut1.GetLiantong(ListNum,ListRect,ImgOutLianTong,0);
POSITION pos;
POSITION pos1;
int nIndex = ListNum.GetCount()-1;
int nPix = ImgOut1.GetWidth()*ImgOut1.GetHeight();
while (nIndex>=0)
{
pos1 = ListRect.FindIndex(nIndex);
pos = ListNum.FindIndex(nIndex);
int nVal = ListNum.GetAt(pos);
BOOL bNoise = FALSE;
if (nVal<=0)
{
bNoise = TRUE;
}
else if (nVal<5&&nVal>0)
{
bNoise = TRUE;
for(i=0;i<nPix;i++)
{
if (ImgOutLianTong.m_pR[i]==nIndex)
{
ImgOut1.m_pR[i] = 255;
}
}
}
/* else if (nVal>=5)
{
CRect rcR = ListRect.GetAt(pos1);
double dRate = ((double)nVal/((rcR.Width()+1)*(rcR.Height()+1)));
if (rcR.Height()<ImgOut1.GetHeight()*2/3||(dRate>0.9&&rcR.Width()>2))
{
bNoise = TRUE;
for(i=0;i<nPix;i++)
{
if (ImgOutLianTong.m_pR[i]==nIndex)
{
ImgOut1.m_pR[i] = 255;
}
}
}
}*/
if (bNoise)
{
ListRect.RemoveAt(pos1);
ListNum.RemoveAt(pos);
}
nIndex--;
}
int nCount = ListNum.GetCount();
ImgOut = ImgOut1;
ImgOut1.SaveBMP("c:\\1.bmp");
int nMaxMin[2];
int nWidth = ImgOut.GetWidth();
int nHeight = ImgOut.GetHeight();
/*
if (nWidth>200) //太宽
{
return FALSE;
}*/
int *nX = new int[ImgOut.GetWidth()];//垂直方向黑点个数
for(i=0;i<nWidth;i++)
{
nX[i] = 0;
for(j=0;j<nHeight;j++)
{
if (ImgOut.m_pR[j*nWidth+i]==0)
{
nX[i]++;
}
}
}
CList<CPoint,CPoint> ptList;
nMaxMin[0] = int(nHeight*0.7);
nMaxMin[1] = int(nHeight*0.2);
int nStart = -1;
int nEnd = -1;
CPoint ptTemp;
CImage ImgTemp;
CRect rcNead;
CString strTempTrace = GetIntToString(nX,ImgOut.GetWidth());
int nTraceLen = min(510,strTempTrace.GetLength());
TRACE(strTempTrace.Mid(0,nTraceLen));
#define MAXWIDTH 25
int nWid = nWidth/8;//字宽
nWid = min(nWid,MAXWIDTH);
nWid = max(nWid,5);
for(int kk=1;kk<4;kk++)
{
ptList.RemoveAll();
i = 0;
while (i<nWidth)
{
if (nX[i]>=kk)
{
if (i==0||nStart<0)//是否该开始
{
nStart = i;
}
if (nStart>=0)
{
if (i==nWidth-1)
{
ptList.AddTail(CPoint(nStart,i));
nStart = -1;
nEnd = -1;
}
else if(i-nStart>nWid+1)//寻找波谷
{
int nXu = nStart+2;
int nMin = nX[nXu];
for(int k=nXu;k<=i;k++)
{
if (nX[k]<=nMin)
{
nMin = nX[k];
nXu = k;
}
}
ptList.AddTail(CPoint(nStart,nXu-1));
i = nXu;
nStart = -1;
nEnd = -1;
}
}
}
else
{
if (i==nWidth-1||nStart>=0)
{
if (i<nWidth-1)
{
if (i-nStart<4)//还不够长,应该往下看
{
BOOL bNot1 = TRUE;
for(int k=nStart;k<=i;k++)
{
if (nX[k]>=nMaxMin[0])
{
bNot1 = FALSE;
break;
}
}
if (bNot1==FALSE) //一定是1
{
int nXiao = 0;//判断1的旁边是否有空位
for(k=nStart;k<i+3;k++)
{
if (k>=0&&k<m_nWidth)
{
if (nX[k]<nMaxMin[1])
{
nXiao++;
}
}
}
if (nXiao>=2)
{
ptList.AddTail(CPoint(nStart,i));
nStart = -1;
nEnd = -1;
}
}
else
{
if (nX[i+1]<kk) //噪音
{
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -