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

📄 image.cpp

📁 车牌识别(改定位)武汉理工大学
💻 CPP
📖 第 1 页 / 共 5 页
字号:
	
	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 + -