📄 platerecoview.cpp
字号:
// 设置脏标记
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();
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -