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");
}