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

📄 locateview.cpp

📁 车牌定位识别系统地涉及具体由车牌定位
💻 CPP
📖 第 1 页 / 共 2 页
字号:
// LocateView.cpp : implementation of the CLocateView class
//

#include "stdafx.h"
#include "Locate.h"
#include "LocateDoc.h"
#include "LocateView.h"
#include "MainFrm.h"
#include "DIBAPI.h"
#include "DibAlgo.h"
#include "EdgeContour.h"
#include "DlgHistShow.h"
#include "SetParamtDlg.h"
#include <afxtempl.h>
#include <fstream.h>
#include <math.h>

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

/////////////////////////////////////////////////////////////////////////////
// CLocateView

IMPLEMENT_DYNCREATE(CLocateView, CView)

BEGIN_MESSAGE_MAP(CLocateView, CView)
	//{{AFX_MSG_MAP(CLocateView)
	ON_COMMAND(ID_IMAGE_TOGRAY, OnImageToGray)
	ON_COMMAND(ID_GRAY_TOSTRE, OnStretch)
	ON_COMMAND(ID_GRAY_TOTHRE, OnThreshold)
	ON_COMMAND(ID_GRAY_TOTEMP, OnTemplate)
	ON_COMMAND(ID_MEDIAN_TOFILTER, OnMedianFilter)
	ON_COMMAND(ID_IMAGE_TOPROJECT, OnFiltrate)
	ON_COMMAND(ID_TEMP_TOSUBRECT, OnSubrect)
	ON_COMMAND(ID_IMAGE_OPEN, OnImageOpen)
	ON_COMMAND(ID_GRAY_EQUA, OnGrayEqualize)
	ON_COMMAND(ID_VIEW_HIST, OnViewHist)
	ON_COMMAND(ID_IMAGE_SAVE, OnImageSave)
	ON_COMMAND(ID_OPTION_PARAM, OnOptionParam)
	//}}AFX_MSG_MAP
	// Standard printing commands
END_MESSAGE_MAP()

/////////////////////////////////////////////////////////////////////////////
// CLocateView construction/destruction

CLocateView::CLocateView()
{
	m_hDIB   = NULL;
	m_palDIB = NULL;

	m_lMaxDist   = 20;	// 最大允许的跳变点间距
	m_lMinDotNum = 10;	// 最小允许的每行跳变点数

	m_nMaxOffset = 100;	// 同一区域两行最左端允许相差的最大距离
	m_nMaxGap    = 4;	// 同一区域最多允许的间断行数
	m_nMinHeight = 10;	// 车牌照的最小高度
	m_nMinWidth  = 80;	// 车牌照的最小宽度
}

CLocateView::~CLocateView()
{
	if (m_hDIB != NULL)
	{
		::GlobalFree((HGLOBAL) m_hDIB);
	}
	
	if (m_palDIB != NULL)	// 判断调色板是否存在
	{
		delete m_palDIB;
	}
}

/////////////////////////////////////////////////////////////////////////////
// CLocateView drawing

void CLocateView::OnDraw(CDC* pDC)
{
	// 显示等待光标
	BeginWaitCursor();

	// 判断DIB是否为空
	if (m_hDIB != NULL)
	{
		LPSTR lpDIB = (LPSTR) ::GlobalLock((HGLOBAL) m_hDIB);
		
		// 获取DIB宽度
		int cxDIB = (int) ::DIBWidth(lpDIB);
		
		// 获取DIB高度
		int cyDIB = (int) ::DIBHeight(lpDIB);

		::GlobalUnlock((HGLOBAL) m_hDIB);
		
		CRect rcDIB;
		rcDIB.top = rcDIB.left = 0;
		rcDIB.right = cxDIB;
		rcDIB.bottom = cyDIB;
		
		// 输出DIB
		::PaintDIB(pDC->m_hDC, &rcDIB, m_hDIB ,	&rcDIB, GetViewPalette());
	}
	
	// 恢复正常光标
	EndWaitCursor();
}

/////////////////////////////////////////////////////////////////////////////
// CLocateView diagnostics

#ifdef _DEBUG
void CLocateView::AssertValid() const
{
	CView::AssertValid();
}

void CLocateView::Dump(CDumpContext& dc) const
{
	CView::Dump(dc);
}

CLocateDoc* CLocateView::GetDocument() // non-debug version is inline
{
	ASSERT(m_pDocument->IsKindOf(RUNTIME_CLASS(CLocateDoc)));
	return (CLocateDoc*)m_pDocument;
}
#endif //_DEBUG

/////////////////////////////////////////////////////////////////////////////
// CLocateView message handlers

// 打开车牌照片
void CLocateView::OnImageOpen() 
{
	CString strPhotoPath;	// 照片文件路径

	CFileDialog dlg(TRUE,NULL,NULL,0,"JPEG Files (*.jpg)|*.jpg||",this);
	if (dlg.DoModal() != IDOK)
	{
		return;
	}
	strPhotoPath = dlg.GetPathName();

	// 调用JpgVsBmp.dll中提供的JPG=>BMP的功能
	HINSTANCE hInst = ::LoadLibrary("JpgVSbmp.dll");
	if( hInst == NULL )
	{
		AfxMessageBox("缺少JpgVSbmp.dll文件!");
		return;
	}
	typedef  bool(__stdcall CHANGE)(LPCTSTR,LPCTSTR,int);
	CHANGE* pFunc	= (CHANGE *)::GetProcAddress(hInst,"JpgToBmp");
	pFunc(strPhotoPath, "Temp.bmp", 24);
	::FreeLibrary(hInst);
	
	// 从磁盘载入bmp文件
	CFile file;
	file.Open("Temp.bmp", CFile::modeRead);
	m_hDIB = ::ReadDIBFile(file);
 	if (m_hDIB != NULL)
 	{
 		Invalidate();
 	}

	file.Close();
	CFile::Remove("Temp.bmp");
}

// 保存车牌照片为bmp文件
void CLocateView::OnImageSave() 
{
	CFileDialog dlg(FALSE,NULL,NULL,0,"BMP Files (*.bmp)|*.bmp||",this);
	if (dlg.DoModal() != IDOK)
	{
		return;
	}
	CString strBMPPath = dlg.GetPathName();

	CFile file;
	file.Open(strBMPPath, CFile::modeCreate|CFile::modeWrite);
	::SaveDIB(m_hDIB,file);
	file.Close();
}

// 灰度化
void CLocateView::OnImageToGray() 
{
	if (m_hDIB == NULL)
		return;

	Copy();	// 在处理之前先保存原来的图像

	LPSTR lpDIB = (LPSTR) ::GlobalLock((HGLOBAL) m_hDIB);	
	ConvertToGrayScale(lpDIB);
	::GlobalUnlock((HGLOBAL) m_hDIB);

	Invalidate();
}

// 直方图均衡化
void CLocateView::OnGrayEqualize() 
{
	if (m_hDIB == NULL)
		return;

	LPSTR lpDIB = (LPSTR) ::GlobalLock((HGLOBAL) m_hDIB);	
	LPSTR lpDIBBits = FindDIBBits(lpDIB);
	int lWidth = DIBWidth(lpDIB);
	int lHeight = DIBHeight(lpDIB);
	InteEqualize(lpDIBBits,lWidth,lHeight);
	::GlobalUnlock((HGLOBAL) m_hDIB);

	Invalidate();
}

// 灰度拉伸
void CLocateView::OnStretch() 
{
	if (m_hDIB == NULL)
		return;

	// 点1坐标
	BYTE	bX1;
	BYTE	bY1;
	
	// 点2坐标
	BYTE	bX2;
	BYTE	bY2;
	
	// 锁定DIB
	LPSTR lpDIB = (LPSTR) ::GlobalLock((HGLOBAL) m_hDIB);

	// 找到DIB图像象素起始位置
	LPSTR lpDIBBits = ::FindDIBBits(lpDIB);
	
	//(重要)
	bX1 = 100;
	bY1 = 1;
	bX2 = 150;
	bY2 = 255;
	
	BeginWaitCursor();
	
	// 调用GrayStretch()函数进行灰度拉伸
	GrayStretch(lpDIBBits, ::DIBWidth(lpDIB), ::DIBHeight(lpDIB), bX1, bY1, bX2, bY2);

	Invalidate();
	
	// 解除锁定
	::GlobalUnlock((HGLOBAL) m_hDIB);

	EndWaitCursor();
}

// 阈值变换(二值化)
void CLocateView::OnThreshold() 
{
	if (m_hDIB == NULL)
		return;

	unsigned char * lpSrc;             //指向原图像象素点的指针
	
	LPSTR lpDIB = (LPSTR) ::GlobalLock((HGLOBAL)m_hDIB);//获得当前位图
	LPSTR lpDIBBits = ::FindDIBBits(lpDIB);
	LONG lWidth = ::DIBWidth(lpDIB);   //DIB 宽度
	LONG lHeight = ::DIBHeight(lpDIB); //DIB 高度

	// 计算图像每行的字节数
	LONG lLineBytes = WIDTHBYTES(lWidth * 8);
	
	long lCount[256];
	for(long i=0;i<256;i++)
	{
		lCount[i]=0;  //清零
	}
	if(::DIBNumColors(lpDIB) != 256)  //256色位图不作任何处理
	{
		return;
	}
	for(i = 0; i < lHeight; i++)
	{
		for(long j = 0; j < lWidth; j++)
		{
//			lpSrc=(unsigned char *)lpDIB+lLineBytes*i+j;
			lpSrc=(unsigned char *)lpDIBBits+lLineBytes*i+j;
			lCount[*(lpSrc)]++;
		}
	}
	
	//求窗口变换的上限和下限
	long temp[16];
	int k=0;
	
	for(k=0;k<16;k++)
	{
		temp[k]=0;
		for(i=k*16;i<(k+1)*16;i++)
			temp[k]+=lCount[i];
	}
	
	long max=0;
	int t=0;
	for(k=15;k>=0;k--)
	{
		if(temp[k]>max)
		{
			max=temp[k];
			t=k;
		}		
	}
	
	int bLow=0,bUp=0;
	bLow=(t-1)*16;
	//	bUp=(t+5)*16;
	
	//	bLow=100;
	bUp=255;

	// 阈值(重要)
	INT bThre=(INT)((2*bUp+bLow)/3);
//	INT bThre = 150;
	
	BeginWaitCursor();
	
	// 调用ThresholdTrans()函数进行阈值变换
	ThresholdTrans(lpDIBBits, ::DIBWidth(lpDIB), ::DIBHeight(lpDIB), bThre);
	
	Invalidate();
	::GlobalUnlock((HGLOBAL) m_hDIB);

	EndWaitCursor();
}

// 模板变换
void CLocateView::OnTemplate() 
{
	if (m_hDIB == NULL)
		return;

	LPSTR lpDIB = (LPSTR) ::GlobalLock((HGLOBAL) m_hDIB);//获得当前位图

	LPSTR lpDIBBits = ::FindDIBBits(lpDIB);
	int w = ::DIBWidth(lpDIB);
	int h = ::DIBHeight(lpDIB);

	//用自定义的模板消弱背景干扰
	Template(lpDIB);
//	::RobertDIB(lpDIBBits,w,h);

	Invalidate();

	::GlobalUnlock((HGLOBAL) m_hDIB);
}

// 中值滤波
void CLocateView::OnMedianFilter() 
{
	LPSTR	lpDIB;		// 指向DIB的指针
	LPSTR   lpDIBBits;	// 指向DIB象素指针
	int iFilterH;		// 滤波器的高度
	int iFilterW;		// 滤波器的宽度
	int iFilterMX;		// 中心元素的X坐标
	int iFilterMY;		// 中心元素的Y坐标
	
	// 锁定DIB
	lpDIB = (LPSTR) ::GlobalLock((HGLOBAL) m_hDIB);
	
	// 找到DIB图像象素起始位置
	lpDIBBits = ::FindDIBBits(lpDIB);
	
	// 初始化变量值(重要)
	iFilterH = 5;
	iFilterW = 1;
	iFilterMX = 0;
	iFilterMY = 2;
		
	BeginWaitCursor();
	
	// 调用MedianFilter()函数中值滤波
	if (MedianFilter(lpDIBBits, ::DIBWidth(lpDIB), ::DIBHeight(lpDIB), 
		iFilterH, iFilterW, iFilterMX, iFilterMY))
	{
		Invalidate();
	}
	else
	{
		MessageBox("分配内存失败!", "系统提示" , MB_ICONINFORMATION | MB_OK);
	}
	
	// 解除锁定
	::GlobalUnlock((HGLOBAL) m_hDIB);
	
	EndWaitCursor();
}

// 核心代码: 筛选可能存在拍照的区域
void CLocateView::OnFiltrate() 
{
	if (m_hDIB == NULL)
		return;

	long lRows = 0;	// 有效的行数
	long L,K;		// 用于迭代的行列号
	long lDist;		// 跳变点的间距
	CPoint s[1000];	// 某一段跳变点的起始坐标
	CPoint e[1000];	// 某一段跳变点的终止坐标
	long   r[1000];	// 每行的跳变点数

	LPSTR lpDIB      = (LPSTR)::GlobalLock((HGLOBAL)m_hDIB);
	LPSTR lpDIBBits  = ::FindDIBBits(lpDIB);	
	long  lWidth     = ::DIBWidth(lpDIB);
	long  lHeight    = ::DIBHeight(lpDIB);	
	long  lLineBytes = WIDTHBYTES(lWidth * 8);

	#define VALUE(i,j) (*((unsigned char*)lpDIBBits + lLineBytes * (lHeight - 1 - i) + j))

	BOOL* lFlag = new BOOL[lHeight]; // 记录每一行是否存在有效跳边点段
	memset(lFlag,0,sizeof(BOOL)*lHeight);

	for(L = 0; L < lHeight; L++)
	{
		for (K = 0,lDist = -1; K < lWidth; K++)
		{
			// 跳过黑色点		
			while (VALUE(L,K) == 0)	
			{
				K++;
				if (lDist >= 0)
				{
					lDist++;
				}
			}	

			if (lDist == -1)
			{
				s[lRows] = e[lRows] = CPoint(L,K);
				r[lRows] = 1;
				lDist = 0;
			}
			else if (lDist >= 0 && lDist <= m_lMaxDist)

⌨️ 快捷键说明

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