www.pudn.com > numberdetect.rar > mydiblib.h


#include "dibapi.h" 
#include  
#include  
#include  
using namespace std; 
 
typedef deque CRectLink; 
typedef deque  HDIBLink; 
 
//声明一些必要的全局变量 
int w_sample=8; 
int h_sample=16; 
bool fileloaded; 
bool gyhinfoinput; 
bool gyhfinished; 
int digicount; 
int m_lianXuShu; 
CRectLink m_charRectCopy; 
CRectLink m_charRect; 
HDIBLink  m_dibRect; 
HDIBLink  m_dibRectCopy; 
HDIB m_hDIB; 
CString strPathName; 
CString strPathNameSave; 
 
/********************************function declaration*************************************/ 
 
//清楚屏幕 
void ClearAll(CDC* pDC); 
//在屏幕上显示位图 
void DisplayDIB(CDC* pDC,HDIB hDIB); 
//对分割后的位图进行尺寸标准归一化 
void StdDIBbyRect(HDIB hDIB, int tarWidth, int tarHeight); 
//整体斜率调整 
void SlopeAdjust(HDIB hDIB); 
//去除离散噪声点 
void RemoveScatterNoise(HDIB hDIB); 
//梯度锐化 
void GradientSharp(HDIB hDIB); 
//画框 
void DrawFrame(CDC* pDC,HDIB hDIB, CRectLink charRect,unsigned int linewidth,COLORREF color); 
//将灰度图二值化 
void ConvertGrayToWhiteBlack(HDIB hDIB); 
//将256色位图转为灰度图 
void Convert256toGray(HDIB hDIB); 
//细化 
void Thinning(HDIB hDIB); 
//对位图进行分割.返回一个存储着每块分割区域的链表 
CRectLink CharSegment(HANDLE hDIB); 
//紧缩、重排调整 
HDIB AutoAlign(HDIB hDIB); 
//判断是否是离散噪声点 
bool DeleteScaterJudge(LPSTR lpDIBBits,WORD lLineBytes, LPBYTE lplab, int lWidth, int lHeight, int x, int y, CPoint lab[], int lianXuShu); 
//对图像进行模板操作 
HDIB Template(HDIB hDIB,double * tem ,int tem_w,int tem_h,double xishu); 
//对图像进行中值滤波 
HDIB MidFilter(HDIB hDIB,int tem_w,int tem_h); 
//对图像进行直方图均衡 
void Equalize(HDIB hDIB); 
/***********************************implementation*************************************/ 
 
/*********************************** ************************************ 
函数名称:DisplayDIB 
参数: 
	CDC* pDC			-指向当前设备上下文(Divice Context)的指针 
	HDIB hDIB			-要显示的位图的句柄 
**********************************************************************/ 
 
void DisplayDIB(CDC* pDC,HDIB hDIB) 
{ 
	BYTE* lpDIB=(BYTE*)::GlobalLock((HGLOBAL)hDIB); 
	// 获取DIB宽度和高度 
	int cxDIB =  ::DIBWidth((char*) lpDIB); 
	int cyDIB =  ::DIBHeight((char*)lpDIB); 
	CRect rcDIB,rcDest; 
	rcDIB.top = rcDIB.left = 0; 
	rcDIB.right = cxDIB; 
	rcDIB.bottom = cyDIB; 
	//设置目标客户区输出大小尺寸 
	rcDest = rcDIB; 
	//CDC* pDC=GetDC(); 
	ClearAll(pDC); 
	//在客户区显示图像 
	//for(int ii=0;ii<10;ii++) 
		::PaintDIB(pDC->m_hDC,rcDest,hDIB,rcDIB,NULL); 
	::GlobalUnlock((HGLOBAL)hDIB); 
} 
 
void ClearAll(CDC *pDC) 
{ 
	CRect rect; 
	//GetClientRect(&rect); 
	rect.left =0;rect.top =0;rect.right =2000;rect.bottom =1000; 
	CPen pen; 
	pen.CreatePen (PS_SOLID,1,RGB(255,255,255)); 
	pDC->SelectObject (&pen); 
	pDC->Rectangle (&rect); 
	::DeleteObject (pen); 
} 
/******************************************* 
* 
*  函数名称: 
*  AutoAlign() 
* 
*  参数: 
*    HDIB   hDIB        -原图像的句柄 
* 
*  返回值    
*    HDIB               -紧缩排列后的新图像的句柄 
* 
*  功能: 
*     将经过了标准化处理的字符进行规整的排列,以方便下一步的处理 
* 
*  说明: 
*     紧缩排列的操作必须在标准化操作之后进行 
* 
********************************************************/ 
 
 
HDIB AutoAlign(HDIB hDIB) 
{    
	 
	//指向图像的指针 
 	BYTE* lpDIB=(BYTE*)::GlobalLock ((HGLOBAL)hDIB); 
 
	//指向象素起始位置的指针 
	BYTE* lpDIBBits=(BYTE*)::FindDIBBits ((char*)lpDIB); 
 
	//指向象素的指针 
	BYTE* lpSrc; 
 
	//获取图像的宽度 
	LONG lWidth=::DIBWidth ((char*)lpDIB); 
 
	//获取图像的高度 
	LONG lHeight=::DIBHeight ((char*)lpDIB); 
 
	//获取标准化的宽度 
	int w=m_charRect.front ().Width() ; 
 
	//获取标准化的高度 
	int h=m_charRect.front ().Height() ; 
 
	//建立一个新的图像正好能够将标准化的字符并排放置 
	HDIB hNewDIB=::NewDIB (digicount*w,h,8); 
 
	//指向新的图像的指针 
	BYTE* lpNewDIB=(BYTE*) ::GlobalLock((HGLOBAL)hNewDIB); 
	 
	//指向象素起始位置的指针 
	BYTE* lpNewDIBBits=(BYTE*)::FindDIBBits((char*)lpNewDIB); 
 
	//指向象素的指针 
	BYTE* lpDst=lpNewDIBBits; 
 
	//计算原图像每行的字节数 
	LONG lLineBytes=(lWidth+3)/4*4; 
 
	//计算新图像每行的字节数 
	LONG lLineBytesnew =(digicount*w+3)/4*4; 
 
	//将新的图像初始化为白色 
	memset(lpDst,(BYTE)255,lLineBytesnew * h); 
 
	//映射操作的坐标变量 
	int i_src,j_src; 
 
	//循环变量 
	int i,j; 
 
	//统计字符个数的变量 
	int counts=0; 
 
	//存放位置信息的结构体 
	CRect rect,rectnew; 
 
	//清空一个新的链表来存放新的字符位置信息 
	m_charRectCopy.clear (); 
 
	//从头至尾逐个扫描原链表的各个结点 
	while(!m_charRect.empty() ) 
	{    
		//从表头上得到一个矩形框 
		rect=m_charRect.front (); 
 
		//将这个矩形框从链表上删除 
		m_charRect.pop_front (); 
 
		//计算新的矩形框的位置信息 
 
		//左边界 
		rectnew.left =counts*w; 
 
		//右边界 
		rectnew.right =(counts+1)*w; 
 
		//上边界 
		rectnew.top =0; 
 
		//下边界 
		rectnew.bottom =h; 
 
		//将获得的新的矩形框插入到新的链表中 
		m_charRectCopy.push_back (rectnew); 
 
		//将原矩形框内的象素映射到新的矩形框中 
		for(i=0;i0) 
                    { 
                        if(!cond) 
                            continue; 
                        g[kk] = 0; 
                        shori = 1; 
                        continue; 
                    } 
 
                    if(n[6]==1 && n48==0 && n123>0) 
                    { 
                        if(!cond) 
                            continue; 
                        g[kk] = 0; 
                        shori = 1; 
                        continue; 
                    } 
 
                    if(n[8]==1 && n26==0 && n345>0) 
                    { 
                        if(!cond) 
                            continue; 
                        g[kk] = 0; 
                        shori = 1; 
                        continue; 
                    } 
 
                    if(n[4]==1 && n26==0 && n781>0) 
                    { 
                        if(!cond) 
                            continue; 
                        g[kk] = 0; 
                        shori = 1; 
                        continue; 
                    } 
 
                    if(n[5]==1 && n46==0) 
                    { 
                        if(!cond) 
                            continue; 
                        g[kk] = 0; 
                        shori = 1; 
                        continue; 
                    } 
 
                    if(n[7]==1 && n68==0) 
                    { 
                        if(!cond) 
                            continue; 
                        g[kk] = 0; 
                        shori = 1; 
                        continue; 
                    } 
 
                    if(n[1]==1 && n82==0) 
                    { 
                        if(!cond) 
                            continue; 
                        g[kk] = 0; 
                        shori = 1; 
                        continue; 
                    } 
 
                    if(n[3]==1 && n24==0) 
                    { 
                        if(!cond) 
                            continue; 
                        g[kk] = 0; 
                        shori = 1; 
                        continue; 
                    } 
 
                    cond = 1; 
                    if(!cond) 
                        continue; 
                    g[kk] = 0; 
                    shori = 1; 
                } 
            } 
 
            for(i=0; i=0;i--) 
    { 
 
		//列 
		for (j=0;j=rect.top  ;i--) 
		{ 
			//列 
			for(j=rect.left ;jbmiColors[i].rgbRed + 
 
					     0.587 * lpbmi->bmiColors[i].rgbGreen + 
 
				         0.114 * lpbmi->bmiColors[i].rgbBlue + 0.5);			 
		// 更新DIB调色板红色分量 
		lpbmi->bmiColors[i].rgbRed = i;	 
		 
		// 更新DIB调色板绿色分量 
		lpbmi->bmiColors[i].rgbGreen = i;	 
		 
		// 更新DIB调色板蓝色分量 
		lpbmi->bmiColors[i].rgbBlue = i; 
			 
		// 更新DIB调色板保留位 
		lpbmi->bmiColors[i].rgbReserved = 0; 
 
	} 
	// 找到DIB图像象素起始位置 
	lpDIBBits = ::FindDIBBits(lpDIB); 
		 
	// 获取图像宽度 
	lWidth = ::DIBWidth(lpDIB);	 
 
	// 获取图像高度 
	lHeight = ::DIBHeight(lpDIB);	 
 
	// 计算图像每行的字节数 
	lLineBytes = WIDTHBYTES(lWidth * 8);	 
 
// 更换每个象素的颜色索引(即按照灰度映射表换成灰度值) 
 
//逐行扫描 
for(i = 0; i < lHeight; i++) 
{ 
 
  //逐列扫描 
for(j = 0; j < lWidth; j++) 
{ 
	// 指向DIB第i行,第j个象素的指针 
	lpSrc = (unsigned char*)lpDIBBits + lLineBytes * (lHeight - 1 - i) + j; 
			 
	// 变换 
	*lpSrc = bMap[*lpSrc]; 
} 
} 
 
//解除锁定 
::GlobalUnlock ((HGLOBAL)hDIB); 
} 
 
/****************************************************************** 
* 
* 函数名称ConvertGrayToWhiteBlack() 
* 
* 参数 :HDIB hDIB     -原图的句柄 
* 
* 返回值:无 
* 
* 功能: ConvertGrayToWhiteBlack函数采用硬阈值的方法,实现将图像二值化的功能。 
*  
* 说明: 
要求待处理的图片为256色 
************************************************************************/ 
 
void ConvertGrayToWhiteBlack(HDIB hDIB) 
{ 
	// 指向DIB的指针 
	LPSTR	lpDIB; 
	 
	// 由DIB句柄得到DIB指针并锁定DIB 
	lpDIB = (LPSTR) ::GlobalLock((HGLOBAL)hDIB); 
	 
	// 指向DIB象素数据区的指针 
	LPSTR   lpDIBBits; 
	 
	// 指向DIB象素的指针 
	BYTE *	lpSrc;	 
 
	// 图像宽度 
	LONG	lWidth;	 
 
	// 图像高度 
	LONG	lHeight;	 
	// 图像每行的字节数 
	LONG	lLineBytes;	 
 
	// 找到DIB图像象素起始位置 
	lpDIBBits = ::FindDIBBits(lpDIB);	 
	 
	// 获取图像宽度 
	lWidth = ::DIBWidth(lpDIB);	 
 
	// 获取图像高度 
	lHeight = ::DIBHeight(lpDIB);	 
 
	// 计算图像每行的字节数 
	lLineBytes = WIDTHBYTES(lWidth * 8);	 
 
	// 更换每个象素的颜色索引(即按照灰度映射表换成灰度值) 
	int i,j; 
 
    //逐行扫描 
	for(i = 0; i < lHeight; i++) 
 { 
 
   //逐列扫描 
	for(j = 0; j < lWidth; j++) 
	{ 
 
	// 指向DIB第i行,第j个象素的指针 
	lpSrc = (unsigned char*)lpDIBBits + lLineBytes * i + j; 
 
	// 二值化处理 
 
   //大于220,设置为255,即白点 
	if(*lpSrc>220) *lpSrc=255; 
 
  //否则设置为0,即黑点 
	else *lpSrc=0; 
 
	} 
 
} 
	 
 //解除锁定 
::GlobalUnlock((HGLOBAL)hDIB); 
} 
 
/***************************************************************** 
* 
*  函数名称  
*       DeleteScaterJudge() 
* 
*  参数: 
*     LPSTR   lpDIBBits      -指向象素起始位置的指针 
*	  WORD    lLineBytes     -图像每行的字节数 
*     LPBYTE  lplab          -标志位数组 
*     int     lWidth         -图像的宽度 
*	  int     lHeight        -图像的高度 
*     int     x              -当前点的横坐标 
*	  int     y              -当前点的纵坐标  
*     CPoint  lab[]          -存放议考察过的连续点坐标 
*     int     lianXuShu      -离散点的判定长度 
* 
*  返回值: 
*     Bool                   -是离散点返回false 不是离散点返回true 
*	  
*  功能: 
*     利用递归算法统计连续点的个数,通过阈值来判定是否为离散点 
* 
*  说明: 
*     只能对2值图像进行处理 
******************************************************************/      
 
 
bool DeleteScaterJudge(LPSTR lpDIBBits, WORD lLineBytes, LPBYTE lplab, int lWidth, int lHeight, int x, int y, CPoint lab[], int lianXuShu) 
{ 
	 
	//如果连续长度满足要求,说明不是离散点,返回 
	if(m_lianXuShu>=lianXuShu) 
		return TRUE; 
 
	//长度加一 
	m_lianXuShu++; 
 
	//设定访问标志 
	lplab[lWidth * y +x] = true; 
	 
	//保存访问点坐标 
	lab[m_lianXuShu-1].x = x; 
	lab[m_lianXuShu-1].y = y; 
 
	//象素的灰度值 
	int gray; 
   
	//指向象素的指针 
	LPSTR lpSrc; 
 
	//长度判定 
    //如果连续长度满足要求,说明不是离散点,返回 
	if(m_lianXuShu>=lianXuShu) 
		return TRUE; 
	 
	//下面进入递归 
	else 
	{	 
		//考察上下左右以及左上、右上、左下、右下八个方向 
		//如果是黑色点,则调用函数自身进行递归 
 
		//考察下面点 
		 
		lpSrc=(char*)lpDIBBits + lLineBytes * (y-1) + x; 
 
		//传递灰度值 
		gray=*lpSrc; 
 
		//如果点在图像内、颜色为黑色并且没有被访问过 
		if(y-1 >=0 && gray == 0 && lplab[(y-1)*lWidth+x] == false) 
 
		//进行递归处理		 
		DeleteScaterJudge(lpDIBBits,lLineBytes,lplab,lWidth,lHeight,x,y-1,lab,lianXuShu); 
 
		//判断长度 
		//如果连续长度满足要求,说明不是离散点,返回 
		if(m_lianXuShu>=lianXuShu) 
		return TRUE; 
		 
		//左下点 
		 
		lpSrc=(char*)lpDIBBits + lLineBytes * (y-1) + x-1; 
 
        //传递灰度值 
		gray=*lpSrc; 
 
        //如果点在图像内、颜色为黑色并且没有被访问过 
		if(y-1 >=0 &&  x-1 >=0 && gray== 0 && lplab[(y-1)*lWidth+x-1] == false) 
 
      	//进行递归处理		 
		DeleteScaterJudge(lpDIBBits,lLineBytes,lplab,lWidth,lHeight,x-1,y-1,lab,lianXuShu); 
 
        //判断长度 
		//如果连续长度满足要求,说明不是离散点,返回 
		if(m_lianXuShu>=lianXuShu) 
		return TRUE; 
		 
		//左边 
		 
		lpSrc=(char*)lpDIBBits + lLineBytes * y + x-1; 
 
		//传递灰度值 
		gray=*lpSrc; 
 
        //如果点在图像内、颜色为黑色并且没有被访问过 
		if(x-1 >=0 &&  gray== 0 && lplab[y*lWidth+x-1] == false) 
 
        //进行递归处理		 
		DeleteScaterJudge(lpDIBBits,lLineBytes,lplab,lWidth,lHeight,x-1,y,lab,lianXuShu); 
 
        //判断长度 
		//如果连续长度满足要求,说明不是离散点,返回 
		if(m_lianXuShu>=lianXuShu) 
			return TRUE; 
		 
		//左上 
		 
		lpSrc=(char*)lpDIBBits + lLineBytes * (y+1) + x-1; 
 
		//传递灰度值 
		gray=*lpSrc; 
 
        //如果点在图像内、颜色为黑色并且没有被访问过 
		if(y+1 = 0 && gray == 0 && lplab[(y+1)*lWidth+x-1] == false) 
 
		//进行递归处理 
		 
		DeleteScaterJudge(lpDIBBits,lLineBytes,lplab,lWidth,lHeight,x-1,y+1,lab,lianXuShu); 
 
        //判断长度 
		//如果连续长度满足要求,说明不是离散点,返回 
		if(m_lianXuShu>=lianXuShu) 
			return TRUE; 
		 
		//上面 
		 
		lpSrc=(char*)lpDIBBits + lLineBytes * (y+1) + x; 
 
        //传递灰度值 
		gray=*lpSrc; 
 
        //如果点在图像内、颜色为黑色并且没有被访问过 
		if(y+1 < lHeight && gray == 0 && lplab[(y+1)*lWidth+x] == false) 
 
        //进行递归处理 
		 
		DeleteScaterJudge(lpDIBBits,lLineBytes,lplab,lWidth,lHeight,x,y+1,lab,lianXuShu); 
 
        //判断长度 
		//如果连续长度满足要求,说明不是离散点,返回 
		if(m_lianXuShu>=lianXuShu) 
			return TRUE; 
		 
		//右上 
		 
		lpSrc=(char*)lpDIBBits + lLineBytes * (y+1) + x+1; 
         
		//传递灰度值 
		gray=*lpSrc; 
 
        //如果点在图像内、颜色为黑色并且没有被访问过 
		if(y+1 =lianXuShu) 
			return TRUE; 
		 
		//右边 
	 
		lpSrc=(char*)lpDIBBits + lLineBytes * y + x+1; 
 
        //传递灰度值 
		gray=*lpSrc; 
 
		//如果点在图像内、颜色为黑色并且没有被访问过 
		if(x+1 =lianXuShu) 
			return TRUE; 
		 
		//右下 
		 
		lpSrc=(char*)lpDIBBits + lLineBytes * (y-1) + x+1; 
 
        //传递灰度值 
		gray=*lpSrc; 
 
        //如果点在图像内、颜色为黑色并且没有被访问过 
		if(y-1 >=0 && x+1 =lianXuShu) 
			return TRUE; 
	} 
	 
 
	//如果递归结束,返回false,说明是离散点 
	return FALSE; 
 
} 
 
 
/*****************绘制数字字符外面的矩形框*******************/ 
void DrawFrame(CDC* pDC,HDIB hDIB, CRectLink charRect,unsigned int linewidth,COLORREF color) 
{	 
	CPen pen; 
	pen.CreatePen (PS_SOLID,linewidth,color); 
	pDC->SelectObject (&pen); 
	::SelectObject (*pDC,GetStockObject(NULL_BRUSH)); 
	CRect rect,rect2; 
	BYTE* lpDIB=(BYTE*)::GlobalLock ((HGLOBAL)hDIB); 
	while(!charRect.empty()) 
	{ 
		 
		//从表头上得到一个矩形 
		rect2=rect= charRect.front(); 
		//从链表头上面删掉一个 
		charRect.pop_front(); 
		//注意,这里原先的rect是相对于图像原点(左下角)的, 
		//而在屏幕上绘图时,要转换以客户区为原点的坐标 
		rect.top =::DIBHeight ((char*)lpDIB)-rect2.bottom; 
		rect.bottom =::DIBHeight ((char*)lpDIB)-rect2.top ; 
		pDC->Rectangle (&rect); 
	} 
	::GlobalUnlock ((HGLOBAL)hDIB); 
} 
/*********************************************** 
* 
* 函数名称: 
*   GradientSharp()  
* 
*参数 : 
*  HDIB hDIB    -待处理图像的句柄 
* 
* 返回值: 
*       无 
*  
*功能: 
*    现图像的梯度锐化 
 
*说明: 
*    只能对2值图像进行处理,如果图像本身边缘较细,可能造成信息的损失 
**********************************************************************/ 
void GradientSharp(HDIB hDIB) 
{ 
	// 指向DIB的指针 
	LPSTR lpDIB=(LPSTR) ::GlobalLock((HGLOBAL)hDIB); 
 
	// 指向DIB象素指针 
	LPSTR    lpDIBBits;	 
 
	// 找到DIB图像象素起始位置 
	lpDIBBits = ::FindDIBBits(lpDIB);	 
 
    //获取图像的宽度 
	LONG lWidth=::DIBWidth ((char*)lpDIB); 
 
    //获取图像的长度 
	LONG lHeight=::DIBHeight ((char*)lpDIB); 
 
    // 阈值 
	BYTE	bThre = 2; 
 
	// 调用GradSharp()函数进行梯度板锐化 
 
	// 指向源图像的指针 
	unsigned char*	lpSrc; 
	unsigned char*	lpSrc1; 
	unsigned char*	lpSrc2; 
	 
	// 循环变量 
	LONG	i; 
	LONG	j; 
	 
	// 图像每行的字节数 
	LONG	lLineBytes; 
	 
	// 中间变量 
	BYTE	bTemp; 
	 
	// 计算图像每行的字节数 
	lLineBytes = WIDTHBYTES(lWidth * 8); 
	 
	// 每行 
   for(i = 0; i < lHeight; i++) 
	{ 
		 
     // 每列 
	 for(j = 0; j < lWidth; j++) 
		{ 
			 
             // 指向DIB第i行,第j个象素的指针 
			lpSrc  = (unsigned char*)lpDIBBits + lLineBytes * (lHeight - 1 - i) + j; 
			 
			// 指向DIB第i+1行,第j个象素的指针 
			lpSrc1 = (unsigned char*)lpDIBBits + lLineBytes * (lHeight - 2 - i) + j; 
			 
		     // 指向DIB第i行,第j+1个象素的指针 
		     lpSrc2 = (unsigned char*)lpDIBBits + lLineBytes * (lHeight - 1 - i) + j + 1; 
			 
 
              //计算梯度值 
		     bTemp = abs((*lpSrc)-(*lpSrc1)) + abs((*lpSrc)-(*lpSrc2)); 
			 
		    // 判断是否小于阈值 
		    if (bTemp < 255) 
			{   
 
		     // 判断是否大于阈值,对于小于情况,灰度值不变。 
			   if (bTemp >= bThre) 
			   { 
 
			// 直接赋值为bTemp 
			 *lpSrc = bTemp; 
 
			   } 
 
			} 
			 
           else 
			{ 
				// 直接赋值为255 
				*lpSrc = 255; 
			} 
	 } 
   } 
 
//最后还要处理一下图像中最下面那行 
for(j = 0; j < lWidth; j++) 
{    
	 
 //指向最下边一行,第j个象素的指针 
  lpSrc  = (unsigned char*)lpDIBBits + lLineBytes * 0 + j; 
 
   //将此位置的象素设置为255,即白点 
	*lpSrc=255; 
} 
 
   //解除锁定 
	::GlobalUnlock ((HGLOBAL)hDIB); 
} 
 
 
/************************************************************ 
* 
*  函数名称: 
*       RemoveScatterNoise() 
* 
*  参数: 
*     HDIB    hDIB     -原图像的句柄 
* 
*  返回值: 
*       无 
* 
*  功能: 
*     通过对连续点长度的统计来去除离散杂点 
* 
*  说明: 
*      只能对2值图像进行处理 
****************************************************************/ 
void RemoveScatterNoise(HDIB hDIB) 
{ 
	 
	// 指向DIB的指针 
	LPSTR lpDIB=(LPSTR) ::GlobalLock((HGLOBAL)hDIB); 
	 
	// 指向DIB象素指针 
	LPSTR    lpDIBBits;	 
 
	// 找到DIB图像象素数据区的起始位置 
	lpDIBBits = ::FindDIBBits(lpDIB); 
	 
	//获得图像的长度 
	LONG lWidth=::DIBWidth ((char*)lpDIB); 
 
	//获得图像的高度 
	LONG lHeight=::DIBHeight ((char*)lpDIB); 
 
	//设置判定噪声的长度阈值为15 
	//即如果与考察点相连接的黑点的数目小于15则认为考察点是噪声点 
	int length=15; 
	 
	// 循环变量 
	m_lianXuShu=0; 
	LONG	i; 
	LONG	j;	 
	LONG    k; 
 
	// 图像每行的字节数 
	LONG	lLineBytes; 
 
	// 计算图像每行的字节数 
	lLineBytes = WIDTHBYTES(lWidth * 8); 
 
     
	LPSTR lpSrc; 
 
	//开辟一块用来存放标志的内存数组 
	LPBYTE lplab = new BYTE[lHeight * lWidth]; 
 
	//开辟一块用来保存离散判定结果的内存数组 
	bool *lpTemp = new bool[lHeight * lWidth]; 
 
    //初始化标志数组 
	for (i=0;i=lHeight ) 
				gray = 255; 
 
			else 
			{	 
				//否则到源图像中找点,取得象素值 
 
				//指向第i_src行第j个象素的指针 
				lpSrc=(unsigned char *)lpDIBBits + lLineBytes *  i_src + j; 
				gray = *lpSrc; 
			} 
			 
			//把新图像的点用得到的象素值填充 
            //指向第i行第j个象素的指针 
			lpDst = (char *)lpNewDIBBits + lLineBytes * i + j; 
			*lpDst=gray; 
		} 
	} 
 
	// 将新的图像的内容拷贝到旧的图像中 
	memcpy(lpDIBBits,lpNewDIBBits,lLineBytes*lHeight); 
 
   // 解除锁定 
	::GlobalUnlock ((HGLOBAL)hDIB); 
} 
 
 
 
/****************************************************************** 
* 
*  函数名称: 
*      StdDIBbyRect() 
* 
*  参数: 
*     HDIB  hDIB          -图像的句柄 
*     int   tarWidth      -标准化的宽度 
*     int   tarHeight     -标准化的高度 
* 
*  返回值: 
*         无 
* 
*  功能: 
*     将经过分割的字符,进行缩放处理使他们的宽和高一直,以方便特征的提取 
* 
*  说明: 
*     函数中用到了,每个字符的位置信息,所以必须在执行完分割操作之后才能执行标准化操作 
* 
******************************************************************/ 
void StdDIBbyRect(HDIB hDIB, int tarWidth, int tarHeight) 
{	 
 
	//指向图像的指针 
	BYTE* lpDIB=(BYTE*)::GlobalLock ((HGLOBAL)hDIB); 
 
	//指向象素起始位置的指针 
	BYTE* lpDIBBits=(BYTE*)::FindDIBBits ((char*)lpDIB); 
	 
	//指向象素的指针 
	BYTE* lpSrc; 
 
	//获取图像的的宽度 
	LONG lWidth=::DIBWidth ((char*)lpDIB); 
 
	//获取图像的高度 
	LONG lHeight=::DIBHeight ((char*)lpDIB); 
 
	// 循环变量 
	int	i; 
	int	j; 
	 
	// 图像每行的字节数 
	LONG	lLineBytes = WIDTHBYTES(lWidth * 8); 
 
	//宽度、高度方向上的缩放因子 
	double wscale,hscale; 
 
	//开辟一块临时缓存区,来存放变化后的图像信息 
	LPSTR lpNewDIBBits; 
	LPSTR lpDst; 
  
    //缓存区的大小和原图像的数据区大小一样 
	HLOCAL nNewDIBBits=LocalAlloc(LHND,lLineBytes*lHeight); 
 
	//指向缓存区开始位置的指针 
	lpNewDIBBits=(char*)LocalLock(nNewDIBBits); 
 
	//指向缓存内信息的指针 
	lpDst=(char*)lpNewDIBBits; 
 
	//将缓存区的内容赋初始值 
	memset(lpDst,(BYTE)255,lLineBytes*lHeight); 
 
	//进行映射操作的坐标变量 
	int i_src,j_src; 
 
	//存放字符位置信息的结构体 
	CRect rect; 
	CRect rectnew; 
 
	//先清空一个新的矩形区域链表以便存储标准化后的矩形区域链表 
	m_charRectCopy.clear (); 
 
	//从头到尾逐个扫描各个结点 
	while(!m_charRect.empty()) 
	{ 
		//从表头上得到一个矩形 
		rect= m_charRect.front(); 
 
		//从链表头上面删掉一个 
		m_charRect.pop_front(); 
 
		//计算缩放因子 
 
		//横坐标方向的缩放因子 
		wscale=(double)tarWidth/rect.Width (); 
 
		//纵坐标方向的缩放因子 
		hscale=(double)tarHeight/rect.Height (); 
 
		//计算标准化矩形 
 
		//上边界 
		rectnew.top =rect.top ; 
 
		//下边界 
		rectnew.bottom =rect.top +tarHeight; 
 
		//左边界 
		rectnew.left =rect.left ; 
 
		//右边界 
		rectnew.right =rectnew.left +tarWidth; 
 
		//将原矩形框内的象素映射到新的矩形框内 
		for(i=rectnew.top ;i(w-(tem_w+1)/2) || i<((tem_h-1)/2) || i>(h-(tem_h+1)/2) ) 
	      *(newbuf+i*dw+j)=*(oldbuf+i*dw+j); 
		  
         //对于其他的象素进行模板操作 
		 else  
         {  
 
          //将点(i,j)点作为模板的中心 
          for(m=i-((tem_h-1)/2);m<=i+((tem_h-1)/2);m++) 
          { 
		     for(n=j-((tem_w-1)/2);n<=j+((tem_w-1)/2);n++) 
		     
             //将以点(i,j)为中心,与模板大小相同的范围内的象素与模板对用位置的系数 
			 //进行相乘并线形叠加 
		     sum+=*(oldbuf+m*dw+n)* tem[(m-i+((tem_h-1)/2))*tem_w+n-j+((tem_w-1)/2)]; 
		   
		  } 
           
		  //将结果乘上总的模板系数 
          sum=(int)sum*xishu; 
 
		  //计算绝对值 
		  sum = fabs(sum); 
 
		  //如果小于0,强制赋值为0 
          if(sum<0)      
          sum=0; 
 
		  //如果大于255,强制赋值为255 
          if(sum>255) 
		  sum=255; 
 
		  //将计算的结果放到新的位图的相应位置 
	      *(newbuf+i*dw+j)=sum; 
		 } 
	   } 
	}  
    
	//解除锁定 
	::GlobalUnlock((HGLOBAL)hDIB); 
     
	//返回新的位图的句柄 
    return(newhDIB); 
} 
/***************************************************** 
*  
*   函数名称: 
*      Template: 
* 
*    参数: 
*	   HDIB    hDIB         -图像的句柄 
*      int  tem_w           -模板的宽度 
*      int  tem_h           -模板的高度 
*       
*    功能: 
*	   对图像进行中值 
* 
*    说明: 
*	   为处理方便起见,模板的宽度和高度都应为奇数 
*******************************************************/ 
 
HDIB MidFilter(HDIB hDIB,int tem_w,int tem_h) 
{ 
 
    //统计中间值 
    double mid; 
 
	BYTE *temp=(BYTE*)malloc(tem_w*tem_h*sizeof(BYTE)); 
 
    //指向图像起始位置的指针 
    BYTE *lpDIB=(BYTE*)::GlobalLock((HGLOBAL) hDIB); 
 
	//指向象素起始位置的指针 
	BYTE *pScrBuff =(BYTE*)::FindDIBBits((char*)lpDIB); 
    
	//获取图像的颜色信息 
    int numColors=(int) ::DIBNumColors((char *)lpDIB); 
 
    //如果图像不是256色返回 
     if (numColors!=256)  
	 {    
        //解除锁定 
	  	::GlobalUnlock((HGLOBAL) hDIB); 
 
		//返回 
		return(hDIB); 
	 } 
     
    //将指向图像象素起始位置的指针,赋值给指针变量 
    BYTE* oldbuf = pScrBuff; 
 
    //循环变量 
    int i,j,m,n; 
 
	int w, h, dw; 
 
	//获取图像的宽度 
	w = (int) ::DIBWidth((char *)lpDIB); 
	 
	//获取图像的高度 
	h = (int) ::DIBHeight((char *)lpDIB); 
	 
	//计算图像每行的字节数 
	dw = (w+3)/4*4;       
	 
	//建立一个和原图像大小相同的25色灰度位图 
    HDIB newhDIB=NewDIB(w,h,8);   
     
	//指向新的位图的指针 
	BYTE *newlpDIB=(BYTE*)::GlobalLock((HGLOBAL) newhDIB); 
 
	//指向新的位图的象素起始位置的指针  
    BYTE *destBuf = (BYTE*)FindDIBBits((char *)newlpDIB); 
     
   //将指向新图像象素起始位置的指针,赋值给指针变量 
    BYTE *newbuf=destBuf;  
	 
	//对图像进行扫描 
    
	//行  
    for(i=0;i(w-(tem_w+1)/2) || i<((tem_h-1)/2) || i>(h-(tem_h+1)/2) ) 
	      *(newbuf+i*dw+j)=*(oldbuf+i*dw+j); 
		  
         //对于其他的象素进行模板操作 
		 else  
         {  
 
          //将点(i,j)点作为模板的中心 
          for(m=i-((tem_h-1)/2);m<=i+((tem_h-1)/2);m++) 
          { 
		     for(n=j-((tem_w-1)/2);n<=j+((tem_w-1)/2);n++) 
		     
             //将以点(i,j)为中心,与模板大小相同的范围内的象素传递到模板矩阵中 
		     temp[(m-i+((tem_h-1)/2))*tem_w+n-j+((tem_w-1)/2)]=*(oldbuf+m*dw+n); 
		   
		  } 
           
		 //利用气泡法计算中值 
           for(m=0;mtemp[n+1])  
			    mid=temp[n]; 
                temp[n]=temp[n+1]; 
			    temp[n+1]=mid; 
			  } 
		    
		   }  
 
           //将计算的结果放到新的位图的相应位置 
	      *(newbuf+i*dw+j)=temp[(tem_w*tem_h-1)/2]; 
		 } 
	   } 
	}  
    
	//解除锁定 
	::GlobalUnlock((HGLOBAL)hDIB); 
     
	//返回新的位图的句柄 
    return(newhDIB); 
} 
 
 
 
/************************************************************************* 
 * 
 * 函数名称: 
 *   Equalize() 
 * 
 * 参数: 
 *   HDIB hDIB 
 * 
 * 
 * 说明: 
 *   该函数用来对图像进行直方图均衡。 
 * 
 ************************************************************************/ 
void Equalize(HDIB hDIB) 
{ 
	BYTE* lpDIB=(BYTE*)::GlobalLock ((HGLOBAL)hDIB); 
	BYTE* lpDIBBits=(BYTE*)::FindDIBBits((char*)lpDIB); 
	LONG lHeight=::DIBHeight ((char*)lpDIB); 
	LONG lWidth=::DIBWidth ((char*)lpDIB); 
	// 指向源图像的指针 
	unsigned char*	lpSrc; 
	 
	// 临时变量 
	LONG	lTemp; 
	 
	// 循环变量 
	LONG	i; 
	LONG	j; 
	 
	// 灰度映射表 
	BYTE	bMap[256]; 
	 
	// 灰度映射表 
	LONG	lCount[256]; 
	 
	// 图像每行的字节数 
	LONG	lLineBytes; 
	 
	// 计算图像每行的字节数 
	lLineBytes = WIDTHBYTES(lWidth * 8); 
	 
	// 重置计数为0 
	for (i = 0; i < 256; i ++) 
	{ 
		// 清零 
		lCount[i] = 0; 
	} 
	 
	// 计算各个灰度值的计数 
	for (i = 0; i < lHeight; i ++) 
	{ 
		for (j = 0; j < lWidth; j ++) 
		{ 
			lpSrc = (unsigned char *)lpDIBBits + lLineBytes * i + j; 
			 
			// 计数加1 
			lCount[*(lpSrc)]++; 
		} 
	} 
	 
	// 计算灰度映射表 
	for (i = 0; i < 256; i++) 
	{ 
		// 初始为0 
		lTemp = 0; 
		 
		for (j = 0; j <= i ; j++) 
		{ 
			lTemp += lCount[j]; 
		} 
		 
		// 计算对应的新灰度值 
		bMap[i] = (BYTE) (lTemp * 255 / lHeight / lWidth); 
	} 
	 
	// 每行 
	for(i = 0; i < lHeight; i++) 
	{ 
		// 每列 
		for(j = 0; j < lWidth; j++) 
		{ 
			// 指向DIB第i行,第j个象素的指针 
			lpSrc = (unsigned char*)lpDIBBits + lLineBytes * (lHeight - 1 - i) + j; 
			 
			// 计算新的灰度值 
			*lpSrc = bMap[*lpSrc]; 
		} 
	} 
	 
	::GlobalUnlock ((HGLOBAL)hDIB); 
}