www.pudn.com > VC20070605zghLPR.rar > PlateRecoView.cpp
// PlateRecoView.cpp : implementation of the CPlateRecoView class
//
#include "stdafx.h"
#include "PlateReco.h"
#include "MainFrm.h"
#include "DlgRecoResult.h"
#include "PlateRecoDoc.h"
#include "PlateRecoView.h"
#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif
/////////////////////////////////////////////////////////////////////////////
// CPlateRecoView
IMPLEMENT_DYNCREATE(CPlateRecoView, CView)
BEGIN_MESSAGE_MAP(CPlateRecoView, CView)
//{{AFX_MSG_MAP(CPlateRecoView)
ON_COMMAND(ID_LPR_platelocation, OnLPRplatelocation)
ON_COMMAND(ID_LPR_plate2binarycolor, OnLPRplate2binarycolor)
ON_COMMAND(ID_LPR_platenorm, OnLPRplatenorm)
ON_COMMAND(ID_LPR_platecharthinning, OnLPRplatecharthinning)
ON_COMMAND(ID_LPR_feature16seg, OnLPRfeature16seg)
ON_COMMAND(ID_LPR_platereco, OnLPRplatereco)
ON_COMMAND(ID_LPR_platepreprocessall, OnLPRplatepreprocessall)
//}}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()
/////////////////////////////////////////////////////////////////////////////
// CPlateRecoView construction/destruction
CPlateRecoView::CPlateRecoView()
{
// TODO: add construction code here
for(int i = 0; i < 13; i++)
{
m_fCode13Sect[i] = 0.0;
}
for(int j = 0; j < 16; j++)
{
m_fCode13Sect[j] = 0.0;
}
m_iPlateType = 0;
}
CPlateRecoView::~CPlateRecoView()
{
}
BOOL CPlateRecoView::PreCreateWindow(CREATESTRUCT& cs)
{
// TODO: Modify the Window class or styles here by modifying
// the CREATESTRUCT cs
return CView::PreCreateWindow(cs);
}
/////////////////////////////////////////////////////////////////////////////
// CPlateRecoView drawing
void CPlateRecoView::OnDraw(CDC* pDC)
{
// 显示等待光标
BeginWaitCursor();
// 获取文档
CPlateRecoDoc* pDoc = GetDocument();
ASSERT_VALID(pDoc);
// 获取DIB
HDIB hDIB = pDoc->GetHDIB();
// 判断DIB是否为空
if (hDIB != NULL)
{
LPSTR lpDIB = (LPSTR) ::GlobalLock((HGLOBAL) hDIB);
// 获取DIB宽度
int cxDIB = (int) ::DIBWidth(lpDIB);
// 获取DIB高度
int cyDIB = (int) ::DIBHeight(lpDIB);
::GlobalUnlock((HGLOBAL) hDIB);
CRect rcDIB;
rcDIB.top = rcDIB.left = 0;
rcDIB.right = cxDIB;
rcDIB.bottom = cyDIB;
CRect rcDest;
// 判断是否是打印
if (pDC->IsPrinting())
{
// 是打印,计算输出图像的位置和大小,以便符合页面
// 获取打印页面的水平宽度(象素)
int cxPage = pDC->GetDeviceCaps(HORZRES);
// 获取打印页面的垂直高度(象素)
int cyPage = pDC->GetDeviceCaps(VERTRES);
// 获取打印机每英寸象素数
int cxInch = pDC->GetDeviceCaps(LOGPIXELSX);
int cyInch = pDC->GetDeviceCaps(LOGPIXELSY);
// 计算打印图像大小(缩放,根据页面宽度调整图像大小)
rcDest.top = rcDest.left = 0;
rcDest.bottom = (int)(((double)cyDIB * cxPage * cyInch)
/ ((double)cxDIB * cxInch));
rcDest.right = cxPage;
// 计算打印图像位置(垂直居中)
int temp = cyPage - (rcDest.bottom - rcDest.top);
rcDest.bottom += temp/2;
rcDest.top += temp/2;
}
else
// 非打印
{
// 不必缩放图像
rcDest = rcDIB;
}
// 输出DIB
::PaintDIB(pDC->m_hDC, &rcDest, pDoc->GetHDIB(),
&rcDIB, pDoc->GetDocPalette());
}
CSize sizeTotal(1200,900);
SetScrollSizes(MM_TEXT, sizeTotal);
// 恢复正常光标
EndWaitCursor();
}
void CPlateRecoView::OnInitialUpdate()
{
CScrollView::OnInitialUpdate();
CSize sizeTotal;
// TODO: calculate the total size of this view
sizeTotal.cx =1200;
sizeTotal.cy =900;
SetScrollSizes(MM_TEXT, sizeTotal);
// 获取文档
CPlateRecoDoc* pDoc = GetDocument();
// 指向DIB的指针
LPSTR lpDIB;
// 锁定DIB
lpDIB = (LPSTR) ::GlobalLock((HGLOBAL) pDoc->GetHDIB());
// 保存原图像大小
m_iWidth = ::DIBWidth(lpDIB);
m_iHeight = ::DIBHeight(lpDIB);
/*
CScrollView::OnInitialUpdate();
CSize sizeTotal(1000,600);//::DIBWidth(lpDIB), ::DIBHeight(lpDIB));
SetScrollSizes(MM_TEXT, sizeTotal);
CMainFrame* pAppFrame = (CMainFrame*) AfxGetApp()->m_pMainWnd;
ASSERT_KINDOF(CMainFrame, pAppFrame);
CRect rc;
pAppFrame->GetClientRect(&rc);
if (rc.Width() >= sizeTotal.cx && rc.Height() >= sizeTotal.cy &&
(sizeTotal.cx>0 || sizeTotal.cy>0))
ResizeParentToFit(FALSE);
*/
}
/////////////////////////////////////////////////////////////////////////////
// CPlateRecoView printing
BOOL CPlateRecoView::OnPreparePrinting(CPrintInfo* pInfo)
{
// 设置总页数为一。
pInfo->SetMaxPage(1);
// default preparation
return DoPreparePrinting(pInfo);
}
void CPlateRecoView::OnBeginPrinting(CDC* /*pDC*/, CPrintInfo* /*pInfo*/)
{
// TODO: add extra initialization before printing
}
void CPlateRecoView::OnEndPrinting(CDC* /*pDC*/, CPrintInfo* /*pInfo*/)
{
// TODO: add cleanup after printing
}
/////////////////////////////////////////////////////////////////////////////
// CPlateRecoView diagnostics
#ifdef _DEBUG
void CPlateRecoView::AssertValid() const
{
CView::AssertValid();
}
void CPlateRecoView::Dump(CDumpContext& dc) const
{
CView::Dump(dc);
}
CPlateRecoDoc* CPlateRecoView::GetDocument() // non-debug version is inline
{
ASSERT(m_pDocument->IsKindOf(RUNTIME_CLASS(CPlateRecoDoc)));
return (CPlateRecoDoc*)m_pDocument;
}
#endif //_DEBUG
/////////////////////////////////////////////////////////////////////////////
// CPlateRecoView message handlers
LRESULT CPlateRecoView::OnDoRealize(WPARAM wParam, LPARAM)
{
ASSERT(wParam != NULL);
// 获取文档
CPlateRecoDoc* pDoc = GetDocument();
// 判断DIB是否为空
if (pDoc->GetHDIB() == NULL)
{
// 直接返回
return 0L;
}
// 获取Palette
CPalette* pPal = pDoc->GetDocPalette();
if (pPal != NULL)
{
// 获取MainFrame
CMainFrame* pAppFrame = (CMainFrame*) AfxGetApp()->m_pMainWnd;
ASSERT_KINDOF(CMainFrame, pAppFrame);
CClientDC appDC(pAppFrame);
// All views but one should be a background palette.
// wParam contains a handle to the active view, so the SelectPalette
// bForceBackground flag is FALSE only if wParam == m_hWnd (this view)
CPalette* oldPalette = appDC.SelectPalette(pPal, ((HWND)wParam) != m_hWnd);
if (oldPalette != NULL)
{
UINT nColorsChanged = appDC.RealizePalette();
if (nColorsChanged > 0)
pDoc->UpdateAllViews(NULL);
appDC.SelectPalette(oldPalette, TRUE);
}
else
{
TRACE0("\tCCh1_1View::OnPaletteChanged中调用SelectPalette()失败!\n");
}
}
return 0L;
}
/////////////////////////////////////////////////////////////////////////////
// CPlateRecoView message handlers
void CPlateRecoView::OnLPRplatelocation()
{
// TODO: Add your command handler code here
// 获取文档
CPlateRecoDoc* pDoc = GetDocument();
// 指向DIB的指针
LPSTR lpDIB;
// 指向DIB象素指针
LPSTR lpDIBBits;
// 锁定DIB
lpDIB = (LPSTR) ::GlobalLock((HGLOBAL) pDoc->GetHDIB());
// 判断是否是8-bpp位图(这里为了方便,只处理8-bpp位图的边缘检测,其它的可以类推)
if (::DIBNumColors(lpDIB) != 256)
{
// 提示用户
MessageBox("目前只支持256色位图的运算!", "系统提示" , MB_ICONINFORMATION | MB_OK);
// 解除锁定
::GlobalUnlock((HGLOBAL) pDoc->GetHDIB());
// 返回
return;
}
// 找到DIB图像象素起始位置
lpDIBBits = ::FindDIBBits(lpDIB);
// 指向缓存图像的指针
LPSTR lpDst1;
LPSTR lpDst2;
// 指向缓存DIB图像的指针
LPSTR lpNewDIBBits1;
HLOCAL hNewDIBBits1;
LPSTR lpNewDIBBits2;
HLOCAL hNewDIBBits2;
int *pPlateLine1,*pPlateLine2;
// 获取车牌位置信息
int *pPlatePosition;
//循环变量
long i;
long j;
for(i=0;i<40;i++)
m_iPlateLine[i]=0;
// 指向源图像象素的指针
unsigned char * lpSrc;
// 阈值
BYTE bThre;
// 各个灰度值的计数
LONG lCount[256];
int temp1,temp2,iOldLeixin1,iOldLeixin2,iNum1,iNum2,iGrayCore1,iGrayCore2,iMeanGray;
// 参数对话框
//CDlgBinary myDlgBinary;
// 暂时分配内存,以保存新图像
hNewDIBBits1 = LocalAlloc(LHND, m_iWidth * m_iHeight);
if (hNewDIBBits1 == NULL)
{
// 分配内存失败
return;
}
// 锁定内存
lpNewDIBBits1 = (char * )LocalLock(hNewDIBBits1);
// 暂时分配内存,以保存新图像
hNewDIBBits2 = LocalAlloc(LHND, m_iWidth * m_iHeight);
if (hNewDIBBits2 == NULL)
{
// 分配内存失败
return;
}
// 锁定内存
lpNewDIBBits2 = (char * )LocalLock(hNewDIBBits2);
// 拷贝源图像到缓存图像中
lpDst1 = (char *)lpNewDIBBits1;
memcpy(lpNewDIBBits1, lpDIBBits, m_iWidth * m_iHeight);
lpDst2 = (char *)lpNewDIBBits2;
memcpy(lpNewDIBBits2, lpDIBBits, m_iWidth * m_iHeight);
// 复制经过模板运算后的图像到源图像
// memcpy(lpDIBBits, lpNewDIBBits1, m_iWidth * m_iHeight);
// 更改光标形状
BeginWaitCursor();
////////////////////////////////////////////////////////
// 水平差分
if (DifferDIB(lpDIBBits, WIDTHBYTES(::DIBWidth(lpDIB) * 8), ::DIBHeight(lpDIB)))
{
// 设置脏标记
pDoc->SetModifiedFlag(TRUE);
// 更新视图
pDoc->UpdateAllViews(NULL);
}
else
{
// 提示用户
MessageBox("分配内存失败!", "系统提示" , MB_ICONINFORMATION | MB_OK);
}
////////////////////////////////////////////////////////
// 调用HprojectDIB()函数对DIB进行水平投影
if (pPlateLine1 = HDifferProjDIB4(lpDIBBits,::DIBWidth(lpDIB), ::DIBHeight(lpDIB)))
{
for(int i=0;i<40;i++)
{
m_iPlateLine[i]=*pPlateLine1;
pPlateLine1++;
}
// 设置脏标记
pDoc->SetModifiedFlag(TRUE);
// 更新视图
pDoc->UpdateAllViews(NULL);
}
else
{
// 提示用户
MessageBox("分配内存失败!", "系统提示" , MB_ICONINFORMATION | MB_OK);
}
////////////////////////////////////////////////////////
int iLineNumber=0;
for(iLineNumber=0;iLineNumber<40;iLineNumber++)
{
////////////////////////////////////////////////////////
// 复制原图象
memcpy(lpDIBBits, lpNewDIBBits1, m_iWidth * m_iHeight);
// 设置脏标记
pDoc->SetModifiedFlag(TRUE);
// 更新视图
pDoc->UpdateAllViews(NULL);
// AfxMessageBox("又一次");
////////////////////////////////////////////////////////
// 边缘检测
pPlateLine2 = &m_iPlateLine[iLineNumber];
// 调用SobelDIB()函数对DIB进行边缘检测
if (PlateDIB1(lpDIBBits,::DIBWidth(lpDIB), ::DIBHeight(lpDIB),pPlateLine2))
{
// 设置脏标记
pDoc->SetModifiedFlag(TRUE);
// 更新视图
pDoc->UpdateAllViews(NULL);
}
else
{
// 提示用户
MessageBox("分配内存失败!", "系统提示" , MB_ICONINFORMATION | MB_OK);
}
////////////////////////////////////////////////////////
// 二值化
// 重置计数为0
for (i = 0; i < 256; i ++)
{
// 清零
lCount[i] = 0;
}
// 图像每行的字节数
LONG lLineBytes;
// 计算图像每行的字节数
lLineBytes = WIDTHBYTES(m_iWidth * 8);
// 计算各个灰度值的计数
for (i = 0; i < m_iHeight; i ++)
{
for (j = 0; j < m_iWidth; j ++)
{
lpSrc = (unsigned char *)lpDIBBits + lLineBytes * i + j;
// 计数加1
lCount[*(lpSrc)]++;
}
}
// 计算平均灰度值
iMeanGray = 0;
for(i = 1; i < 255; i++)
{
iMeanGray += i * lCount[i];
}
iMeanGray = (int)iMeanGray / (m_iHeight * m_iWidth);
// 初始的类心,可任意设定
iGrayCore1 = (int)(iMeanGray/2);
iGrayCore2 = (int)(iMeanGray+(255-iMeanGray)/2);
do // K-均值聚类分析
{
iNum1 = 0;
iNum2 = 0;
temp1 = 0;
temp2 = 0;
iOldLeixin1 = iGrayCore1;
iOldLeixin2 = iGrayCore2;
for(i = 0; i < m_iHeight; i++)
{
for(j = 0; j < m_iWidth; j++)
{
lpSrc = (unsigned char *)lpDIBBits + lLineBytes * i + j;
if(abs(iGrayCore1-*lpSrc)<=abs(iGrayCore2-*lpSrc))
{
temp1 += *lpSrc;
iNum1++;
}
else
{
temp2 += *lpSrc;
iNum2++;
}
}
}
iGrayCore1 = (int)(temp1/iNum1);
iGrayCore2 = (int)(temp2/iNum2);
}while((iGrayCore1!=iOldLeixin1)||(iGrayCore2!=iOldLeixin2));
bThre = iGrayCore2+30;
// 删除对话框
// delete myDlgBinary;
// 更改光标形状
BeginWaitCursor();
// 调用ThresholdTrans()函数进行阈值变换
ThresholdTrans(lpDIBBits, ::DIBWidth(lpDIB), ::DIBHeight(lpDIB), bThre);
// 设置脏标记
pDoc->SetModifiedFlag(TRUE);
// 更新视图
pDoc->UpdateAllViews(NULL);
///////////////////////////////////////////////////////
// 提取车牌
// 缩放后图像的宽度和高度
LONG lNewWidth = 140;
LONG lNewHeight = 40;
// 缩放后图像的宽度(lNewWidth',必须是4的倍数)
LONG lNewLineBytes;
// 创建新DIB
HDIB hNewDIB = NULL;
// 指向缩放图像的指针
LPSTR lpNewDIB ;
// 指向BITMAPINFO结构的指针(Win3.0)
LPBITMAPINFOHEADER lpbmi;
// 指向BITMAPCOREINFO结构的指针
LPBITMAPCOREHEADER lpbmc;
// 计算新图像每行的字节数
lNewLineBytes = WIDTHBYTES(lNewWidth * 8);
// 更改光标形状
BeginWaitCursor();
// 找到DIB图像象素起始位置
lpDIBBits = ::FindDIBBits(lpDIB);
pPlatePosition = RowscanDIB3 (lpDIBBits,lpNewDIBBits1,::DIBWidth(lpDIB), ::DIBHeight(lpDIB), pPlateLine2);
for(i=0;i<5;i++)
{
m_iPlatePosition[i] = *pPlatePosition;
pPlatePosition++;
}
if(m_iPlatePosition[0]==1)
{
// AfxMessageBox("找到了!");
// 显示车牌位置信息
// CDlgShowPlate dlgShowPlate;
// dlgShowPlate.m_iTop = ::DIBHeight(lpDIB) - m_iPlatePosition[0];
// dlgShowPlate.m_iLow = ::DIBHeight(lpDIB) - m_iPlatePosition[1];
// dlgShowPlate.m_iLeft = m_iPlatePosition[2];
// dlgShowPlate.m_iRight = m_iPlatePosition[3];
// dlgShowPlate.DoModal();
// 分配内存,以保存新DIB
hNewDIB = (HDIB) ::GlobalAlloc(GHND, lNewLineBytes * lNewHeight + *(LPDWORD)lpDIB + ::PaletteSize(lpDIB));
// 判断是否内存分配失败
if (hNewDIB != NULL)
{
lpNewDIB = (char * )::GlobalLock((HGLOBAL) hNewDIB);
// 复制DIB信息头、调色板和车牌图像
memcpy(lpNewDIB, lpDIB, *(LPDWORD)lpDIB + ::PaletteSize(lpDIB) + lNewLineBytes * lNewHeight);
// 获取指针
lpbmi = (LPBITMAPINFOHEADER)lpNewDIB;
lpbmc = (LPBITMAPCOREHEADER)lpNewDIB;
// 更新DIB中图像的高度和宽度
if (IS_WIN30_DIB(lpNewDIB))
{
// 对于Windows 3.0 DIB
lpbmi->biWidth = lNewWidth;
lpbmi->biHeight = lNewHeight;
}
else
{
// 对于其它格式的DIB
lpbmc->bcWidth = (unsigned short) lNewWidth;
lpbmc->bcHeight = (unsigned short) lNewHeight;
}
// TRACE("\n*******%d*******\n",m_iPlatePosition[0]);
// 替换DIB,同时释放旧DIB对象
pDoc->ReplaceHDIB(hNewDIB);
// 更新DIB大小和调色板
pDoc->InitDIBData();
// 设置脏标记
pDoc->SetModifiedFlag(TRUE);
// 更新视图
pDoc->UpdateAllViews(NULL);
}
}
else
{
// 提示用户
// AfxMessageBox("这次没找到!");
}
if( (m_iPlateLine[iLineNumber+2]>=0)||((m_iPlatePosition[0]==1)))
break;
}
// 释放内存
LocalUnlock(hNewDIBBits1);
LocalFree(hNewDIBBits1);
LocalUnlock(hNewDIBBits2);
LocalFree(hNewDIBBits2);
// 解除锁定
::GlobalUnlock((HGLOBAL) pDoc->GetHDIB());
// 恢复光标
EndWaitCursor();
}
void CPlateRecoView::OnLPRplate2binarycolor()
{
// TODO: Add your command handler code here
// 二值化
// 获取文档
CPlateRecoDoc* pDoc = GetDocument();
// 指向DIB的指针
LPSTR lpDIB;
// 指向DIB象素指针
LPSTR lpDIBBits;
// 参数对话框
//CDlgBinary myDlgBinary;
// 阈值
BYTE bThre;
// 锁定DIB
lpDIB = (LPSTR) ::GlobalLock((HGLOBAL) pDoc->GetHDIB());
// 找到DIB图像象素起始位置
lpDIBBits = ::FindDIBBits(lpDIB);
// 判断是否是8-bpp位图(这里为了方便,只处理8-bpp位图的阈值变换,其它的可以类推)
if (::DIBNumColors(lpDIB) != 256)
{
// 提示用户
MessageBox("目前只支持256色位图的阈值变换!", "系统提示" ,
MB_ICONINFORMATION | MB_OK);
// 解除锁定
::GlobalUnlock((HGLOBAL) pDoc->GetHDIB());
// 返回
return;
}
// 各个灰度值的计数
LONG lCount[256];
int temp1,temp2,iOldLeixin1,iOldLeixin2,iNum1,iNum2,iGrayCore1,iGrayCore2,iMeanGray;
// 指向源图像象素的指针
unsigned char * lpSrc;
// 循环变量
LONG i;
LONG j;
// 重置计数为0
for (i = 0; i < 256; i ++)
{
// 清零
lCount[i] = 0;
}
// 车牌图像的长、宽
int iWidth;
int iHeight;
iWidth = ::DIBWidth(lpDIB);
iHeight = ::DIBHeight(lpDIB);
// 图像每行的字节数
LONG lLineBytes;
// 计算图像每行的字节数
lLineBytes = WIDTHBYTES(iWidth * 8);
// 计算各个灰度值的计数
for (i = 0; i < iHeight; i ++)
{
for (j = 0; j < iWidth; j ++)
{
lpSrc = (unsigned char *)lpDIBBits + lLineBytes * i + j;
// 计数加1
lCount[*(lpSrc)]++;
}
}
// 计算平均灰度值
iMeanGray = 0;
for(i = 1; i < 255; i++)
{
iMeanGray += i * lCount[i];
}
iMeanGray = (int)iMeanGray / (iHeight * iWidth);
// 初始的类心,可任意设定
iGrayCore1 = (int)(iMeanGray/2);
iGrayCore2 = (int)(iMeanGray+(255-iMeanGray)/2);
do // K-均值聚类分析
{
iNum1 = 0;
iNum2 = 0;
temp1 = 0;
temp2 = 0;
iOldLeixin1 = iGrayCore1;
iOldLeixin2 = iGrayCore2;
for(i = 0; i < iHeight; i++)
{
for(j = 0; j < iWidth; j++)
{
lpSrc = (unsigned char *)lpDIBBits + lLineBytes * i + j;
if(abs(iGrayCore1-*lpSrc)<=abs(iGrayCore2-*lpSrc))
{
temp1 += *lpSrc;
iNum1++;
}
else
{
temp2 += *lpSrc;
iNum2++;
}
}
}
iGrayCore1 = (int)(temp1/iNum1);
iGrayCore2 = (int)(temp2/iNum2);
}while((iGrayCore1!=iOldLeixin1)||(iGrayCore2!=iOldLeixin2));
// 初始化变量值
//myDlgBinary.m_bThre = iGrayCore2-20;
/* 显示对话框,提示用户设定阈值
if (myDlgBinary.DoModal() != IDOK)
{
// 返回
return;
}*/
// 获取用户设定的阈值
bThre = 112; //myDlgBinary.m_bThre;
// 删除对话框
//delete myDlgBinary;
// 更改光标形状
BeginWaitCursor();
// 调用ThresholdTrans()函数进行阈值变换
ThresholdTrans(lpDIBBits, ::DIBWidth(lpDIB), ::DIBHeight(lpDIB), bThre);
// 设置脏标记
pDoc->SetModifiedFlag(TRUE);
// 更新视图
pDoc->UpdateAllViews(NULL);
// 解除锁定
::GlobalUnlock((HGLOBAL) pDoc->GetHDIB());
// 恢复光标
EndWaitCursor();
}
void CPlateRecoView::OnLPRplatenorm()
{
// TODO: Add your command handler code here
// 字符归一化
// 获取文档
CPlateRecoDoc* pDoc = GetDocument();
// 指向DIB的指针
LPSTR lpDIB;
// 指向DIB象素指针
LPSTR lpDIBBits;
LPSTR lpNewDIBBits2;
// 字符归一化后的新的高度与宽度
int iNewWidth;
int iOldHeight;
int iNewHeight;
int* pNewHeight;
int iTemp;
// 锁定DIB
lpDIB = (LPSTR) ::GlobalLock((HGLOBAL) pDoc->GetHDIB());
iNewWidth = ::DIBWidth(lpDIB);
iOldHeight = ::DIBHeight(lpDIB);
// 找到DIB图像象素起始位置
lpDIBBits = ::FindDIBBits(lpDIB);
// 判断是否是8-bpp位图(这里为了方便,只处理8-bpp位图的阈值变换,其它的可以类推)
if (::DIBNumColors(lpDIB) != 256)
{
// 提示用户
MessageBox("目前只支持256色位图的阈值变换!", "系统提示" ,
MB_ICONINFORMATION | MB_OK);
// 解除锁定
::GlobalUnlock((HGLOBAL) pDoc->GetHDIB());
// 返回
return;
}
// 更改光标形状
BeginWaitCursor();
pNewHeight = RowscanDIB4(lpDIBBits,::DIBWidth(lpDIB), ::DIBHeight(lpDIB));
iTemp = *pNewHeight;
pNewHeight++;
iNewHeight = *pNewHeight;
iNewHeight = abs(iNewHeight - iTemp);
// 缩放后图像的宽度(lNewWidth',必须是4的倍数)
LONG lNewLineBytes;
// 创建新DIB
HDIB hNewDIB = NULL;
// 指向缩放图像的指针
LPSTR lpNewDIB ;
// 指向缩放图像的指针
LPSTR lpNewDIB2;
// 指向BITMAPINFO结构的指针(Win3.0)
LPBITMAPINFOHEADER lpbmi;
// 指向BITMAPCOREINFO结构的指针
LPBITMAPCOREHEADER lpbmc;
// 计算新图像每行的字节数
lNewLineBytes = WIDTHBYTES(iNewWidth * 8);
// 分配内存,以保存新DIB
hNewDIB = (HDIB) ::GlobalAlloc(GHND, lNewLineBytes * iNewHeight + *(LPDWORD)lpDIB + ::PaletteSize(lpDIB));
// 判断是否内存分配失败
if (hNewDIB != NULL)
{
lpNewDIB = (char * )::GlobalLock((HGLOBAL) hNewDIB);
// 复制DIB信息头、调色板和车牌图像
memcpy(lpNewDIB, lpDIB, *(LPDWORD)lpDIB + ::PaletteSize(lpDIB) + lNewLineBytes * iNewHeight);
// 获取指针
lpbmi = (LPBITMAPINFOHEADER)lpNewDIB;
lpbmc = (LPBITMAPCOREHEADER)lpNewDIB;
// 更新DIB中图像的高度和宽度
if (IS_WIN30_DIB(lpNewDIB))
{
// 对于Windows 3.0 DIB
lpbmi->biWidth = iNewWidth;
lpbmi->biHeight = iNewHeight;
}
else
{
// 对于其它格式的DIB
lpbmc->bcWidth = (unsigned short) iNewWidth;
lpbmc->bcHeight = (unsigned short) iNewHeight;
}
// TRACE("\n*******%d*******\n",m_iPlatePosition[0]);
// 替换DIB,同时释放旧DIB对象
pDoc->ReplaceHDIB(hNewDIB);
// 更新DIB大小和调色板
pDoc->InitDIBData();
// 设置脏标记
pDoc->SetModifiedFlag(TRUE);
// 更新视图
// pDoc->UpdateAllViews(NULL);
}
LocalUnlock(lpDIB);
LocalFree(lpDIB);
// 创建新DIB
HDIB hNewDIB2 = NULL;
// 更改光标形状
BeginWaitCursor();
float fXZoomRatio = 1.0;
float fYZoomRatio;
fYZoomRatio = (float)iOldHeight / (float)::DIBHeight(lpNewDIB);
// 调用ZoomDIB()函数转置DIB
hNewDIB2 = (HDIB) ZoomDIB(lpNewDIB, fXZoomRatio, fYZoomRatio);
// 判断缩放是否成功
if (hNewDIB2 != NULL)
{
// 替换DIB,同时释放旧DIB对象
pDoc->ReplaceHDIB(hNewDIB2);
// 更新DIB大小和调色板
pDoc->InitDIBData();
// 设置脏标记
pDoc->SetModifiedFlag(TRUE);
lpNewDIB2 = (char * )::GlobalLock((HGLOBAL) hNewDIB2);
// 重新设置滚动视图大小
SetScrollSizes(MM_TEXT, pDoc->GetDocSize());
// 更新视图
// pDoc->UpdateAllViews(NULL);
}
else
{
// 提示用户
MessageBox("分配内存失败!", "系统提示" , MB_ICONINFORMATION | MB_OK);
}
LocalUnlock(lpNewDIB);
LocalFree(lpNewDIB);
// 找到DIB图像象素起始位置
lpNewDIBBits2 = ::FindDIBBits(lpNewDIB2);
// 调用ThresholdTrans()函数进行阈值变换
if(CharacterUnit(lpNewDIBBits2, ::DIBWidth(lpNewDIB2), ::DIBHeight(lpNewDIB2)) != TRUE)
{
return;
}
// 设置脏标记
pDoc->SetModifiedFlag(TRUE);
// 更新视图
pDoc->UpdateAllViews(NULL);
// 解除锁定
::GlobalUnlock((HGLOBAL) pDoc->GetHDIB());
// 恢复光标
EndWaitCursor();
}
void CPlateRecoView::OnLPRplatecharthinning()
{
// TODO: Add your command handler code here
// 获取文档
CPlateRecoDoc* pDoc = GetDocument();
// 指向DIB的指针
LPSTR lpDIB;
// 指向DIB象素指针
LPSTR lpDIBBits;
// 线性变换的斜率
FLOAT fA;
// 线性变换的截距
FLOAT fB;
// 反色操作的线性变换的方程是-x + 255
fA = -1.0;
fB = 255.0;
// 锁定DIB
lpDIB = (LPSTR) ::GlobalLock((HGLOBAL) pDoc->GetHDIB());
// 找到DIB图像象素起始位置
lpDIBBits = ::FindDIBBits(lpDIB);
// 判断是否是8-bpp位图(这里为了方便,只处理8-bpp位图的反色,其它的可以类推)
if (::DIBNumColors(lpDIB) != 256)
{
// 提示用户
MessageBox("目前只支持256色位图的反色!", "系统提示" , MB_ICONINFORMATION | MB_OK);
// 解除锁定
::GlobalUnlock((HGLOBAL) pDoc->GetHDIB());
// 返回
return;
}
// 更改光标形状
BeginWaitCursor();
// 调用LinerTrans()函数反色
LinerTrans(lpDIBBits, ::DIBWidth(lpDIB), ::DIBHeight(lpDIB), fA, fB);
// 设置脏标记
pDoc->SetModifiedFlag(TRUE);
// 更新视图
// pDoc->UpdateAllViews(NULL);
// 解除锁定
// ::GlobalUnlock((HGLOBAL) pDoc->GetHDIB());
// 恢复光标
// EndWaitCursor();
// 找到DIB图像象素起始位置
// lpDIBBits = ::FindDIBBits(lpDIB);
// 调用ThiningDIB()函数对DIB进行闭运算
if (ThiningDIB(lpDIBBits, WIDTHBYTES(::DIBWidth(lpDIB) * 8), ::DIBHeight(lpDIB)))
{
// 设置脏标记
pDoc->SetModifiedFlag(TRUE);
// 更新视图
pDoc->UpdateAllViews(NULL);
}
else
{
// 提示用户
MessageBox("分配内存失败或者图像中含有0和255之外的像素值!", "系统提示" , MB_ICONINFORMATION | MB_OK);
}
// 解除锁定
::GlobalUnlock((HGLOBAL) pDoc->GetHDIB());
// 恢复光标
EndWaitCursor();
}
void CPlateRecoView::OnLPRfeature16seg()
{
// TODO: Add your command handler code here
// 基于13段投影法的特征提取
// 获取文档
CPlateRecoDoc* pDoc = GetDocument();
// 指向DIB的指针
LPSTR lpDIB;
// 指向DIB象素指针
LPSTR lpDIBBits;
// 锁定DIB
lpDIB = (LPSTR) ::GlobalLock((HGLOBAL) pDoc->GetHDIB());
// 找到DIB图像象素起始位置
lpDIBBits = ::FindDIBBits(lpDIB);
// 用于传递13段投影编码表
float* pCode16Section;
float fCode16Sect[6][16];
FILE *fpPlateCharData;
char *pPlateCharDataFileName = "识别数据_16段映射.txt ";
LONG i,j;
// 判断是否是8-bpp位图(这里为了方便,只处理8-bpp位图的沃尔什-哈达玛变换,其它的可以类推)
if (::DIBNumColors(lpDIB) != 256)
{
// 提示用户
MessageBox("目前只支持256色位图的沃尔什-哈达玛变换!", "系统提示" ,
MB_ICONINFORMATION | MB_OK);
// 解除锁定
::GlobalUnlock((HGLOBAL) pDoc->GetHDIB());
// 返回
return;
}
pCode16Section = CharExtract16Sect(lpDIBBits, ::DIBWidth(lpDIB), ::DIBHeight(lpDIB));
// TRACE("\n");
for(i=0;i<6;i++)
{
for(j=0;j<16;j++)
{
fCode16Sect[i][j] = *pCode16Section;
m_fCode16Sect[i][j] = fCode16Sect[i][j];
pCode16Section++;
}
// TRACE("\t%f",m_fCode13Sect[i]);
}
if((fpPlateCharData = fopen(pPlateCharDataFileName,"w+"))==NULL)
{
AfxMessageBox(" 无法正确创建文件!\n请检查您代码中的文件名!");
return;
}
int q1=0;
// 将提取出的各字符的特征量存成文件
// 将指针移到文件头
fseek(fpPlateCharData,0l,SEEK_SET);
for(i = 0; i < 6; i++)
{
for(j = 0; j < 16; j++)
{
// fprintf(fpHidWeight,"%f",fHidWeight[i][j]);
fprintf(fpPlateCharData,"%10f",fCode16Sect[i][j]);
}
fprintf(fpPlateCharData,"\n","");
if(i==5)
fprintf(fpPlateCharData,"\n","");
}
fclose(fpPlateCharData);
// TRACE("\n");
// 解除锁定
::GlobalUnlock((HGLOBAL) pDoc->GetHDIB());
// 更改光标形状
BeginWaitCursor();
}
void CPlateRecoView::OnLPRplatereco()
{
OnLPRfeature16seg();
CPlateRecoDoc* pDoc = GetDocument();
float* pReco16Section;
// CString strRecoChars,strTemp;
CDlgRecoResult myDlgRecoResult;
pReco16Section = &m_fCode16Sect[0][0];
// 字符识别
m_cRecoChar[0] = BPReco16SectionLetter(pReco16Section);
pReco16Section = &m_fCode16Sect[1][0];
if(m_iPlateType==0)
{
m_cRecoChar[1] = BPReco16SectionLetter(pReco16Section);
}
else
{
m_cRecoChar[1] = BPReco16SectionNumber(pReco16Section);
}
// strTemp.Format("%c",m_cRecoChar[0]);
pReco16Section = &m_fCode16Sect[2][0];
m_cRecoChar[2] = BPReco16SectionNumber(pReco16Section);
pReco16Section = &m_fCode16Sect[3][0];
m_cRecoChar[3] = BPReco16SectionNumber(pReco16Section);
pReco16Section = &m_fCode16Sect[4][0];
m_cRecoChar[4] = BPReco16SectionNumber(pReco16Section);
pReco16Section = &m_fCode16Sect[5][0];
m_cRecoChar[5] = BPReco16SectionNumber(pReco16Section);
myDlgRecoResult.m_cRecoChar[0]= m_cRecoChar[0];
myDlgRecoResult.m_cRecoChar[1]= m_cRecoChar[1];
myDlgRecoResult.m_cRecoChar[2]= m_cRecoChar[2];
myDlgRecoResult.m_cRecoChar[3]= m_cRecoChar[3];
myDlgRecoResult.m_cRecoChar[4]= m_cRecoChar[4];
myDlgRecoResult.m_cRecoChar[5]= m_cRecoChar[5];
myDlgRecoResult.DoModal();
delete myDlgRecoResult;
return;
}
void CPlateRecoView::OnLPRplatepreprocessall()
{
OnLPRplatelocation();
OnLPRplate2binarycolor();
OnLPRplatenorm();
OnLPRplatecharthinning();
}