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

📄 reconizedlg.cpp

📁 车牌识辨源程序
💻 CPP
📖 第 1 页 / 共 2 页
字号:
// ReconizeDlg.cpp : implementation file
//著者:刘海锋      2006,11,20

#include "stdafx.h"
#include "Reconize.h"
#include "ReconizeDlg.h"
#include "math.h"

#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif

BYTE Buffer[1000][1000][3];	// 24位真彩色图// 0--blue 1--green 2--red
BYTE Buffer1[1000][1000];	// 灰度图
BYTE BufferReg[1000][1000];	//二值图
BYTE pByte[3200000];	//内存镜像文件

int Flag=-1;

int index1,index2,index3,index4;	//分别是以下四个数组的上界标识.
int  PointLT[50000][3] ,PointRT[50000][3] ,PointRB[50000][3] ,PointLB[50000][3] ;

 int pointX1,pointY1,pointX2,pointY2;//(x1,y1),(x2,y2) 为车牌照的左上与右下点坐标

int indexRect;
int  Rect[50000][4];	//匹配的矩形记录,里面放的是PointLT等..中对应坐标的索引.

int  avgPointLT[50000][3] ,avgPointRT[50000][3] ,avgPointRB[50000][3] ,avgPointLB[50000][3] ;//依次对应匹配的平均矩形的左顶点,右顶点,右底点,左底点底坐标
int  avgindexRect; //匹配的平均矩形记录

int  HaveJumpRectLT[50000][3],HaveJumpRectRT[50000][3],HaveJumpRectRB[50000][3],HaveJumpRectLB[50000][3];//含有足够跳变的矩形坐标记录
int  JumpindexRect; //含有足够跳变的矩形数目
///////////////////////////////////////////////////////////////////////////
// CAboutDlg dialog used for App About

class CAboutDlg : public CDialog
{
public:
	CAboutDlg();

// Dialog Data
	//{{AFX_DATA(CAboutDlg)
	enum { IDD = IDD_ABOUTBOX };
	//}}AFX_DATA

	// ClassWizard generated virtual function overrides
	//{{AFX_VIRTUAL(CAboutDlg)
	protected:
	virtual void DoDataExchange(CDataExchange* pDX);    // DDX/DDV support
	//}}AFX_VIRTUAL

// Implementation
protected:
	//{{AFX_MSG(CAboutDlg)
	//}}AFX_MSG
	DECLARE_MESSAGE_MAP()
};

CAboutDlg::CAboutDlg() : CDialog(CAboutDlg::IDD)
{
	//{{AFX_DATA_INIT(CAboutDlg)
	//}}AFX_DATA_INIT
}

void CAboutDlg::DoDataExchange(CDataExchange* pDX)
{
	CDialog::DoDataExchange(pDX);
	//{{AFX_DATA_MAP(CAboutDlg)
	//}}AFX_DATA_MAP
}

BEGIN_MESSAGE_MAP(CAboutDlg, CDialog)
	//{{AFX_MSG_MAP(CAboutDlg)
		// No message handlers
	//}}AFX_MSG_MAP
END_MESSAGE_MAP()

/////////////////////////////////////////////////////////////////////////////
// CReconizeDlg dialog

CReconizeDlg::CReconizeDlg(CWnd* pParent /*=NULL*/)
	: CDialog(CReconizeDlg::IDD, pParent)
{
	//{{AFX_DATA_INIT(CReconizeDlg)
		// NOTE: the ClassWizard will add member initialization here
	//}}AFX_DATA_INIT
	// Note that LoadIcon does not require a subsequent DestroyIcon in Win32
	m_hIcon = AfxGetApp()->LoadIcon(IDR_MAINFRAME);
}

void CReconizeDlg::DoDataExchange(CDataExchange* pDX)
{
	CDialog::DoDataExchange(pDX);
	//{{AFX_DATA_MAP(CReconizeDlg)
		// NOTE: the ClassWizard will add DDX and DDV calls here
	//}}AFX_DATA_MAP
}

BEGIN_MESSAGE_MAP(CReconizeDlg, CDialog)
	//{{AFX_MSG_MAP(CReconizeDlg)
	ON_WM_SYSCOMMAND()
	ON_WM_PAINT()
	ON_WM_QUERYDRAGICON()
	ON_BN_CLICKED(IDC_OPEN_FILE, OnOpenFile)
	ON_BN_CLICKED(IDC_TO_GRAY, OnToGray)
	ON_BN_CLICKED(IDC_FILE_EXIT, OnFileExit)
	ON_BN_CLICKED(IDC_WHITE_BLACK, OnWhiteBlack)
	ON_BN_CLICKED(IDC_DRAW_EDGE, OnDrawEdge)
	ON_BN_CLICKED(IDC_DRAW_RECT, OnDrawRect)
	ON_BN_CLICKED(IDC_QUICK_RECONIZE, OnQuickReconize)
	ON_BN_CLICKED(IDC_huidujunheng, Onhuidujunheng)
	ON_BN_CLICKED(IDC_SobelCheck, OnSobelCheck)
	ON_BN_CLICKED(IDC_YawpDrop, OnYawpDrop)
	//}}AFX_MSG_MAP
END_MESSAGE_MAP()

/////////////////////////////////////////////////////////////////////////////
// CReconizeDlg message handlers

BOOL CReconizeDlg::OnInitDialog()
{
	CDialog::OnInitDialog();

	// Add "About..." menu item to system menu.

	// IDM_ABOUTBOX must be in the system command range.
	ASSERT((IDM_ABOUTBOX & 0xFFF0) == IDM_ABOUTBOX);
	ASSERT(IDM_ABOUTBOX < 0xF000);

	CMenu* pSysMenu = GetSystemMenu(FALSE);
	if (pSysMenu != NULL)
	{
		CString strAboutMenu;
		strAboutMenu.LoadString(IDS_ABOUTBOX);
		if (!strAboutMenu.IsEmpty())
		{
			pSysMenu->AppendMenu(MF_SEPARATOR);
			pSysMenu->AppendMenu(MF_STRING, IDM_ABOUTBOX, strAboutMenu);
		}
	}

	// Set the icon for this dialog.  The framework does this automatically
	//  when the application's main window is not a dialog
	SetIcon(m_hIcon, TRUE);			// Set big icon
	SetIcon(m_hIcon, FALSE);		// Set small icon
	
	// TODO: Add extra initialization here
	
	return TRUE;  // return TRUE  unless you set the focus to a control
}

void CReconizeDlg::OnSysCommand(UINT nID, LPARAM lParam)
{
	if ((nID & 0xFFF0) == IDM_ABOUTBOX)
	{
		CAboutDlg dlgAbout;
		dlgAbout.DoModal();
	}
	else
	{
		CDialog::OnSysCommand(nID, lParam);
	}
}

// If you add a minimize button to your dialog, you will need the code below
//  to draw the icon.  For MFC applications using the document/view model,
//  this is automatically done for you by the framework.

void CReconizeDlg::OnPaint() 
{
	if (IsIconic())
	{
		CPaintDC dc(this); // device context for painting

		SendMessage(WM_ICONERASEBKGND, (WPARAM) dc.GetSafeHdc(), 0);

		// Center icon in client rectangle
		int cxIcon = GetSystemMetrics(SM_CXICON);
		int cyIcon = GetSystemMetrics(SM_CYICON);
		CRect rect;
		GetClientRect(&rect);
		int x = (rect.Width() - cxIcon + 1) / 2;
		int y = (rect.Height() - cyIcon + 1) / 2;

		// Draw the icon
		dc.DrawIcon(x, y, m_hIcon);
	}
	else
	{
		CDialog::OnPaint();
	}
}

// The system calls this to obtain the cursor to display while the user drags
//  the minimized window.
HCURSOR CReconizeDlg::OnQueryDragIcon()
{
	return (HCURSOR) m_hIcon;
}

void CReconizeDlg::OnOpenFile() 
{
	// TODO: Add your control notification handler code here
	LPCTSTR lpszFilter="位图文件(*.BMP)|*.bmp|ALL FILES(*.*)|*.*";
	CFileDialog OpenDlg(TRUE,lpszFilter,NULL,OFN_HIDEREADONLY|OFN_OVERWRITEPROMPT,lpszFilter,NULL);
	if(OpenDlg.DoModal()==IDOK)
	{
		InvalidateRect(NULL);
		FillMatrix(OpenDlg.GetPathName());
		DrawBMP();
		 drawXYchou();   // 画坐标轴
	}

	Flag=0;
}

void CReconizeDlg::DrawBMP()//绘制bmp
{
	CClientDC dc(this);
	int i,j;
	for(i=0;i<m_Width;i++)  //rgb i=0;i<m_Width;i++
		for(j=0;j<m_Height;j++)
			dc.SetPixel(i+1,j+1,RGB(Buffer[i][j][2],Buffer[i][j][1],Buffer[i][j][0]) );	//why 0--blue 1--green 2--red
////////////////////////////////////////////////////////
}

void CReconizeDlg::FillMatrix(CString filename)	//将原始图形文件读入数组Buffer
{
////////////////////////////////////////////////////
	m_Width=0;
	m_Height=0;
	CFile fbmp;
	if (fbmp.Open(filename,CFile::modeRead)==FALSE)
	{
		MessageBox("文件打开出错");
		return;
	}

	char head1,head2;
	fbmp.Read(&head1,1);
	fbmp.Read(&head2,1);
	if(head1!='B' || head2!='M' )
	{
		MessageBox("找不到bmp文件");
		fbmp.Close();
		return;
	}
////////////////////////////////////////////////////
	DWORD filesize=fbmp.GetLength();
	fbmp.Seek(0,CFile::begin);
	fbmp.ReadHuge(pByte,filesize);
	fbmp.Close();

	BYTE *p;
	p=pByte+18;//18
	int tmpWidth,tmpHeight;

	tmpWidth= *p + (*(p+1)) *256 + (*(p+2)) *256*256 + (*(p+3)) *256*256*256 ; //256
	p=pByte+22;//22
	tmpHeight= *p + (*(p+1)) *256 + (*(p+2)) *256*256 + (*(p+3)) *256*256*256 ;//256 
	CString tmpStr1;
//	MessageBox("刘海锋----2006--11--20");
	tmpStr1.Format("图象文件大小:宽 %d , 高 %d",tmpWidth,tmpHeight);
	MessageBox(tmpStr1);
	if(tmpWidth>1000 || tmpHeight >1000)
	{                                                                                                                                                                                                
		MessageBox("处理的bmp文件太大");
		return;
	}

	int especial=tmpWidth%4;	
	p=pByte+10;//10
	int bmpflg;                                                                              
	bmpflg= *p + (*(p+1)) *256 + (*(p+2)) *256*256 + (*(p+3)) *256*256*256 ;
	p=pByte+bmpflg;//bmpflg
	int i,j,k;
	for(i=tmpHeight-1;i>=0;i--)                                                                                                                                   
		for(j=0;j<tmpWidth;j++)
		{
			for(k=0;k<3;k++)
			{
				Buffer[j][i][k]=*p;//
				p++;
			}//图象数据
    if(j==tmpWidth-1)
	{                                                                                                                      
		p=p+especial;
	}
		}

	m_Width=tmpWidth;
	m_Height=tmpHeight;

}

void CReconizeDlg::GetGrayBmp()
{
	// TODO: Add your command handler code here
	//二值化。
	int i,j;
	// x=0.299*red+0.587*green+0.114*blue;
	for(i=0;i<m_Width;i++)
		for(j=0;j<m_Height;j++)
		   Buffer1[i][j]=(BYTE)( 0.114*Buffer[i][j][0]+0.587*Buffer[i][j][1]+0.299*Buffer[i][j][2] );
}

void CReconizeDlg::OnToGray() 
{
	// TODO: Add your control notification handler code here
	int i,j;
	int huidu[256];         
	  for(i=0;i<256;i++) 
		 huidu[i]=0;
	
	GetGrayBmp();
	CClientDC dc(this);
       	if(m_Width>500||m_Height>400)
	{
		MessageBox("图象太大,处理会出错!!","出错",MB_ICONSTOP|MB_OK);
		return;
	}
	for(i=0;i<m_Width;i++)  //rgb
		for(j=0;j<m_Height;j++)
		{
			dc.SetPixel(i+1,j+1,RGB(Buffer1[i][j],Buffer1[i][j],Buffer1[i][j]) );
           huidu[Buffer1[i][j]]++;//统计灰度
		}

		drawzhifatu();  //对当前图象画直方图

    Flag=1;
}

void CReconizeDlg::OnFileExit() 
{
	// TODO: Add your control notification handler code here
	exit(0);
}
void CReconizeDlg::OnWhiteBlack()  //将得到的车牌二值化
{
 CClientDC dc(this);
	 
   for(int i=pointX1-2;i<pointX2+2;i++)  // 
	 
     for(int j=pointY1-2;j<pointY2+2;j++)   
	 {  if(Buffer1[i][j]>50)
		 dc.SetPixel(i-pointX1+20,j-pointY1+350,RGB(255,255,255));
		 else
         dc.SetPixel(i-pointX1+20,j-pointY1+350,RGB(0,0,0));
	 }
}
void CReconizeDlg::DrawGetregion() //计算出二值图
{
	// TODO: Add your command handler code here
	int i,j;
	int defvalue=15;//阈值点
	for(i=0;i<m_Width;i++)
		for(j=0;j<m_Height;j++)
			BufferReg[i][j]=0;

	for(i=0;i<m_Height;i++)
		for(j=0;j<m_Width-1;j++)
		{
			if( abs(Buffer1[j][i]-Buffer1[j+1][i])>defvalue )
				BufferReg[j][i]=255;
		}
	
	for(i=0;i<m_Width;i++)
		for(j=0;j<m_Height-1;j++)
		{
			if( abs(Buffer1[i][j]-Buffer1[i][j+1])>defvalue )
				BufferReg[i][j]=255;
		}
}

void CReconizeDlg::DrawRegion() //绘出二值图
{
	// TODO: Add your command handler code here
	int i,j;
	CClientDC dc(this);
	for(i=0;i<m_Width;i++)  //rgb
		for(j=0;j<m_Height;j++)
			dc.SetPixel(i+1,j+1,RGB( BufferReg[i][j],
										BufferReg[i][j],
										BufferReg[i][j] )  );
}///////////////////////////////////////////////////////////

void CReconizeDlg::EraseDot()
{ //m_Width,m_Height
  int i,j;
    for(i=1;i<m_Width-1;i++)
		for(j=1;j<m_Height-1;j++)
		{
		   if( (BufferReg[i][j]!=BufferReg[i-1][j-1]) && (BufferReg[i][j]!=BufferReg[i][j-1])
			  && (BufferReg[i][j]!=BufferReg[i+1][j-1]) && (BufferReg[i][j]!=BufferReg[i-1][j])
			  && (BufferReg[i][j]!=BufferReg[i+1][j]) && (BufferReg[i][j]!=BufferReg[i-1][j+1])
			  &&(BufferReg[i][j]!=BufferReg[i][j+1]) && (BufferReg[i][j]!=BufferReg[i+1][j+1])
			  )
			  BufferReg[i][j]=255-BufferReg[i][j];  
		}///////////////////////////////////////
}

void CReconizeDlg::EraseDot2()
{
	EraseDot();
	int i,j;
	for(i=4;i<m_Width-4;i++)
		for(j=4;j<m_Height-4;j++)
		{
			if(		BufferReg[i-1][j-1]==BufferReg[i][j-1] 
				&&  BufferReg[i-1][j-1]==BufferReg[i+1][j-1] 
				&&	BufferReg[i-1][j-1]==BufferReg[i+2][j-1]

				&&	BufferReg[i-1][j-1]==BufferReg[i-1][j]
				&&	BufferReg[i-1][j-1]==BufferReg[i+2][j]

				&&	BufferReg[i-1][j-1]==BufferReg[i-1][j+1]
				&&	BufferReg[i-1][j-1]==BufferReg[i+2][j+1]

				&&	BufferReg[i-1][j-1]==BufferReg[i-1][j+2]
				&&	BufferReg[i-1][j-1]==BufferReg[i][j+2]
				&&	BufferReg[i-1][j-1]==BufferReg[i+1][j+2]
				&&	BufferReg[i-1][j-1]==BufferReg[i+2][j+2]
			   )
			{
				BufferReg[i][j]=BufferReg[i-1][j-1];
				BufferReg[i+1][j]=BufferReg[i-1][j-1];
				BufferReg[i][j+1]=BufferReg[i-1][j-1];
				BufferReg[i+1][j+1]=BufferReg[i-1][j-1];
			}
		
		}
}

void CReconizeDlg::Getpts() 
{
}

void CReconizeDlg::OnDrawEdge() //找出合理的边界 ,并标记出来
{
	// TODO: Add your command handler code here
	int i,j,count=0;
	int low=0 ,high=0;
	int late=0;
    bool lflag[500],rflag[500],flag=true;//行列边界有效标记
	  for(i=0;i<500;i++)
	  {
		  lflag[i]=false;
		  rflag[i]=false;
	  }

  int num=0;
  int Active_low[50];               //有效行记录,不多于50行
  for(i=0;i<50;i++)
  {
	  Active_low[i]=0;
  }
  //////////////////////////////////////////    
 		for(j=m_Height*1/10;j<m_Height*19/20;j++)       //对行进行标记,上面1/10,下面1/20不考虑
          for(i=m_Width*1/10;i<m_Width*9/10;i++)  
		  {
			  
			  if((abs(Buffer1[i][j]-Buffer1[i+1][j])<6)&&Buffer1[i][j]>130) count++;
			  else 
				  count=0;
			  if(count>30) { lflag[j]=true;}
		  }

    for(j=m_Height*1/10;j<m_Height;j++)
	  {
		  
		  if(lflag[j]==true)
             
		  {
			  Active_low[num++]=j;                //记录此行
			   
			  for(i=0;i<m_Width;i++)
			  {
				  Buffer1[i][j]=255;              //把此行变白
				 
			  }
			  late=j+1;            //如果第j行后有连续多行满足要求,以次行代替就可以了
			   while(lflag[late]==true)  late++;
			   j=late;

		  }

	  }

     for(j=m_Height*1/10;j<m_Height*19/20;j++)  //找出满足条件的最高和最低行
		  if(lflag[j]==true&&flag==true)
		  {
			  low=j;flag=false;
		  }
           flag=true;
     for(j=m_Height*9/10;j>m_Height/3;j--)  
		 if(lflag[j]==true&&flag==true)
		  {
			  high=j;flag=false;
		  }


  int Ltopi[100], Ltopj[100];//用于存放可行车牌垂直边上顶点
  int Rlowi[100],Rlowj[100]; //用于存放可行车牌垂直边下顶点
  int col=0;
  for(i=0;i<100;i++)
  {
	  Ltopi[0]=0;Ltopj[0]=0;  
	  Rlowi[0]=0;Rlowj[0]=0;  
  }
   num=0;
   int k=0;
   
  for(int L=Active_low[num];L<high&&L>0; )    //在有效行中找两行,并确定车牌照坐上与右下点坐标
   { 	
	 k=num+1;
	 for(int H=Active_low[k];H<=m_Height&&H>L; )   //移动下行
	 {
		  
		   
        for(i=m_Width*1/10;i<m_Width*19/20&&(H-L)>20&&(H-L)<50;i++)    //认为车牌垂直边大于20&&<50象数
		{
			 int count1=0;
		    
            for(int p=L;p<H&&(H-L)<50;p++)       
			{  
			   if((float)count1/(float)(H-L)>=0.8)
			   { 
				   Ltopi[col]=i;Ltopj[col]=L;  //记录上顶点
				   Rlowi[col]=i;Rlowj[col]=H;  //记录下顶点
				   col++;
				                
				   count1=0;
				   break;
			   }   
		      if(Buffer1[i][p]>80)  count1++;
			           
		       else   count1=0;
			}
  
		}
	//	count1=0;
		H=Active_low[++k];
	 }//移动下行
	  
	   L=Active_low[++num];
	 
   }
 
  int left=0,right=0;
  for(col=0;col<100&&Ltopi[col]>0;col++) //统计列数
  {
	  right=col;
  }

 

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -