📄 image.cpp
字号:
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 CutFromImg(ImgOut,rcReal);
}
//剪切各个字符
BOOL CImage::GetExactText(CList<CImage,CImage&> &ImgList)
{
int i,j;
ImgList.RemoveAll();
int nCalWidth[10];
memset(nCalWidth,0,10*sizeof(int));
CImage ImgOut,ImgOut1;
ImgOut1 = *this;
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) //噪音
{
nStart = -1;
nEnd = -1;
}
}
}
else
{
ptList.AddTail(CPoint(nStart,i));
nStart = -1;
nEnd = -1;
}
}
else
{
if (nStart>=0)
{
ptList.AddTail(CPoint(nStart,i));
nStart = -1;
nEnd = -1;
}
}
}
}
i++;
}
int nCount = ptList.GetCount();
if (nCount<6)
{
continue;
}
else if (nCount>=6) //正常
{
break;
}
}
int nWNum[MAXWIDTH];
memset(nWNum,0,sizeof(int)*MAXWIDTH);
pos = ptList.GetHeadPosition();
while (pos)
{
ptTemp = ptList.GetNext(pos);
if (ptTemp.y-ptTemp.x<MAXWIDTH&&ptTemp.y-ptTemp.x>3)
{
nWNum[ptTemp.y-ptTemp.x]++;
}
}
int nMaxNum = nWNum[0];
int nMaxNo = 0;
for(i=0;i<MAXWIDTH;i++)
{
if (nMaxNum<nWNum[i])
{
nMaxNum = nWNum[i];
nMaxNo = i;
}
}
//字宽应该是nMaxNo
if (nMaxNo<3)
{
delete []nX;
return FALSE;
}
//排除第3个黑点
if (ptList.GetCount()>7)
{
for(i=1;i<4;i++)
{
pos = ptList.FindIndex(i);
ptTemp = ptList.GetAt(pos);
if (ptTemp.y-ptTemp.x<nMaxNo-1)
{
BOOL bHave = TRUE;
for(int j=ptTemp.x;j<=ptTemp.y;j++)
{
if (nX[j]>nHeight*0.8)
{
bHave = FALSE;
break;
}
}
if (bHave)
{
ptList.RemoveAt(pos);
break;
}
}
}
}
nCount = ptList.GetCount();
int nMinNum,nMinNo;
POSITION posLast;
//先看有合并的没有
pos = ptList.GetHeadPosition();
POSITION posNext;
int nNo = 0;
CPoint ptTemp1;
while (pos)
{
ptTemp = ptList.GetNext(pos);
if (ptTemp.y-ptTemp.x<=nMaxNo/2)
{
if (pos)
{
posNext = pos;
ptTemp1 = ptList.GetNext(posNext);
if (ptTemp1.y-ptTemp1.x<=nMaxNo/2&&ptTemp1.y-ptTemp.x<nMaxNo+2)//应该合并
{
ptList.GetPrev(pos);
ptList.SetAt(pos,CPoint(ptTemp.x,ptTemp1.y));
posNext = pos;
ptList.GetNext(posNext);
ptList.RemoveAt(posNext);
}
}
}
}
//再看有没有可以分解的
pos = ptList.GetHeadPosition();
nIndex = 0;
posLast = pos;
while (pos)
{
ptTemp = ptList.GetNext(pos);
if (ptTemp.y-ptTemp.x>nMaxNo+2&&nIndex>1) //需要拆分
{
nMinNo = ptTemp.x+1;
nMinNum = nX[ptTemp.x+1];
for(i=ptTemp.x+1;i<ptTemp.y-1;i++)
{
if (nMinNum>nX[i])
{
nMinNum = nX[i];
nMinNo = i;
}
}
if (nMinNum<3&&(nMinNo-ptTemp.x>3)&&(ptTemp.y-nMinNo>3))
{
ptList.InsertBefore(posLast,CPoint(ptTemp.x,nMinNo));
ptList.SetAt(posLast,CPoint(nMinNo,ptTemp.y));
}
}
nIndex++;
posLast = pos;
}
pos = ptList.GetHeadPosition();
posLast = pos;
nIndex = 0;
while (pos)
{
ptTemp = ptList.GetNext(pos);
if (ptTemp.y-ptTemp.x>nMaxNo+1) //有噪音
{
nMinNum = nX[ptTemp.x];
nMinNo = ptTemp.x;
for(i=ptTemp.x+1;i<ptTemp.y-1;i++)
{
if (nMinNum>nX[i])
{
nMinNum = nX[i];
nMinNo = i;
}
}
if (nMinNum<3&&(nIndex<=3||nIndex==ptList.GetCount()-1))
{
if (nMinNo-ptTemp.x<3&&ptTemp.y-nMinNo>nMaxNo-3)
{
ptList.SetAt(posLast,CPoint(nMinNo,ptTemp.y));
}
else if (nMinNo-ptTemp.x>nMaxNo-3&&ptTemp.y-nMinNo<=3)
{
ptList.SetAt(posLast,CPoint(ptTemp.x,nMinNo));
}
}
}
posLast = pos;
nIndex++;
}
//去掉最后一竖
nCount = ptList.GetCount();
if (nCount>7)
{
ptTemp = ptList.GetTail();
if (ptTemp.y-ptTemp.x<3)
{
double dCenter[4];
for(i=nCount-1;i>nCount-5;i--)
{
pos = ptList.FindIndex(i);
ptTemp = ptList.GetAt(pos);
dCenter[nCount-1-i] = (ptTemp.y+ptTemp.x)/2;
}
for(i=0;i<3;i++)
{
dCenter[i] = dCenter[i]-dCenter[i+1];
}
if (dCenter[0]<(dCenter[1]+dCenter[2])/2-2)
{
ptList.RemoveTail();
}
}
}
//去上下边框
pos = ptList.GetHeadPosition();
int nTop[20];
int nButtom[20];
nIndex = 0;
CImage imgTemp;
while (pos)
{
ptTemp = ptList.GetNext(pos);
ImgOut.CutFromImg(imgTemp,CRect(ptTemp.x,0,ptTemp.y+1,ImgOut.GetHeight()));
ImgList.AddTail(imgTemp);
imgTemp.CutUpAndDown(nTop[nIndex],nButtom[nIndex]);
nIndex++;
}
int nTopOut[20];
int nButtomOut[20];
GetOutUpAndDown(nTop, nButtom, nIndex, nTopOut, nButtomOut,ImgOut.GetHeight());
pos = ptList.GetHeadPosition();
posLast = pos;
ImgList.RemoveAll();
nIndex = 0;
int nH = (int)(ImgOut.GetHeight()*0.5);
nH = max(nH,7);
while (pos)
{
ptTemp = ptList.GetNext(pos);
ImgOut.CutFromImg(imgTemp,CRect(ptTemp.x,0,ptTemp.y+1,ImgOut.GetHeight()));
//下面为只保留最大连通区域...可考虑修改去掉点少的和连通域在右边的,而且第一个汉字不用执行。
imgTemp.DenoiseMax();
imgTemp.CutOffUnUsedArea();
ImgList.AddTail(imgTemp);
posLast = pos;
nIndex++;
}
delete []nX;
//去前面几个黑块
int nRemove = 0;
if (ImgList.GetCount()>7)
{
int nIndex = 0;
for(i=2;i>0;i--)
{
pos = ImgList.FindIndex(i);
imgTemp = ImgList.GetAt(pos);
double dPix = imgTemp.GetAllTextPointNum(CRect(0,0,imgTemp.GetWidth(),imgTemp.GetHeight()),0);
dPix /= imgTemp.GetWidth()*imgTemp.GetHeight();
if (dPix>0.65)
{
nIndex = i;
break;
}
}
for(i=nIndex-1;i>=0;i--)
{
pos = ImgList.FindIndex(i);
ImgList.RemoveAt(pos);
pos = ptList.FindIndex(i);
ptList.RemoveAt(pos);
}
if (nIndex>0)
{
while (ImgList.GetCount()>7)
{
ImgList.RemoveTail();
}
while (ptList.GetCount()>7) {
ptList.RemoveTail();
}
}
}
if (ptList.GetCount()>7)
{
//先根据第2和第三个字之间有一个点来确定去掉什么地方
//算出两个字之间的距离最大的两个
pos = ptList.FindIndex(4);
CPoint ptLast = ptList.GetAt(pos);
nMaxNum = 0;
nMaxNo = 4;
for(i=3;i>0;i--)
{
pos = ptList.FindIndex(i);
ptTemp = ptList.GetAt(pos);
if (ptLast.y-ptTemp.x>nMaxNum)
{
nMaxNum = ptLast.y - ptTemp.x;
nMaxNo = i;
}
ptLast = ptTemp;
//如果是1
if (ptTemp.y-ptTemp.x<=nMaxNo/2)
{
ptLast.y = ptLast.x + nMaxNo;
}
}
nMaxNo+=2;
//要是nMaxNo>0,说明在第nMaxNo前有一个点
nIndex = ImgList.GetCount();
if (nMaxNo>1&&nIndex>7)
{
for(i=0;i<nMaxNo-3;i++)
{
if (ImgList.GetCount()<=7) {
break;
}
ImgList.RemoveHead();
nRemove++;
}
for(i=0;i<nIndex-nMaxNo-4;i++)
{
if (ImgList.GetCount()<=7)
{
break;
}
ImgList.RemoveTail();
}
}
}
return TRUE;
}
//切割文字
BOOL CImage::CutText(CList<CImage,CImage&> &ImgOutList,BOOL bBlackText)
{
//白底黑字化
CImage ImgTemp;
CImage ImgOut = *this;
double dA[2];
double dB[2];
ImgOut.Rectify(*this,dA,dB,bBlackText?255:0);
BYTE pHist[3][256];
BYTE pMean[3];
double dS[3];
CalCulate(pHist,pMean,dS);
int min=0;
for(int i=0;i<pMean[0];i++)
{
if (pHist[0][i]>0)
{
min=i;
break;
}
}
int nToTalPix =GetWidth()* GetHeight();
double dPercent = 0.1;
//求阈值
int pos=0;
double nPix = 0;
for(i=255;i>0;i--)
{
nPix += pHist[0][i];
if (nPix/nToTalPix>dPercent)
{
pos=i;
break;
}
}
//进行灰度拉伸
CImage Imgout;
GrayStretch(Imgout,pos,min);
*this = Imgout;
double ratio = 0.25;
CImage Template2,Template3,Template4;
MaxMinGrid(Template2,CSize(7,11),FALSE);
MaxMinMinusGrid(Template3,CSize(7,11),FALSE);
Template2.AvgGrid(Template4,CSize(7,11),FALSE);
Threold1(ImgOut,Template4,Template3,pos,min,bBlackText,ratio);
double dRate = ImgOut.GetAllTextPointNum(CRect(m_nWidth/4,m_nHeight/4,m_nWidth*3/4,m_nHeight*3/4),0);
dRate/=((GetWidth()/2)*(GetHeight()/2));
double dRate1 = 0;
int Enter = 0;
//CImage imgOut1;
while( dRate<0.3 && (ratio<0.4 && ratio>0.1) )
{
/*
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -