www.pudn.com > chepaishibiexitong.rar > dipView.cpp


// dipView.cpp : implementation of the CDipView class 
// 
 
#include "stdafx.h" 
#include "dip.h" 
 
#include "dipDoc.h" 
#include "dipView.h" 
#include "afxdlgs.h" 
#include "afxwin.h" 
#include "math.h" 
#include ".\dipview.h" 
#include "stdlib.h" 
#include "malloc.h" 
#include "mainfrm.h" 
#include "charview.h" 
#include "recvchar.h" 
 
#include "training.h" 
 
 
#ifdef _DEBUG 
#define new DEBUG_NEW 
#undef THIS_FILE 
static char THIS_FILE[] = __FILE__; 
#endif 
 
///////////////////////////////////////////////////////////////////////////// 
// CDipView 
 
IMPLEMENT_DYNCREATE(CDipView, CView) 
 
BEGIN_MESSAGE_MAP(CDipView, CView) 
	//{{AFX_MSG_MAP(CDipView) 
	ON_COMMAND(ID_FILE_OPEN, OnFileOpen) 
	ON_WM_PAINT() 
	ON_COMMAND(ID_FILE_SAVE, OnFileSave) 
	ON_COMMAND(ID_reopen, Onreopen) 
	ON_WM_MOUSEMOVE() 
	ON_WM_CREATE() 
	ON_COMMAND(ID_LINE, OnLine)	 
	ON_COMMAND(ID_F3, Onfse) 
	ON_COMMAND(ID_F4, Onfz) 
	ON_COMMAND(ID_MoHu, OnMoHu) 
	ON_COMMAND(ID_ForHandle, OnForHandle) 
	ON_COMMAND(ID_HSearch, OnHSearch) 
	ON_COMMAND(ID_Banlance, OnBanlance) 
	ON_COMMAND(ID_SubVertical, OnSubVertical) 
	ON_COMMAND(ID_SubHorizontal, OnSubHorizontal) 
	ON_COMMAND(ID_MidValue, OnMidValue) 
	ON_COMMAND(ID_Average, OnAverage) 
	ON_COMMAND(ID_Bool, OnBool) 
	ON_COMMAND(ID_Choose, OnChoose) 
	ON_COMMAND(ID_TRAINFROMVEHICLE, OnTrainfromvehicle) 
	ON_COMMAND(ID_SAVESA, OnSave) 
	ON_COMMAND(ID_READSA, OnLoad) 
	ON_COMMAND(ID_CHANGE, OnChange) 
	ON_COMMAND(ID_TRAIN, OnTrain) 
	ON_COMMAND(ID_SAVEBP, OnSavebp) 
	ON_COMMAND(ID_VSearch, OnVSearch) 
	ON_COMMAND(ID_Locate, OnLocate) 
	ON_COMMAND(ID_Sobel, OnSobel) 
	ON_COMMAND(ID_VSplit, OnVSplit) 
	ON_COMMAND(ID_CharacterRec, OnCharacterRecg) 
	ON_COMMAND(ID_READBP, OnReadbp) 
	//}}AFX_MSG_MAP 
	// Standard printing commands 
	ON_COMMAND(ID_FILE_PRINT, CView::OnFilePrint) 
	ON_COMMAND(ID_FILE_PRINT_DIRECT, CView::OnFilePrint) 
	ON_COMMAND(ID_FILE_PRINT_PREVIEW, CView::OnFilePrintPreview) 
END_MESSAGE_MAP() 
 
///////////////////////////////////////////////////////////////////////////// 
// CDipView construction/destruction 
 
CDipView::CDipView() 
//: Height(NULL) 
//, TopRow(NULL) 
//: Widths(NULL) 
//, Left(NULL) 
//: Rect_X(NULL) 
//, Rect_Y(NULL) 
//, Rect_W(NULL) 
//, Rect_H(NULL) 
//, Rect_Areas(0) 
{ 
	// TODO: add construction code here 
	//初始化 
	m_pMemDC=new CDC;		//分配内存DC 
	m_pBitmap=new CBitmap;	//分配背景图像的空间 
	IsNewFile=true;			 
	IsNewBitmap=true; 
	m_pBmp=NULL; 
	Height=new int[20]; 
	TopRow=new int[20];	 
	Widths=new int[30];                     //Top' width 
	Left=new int[30];                   //Top' top col 
	Rect_X=new int[50]; 
    Rect_Y=new int[50];  
	Rect_W=new int[50]; 
    Rect_H=new int[50]; 
	Rect_Areas=0; 
	cRects=new crect[10]; 
	CharacterNum=0; 
	cDatas=new cData[10];        //实际大小由CharacterNum确定 
	char_ConnectPos=NULL; 
	num_ConnectPos=NULL; 
	han_ConnectPos=NULL; 
 
} 
 
CDipView::~CDipView() 
{ 
	//释放内存 
	delete m_pBitmap; 
	delete m_pMemDC; 
} 
 
BOOL CDipView::PreCreateWindow(CREATESTRUCT& cs) 
{ 
	// TODO: Modify the Window class or styles here by modifying 
	//  the CREATESTRUCT cs 
	return CView::PreCreateWindow(cs); 
} 
 
///////////////////////////////////////////////////////////////////////////// 
// CDipView drawing 
 
void CDipView::OnDraw(CDC* pDC) 
{ 
	CDipDoc* pDoc = GetDocument();	 
	ASSERT_VALID(pDoc); 
	// TODO: add draw code for native data here 
	 
	//如果已经读入一幅新的图像,则向CDC中写入新的图像信息 
	if ((pDoc->ImgData!=NULL)&&IsNewFile) 
	{ 
		// 
	   ChageStatuBar(&"正在打开文件 "); 
		// 
		int i,j,k; 
		k=0; 
		BYTE r,g,b; 
		for(i=0;iImgHeight;i++) 
			for(j=0;jImgWidth;j++) 
			{ 
				//从调色板中得到r,g,b分量 
				r=pDoc->palette[pDoc->ImgData[k]].rgbBlue;	 
				g=pDoc->palette[pDoc->ImgData[k]].rgbGreen; 
				b=pDoc->palette[pDoc->ImgData[k]].rgbRed; 
				pDC->SetPixel(j,i,(r<<16)|(g<<8)|b); 
				k++; 
			} 
		IsNewFile=false;	//写完后,将文件标志位置为假 
	    //恢复鼠标 
		 
		  
	    char * path =pDoc->FileName.GetBuffer(256) ; 
		ChageStatuBar(path); 
	} 
 
        
} 
 
///////////////////////////////////////////////////////////////////////////// 
// CDipView printing 
 
BOOL CDipView::OnPreparePrinting(CPrintInfo* pInfo) 
{ 
	// default preparation 
	return DoPreparePrinting(pInfo); 
} 
 
void CDipView::OnBeginPrinting(CDC* /*pDC*/, CPrintInfo* /*pInfo*/) 
{ 
	// TODO: add extra initialization before printing 
} 
 
void CDipView::OnEndPrinting(CDC* /*pDC*/, CPrintInfo* /*pInfo*/) 
{ 
	// TODO: add cleanup after printing 
} 
 
///////////////////////////////////////////////////////////////////////////// 
// CDipView diagnostics 
 
#ifdef _DEBUG 
void CDipView::AssertValid() const 
{ 
	CView::AssertValid(); 
} 
//setpentext 
void CDipView::Dump(CDumpContext& dc) const 
{ 
	CView::Dump(dc); 
} 
 
CDipDoc* CDipView::GetDocument() // non-debug version is inline 
{ 
	ASSERT(m_pDocument->IsKindOf(RUNTIME_CLASS(CDipDoc))); 
	return (CDipDoc*)m_pDocument; 
} 
#endif //_DEBUG 
 
///////////////////////////////////////////////////////////////////////////// 
// CDipView message handlers 
 
//打开一个BMP文件 
void CDipView::OnFileOpen()  
{ 
	// TODO: Add your command handler code here 
	CFileDialog mydlg(true); 
	CString filename; 
	mydlg.m_ofn.lpstrFilter="BMP files(*.bmp)\0*.bmp\0JPG files(*.jpg)\0*.jpg\0"; 
 
	//显示文件对话框 
	if (mydlg.DoModal()==IDOK) 
	{ 
		filename=mydlg.GetPathName(); 
		 
		//读入文件 
		CDipDoc * myDoc; 
		myDoc=GetDocument();            //enable you to call the number 
		                                //function of CDocment  
		myDoc->FileOpen(filename); 
		 
		//将文件标志位和图像标志位置为真 
		IsNewFile=true; 
		IsNewBitmap=true; 
 
		//刷新屏幕 
		myDoc->UpdateAllViews(NULL); 
	} 
} 
 
void CDipView::OnPaint()  
{ 
	CPaintDC dc(this); // device context for painting 
	// TODO: Add your message handler code here 
	this->GetActiveWindow()->SetWindowText("数字图像处理程序"); 
	//设定从内存DC到屏幕DC的拷贝区域 
	CRect rc(0,0,::GetSystemMetrics(SM_CXSCREEN),::GetSystemMetrics(SM_CYSCREEN)); 
 
	CBitmap * pOldBitmap=(CBitmap *)(m_pMemDC->SelectObject(m_pBitmap)); 
 
	if (IsNewBitmap) 
		m_pMemDC->Rectangle(-1,-1,2000,2000);	//新图,清除背景 
	else 
		m_pMemDC->SelectObject(mymap);			//旧图,直接调用内存中的图像 
 
	m_pMemDC->SelectClipRgn(NULL); 
	OnDraw(m_pMemDC);							//向内存DC中画图像 
	//拷贝到屏幕DC中 
	dc.BitBlt(rc.left,rc.top,rc.Width(),rc.Height(),m_pMemDC,rc.left,rc.top,SRCCOPY); 
		if (IsNewBitmap) 
	{ 
		//保存历史图像,已备下次显示 
		mymap=m_pMemDC->GetCurrentBitmap(); 
		IsNewBitmap=false; 
	} 
 
	m_pMemDC->SelectObject(pOldBitmap); 
 
//	m_wait=theapp->LoadCursor(IDC_ARROW); 
//	SetCursor(m_wait); 
	// Do not call CView::OnPaint() for painting messages 
} 
 
void CDipView::OnInitialUpdate()  
{ 
	CView::OnInitialUpdate(); 
//	ChageStatuBar(&"请打开一个BMP格式的位图文件");	 
	// TODO: Add your specialized code here and/or call the base class 
	//初始化m_pMemDC和m_pBitmap 
	if (m_pMemDC->GetSafeHdc()==NULL) 
	{ 
		CClientDC dc(this); 
		OnPrepareDC(&dc); 
		//设定背景图像的大小 
		CRect rc(0,0,::GetSystemMetrics(SM_CXSCREEN),::GetSystemMetrics(SM_CYSCREEN)); 
		m_pMemDC->CreateCompatibleDC(&dc); 
		m_pBitmap->CreateCompatibleBitmap(&dc,rc.right,rc.bottom); 
	} 
 
	CDipDoc* pDoc=GetDocument(); 
	int i; 
   for( i=0;iImgWidth*pDoc->ImgHeight;i++) 
	   img[i]=pDoc->ImgData[i]; 
	    
} 
 
 
 
void CDipView::OnFileSave()  
{ 
	// TODO: Add your command handler code here 
	CFileDialog mydlg(false); 
	CString filename,promt; 
	mydlg.m_ofn.lpstrFilter="BMP files(*.bmp)\0*.bmp\0\0"; 
	//打开存储对话框 
	if (mydlg.DoModal()==IDOK) 
	{ 
		filename=mydlg.GetPathName(); 
		if(filename.Find(".bmp")<=0) 
			filename=filename+".bmp"; 
		 
		//存储图像 
		CDipDoc* pDoc = GetDocument(); 
		pDoc->FileSave(filename); 
	} 
} 
 
//重新显示原始图像 
void CDipView::Onreopen()  
{ 
	// TODO: Add your command handler code here 
	CDipDoc* pDoc = GetDocument(); 
	pDoc->FileOpen(); 
	IsNewBitmap=true; 
	IsNewFile=true; 
	pDoc->UpdateAllViews(NULL); 
} 
 
void CDipView::OnMouseMove(UINT nFlags, CPoint point)  
{ 
		if (AfxGetApp() != NULL && AfxGetApp()->m_pMainWnd != NULL) { 
		char buffer[256]; 
		CStatusBar* pStatus = (CStatusBar*)  
			AfxGetApp()->m_pMainWnd->GetDescendantWindow(AFX_IDW_STATUS_BAR); 
 
		va_list argptr;	 
		pStatus->SetPaneInfo(2,2,SBPS_STRETCH  ,7);        
		CString x; 
		x.Format(_T("%d"),point.x);  
 
			CString y; 
		y.Format(_T("%d"),point.y);  
 
		 CString zuobiao=" x= "+x + " , " + "y= " +y; 
	char * fmt=zuobiao.GetBuffer(12); 
		va_start(argptr, fmt); 
		vsprintf(buffer, fmt, argptr); 
		va_end(argptr); 
       	if (pStatus != NULL) 
		{ 
			pStatus->SetPaneText(2, buffer); 
			pStatus->UpdateWindow(); 
		} 
	} 
	// TODO: Add your message handler code here and/or call default 
	CView::OnMouseMove(nFlags, point); 
} 
 
void CDipView::ChageStatuBar(char * fmt) 
{ 
 
	if (AfxGetApp() != NULL && AfxGetApp()->m_pMainWnd != NULL) { 
		char buffer[256]; 
		CStatusBar* pStatus = (CStatusBar*)  
			AfxGetApp()->m_pMainWnd->GetDescendantWindow(AFX_IDW_STATUS_BAR); 
 
		va_list argptr; 
		va_start(argptr, fmt); 
		vsprintf(buffer, fmt, argptr); 
		va_end(argptr); 
		if (pStatus != NULL) { 
			pStatus->SetPaneText(0, buffer); 
			pStatus->UpdateWindow(); 
		} 
	} 
 
 
} 
 
//DEL BOOL CDipView::OnEraseBkgnd(CDC* pDC)  
//DEL { 
//DEL 	// TODO: Add your message handler code here and/or call default 
//DEL 	if (AfxGetApp() != NULL && AfxGetApp()->m_pMainWnd != NULL) { 
//DEL 		char buffer[256]; 
//DEL 		CStatusBar* pStatus = (CStatusBar*)  
//DEL 			AfxGetApp()->m_pMainWnd->GetDescendantWindow(AFX_IDW_STATUS_BAR); 
//DEL  
//DEL 		va_list argptr; 
//DEL 	//	char * fmt =&" BMPBMPBMPBMP"; 
//DEL //gai kuandu 
//DEL 		pStatus->SetPaneInfo(2,2,SBPS_STRETCH  ,7); 
//DEL        //itoa(point.x,,10) 
//DEL 	 
//DEL 	char * fmt="请打开文件"; 
//DEL 		va_start(argptr, fmt); 
//DEL 		vsprintf(buffer, fmt, argptr); 
//DEL 		va_end(argptr); 
//DEL        	if (pStatus != NULL) 
//DEL 		{ 
//DEL 		//	pStatus 
//DEL 			pStatus->SetPaneText(2, buffer); 
//DEL 			pStatus->UpdateWindow(); 
//DEL 		} 
//DEL 	} 
//DEL 	return CView::OnEraseBkgnd(pDC); 
//DEL } 
 
int CDipView::OnCreate(LPCREATESTRUCT lpCreateStruct)  
{ 
	if (CView::OnCreate(lpCreateStruct) == -1) 
		return -1; 
	 
	OnLoad(); 
	char_bp.Initialize(3434); 
	char_bp.CreateBP(13,60,26); 
	num_bp.Initialize(3434); 
	num_bp.CreateBP(13,60,10); 
	char_num_bp.Initialize(3434); 
	char_num_bp.CreateBP(13,60,36); 
 
 
// TODO: Add your specialized creation code here 
//	ChageStatuBar(&"请打开一个BMP格式的位图文件");	 
	return 0; 
} 
 
void CDipView::OnLine()  
{ 
	// TODO: Add your command handler code here 
	CDipDoc* pDoc = GetDocument();	 
	ASSERT_VALID(pDoc); 
	Mdlg dlg; 
	dlg.DoModal(); 
	a=dlg.m_edit1; 
	b=dlg.m_edit2; 
	for(int i=0;iImgWidth*pDoc->ImgHeight;i++) 
	{ 
		pDoc->ImgData[i]=a*pDoc->ImgData[i]+b; 
		if(pDoc->ImgData[i]>255) pDoc->ImgData[i]=255; 
		if(pDoc->ImgData[i]<0) pDoc->ImgData[i]=0; 
	} 
 
     IsNewFile=true; 
     IsNewBitmap=true; 
		 	 
	Invalidate(); 
 
 
	 
} 
 
void CDipView::Onfse()  
{ 
	// TODO: Add your command handler code here 
	CDipDoc* pDoc = GetDocument();	 
	ASSERT_VALID(pDoc); 
		for(int i=0;iImgWidth*pDoc->ImgHeight;i++) 
	{ 
		//pDoc->ImgData[i]=a*pDoc->ImgData[i]+b; 
	  pDoc->ImgData[i]=255-pDoc->ImgData[i]; 
		//if(pDoc->ImgData[i]<0) pDoc->ImgData[i]=0; 
	} 
		 IsNewFile=true; 
     IsNewBitmap=true; 
		 	 
	Invalidate(); 
	 
} 
 
void CDipView::Onfz()  
{ 
	// TODO: Add your command handler code here 
		CDipDoc* pDoc = GetDocument();	 
 
	ASSERT_VALID(pDoc); 
	BYTE * ImgData1=new BYTE[pDoc->ImgWidth*pDoc->ImgHeight]; 
		for(int i=0;iImgWidth*pDoc->ImgHeight;i++) 
	{ 
		//pDoc->ImgData[i]=a*pDoc->ImgData[i]+b; 
	  ImgData1[pDoc->ImgWidth*pDoc->ImgHeight-i]=pDoc->ImgData[i]; 
		//if(pDoc->ImgData[i]<0) pDoc->ImgData[i]=0; 
	} 
			for( i=0;iImgWidth*pDoc->ImgHeight;i++) 
	{ 
		//pDoc->ImgData[i]=a*pDoc->ImgData[i]+b; 
			pDoc->ImgData[i]=ImgData1[i]; 
		//if(pDoc->ImgData[i]<0) pDoc->ImgData[i]=0; 
	} 
		 IsNewFile=true; 
     IsNewBitmap=true; 
		 	 
	Invalidate();	 
} 
 
void CDipView::OnMoHu()  
{ 
	// TODO: Add your command handler code here 
		CDipDoc* pDoc = GetDocument(); 
	int h=pDoc->ImgHeight; 
	int w=pDoc->ImgWidth; 
	BYTE * g=new BYTE[h*w]; 
	float temp; 
	//标示图象的坐标 
	int x,y; 
	//标示算子的坐标 
	int i,j; 
 
	BYTE mb[3][3]={{-1,0,0},{0,0,0},{0,0,1}}; 
   
	for(x=1;xImgData[(x-1+i)*w+(y-1+j)]))); 
				}				 
			}		 
			g[x*w+y]=int(temp);			 
		} 
	} 
	for(x=1;xImgData[x*w+y]=g[x*w+y]; 
 
	IsNewFile=true; 
    IsNewBitmap=true;		 	 
	Invalidate();	 
} 
 
void CDipView::OnForHandle()  
{ 
	// TODO: Add your command handler code here	 
	 CDipDoc *p=GetDocument(); 
	 BYTE *temp=new BYTE[p->ImgHeight*p->ImgWidth]; 
	 int x,y;	 
 
	for(x=0;xImgHeight;x++) 
	{ 
		for(y=0;yImgWidth;y++) 
		 { 
			temp[(x*p->ImgWidth)+y]=p->ImgData[(x*p->ImgWidth)+y]; 
		} 
	} 
 
	 long double total=0; 
	 float aver=0; 
	 for(x=0;xImgHeight;x++) 
	 { 
		 for(y=0;yImgWidth;y++) 
		 {	 
			 total+=p->ImgData[x*p->ImgWidth+y];			 
		 } 
	 } 
	 aver=(BYTE)(total/(float)(p->ImgHeight*p->ImgWidth)); 
 
	 float delt;  
	 float sub=0;  
	 for(x=0;xImgHeight;x++) 
	 { 
		 for(y=0;yImgWidth;y++) 
		 {			 
			 sub+=(p->ImgData[x*p->ImgWidth+y]-aver)*(p->ImgData[x*p->ImgWidth+y]-aver);			  
		 } 
	 } 
	 delt=(float)(sqrt(sub/(float)(p->ImgHeight*p->ImgWidth))); 
 
	 BYTE judge; 
	 judge=(BYTE)(delt+aver); 
	 for(x=0;xImgHeight;x++) 
	 { 
		for(y=0;yImgWidth;y++) 
		 { 
			if(p->ImgData[(x*p->ImgWidth)+y]>=judge) 
			{ 
				p->ImgData[(x*p->ImgWidth)+y]=255; 
			} 
			else 
			{ 
				p->ImgData[(x*p->ImgWidth)+y]=0; 
			} 
		} 
	} 
	  
	 free(temp); 
	 IsNewBitmap=true; 
	 IsNewFile=true; 
	 p->UpdateAllViews(NULL); 
} 
 
void CDipView::OnHSearch()  
{ 
	// TODO: Add your command handler code here 
	CDipDoc *pDoc=GetDocument(); 
 
	int width,height; 
	width=pDoc->ImgWidth; 
	height=pDoc->ImgHeight; 
 
	BYTE *g=new BYTE[width*height]; 
 
    int *Count= new int[height]; 
	int *TempCount=new int[height]; 
	int *maxChanges=new int[10]; 
	int *Rows=new int[10];                                  	 
	 
	int H[20]; 
	int Top[20]; 
	  
	for(int row=0;rowImgHeight;row++) 
	 { 
		for(int col=0;colImgWidth;col++) 
		{	 
		   g[row*width+col]=pDoc->ImgData[row*width+col];			 
		} 
	 } 
	  
	for(int c=0;cImgData[row*width+col]!=pDoc->ImgData[row*width+col+1]) 
				Count[row]++;		 
		} 
		TempCount[row]=Count[row]; 
	} 
 
	/////////////////////////////////////Top 10 chage row 
	for(int top=0;top<10;top++) 
	{ 
		int Max=0; 
		for(row=0;rowImgWidth;col++) 
		{	 
		    if(g[row*width+col]<255) 
			{ 
               g[row*width+col]=0; 
			} 
		} 
	 }	 
 
	int Area=0;                   //标识区域的地点 
	if(g[0*width+10]==255) 
	{ 
		Area++;		 
		H[Area]++; 
	    Top[Area]=0;	 
	} 
	for(row=1;row20)                                //特定应用条件,拍摄所得车牌的区域高度、宽度均有一定的范围 
		{                                       //分析图象可得 
		    int r=0; 
			int r0=0; 
			r=Top[x]; 
			r0=Top[x]+h; 
 
			if(r!=0&&r0!=height) 
			{ 
				for(int col=0;colImgData[r*width+col]=255;			 
					pDoc->ImgData[r0*width+col]=255;	 
				}				 
			} 
			else 
			{ 
				if(r==0) 
				{ 
					r=5;				 
					for(int col=0;colImgData[r*width+col]=255;			 
						pDoc->ImgData[r0*width+col]=255;	 
					}				 
				} 
				else 
				{ 
					if(r0==height) 
					{ 
						r0=height-10; 
						for(int col=0;colImgData[r*width+col]=255;			 
							pDoc->ImgData[r0*width+col]=255;	 
						}						 
					} 
				} 
			} 
		} 
	}	 
 
	free(g); 
	IsNewBitmap=true; 
	IsNewFile=true; 
	pDoc->UpdateAllViews(NULL); 
} 
 
void CDipView::OnBanlance()  
{ 
	// TODO: Add your command handler code here 
	CDipDoc *pDoc=GetDocument(); 
 
	 int width,height; 
	 width=pDoc->ImgWidth; 
	 height=pDoc->ImgHeight; 
	 float num=0; 
	 
	 int row,col; 
	 int count[256]; 
	 float s0[256]; 
	 int s[256];                        //256个灰度等级 
	 int x=0; 
	 int temp=0; 
 
	 for( x=0;x<256;x++) 
	 { 
		 count[x]=0; 
		 s0[x]=0.0; 
		 s[x]=0; 
	 } 
 
	 for(row=0;rowImgHeight;row++)                          //每个灰度等级象素个数 
	 { 
		for(col=0;colImgWidth;col++) 
		{	 
			temp=pDoc->ImgData[row*width+col]; 
			count[temp]++;			 
		} 
	 }	 
 
	 for(x=0;x<256;x++)                                       //对应灰度等级概率 
	 { 
		 num=(float)width*height; 
		 s0[x]=(float)(count[x]/num); 
	 } 
 
	 for( x=1;x<256;x++)                                      //概率累计,合并灰度等级     
	 {	 
		 s0[x]+=s0[x-1];	  
	 }	 
 
     for( x=0;x<256;x++)                                      //映射 
	 {	 
		  s[x]=(int)(s0[x]*255+0.5); 
	 } 
 
	  for(row=0;rowImgHeight;row++)                          //每个灰度等级象素个数 
	 { 
		for(col=0;colImgWidth;col++) 
		{	 
			int reflect=0; 
			temp=pDoc->ImgData[row*width+col]; 
			reflect=s[temp]; 
			pDoc->ImgData[row*width+col]=reflect; 
		} 
	 } 
 
	 IsNewBitmap=true; 
	 IsNewFile=true; 
	 pDoc->UpdateAllViews(NULL); 	 
} 
 
void CDipView::OnSubVertical()  
{ 
	// TODO: Add your command handler code here 
	CDipDoc *pDoc=GetDocument(); 
 
	int width,height; 
	width=pDoc->ImgWidth; 
	height=pDoc->ImgHeight; 
 
    BYTE *g=new BYTE[width*height]; 
	 
	int row,col,sub; 
 
	for(row=0;rowImgData[row*width+col])-(pDoc->ImgData[(row+1)*width+col])); 
			g[row*width+col]=sub; 
		} 
	} 
 
	for(row=0;rowImgData[row*width+col]=g[row*width+col]; 
		} 
	} 
	  
	free(g); 
	IsNewBitmap=true; 
	IsNewFile=true; 
	pDoc->UpdateAllViews(NULL); 
	 
} 
 
void CDipView::OnSubHorizontal()  
{ 
	// TODO: Add your command handler code here 
	CDipDoc *pDoc=GetDocument(); 
 
	int width,height; 
	width=pDoc->ImgWidth; 
	height=pDoc->ImgHeight; 
 
    BYTE *g=new BYTE[width*height]; 
	 
	int row,col,sub; 
 
	for(row=0;rowImgData[row*width+col])-(pDoc->ImgData[row*width+col+1])); 
			if(sub<15) 
			{ 
				g[row*width+col]=0; 
			} 
			else 
			{ 
				if(sub>15) 
				{ 
					g[row*width+col]=sub+50; 
				} 
			//	else 
			//	g[row*width+col]=sub; 
			} 
		} 
	} 
 
	for(row=0;rowImgData[row*width+col]=g[row*width+col]; 
			if(col==0) 
			{ 
				pDoc->ImgData[row*width+col]=0; 
			} 
		} 
	} 
	  
	free(g); 
	IsNewBitmap=true; 
	IsNewFile=true; 
	pDoc->UpdateAllViews(NULL); 
}	 
 
 
void CDipView::OnMidValue()  
{ 
	// TODO: Add your command handler code here 
	CDipDoc *pDoc=GetDocument(); 
 
	int width,height; 
	width=pDoc->ImgWidth; 
	height=pDoc->ImgHeight; 
 
    BYTE *g=new BYTE[width*height]; 
	BYTE temp[25]; 
	 
	int row,col; 
	int u,v,a; 
 
	for(row=2;rowImgData[(row-2+u)*width+(col-2)+v]; 
				} 
			} 
 
			for(u=0;u<25;u++) 
			{ 
				for(v=u+1;v<25;v++) 
				{ 
					if(temp[u]>temp[v]) 
					{ 
						a=temp[u]; 
						temp[u]=temp[v]; 
						temp[v]=a; 
					} 
				} 
			} 
 
			g[row*width+col]=temp[12]; 
		} 
	} 
 
	for(row=0;rowImgData[row*width+col]=g[row*width+col]; 
		} 
	} 
 
	IsNewBitmap=true; 
	IsNewFile=true; 
	pDoc->UpdateAllViews(NULL); 
} 
 
void CDipView::OnAverage()  
{ 
	// TODO: Add your command handler code here 
	CDipDoc *pDoc=GetDocument(); 
 
	 int width,height; 
	 width=pDoc->ImgWidth; 
	 height=pDoc->ImgHeight; 
 
	 BYTE *g=new BYTE[width*height]; 
	 
	 int row,col; 
	 BYTE s[3][3]={{1,1,1},{1,1,1},{1,1,1}}; 
 
	 for(row=1;rowImgHeight-1;row++) 
	 { 
		for(col=1;colImgWidth-1;col++) 
		{	 
			long sum=0; 
			for(int i=0;i<3;i++) 
			{ 
				for(int j=0;j<3;j++) 
				{ 
					sum+=s[i][j]*pDoc->ImgData[((row-1+i)*pDoc->ImgWidth)+(col-1+j)]; 
				} 
			} 
			g[(row*pDoc->ImgWidth)+col]=(BYTE)(sum/9); 
		} 
	 } 
 
	 for(row=0;rowImgData[row*width+col]=g[row*width+col]; 
		} 
     } 
 
	 IsNewBitmap=true; 
	 IsNewFile=true; 
	 pDoc->UpdateAllViews(NULL);  
} 
 
void CDipView::OnBool()  
{ 
	// TODO: Add your command handler code here 
	 CDipDoc *pDoc=GetDocument(); 
 
	 int width,height; 
	 width=pDoc->ImgWidth; 
	 height=pDoc->ImgHeight; 
	 
	 int row,col; 
	 
	 for(row=0;rowImgHeight;row++) 
	 { 
		for(col=0;colImgWidth;col++) 
		{	 
		    if(pDoc->ImgData[row*width+col]<255) 
			{ 
               pDoc->ImgData[row*width+col]=0; 
			} 
		} 
	 } 
	  
	 IsNewBitmap=true; 
	 IsNewFile=true; 
	 pDoc->UpdateAllViews(NULL); 	 
} 
 
void CDipView::OnVSearch() 
{ 
	// TODO: 在此添加命令处理程序代码 
 
	CDipDoc *pDoc=GetDocument(); 
 
	int width,height; 
	width=pDoc->ImgWidth; 
	height=pDoc->ImgHeight; 
 
	BYTE *g=new BYTE[width*height]; 
 
    int *Count= new int[width]; 
	int *TempCount=new int[width]; 
	int *maxChanges=new int[30]; 
	int *Cols=new int[30];                  //maxChanges' col                       	 
	 
	int *W=new int[30];                     //Top' width 
	int *left=new int[30];                   //Top' top col 
	  
	for(int row=0;rowImgHeight;row++) 
	 { 
		for(int col=0;colImgWidth;col++) 
		{	 
		   g[row*width+col]=pDoc->ImgData[row*width+col];			 
		} 
	 } 
	  
	for(int c=0;cImgData[row*width+col]!=pDoc->ImgData[(row+1)*width+col]) 
				Count[col]++;		 
		} 
		TempCount[col]=Count[col]; 
	} 
 
	/////////////////////////////////////Top 30 change col 
	for(int top=0;top<30;top++) 
	{ 
		int Max=0; 
		for(int col=0;col=0&&(Cols[top]+range)10) 
		{ 
		    int c=0; 
			int c0=0; 
			c=left[x]; 
			c0=left[x]+w; 
 
			if(c!=0&&c0!=width) 
			{ 
				for(int row=0;rowImgData[row*width+c]=255;			 
					pDoc->ImgData[row*width+c0]=255;	 
				}	 
			} 
			else 
			{ 
				if(c==0) 
				{ 
					c=10;				 
					for(int row=0;rowImgData[row*width+c]=255;			 
						pDoc->ImgData[row*width+c0]=255;	 
					}	 
				} 
				else 
				{ 
					if(c0==width) 
					{ 
						c0=width-10; 
						for(int row=0;rowImgData[row*width+c]=255;			 
							pDoc->ImgData[row*width+c0]=255;	 
						}	 
					} 
				} 
			} 
		} 
	}	 
	 
	free(g); 
	IsNewBitmap=true; 
	IsNewFile=true; 
	pDoc->UpdateAllViews(NULL);	 
} 
 
///  
/// CDipView::OnLocate()的摘要说明。 
/// 创建人  :刘陈炜 
/// 创建时间:2004.5.1 
/// 函数功能:完成车牌定位的整个过程 
/// 程序流程:1.产生副本 
///           2.水平差分提取边缘,寻找横向的车牌带状区域 
///           3.垂直差分提取边缘,寻找纵向的车牌带状区域 
///           4.利用先验知识标识车牌区域,进行车牌带状区域的选择,(横纵向) 
///           5.构造出车牌矩形域; 
///           6.再次利用利用跳变数选择车牌矩形区域,进行车牌区域的最终选择; 
///           7.精确定位车牌,即削弱车牌横向宽度; 
///           8.更新图象; 
///   
void CDipView::OnLocate() 
{ 
	// TODO: 在此添加命令处理程序代码 
	CDipDoc *pDoc=GetDocument(); 
 
	int width,height; 
	width=pDoc->ImgWidth; 
	height=pDoc->ImgHeight; 
 
	BYTE *g=new BYTE[width*height]; 
 
	CopyImg(pDoc,g,width,height); 
	//Banlance(g,width,height); 
	HSub(g,width,height); 
    Search(g,width,height); 
 
	CopyImg(pDoc,g,width,height); 
	VSub(g,width,height); 
	VSearch(g,width,height);	 
 
	Mark(pDoc,width,height); 
    VMark(pDoc,width,height); 
	DrawRect(pDoc,width,height); 
	Choose(pDoc,width,height); 
	FurtherLocate(pDoc,width,height); 
 
	free(g); 
	IsNewBitmap=true; 
	IsNewFile=true; 
	pDoc->UpdateAllViews(NULL);     
} 
 
// 均衡化图象 
void CDipView::Banlance(BYTE* DisposeImg,int Width,int Height) 
{ 
    float num=0;	 
	int row,col; 
	int count[256]; 
	float s0[256]; 
	int s[256];                        //256个灰度等级 
	int x=0; 
	int temp=0; 
 
	for( x=0;x<256;x++) 
	{ 
		count[x]=0; 
		s0[x]=0.0; 
		s[x]=0; 
	} 
 
	for(row=0;rowImgData[row*Width+col];			 
		} 
	}	 
} 
 
// 图象复制 
void CDipView::CopyImg(BYTE* SourceImg, BYTE* DestImg, int Width , int Height) 
{ 
    for(int row=0;row 
/// CDipView::HSub(BYTE* DisposeImg, int Width , int Height)的摘要说明。 
/// 创建人  :刘陈炜 
/// 创建时间:2004.5.1 
/// 函数功能:水平差分提取图象边缘。 
/// 程序流程:1.逐行扫描,sub=|f(x,y)-f(x,y+1)|; 
///           2.若差值小于20,则g(x,y)=0; 
///             若差值大于30,则增强原图象,令g(x,y)=g(x,y)+30; 
///           3.另最后一列全部为0,即黑色; 
///   
// 水平差分 
void CDipView::HSub(BYTE* DisposeImg, int Width , int Height) 
{ 
	int row,col,sub; 
 
	for(row=0;row30) 
				{					 
                	DisposeImg[row*Width+col]=sub+30; 
				} 
				else 
				DisposeImg[row*Width+col]=sub; 
			} 
		} 
	} 
 
	for(row=0;row10) 
				{					 
                	DisposeImg[row*Width+col]=sub+30; 
				} 
				else 
				DisposeImg[row*Width+col]=sub; 
			}*/ 
			DisposeImg[row*Width+col]=sub;				 
		} 
	} 
 
	for(col=0;col 
/// CDipView::Search(BYTE* DisposeImg, int width , int height)的摘要说明。 
/// 创建人  :刘陈炜 
/// 创建时间:2004.5.1 
/// 函数功能:完成图象车牌区域的初步定位。即寻找出差分扫描后水平跳变数最大的前10个区域。 
/// 程序流程:1.利用间行扫描的方式找出跳变数最大的前10行; 
///           2.对 Top 10 行进行区域细粒度增长选择; 
///             其相似度的选取为:0.7~1.3 倍的该行跳变总数; 
///           3.二值化,threshold=255; 
///           4.任意选择一列,最好不要边缘列,可能有干扰(本程序选择为第十列),搜索出各个带状候选域,存入标志; 
///   
void CDipView::Search(BYTE* DisposeImg, int width , int height) 
{ 
	BYTE*TempImg=new BYTE[width*height]; 
 
    int *Count= new int[height]; 
	int *TempCount=new int[height]; 
	int *maxChanges=new int[10]; 
	int *Rows=new int[10];  
	 
	CopyImg(DisposeImg,TempImg,width,height); 
 
	for(int c=0;c 
/// CDipView::Mark(CDipDoc * DisposeImg, int width , int height)的摘要说明。 
/// 创建人  :刘陈炜 
/// 创建时间:2004.5.1 
/// 函数功能:利用先验知识标识车牌区域,进行车牌区域的选择,(横向) 
/// 函数说明:特定应用条件,拍摄所得车牌的区域高度、宽度均有一定的范围,其大小可以分析图象后可得 
///           根据统计得到:车牌的顶部极少出现在高度小于100个像素的区域; 
///                         车牌高度也一般大于20个像素。 
///           程序的最终结果为满足条件的经过扩展了的带状区域 
/// 程序流程:1.舍弃区域顶部小于100的待选域 
///           2.选择区域高度大于20的待选域 
///           3.区域扩展,上下各增大5个像素。若顶部小于5,则顶部坐标不变,高度加5; 
///                                          若底部大于图象的底部,则底部坐标不变,高度加5; 
///   
void CDipView::Mark(CDipDoc * DisposeImg, int width , int height) 
{ 
	for(int x=0;x<20;x++) 
	{ 
		int h=Height[x]; 
		if(TopRow[x]<=5) 
		{ 
			Height[x]=0; 
			TopRow[x]=-1; 
		} 
	} 
	 for(x=0;x<20;x++) 
	{ 
		int h=Height[x]; 
		if(h>20)                                 
		{                                        
		    int r=0; 
			int r0=0; 
			r=TopRow[x]-5; 
			r0=TopRow[x]+h+5; 
		 
			if((r>0)&&(r0ImgData[r*width+col]=255;			 
//					DisposeImg->ImgData[r0*width+col]=255;						 
//				}		 
 
				TopRow[x]=r+5; 
				Height[x]=h;		 
			} 
			else 
			{ 
				if(r<=0) 
				{		 
					r=r+5; 
 
					//for(int col=0;colImgData[r*width+col]=255;			 
					//	DisposeImg->ImgData[r0*width+col]=255;							 
					//}	 
					TopRow[x]=r; 
					Height[x]=h; 
				} 
				else 
				{ 
					if(r0>=height) 
					{ 
						r0=r0-5;					 
						//for(int col=0;colImgData[r*width+col]=255;			 
						//	DisposeImg->ImgData[r0*width+col]=255;	 
						//}	 
						Height[x]=Height[x]-5; 
					} 
				} 
			} 
		} 
	} 
 
	for(x=0;x<20;x++) 
	{ 
		int h=Height[x]; 
		if(h<20||TopRow[x]<=100) 
		{ 
			Height[x]=0; 
			TopRow[x]=-1; 
		} 
	}	 
} 
 
///  
/// CDipView::VSearch(BYTE* DisposeImg, int width , int height)的摘要说明。 
/// 创建人  :刘陈炜 
/// 创建时间:2004.5.1 
/// 函数功能:水平查找后,纵向查找。完成图象车牌区域的初步定位。即寻找出差分扫描后垂直跳变数最大的前30个区域。 
/// 程序流程:1.利用间行扫描的方式找出跳变数最大的前30行; 
///           2.对 Top 30 行进行区域增长; 
///             其相似度的选取为:0.8~1.2 倍的该行跳变总数; 
///           3.二值化,threshold=255; 
///           4.任意选择一列,(本程序选择为第十行),搜索出各个带状候选域,存入标志; 
///   
// 
void CDipView::VSearch(BYTE* DisposeImg, int width, int height) 
{	 
	BYTE *g=new BYTE[width*height]; 
 
    int *Count= new int[width]; 
	int *TempCount=new int[width]; 
	int *maxChanges=new int[30]; 
	int *Cols=new int[30];                  //maxChanges' col   
 
	CopyImg(DisposeImg,g,width,height);		 
	  
	for(int c=0;c=0&&(Cols[top]+range)100) 
		{ 
		    int c=0; 
			int c0=0; 
			c=Left[x]; 
			c0=Left[x]+w-10; 
 
			if(c!=0&&c0>0) 
			{ 
				//for(int row=0;rowImgData[row*width+c]=255;			 
				//	DisposeImg->ImgData[row*width+c0]=255;	 
				//}	 
				Widths[x]=Widths[x]-10; 
			} 
			else 
			{ 
				if(c<=0) 
				{ 
					c=5;				 
					//for(int row=0;rowImgData[row*width+c]=255;			 
					//	DisposeImg->ImgData[row*width+c0]=255;	 
					//}	 
					Left[x]=c; 
				} 
				else 
				{ 
					if(c0<=0) 
					{ 
						c0=c0+10; 
						//for(int row=0;rowImgData[row*width+c]=255;			 
						//	DisposeImg->ImgData[row*width+c0]=255;	 
						//}	 
						//Widths[x]=Widths[x]-5; 
					} 
				} 
			} 
		} 
	}	 
 
	for(x=0;x<30;x++) 
	{ 
		int w=Widths[x]; 
		if(w<100) 
		{ 
			Widths[x]=0; 
			Left[x]=-1; 
		} 
	} 
} 
 
///  
/// CDipView::DrawRect(CDipDoc* DisposeImg, int width, int height)的摘要说明。 
/// 创建人  :刘陈炜 
/// 创建时间:2004.5.1 
/// 函数功能:利用先验知识标识车牌区域,进行车牌区域的选择,(横纵向) 
/// 函数说明:国家标准:车牌的宽高比近似为3:1; 
/// 程序流程:1.初始化存储数组 
///           2.选择区域高宽比大于3的待选域 
///   
void CDipView::DrawRect(CDipDoc* DisposeImg, int width, int height) 
{ 
	for(int x=0;x<50;x++) 
	{ 
		Rect_X[x]=-1; 
		Rect_Y[x]=-1; 
		Rect_W[x]=0; 
		Rect_H[x]=0; 
	} 
	 
	Rect_Areas=0; 
 
	for(int m=0;m<20;m++) 
	{ 
		for(int n=0;n<30;n++) 
		{ 
			if((Widths[n]>3*Height[m])&&(Widths[n]*Height[m]!=0)) 
			{ 
				Rect_Areas++; 
				Rect_X[Rect_Areas-1]=Left[n]; 
				Rect_Y[Rect_Areas-1]=TopRow[m]; 
				Rect_W[Rect_Areas-1]=Widths[n]; 
				Rect_H[Rect_Areas-1]=Height[m]; 
			} 
		} 
	} 
 
	//for( x=0;xImgData[row*width+Rect_X[x]]=255; 
	//		DisposeImg->ImgData[row*width+Rect_X[x]+Rect_W[x]]=255;			 
	//	} 
	//} 
 
	//for( x=0;xImgData[Rect_Y[x]*width+col]=255; 
	//		DisposeImg->ImgData[(Rect_Y[x]+Rect_H[x])*width+col]=255; 
	//	} 
	//} 
} 
 
 
void CDipView::OnChoose()  
{ 
	// TODO: Add your command handler code here 
} 
 
///  
/// CDipView::Choose(CDipDoc *DisposeImg, int width, int height)的摘要说明。 
/// 创建人  :刘陈炜 
/// 创建时间:2004.5.1 
/// 函数功能:再次利用利用跳变数选择车牌区域,进行车牌区域的最终选择,(横纵向) 
/// 程序流程:1.初始化存储数组 
///           2.计算每个伪车牌区域的跳变数 
///           3.选择具有最大跳变数的区域为车牌区 
///   
void CDipView::Choose(CDipDoc *DisposeImg, int width, int height) 
{ 
	int row=0; 
	int col=0; 
 
	int temp=0; 
 
	int *JumpNums=new int[Rect_Areas]; 
	for(int area=0;areaImgData[(Rect_Y[area]+row)*width+(Rect_X[area]+col)]; 
			} 
		} 
 
		JumpNums[area]=JumpNum(TempImg,Rect_W[area],Rect_H[area]); 
 
		free(TempImg); 
	} 
	 
	temp=MaxJump(JumpNums,Rect_Areas); 
 
	// 区域刻画 
/*	for(row=Rect_Y[temp];row<(Rect_Y[temp]+Rect_H[temp]);row++) 
	{ 
		DisposeImg->ImgData[row*width+Rect_X[temp]]=255; 
		DisposeImg->ImgData[row*width+(Rect_X[temp]+Rect_W[temp])]=255;	 
	} 
	 
    for(col=Rect_X[temp];col<(Rect_X[temp]+Rect_W[temp]);col++) 
	{ 
		DisposeImg->ImgData[Rect_Y[temp]*width+col]=255; 
    	DisposeImg->ImgData[(Rect_Y[temp]+Rect_H[temp])*width+col]=255; 
	}	*/ 
 
	//剔除伪车牌区 
	for(area=0;area 
/// CDipView::JumpNum(BYTE *DisposeImg,int width,int height)的摘要说明。 
/// 创建人  :刘陈炜 
/// 创建时间:2004.5.1 
/// 函数功能:计算伪车牌区的跳变平均数 
/// 程序流程:1.初始化; 
///           2.水平差分,边缘提取; 
///           3.选择车牌的中间1/3行来计算每个伪车牌区域的跳变平均数; 
///  
/// 各个区域的平均跳变数 
int CDipView::JumpNum(BYTE *DisposeImg,int width,int height) 
{ 
	int startRow=0; 
	int endRow=0; 
	long JumpNum=0; 
	int averJump=0; 
	int r=0; 
 
	BYTE* g=new BYTE[width*height]; 
    CopyImg(DisposeImg,g,width,height); 
	 
	HSub(g,width,height);	 
 
	startRow=(int)(0+height/3); 
	endRow=(int)(0+2*height/3);	 
 
	for(int row=startRow;row 
/// CDipView::MaxJump(int *JumpNums,int num)的摘要说明。 
/// 创建人  :刘陈炜 
/// 创建时间:2004.5.1 
/// 函数功能:找出所有伪车牌区域中具有最大跳变平均数的区域号 
/// 程序说明:选择排序 
///  
/// 最大跳变平均数的区域号 
int CDipView::MaxJump(int *JumpNums,int num) 
{	 
	int area=0; 
	int temp=0; 
	int val=0; 
 
	val=JumpNums[0]; 
	for(area=0;areaval) 
		{ 
			temp=area; 
			val=JumpNums[area]; 
		} 
	} 
 
	return temp; 
} 
 
///  
/// CDipView::FurtherLocate(CDipDoc *DisposeImg,int width,int height)的摘要说明。 
/// 创建人  :刘陈炜 
/// 创建时间:2004.5.1 
/// 函数功能:精确定位车牌 
/// 程序流程: 
/// 程序说明:由于水平分割出的伪车牌区域已经比较准确,故仅作垂直方向的进一步定位(缩小宽度) 
///  
void CDipView::FurtherLocate(CDipDoc *DisposeImg,int width,int height) 
{ 
	int row=0; 
	int col=0; 
 
	//copy 到一个暂存数组,以便处理操作且不破坏原图象 
	BYTE* TempImg=new BYTE[Rect_W[0]*Rect_H[0]]; 
	for(row=0;rowImgData[(Rect_Y[0]+row)*width+(Rect_X[0]+col)]; 
		} 
	} 
	 
	VFurthLocate(TempImg,Rect_W[0],Rect_H[0]); 
 
/*	int temp=0; 
	// 区域刻画 
	for(row=Rect_Y[temp];row<(Rect_Y[temp]+Rect_H[temp]);row++) 
	{ 
		DisposeImg->ImgData[row*width+Rect_X[temp]]=255; 
		DisposeImg->ImgData[row*width+(Rect_X[temp]+Rect_W[temp])]=255;	 
	} 
	 
    for(col=Rect_X[temp];col<(Rect_X[temp]+Rect_W[temp]);col++) 
	{ 
		DisposeImg->ImgData[Rect_Y[temp]*width+col]=255; 
    	DisposeImg->ImgData[(Rect_Y[temp]+Rect_H[temp])*width+col]=255; 
	}	*/ 
 
	free(TempImg); 
} 
 
///  
/// CDipView::VFurthLocate(BYTE *DisposeImg, int width, int height)的摘要说明。 
/// 创建人  :刘陈炜 
/// 创建时间:2004.5.1 
/// 函数功能:找出车牌的左右边缘 
/// 程序流程:1.水平差分,二值化; 
///           2.垂直方向投影,统计各列的投影值; 
///           3.去除噪声点; 
///           4.找出左右边缘 
///           5.计算车牌宽度 
///           6.车牌精确定位赋值 
///  
void CDipView::VFurthLocate(BYTE *DisposeImg, int width, int height) 
{ 
	int row=0; 
	int col=0; 
	int num=0; 
 
	int leftCol=0; 
	int rightCol=width-1; 
 
	HSub(DisposeImg,width,height);  
	ForHandle(DisposeImg,width,height);                           //二值化 
 
    //note the value of hProjection 
	int*HProj=new int[width];                         
	for(col=0;col=0;col--) 
	{ 
		num=0; 
		if(HProj[col]==0&&HProj[col-1]!=0) 
		{ 
			num++;		 
			nextCol=FindNextCol_RL(HProj,width,col); 
			w=col-nextCol; 
			rightCol=col; 
		} 
		if(w<3) 
		{ 
			num=num-1; 
		} 
		if(num==1) 
		{ 
			break; 
		} 
	}	 
	 
	int blantCols=0; 
	blantCols=leftCol+(width-rightCol); 
 
	Rect_X[0]+=leftCol; 
	Rect_W[0]=width-blantCols; 
 
	free(HProj); 
} 
 
///  
/// CDipView::ForHandle(BYTE *DisposeImg, int width, int height)的摘要说明。 
/// 创建人  :刘陈炜 
/// 创建时间:2004.5.1 
/// 函数功能:二值化图象 
/// 程序说明:threshold=average+delt; 
/// 程序流程:1.计算图象均值; 
///           2.计算图象方差; 
///           3.二值化 
///  
void CDipView::ForHandle(BYTE *DisposeImg, int width, int height) 
{	 
	 BYTE *temp=new BYTE[height*width]; 
	 int x,y;	 
 
	 CopyImg(DisposeImg,temp,width,height); 
	 
	 long double total=0; 
	 float aver=0; 
	 for(x=0;x=judge) 
			{ 
				DisposeImg[(x*width)+y]=255; 
			} 
			else 
			{ 
				DisposeImg[(x*width)+y]=0; 
			} 
		} 
	} 
	  
	 free(temp);	 
} 
 
// 寻找left==255,right==0的列 
int CDipView::FindNextCol_LR(int* HProj, int size, int objectCol) 
{ 
	int num=0; 
	int x=0; 
	for(x=objectCol;x=0&&HProj[x+1]==0) 
		{ 
			num++;			 
		} 
 
		if(num==1) 
		{ 
			break; 
		} 
	}	 
 
	if(num==0) 
	{ 
		return objectCol;  
	} 
	else 
	{ 
		return x; 
	}	 
} 
 
// 寻找right==255,left==0的列 
int CDipView::FindNextCol_RL(int* HProj, int size, int objectCol) 
{ 
	int num=0; 
	int x=0; 
	for(x=objectCol;x>=0;x--) 
	{ 
		if(HProj[x]>=0&&HProj[x-1]==0) 
		{ 
			num++;			 
		} 
 
		if(num==1) 
		{ 
			break; 
		} 
	}	 
 
	if(num==0) 
	{ 
		return objectCol;  
	} 
	else 
	{ 
		return x; 
	}		 
} 
 
void CDipView::OnSobel() 
{ 
	// TODO: 在此添加命令处理程序代码	 
} 
 
 
///  
/// CDipView::OnVSplit()的摘要说明。 
/// 创建人  :刘陈炜 
/// 创建时间:2004.5.1 
/// 函数功能:车牌字符分割 
/// 程序流程:1.区域扩展; 
///           2.投影分割; 
///           3.字符区域的获取; 
///  
void CDipView::OnVSplit() 
{ 
	// TODO: 在此添加命令处理程序代码 
	CDipDoc *pDoc=GetDocument(); 
 
	int width,height; 
	width=pDoc->ImgWidth; 
	height=pDoc->ImgHeight; 
 
	int row=0; 
	int col=0; 
	 
	//extend area 
	int threshold=2; 
 
	Rect_X[0]=Rect_X[0]; 
	Rect_Y[0]=Rect_Y[0];//-threshold; 
	Rect_W[0]=Rect_W[0]+7; 
	Rect_H[0]=Rect_H[0];//+2*threshold; 
 
	//车牌区域的高度、宽度 
	int w=Rect_W[0]; 
	int h=Rect_H[0]; 
	 
	BYTE* TempImg=new BYTE[w*h];	 
	for(row=0;rowImgData[(Rect_Y[0]+row)*width+(Rect_X[0]+col)]; 
		} 
	} 
 
	//二值化车牌区域图象 
	ForHandle(TempImg,w,h); 
	 
	//搜索各字符域 
	int *projArray=new int[w]; 
	for(col=0;col=0;area--) 
	{ 
		if(cRects[area].w!=0&&cRects[area].x!=-1) 
		{ 
			for(row=cRects[area].y;row<(cRects[area].y+cRects[area].h);row++)  //draw vertical line 
			{ 
				pDoc->ImgData[row*width+cRects[area].x]=255; 
				pDoc->ImgData[row*width+(cRects[area].x+cRects[area].w)]=255;	 
			} 
 
	    	for(col=cRects[area].x;col<(cRects[area].x+cRects[area].w);col++)    //draw horizontal line 
			{ 
				pDoc->ImgData[cRects[area].y*width+col]=255; 
				pDoc->ImgData[(cRects[area].y+cRects[area].h)*width+col]=255; 
			}	 
		}				 
	} 
 
	// 区域刻画 
	//int temp=0; 
	//for(row=Rect_Y[temp];row<(Rect_Y[temp]+Rect_H[temp]);row++) 
	//{ 
	//	pDoc->ImgData[row*width+Rect_X[temp]]=255; 
	//	pDoc->ImgData[row*width+(Rect_X[temp]+Rect_W[temp])]=255;	 
	//} 
	// 
 //   for(col=Rect_X[temp];col<(Rect_X[temp]+Rect_W[temp]);col++) 
	//{ 
	//	pDoc->ImgData[Rect_Y[temp]*width+col]=255; 
 //   	pDoc->ImgData[(Rect_Y[temp]+Rect_H[temp])*width+col]=255; 
	//} 
 
	//for(row=Rect_Y[temp];row<(Rect_Y[temp]+Rect_H[temp]);row++) 
	//{ 
	//	for(col=0;colImgData[row*width+Rect_X[temp]+col]=255; 
	//		//	pDoc->ImgData[row*width+(Rect_X[temp]+Rect_W[temp])]=255;	 
	//		} 
	//	} 
	//} 
 
	free(TempImg); 
	free(projArray); 
 
	IsNewBitmap=true; 
	IsNewFile=true; 
	pDoc->UpdateAllViews(NULL);  
} 
 
// 图像规定化0~100 
void CDipView::GuiYiHua(BYTE* DisposeImg, int width , int height) 
{	 
} 
 
// 增强车牌区,削弱背景 
void CDipView::Hance(BYTE* DisposeImg, int width , int height) 
{	 
} 
 
void CDipView::OnGuiYiHua() 
{ 
	// TODO: 在此添加命令处理程序代码	 
} 
 
void CDipView::OnHance() 
{ 
	// TODO: 在此添加命令处理程序代码	 
} 
 
///  
/// CDipView::HProj(BYTE* DisposeImg, int* projArray, int width , int height)的摘要说明。 
/// 创建人  :刘陈炜 
/// 创建时间:2004.5.1 
/// 函数功能:水平方向投影,分割出字符 
/// 程序流程:1.统计各列白象素个数; 
///           2.平滑投影曲线; 
///           3.寻找波谷(trough)进行分割; 
///  
void CDipView::HProj(BYTE* DisposeImg, int* projArray, int width , int height) 
{ 
	int row=0; 
	int col=0; 
 
	float alph=0.0; 
	int*E=new int[width]; 
	long double*MSE=new long double[9];                         //针对每一个alph的deltl;	 
 
	//统计各列白象素个数 
	for(col=0;colmin) 
		{ 
			min=MSE[x-1]; 
		} 
	} 
	for(x=1;x<10;x++) 
	{ 
		if(MSE[x-1]==min) 
		{ 
			alph=(float)(0.1*x); 
		} 
	} 
		 
	E[0]=projArray[0]; 
	for(col=1;colImgWidth; 
	height=pDoc->ImgHeight;	 
 
    int x=Rect_X[0]; 
	int y=Rect_Y[0]; 
	int w=Rect_W[0]; 
	int h=Rect_H[0]; 
 
    int num=0; 
 
	for(num=0;num<10;num++) 
	{ 
		cRects[num].x=-1; 
		cRects[num].y=-1; 
		cRects[num].w=0; 
		cRects[num].h=0; 
	} 
 
	bool flage=false; 
	 
 
	int row=0; 
	int col=0; 
 
	int area=0; 
	num=0; 
	for(col=0;col=0;area--) 
	{ 
		if(cRects[area].w!=0) 
		{ 
			for(row=cRects[area].y;row<(cRects[area].y+cRects[area].h);row++)  //draw vertical line 
			{ 
				pDoc->ImgData[row*width+cRects[area].x-1]=255; 
				pDoc->ImgData[row*width+(cRects[area].x+cRects[area].w)]=255;	 
			} 
 
			for(col=cRects[area].x;col<(cRects[area].x+cRects[area].w);col++)    //draw horizontal line 
			{ 
				pDoc->ImgData[(cRects[area].y-1)*width+col]=255; 
				pDoc->ImgData[(cRects[area].y+cRects[area].h)*width+col]=255; 
			}	 
		}				 
	} 
 
	//save character 
    for(area=CharacterNum;area>=0;area--) 
	{ 
		cDatas[area].w=cRects[area].w; 
		cDatas[area].h=cRects[area].h; 
		cDatas[area].Img=new BYTE[cRects[area].w*cRects[area].h]; 
 
		for(row=cRects[area].y;row<(cRects[area].y+cRects[area].h);row++)  //draw vertical line 
		{ 
			for(col=cRects[area].x;col<(cRects[area].x+cRects[area].w);col++)    //draw horizontal line 
			{ 
				cDatas[area].Img[(row-cRects[area].y)*cRects[area].w+(col-cRects[area].x)]=pDoc->ImgData[row*width+col];			 
			}				 
		}	 
	} 
} 
/* 
// 读取样本库,传入一个sample类型的数组(从文件里读出的样本数据将放入其中),返回值为样本个数 
int CDipView::LoadCharLib(sample* sa) 
{ 
	CFile cf;	 
	 
	if(cf.Open(".\\mydata.dat",CFile::modeCreate|CFile::modeNoTruncate|CFile::modeReadWrite)==0) 
	{ 
		AfxMessageBox("打开文件失败,\n您最好退出程序"); 
	} 
 
	int num=0; 
	try 
	{ 
		sample sampleTemp; 
		 
		cf.SeekToBegin(); 
		DWORD dwBytesRemaining=(DWORD)(cf.GetLength()); 
		while(dwBytesRemaining) 
		{ 
			UINT nBytesRead=cf.Read(&sampleTemp,sizeof(sample)); 
			sa[num]=sampleTemp; 
			dwBytesRemaining-=nBytesRead; 
			num++; 
		} 
		CString s; 
//		s.Format("共读取数据%d个,最后一个的序列号为%d", 
//			num,sampleTemp.serialnum); 
//		AfxMessageBox(s);	 
	} 
	catch(CFileException *e) 
	{ 
		e->ReportError(); 
		e->Delete(); 
	} 
	cf.Close(); 
	return num; 
} 
 
// 缩放算法,一律缩放为20*36 
void CDipView::Zoom(BYTE* DisposeImg, int width, int height) 
{ 
	if ((width==20)&&(height==36)) 
	return; 
	 
	// 源图像的宽度和高度 
	LONG	lWidth=width; 
	LONG	lHeight=height; 
	 
	BYTE *temp_img=new BYTE[width*height]; 
	 
	// 循环变量 
	int	i; 
	int	j; 
	 
	for(i = 0; i < height; i++) 
	{ 
		for(j = 0; j < width; j++) 
		{			 
			temp_img[j+i*width]=DisposeImg[j+i*width]; 
		} 
	} 
 
// 缩放后图像的宽度和高度 
	LONG	lNewWidth; 
	LONG	lNewHeight; 
 
	float XZRatio=(float)( 20.0/(float)(width)); 
	float YZRatio=(float)(36.0/(float)(height)); 
 
	// 象素在源坐标 
	LONG	i0; 
	LONG	j0; 
	 
	//归一后的大小 
	lNewWidth = 20; 
	lNewHeight = 36; 
	 
	height=lNewHeight; 
	width=lNewWidth; 
 
 
	for(i = 0;i< lNewHeight;i++) 
	{ 
		 
		for(j = 0;j< lNewWidth;j++) 
		{ 
			i0 = (LONG) (i / YZRatio + 0.5); 
			j0 = (LONG) (j / XZRatio + 0.5); 
			 
			// 判断是否在源图范围内 
			if( (j0 >= 0) && (j0 < lWidth) && (i0 >= 0) && (i0 < lHeight)) 
			{ 
				// 复制象素 
				DisposeImg[j+i*lWidth] = temp_img[j0 + i0*lWidth];			 
			} 
			else 
			{ 
				// 对于源图中没有的象素,直接赋值为255				 
		//		DisposeImg[j+i*lWidth] = 0; 
			}			 
		}		 
	} 
	delete [] temp_img; 
} 
 
// 二值化算法,二值化为0和1两种值 
void CDipView::BinaryImg(BYTE* DisposeImg, int width , int height) 
{ 
	 BYTE *temp=new BYTE[height*width]; 
	 int x,y;	 
 
	 CopyImg(DisposeImg,temp,width,height); 
	 
	 long double total=0; 
	 float aver=0; 
	 for(x=0;x=judge) 
			{ 
				DisposeImg[(x*width)+y]=(BYTE)1; 
			} 
			else 
			{ 
				DisposeImg[(x*width)+y]=(BYTE)0; 
			} 
		} 
	 } 
	  
	 free(temp);	 
} 
 
// Hilditch细化算法 
void CDipView::ThinnerHilditch(void* image, unsigned long lx, unsigned long ly) 
{ 
	char *f, *g; 
	char n[10]; 
	unsigned int counter; 
	short k, shori, xx, nrn; 
	unsigned long i, j; 
	long kk, kk11, kk12, kk13, kk21, kk22, kk23, kk31, kk32, kk33, size; 
	size = (long)lx * (long)ly; 
	g = (char *)malloc(size); 
 
	if(g == NULL) 
	{ 
		printf("error in allocating memory!\n"); 
		return; 
	} 
 
	f = (char *)image; 
	for(i=0; iImgWidth; 
	//height=pDoc->ImgHeight; 
 
	//sample mysa[500]; 
 //   double myfeature[13]; 
 //   int num; 
 //   CString result[10]; 
 
	//BYTE*Img; 
	//int row=0; 
	//int col=0; 
 
	//int x=-1; 
	//int y=-1; 
	//int w=0; 
	//int h=0; 
	//int area=0; 
	//for(area=0;area<10;area++); 
	//{	 
	//	if(cRects[area].w>0) 
	//	{ 
	//		x=cRects[area].x; 
	//		y=cRects[area].y; 
	//		w=cRects[area].w; 
	//		h=cRects[area].h; 
 
 //           Img=new BYTE[w*h]; 
	//		for(row=0;rowImgData[y*width+x];				 
	//			} 
	//		} 
 
	////		//num=LoadCharLib(mysa);                         //获取样本库保存到mysa[500]中 
	////		//Zoom(Img,w,h);                                 //对切割出的图象进行大小归一化 
	////		//ThinImage(Img,w,h);                            //对大小归一化后的图象进行细化 
	////		//GetFeature(Img,w,h,myfeature,13);					   //图象细化以后就可以提取特征了 
	////		//result[area]=Recognize(mysa,num,myfeature); 
	//	} 
	//}	 
 
	//delete []mysa; 
	//delete []myfeature; 
	//delete []result; 
}*/ 
 
void CDipView::OnCharacterRecg() 
{ 
	CMainFrame* MainFrame=(CMainFrame*)this->GetParent()->GetParent();  
	CCharView* pchview=(CCharView*)MainFrame->m_wndSplitter.GetPane(0,1);  
	 
	CDigitClass digitTest; 
	CString classResult; 
	CString tempstr; 
	CString strInfo, strTemp; 
	int recgpos=1; 
	for(int k=0;k4) 
		{ 
			if (recgpos!=1&&recgpos<8) 
			{	 
				classResult=classResult+"1"; 
				recgpos++; 
			} 
			continue; 
			 
		} 
		 
		for(int x=0;xm_result.SetSel(0,-1); 
		pchview->m_result.ReplaceSel(""); 
		 
		CString strInfo, strTemp; 
		strInfo.Format(""); 
		int i,j; 
		for(i=0; im_result.SetSel(0,-1); 
		pchview->m_result.ReplaceSel(strInfo); 
	//	AfxMessageBox("hello"); 
		digitTest.GetFeature(); 
		if (recgpos==1) 
		{ 
			 
			double min=100000.0; 
			POSITION pos=hanList.GetHeadPosition(); 
			while(pos!=NULL) 
			{ 
				Sample sa; 
				sa=hanList.GetNext(pos); 
				double diff = 0.0; 
				 
				for(j=0; j<9; j++) 
				{ 
					diff += fabs(digitTest.feature[j] - sa.feature[j]); 
				} 
				 
				for(j=9; j<13; j++) 
				{ 
					diff += fabs(digitTest.feature[j] - sa.feature[j])*9; 
				} 
				 
				if(diff < min) 
				{ 
					min = diff; 
					tempstr.Format("%s",sa.trueClass); 
				} 
			} 
		 
			classResult=classResult+tempstr; 
			 
		} 
	 
		if (recgpos==2) 
		{ 
			double temp[13]; 
			double result1[26]; 
			bool t=0; 
			for (i=0;i<13;i++) 
			{ 
				temp[i]=digitTest.feature[i]/15; 
			} 
			char_bp.Identify(temp,13,result1,26); 
			for(i=0;i<26;i++) 
			{ 
				if (ABS(result1[i]-1)<0.1) 
				{ 
					tempstr.Format("%c",i+'A'); 
					classResult=classResult+tempstr; 
					t=1; 
				} 
 
			} 
			if(t!=1) 
				classResult=classResult+'?'; 
		} 
		//	strTemp.Format("%d", classResult); 
		if (recgpos==3) 
		{ 
			double temp[13]; 
			double result1[36]; 
			bool t=0; 
			for (i=0;i<13;i++) 
			{ 
				temp[i]=digitTest.feature[i]/15; 
			} 
			char_num_bp.Identify(temp,13,result1,36); 
			for(i=0;i<36;i++) 
			{ 
				if (ABS(result1[i]-1)<0.2) 
				{ 
					if(i<=9) 
					{ 
						tempstr.Format("%c",i+'0'); 
						classResult=classResult+tempstr; 
						t=1; 
					} 
					else 
					{ 
						tempstr.Format("%c",i+'A'-10); 
						classResult=classResult+tempstr; 
						t=1; 
					} 
				//	tempstr.Format("%c",i); 
				} 
			} 
			if(t!=1) 
			classResult=classResult+'?'; 
		} 
 
		if (recgpos>3&&recgpos<8) 
		{ 
			double temp[13]; 
			double result1[10]; 
			bool t=0; 
			for (i=0;i<13;i++) 
			{ 
				temp[i]=digitTest.feature[i]/15; 
			} 
			char_num_bp.Identify(temp,13,result1,10); 
			for(i=0;i<10;i++) 
			{ 
				if (ABS(result1[i]-1)<0.1) 
				{ 
					tempstr.Format("%c",i+'0'); 
					classResult=classResult+tempstr; 
					t=1; 
				} 
			} 
			if(t!=1) 
			classResult=classResult+'?'; 
		} 
 
	//	strInfo += "\n\r识别结果为:  "; 
	//	strInfo += classResult; 
		recgpos++; 
	//	pchview->m_result.SetSel(0,-1); 
	//    pchview->m_result.ReplaceSel(strInfo); 
 
 
	} 
	strInfo += "\n\r识别结果为:  "; 
    strInfo += classResult; 
	pchview->m_result.SetSel(0,-1); 
	pchview->m_result.ReplaceSel(strInfo);	 
	 
	 
 
} 
 
void CDipView::OnTrainfromvehicle()  
{ 
	OnLocate(); 
	OnVSplit(); 
	CMainFrame* MainFrame=(CMainFrame*)this->GetParent()->GetParent();  
	CCharView* pchview=(CCharView*)MainFrame->m_wndSplitter.GetPane(0,1);  
	 
	CDigitClass digitTrain; 
	CRecvChar dlg; 
	CString m_class; 
	for(int k=0;km_result.SetSel(0,-1); 
		pchview->m_result.ReplaceSel(""); 
		 
		CString strInfo, strTemp; 
		strInfo.Format(""); 
		int i,j; 
		for(i=0; im_result.SetSel(0,-1); 
		pchview->m_result.ReplaceSel(strInfo); 
 
			 
		if(dlg.DoModal()==IDOK) 
		{ 
			m_class=dlg.m_char; 
			m_class.TrimLeft(); 
			m_class.TrimRight(); 
			digitTrain.GetFeature(); 
			Sample temp; 
			for(i=0; i<13; i++) 
				temp.feature[i] = digitTrain.feature[i]; 
			memcpy(temp.trueClass,(const char*) m_class,3*sizeof(char)); 
			if(temp.trueClass[1]=='\0') 
			{ 
				if (temp.trueClass[0]>='0'&&temp.trueClass[0]<='9') 
				{ 
					temp.serialnum=numList.GetCount(); 
					numList.AddTail(temp); 
				} 
 
				if (temp.trueClass[0]>='A'&&temp.trueClass[0]<='Z') 
				{ 
					temp.serialnum=charList.GetCount(); 
					charList.AddTail(temp); 
				} 
 
			} 
			else if(temp.trueClass[2]=='\0') 
			{ 
				temp.serialnum=hanList.GetCount(); 
				hanList.AddTail(temp); 
			} 
		} 
		 
	} 
		 
 
 
	 
} 
 
void CDipView::OnSave()  
{ 
	CFile char_file,num_file,han_file; 
	if(char_file.Open(".\\chdata.ch",CFile::modeCreate|CFile::modeNoTruncate|CFile::modeReadWrite)==0) 
	{ 
		AfxMessageBox("打开字符文件失败"); 
	} 
 
	 
	try 
	{ 
		Sample sampleTemp; 
		char_file.SeekToEnd(); 
		if(char_ConnectPos!=NULL) 
		{ 
			while(char_ConnectPos!=NULL) 
			{ 
				sampleTemp=charList.GetNext(char_ConnectPos); 
				char_file.Write(&sampleTemp, sizeof(sample)); 
			} 
			char_ConnectPos=charList.GetTailPosition(); 
 
		} 
		else 
		{	 
		//	Sample sampleTemp; 
			POSITION pos=charList.GetHeadPosition(); 
			while(pos!=NULL) 
			{ 
				sampleTemp=charList.GetNext(pos); 
				char_file.Write(&sampleTemp, sizeof(sample)); 
			} 
			char_ConnectPos=charList.GetTailPosition(); 
		 
		} 
 
	} 
	catch(CFileException *e){ 
	//Alert user to error 
		e->Delete(); 
	}//end try-catch 
	char_file.Close(); 
 
	if(num_file.Open(".\\numdata.num",CFile::modeCreate|CFile::modeNoTruncate|CFile::modeReadWrite)==0) 
	{ 
		AfxMessageBox("打开数字文件失败"); 
	} 
 
	try 
	{ 
		Sample sampleTemp; 
		num_file.SeekToEnd(); 
		if(num_ConnectPos!=NULL) 
		{ 
			while(num_ConnectPos!=NULL) 
			{ 
				sampleTemp=numList.GetNext(num_ConnectPos); 
				num_file.Write(&sampleTemp, sizeof(sample)); 
			} 
			num_ConnectPos=numList.GetTailPosition(); 
 
		} 
		else 
		{	 
		//	Sample sampleTemp; 
			POSITION pos=numList.GetHeadPosition(); 
			while(pos!=NULL) 
			{ 
				sampleTemp=numList.GetNext(pos); 
				num_file.Write(&sampleTemp, sizeof(sample)); 
			} 
			num_ConnectPos=numList.GetTailPosition(); 
		 
		} 
 
	} 
	catch(CFileException *e){ 
	//Alert user to error 
		e->Delete(); 
	}//end try-catch 
	num_file.Close(); 
 
 
	if(han_file.Open(".\\handata.han",CFile::modeCreate|CFile::modeNoTruncate|CFile::modeReadWrite)==0) 
	{ 
		AfxMessageBox("打开汉字文件失败"); 
	} 
 
	try 
	{ 
		Sample sampleTemp; 
		han_file.SeekToEnd(); 
		if(han_ConnectPos!=NULL) 
		{ 
			while(han_ConnectPos!=NULL) 
			{ 
				sampleTemp=hanList.GetNext(han_ConnectPos); 
				han_file.Write(&sampleTemp, sizeof(sample)); 
			} 
			han_ConnectPos=hanList.GetTailPosition(); 
 
		} 
		else 
		{	 
		//	Sample sampleTemp; 
			POSITION pos=hanList.GetHeadPosition(); 
			while(pos!=NULL) 
			{ 
				sampleTemp=hanList.GetNext(pos); 
				han_file.Write(&sampleTemp, sizeof(sample)); 
			} 
			han_ConnectPos=hanList.GetTailPosition(); 
		 
		} 
 
	} 
	catch(CFileException *e){ 
	//Alert user to error 
		e->Delete(); 
	}//end try-catch 
	han_file.Close(); 
	 
} 
 
void CDipView::OnLoad()  
{ 
	if (charList.GetCount()!=0||numList.GetCount()!=0||hanList.GetCount()!=0) 
	{ 
		int nReturn; 
		nReturn= 
		AfxMessageBox("训练样本不为空,现在读取会覆盖这些样本,确认覆盖吗?",MB_YESNO); 
		if(nReturn==IDNO) 
			return; 
	} 
	charList.RemoveAll(); 
	numList.RemoveAll(); 
	hanList.RemoveAll(); 
 
	CFile char_file,num_file,han_file; 
	if(char_file.Open(".\\chdata.ch",CFile::modeCreate|CFile::modeNoTruncate|CFile::modeReadWrite)==0) 
	{ 
		AfxMessageBox("打开字符文件失败,您最好退出程序"); 
	} 
	 
	try 
	{ 
		Sample sampleTemp; 
		char_file.SeekToBegin(); 
		DWORD dwBytesRemaining=char_file.GetLength(); 
		while(dwBytesRemaining) 
		{ 
			UINT nBytesRead=char_file.Read(&sampleTemp,sizeof(sample)); 
			charList.AddTail(sampleTemp); 
			dwBytesRemaining-=nBytesRead; 
		} 
		CString s; 
		s.Format("共读取字符数据%d个",charList.GetCount()); 
		AfxMessageBox(s); 
 
	 
	} 
	catch(CFileException *e){ 
 
		e->ReportError(); 
		e->Delete(); 
	} 
	char_file.Close(); 
	char_ConnectPos=charList.GetTailPosition(); 
 
	if(num_file.Open(".\\numdata.num",CFile::modeCreate|CFile::modeNoTruncate|CFile::modeReadWrite)==0) 
	{ 
		AfxMessageBox("打开数字文件失败,您最好退出程序"); 
	} 
	 
	try 
	{ 
		Sample sampleTemp; 
		num_file.SeekToBegin(); 
		DWORD dwBytesRemaining=num_file.GetLength(); 
		while(dwBytesRemaining) 
		{ 
			UINT nBytesRead=num_file.Read(&sampleTemp,sizeof(sample)); 
			numList.AddTail(sampleTemp); 
			dwBytesRemaining-=nBytesRead; 
		} 
		CString s; 
		s.Format("共读取数字数据%d个",numList.GetCount()); 
		AfxMessageBox(s); 
 
	 
	} 
	catch(CFileException *e){ 
 
		e->ReportError(); 
		e->Delete(); 
	} 
	num_file.Close(); 
	num_ConnectPos=numList.GetTailPosition(); 
 
	if(han_file.Open(".\\handata.han",CFile::modeCreate|CFile::modeNoTruncate|CFile::modeReadWrite)==0) 
	{ 
		AfxMessageBox("打开汉字文件失败,您最好退出程序"); 
	} 
 
	try 
	{ 
		Sample sampleTemp; 
		han_file.SeekToBegin(); 
		DWORD dwBytesRemaining=han_file.GetLength(); 
		while(dwBytesRemaining) 
		{ 
			UINT nBytesRead=han_file.Read(&sampleTemp,sizeof(sample)); 
			hanList.AddTail(sampleTemp); 
			dwBytesRemaining-=nBytesRead; 
		} 
		CString s; 
		s.Format("共读取汉字数据%d个",hanList.GetCount()); 
		AfxMessageBox(s); 
 
	 
	} 
	catch(CFileException *e){ 
 
		e->ReportError(); 
		e->Delete(); 
	} 
	han_file.Close(); 
	han_ConnectPos=hanList.GetTailPosition(); 
 
} 
 
void CDipView::OnChange()  
{ 
 
	CFile cf; 
	if(cf.Open(".\\mydata.dat",CFile::modeCreate|CFile::modeNoTruncate|CFile::modeReadWrite)==0) 
	{ 
		AfxMessageBox("打开文件失败,\n您最好退出程序"); 
	} 
 
 
	try 
	{ 
		Sample sampleTemp; 
		cf.SeekToBegin(); 
		DWORD dwBytesRemaining=cf.GetLength(); 
		while(dwBytesRemaining) 
		{ 
			UINT nBytesRead=cf.Read(&sampleTemp,sizeof(sample)); 
			if(sampleTemp.trueClass[1]=='\0') 
			{ 
				if (sampleTemp.trueClass[0]>='0'&&sampleTemp.trueClass[0]<='9') 
				{ 
					 
					numList.AddTail(sampleTemp); 
				} 
 
				if (sampleTemp.trueClass[0]>='A'&&sampleTemp.trueClass[0]<='Z') 
				{	 
					sampleTemp.serialnum=sampleTemp.serialnum-32; 
					charList.AddTail(sampleTemp); 
				} 
 
			} 
			else if(sampleTemp.trueClass[2]=='\0') 
			{ 
				sampleTemp.serialnum=sampleTemp.serialnum-48; 
				hanList.AddTail(sampleTemp); 
			} 
			dwBytesRemaining-=nBytesRead; 
		} 
//		CString s; 
//		s.Format("共读取数据%d个,最后一个的序列号为%d", 
//			TemplateList.GetCount(),sampleTemp.serialnum); 
//		AfxMessageBox(s); 
 
	 
	} 
	catch(CFileException *e){ 
 
		e->ReportError(); 
		e->Delete(); 
	} 
	cf.Close(); 
	 
} 
 
void CDipView::OnTrain()  
{ 
	 
	Sample temp; 
	Sample sa;	 
	double target[36]; 
	POSITION pos; 
	m_pdlg=new CTraining; 
	m_pdlg->Create(IDD_TRAINING); 
	m_pdlg->m_progress.SetRange32(0,2000); 
	m_pdlg->ShowWindow(SW_SHOW); 
	 
	for (int num=0;num<2000;num++) 
	{ 
		pos=charList.GetHeadPosition(); 
	 
		while(pos!=NULL) 
		{ 
			temp=charList.GetNext(pos); 
			for(int i=0; i<13; i++) 
				sa.feature[i] = temp.feature[i]/15; 
			double eo=1,eh=1; 
			if(temp.trueClass[1]=='\0') 
			{ 
				memset(target,0,36*sizeof(double)); 
				target[map(&temp.trueClass[0])-10]=1; 
				char_bp.Train(sa.feature,13,target,26,&eo,&eh); 
			} 
			 
		} 
		m_pdlg->m_output.SetWindowText("正在训练字母网络,请稍候……"); 
		m_pdlg->m_progress.SetPos(num); 
 
	} 
//	bp.Save("bp.dat");	 
	for (num=0;num<2000;num++) 
	{ 
		pos=numList.GetHeadPosition(); 
		while(pos!=NULL) 
		{ 
			temp=numList.GetNext(pos); 
			for(int i=0; i<13; i++) 
				sa.feature[i] = temp.feature[i]/15; 
			double eo=1,eh=1; 
			if(temp.trueClass[1]=='\0') 
			{ 
				memset(target,0,36*sizeof(double)); 
				target[map(&temp.trueClass[0])]=1; 
				num_bp.Train(sa.feature,13,target,10,&eo,&eh); 
			} 
			 
		} 
		m_pdlg->m_output.SetWindowText("正在训练数字网络,请稍候……"); 
		m_pdlg->m_progress.SetPos(num); 
 
	} 
//	bp.Save("bp.dat");	 
	for (num=0;num<2000;num++) 
	{ 
		pos=charList.GetHeadPosition(); 
	 
		while(pos!=NULL) 
		{ 
			temp=charList.GetNext(pos); 
			for(int i=0; i<13; i++) 
				sa.feature[i] = temp.feature[i]/15; 
			double eo=1,eh=1; 
			if(temp.trueClass[1]=='\0') 
			{ 
				memset(target,0,36*sizeof(double)); 
				target[map(&temp.trueClass[0])]=1; 
				char_num_bp.Train(sa.feature,13,target,36,&eo,&eh); 
			} 
			 
		} 
 
		pos=numList.GetHeadPosition(); 
		while(pos!=NULL) 
		{ 
			temp=numList.GetNext(pos); 
			for(int i=0; i<13; i++) 
				sa.feature[i] = temp.feature[i]/15; 
			double eo=1,eh=1; 
			if(temp.trueClass[1]=='\0') 
			{ 
				memset(target,0,36*sizeof(double)); 
				target[map(&temp.trueClass[0])]=1; 
				char_num_bp.Train(sa.feature,13,target,36,&eo,&eh); 
			} 
			 
		} 
		m_pdlg->m_output.SetWindowText("正在训练字母、数字网络,请稍候……"); 
		m_pdlg->m_progress.SetPos(num); 
 
	} 
//	bp.Save("bp.dat");	 
	m_pdlg->DestroyWindow(); 
} 
 
 
int CDipView::map(char *character) 
{ 
	if(*character>='0'&&*character<='9') 
		return *character-'0'; 
	if(*character>='A'&&*character<='Z') 
		return *character-'A'+10; 
} 
 
void CDipView::OnSavebp()  
{ 
	char_bp.Save(".\\char.bp"); 
	num_bp.Save(".\\num.bp"); 
	char_num_bp.Save(".\\char_num.bp"); 
	 
} 
 
void CDipView::OnReadbp()  
{ 
	char_bp.Read(".\\char.bp"); 
	num_bp.Read(".\\num.bp"); 
	char_num_bp.Read(".\\char_num.bp"); 
	 
}