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

📄 platerecoview.cpp

📁 用Visual C++编写的车牌定位与识别系统
💻 CPP
📖 第 1 页 / 共 2 页
字号:

				// 设置脏标记
				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 + -