www.pudn.com > source.rar > Dib.cpp


// Dib.cpp: implementation of the CDib class. 
// 
////////////////////////////////////////////////////////////////////// 
 
#include "stdafx.h" 
#include "INVCR.h" 
#include "Dib.h" 
#include  
 
#ifdef _DEBUG 
#undef THIS_FILE 
static char THIS_FILE[]=__FILE__; 
#define new DEBUG_NEW 
#endif 
 
////////////////////////////////////////////////////////////////////// 
// Construction/Destruction 
////////////////////////////////////////////////////////////////////// 
 
CDib::CDib() 
{ 
	int i,j; 
 
	LineBytes = 0; 
 
 
	for( i = 0; i < IMAGE_HEIGHT; i++ ) 
	{ 
		dataRealColor[i] = new RGBData[IMAGE_WIDTH]; 
		dataNoRealColor[i] = new BYTE[IMAGE_WIDTH]; 
		binaryImageData[i] = new BYTE[IMAGE_WIDTH];		 
 
		for( j = 0; j < IMAGE_WIDTH; j++ ) 
		{ 
            dataRealColor[i][j].Blue = 255; 
			dataRealColor[i][j].Green = 255; 
			dataRealColor[i][j].Red = 255; 
			dataNoRealColor[i][j] = 255; 
			binaryImageData[i][j] = 255; 
		} 
	} 
 
 
} 
 
CDib::~CDib() 
{ 
	int i; 
	 
	//释放图像数组空间 
	for( i = 0; i < IMAGE_HEIGHT; i++ ) 
	{ 
		if( dataRealColor[i] != NULL ) 
		{ 
			delete dataRealColor[i]; 
			dataRealColor[i] = NULL; 
		} 
 
		if( dataNoRealColor[i] != NULL ) 
		{ 
			delete dataNoRealColor[i]; 
			dataNoRealColor[i] = NULL; 
		} 
 
		if( binaryImageData[i] != NULL ) 
		{ 
			delete binaryImageData[i]; 
			binaryImageData[i] = NULL; 
		} 
	} 
 
} 
 
BOOL CDib::Load(const char* pszFilename) 
{ 
	int i,j; 
	int offset; 
	int m_bit24; 
 
	CFile cf; 
	if(!cf.Open(pszFilename,CFile::modeRead)) 
		return FALSE; 
    BITMAPFILEHEADER BFH; 
	BITMAPINFOHEADER BIH; 
 
    if(cf.Read(&BFH,sizeof(BITMAPFILEHEADER))!=sizeof(BITMAPFILEHEADER)) 
		return FALSE;	 
	if(cf.Read(&BIH,sizeof(BITMAPINFOHEADER))!=sizeof(BITMAPINFOHEADER)) 
		return FALSE; 
 
	if( BFH.bfType!='MB' ) 
	{ 
		AfxMessageBox( " 输入图像格式不对,请将扫描图像格式转化为bmp格式,再重试! " ); 
		return FALSE; 
	} 
 
	m_FileHeader.bfSize = BFH.bfSize; 
	m_InfoHeader.biWidth = BIH.biWidth; 
	m_InfoHeader.biHeight = BIH.biHeight; 
	m_InfoHeader.biBitCount = BIH.biBitCount; 
			 
    LineBytes=WIDTHBYTES( BIH.biWidth*BIH.biBitCount ); 
	 
    if( BIH.biBitCount != 24 ) 
	{ 
		m_bit24 = 1; 
	} 
	else 
		m_bit24 = 2; 
 
   offset=BFH.bfOffBits; 
	 
	if(m_bit24 == 2) 
	{	 
		cf.Seek(offset,CFile::begin); 
 
		DWORD atemp = WIDTHBYTES( BIH.biWidth * 24 ); 
		for( j = BIH.biHeight - 1; j >= 0; j-- ) 			 
			cf.Read( dataRealColor[j], atemp ); 
 
		cf.Close(); 
 
		//将彩色图变换成灰度图 
		for( i = 0; i < BIH.biHeight; i++ ) 
			for( j = 0; j< BIH.biWidth; j++ ) 
			dataNoRealColor[i][j]=(int)(dataRealColor[i][j].Blue*0.114+dataRealColor[i][j].Green*0.587+dataRealColor[i][j].Red*0.299);  //将24bit位图变为8bit位图的处理,RGB转化为亮度 
 
	} 
	else if(m_bit24 == 1) 
	{ 
		cf.Seek( offset, CFile::begin ); 
 
		for( j = BIH.biHeight - 1; j >= 0; j-- ) 
		    cf.Read( dataNoRealColor[j], LineBytes ); 
	 
		cf.Close(); 
	} 
	else 
	{ 
		AfxMessageBox("输入图像格式错误!"); 
		return FALSE; 
	} 
 
	return TRUE; 
} 
 
 
BOOL CDib::inclineEmendation()  //发票倾斜校正处理 
{ 
	//左上角点参考点搜索的范围 
	int LT_REF_TOP = 300;   
	int LT_REF_BOTTOM = 400; 
	int LT_REF_LEFT = 60; 
	int LT_REF_RIGHT = 150; 
 
	//右上角点参考点搜索的范围 
	int RT_REF_TOP = 280;   
	int RT_REF_BOTTOM = 450; 
	int RT_REF_LEFT = 2450; 
	int RT_REF_RIGHT = 2580; 
 
	//左下角点参考点搜索的范围 
	int LB_REF_TOP = 1400;   
	int LB_REF_BOTTOM = 1550; 
	int LB_REF_LEFT = 30; 
	int LB_REF_RIGHT = 140; 
 
	int LT_REF_X,LT_REF_Y; //左上角点参考点的坐标 
	int RT_REF_X,RT_REF_Y; //右上角点参考点的坐标 
	int LB_REF_X,LB_REF_Y; //右上角点参考点的坐标 
 
	int i,j,m,n; 
	int matchValue; //匹配变量 
	long int minMatchValue = 100000000; 
	int rcountPixel,dcountPixel; 
 
	//最大类间方差二值化全局图像,找出定位参考点 
	int Hist[256], area; 
	int bwth; 
	int lineBytes = WIDTHBYTES( m_InfoHeader.biWidth * 8 ); //这里处理的都是256级灰度图象,所以biBitCount都取8 
	float uT, maxob2, p[256], u[256], u0[256], u1[256], w0[256], w1[256], ob2[256]; 
 
	for ( i = 0; i < 256; i++ ) 
	{ 
		Hist[i] = 0; 
	} 
 
	for ( i = 0; i < m_InfoHeader.biHeight; i++ ) 
	{ 
		for ( j = 0; j < lineBytes; j++ ) 
		{ 
			Hist[dataNoRealColor[i][j]]++; 
		} 
	} 
	 
	uT = 0.0; 
	area = m_InfoHeader.biHeight * lineBytes; 
	 
	for ( i = 0; i < 256; i++ ) 
	{ 
		p[i] = Hist[i] / ( float ) area; 
		uT = uT + i * p[i]; 
	} 
 
	for ( j = 0; j < 256; j++ )  
	{ 
		u[j] = 0.0;  
		w0[j] = 0.0; 
		 
		for ( i = 0; i < j; i++ ) 
		{ 
			u[j] = u[j] + i * p[i]; 
			w0[j] = w0[j] + p[i]; 
		} 
    
		w1[j] = 1 - w0[j]; 
    
		if ( ( w0[j] > 0 ) && ( w1[j] > 0 ) ) 
		{ 
   			u0[j] = u[j] / w0[j]; 
			u1[j] = ( uT - u[j] ) / w1[j]; 
			ob2[j] = w0[j] * ( u0[j] - uT ) * ( u0[j] - uT ) + w1[j] * ( u1[j] - uT ) * ( u1[j] - uT ); 
		} 
		else 
		{ 
			ob2[j] = 0; 
		} 
	} 
	 
	maxob2 = 0; 
	 
	for ( i = 0; i < 256; i++ ) 
	{ 
		if ( ob2[i] > maxob2 ) 
		{ 
			maxob2 = ob2[i]; 
			bwth = i; 
		} 
	} 
 
	for(i = 0; i < m_InfoHeader.biHeight; i++) 
		for(j = 0; j < m_InfoHeader.biWidth; j++) 
		{ 
			if( dataNoRealColor[i][j] < bwth + 15 )  //这里是要检验出参考点,因而适当放大域值,以增强抗干扰能力 
				binaryImageData[i][j] = 0; 
			else 
				binaryImageData[i][j] = 255; 
		} 
 
	//构造一个检测参考点的模板图像数组 
	BYTE modelImage[30][30];	 
	for( i = 0; i < 30; i++ ) 
		for( j = 0; j < 30; j++ ) 
		{ 
			if( i == 0 || i == 1 || i == 2 || j == 0 || j == 1 || j == 2 ) 
				modelImage[i][j] = 0; 
			else 
				modelImage[i][j] = 255; 
		}	 
 
	for( i = LT_REF_TOP; i <= LT_REF_BOTTOM; i++ ) 
		for( j = LT_REF_LEFT; j <= LT_REF_RIGHT; j++ ) 
		{ 
			matchValue = 0; 
 
			//为了减少运算量,只在上面六行和右边六行进行模板匹配,并且为了增强抗干扰性,先判断是否进行模板匹配的计算 
			rcountPixel = 0; 
			dcountPixel = 0; 
			for( m = 0; m <= 2; m++ ) 
				for( n = 5; n < 20; n++ ) 
				{ 
					if( binaryImageData[i + m][j + n] == 0 ) 
						rcountPixel++; 
				} 
			for( m = 5; m < 20; m++ ) 
				for( n = 0; n <= 2; n++ ) 
				{ 
					if( binaryImageData[i + m][j + n] == 0 ) 
						dcountPixel++; 
				} 
			if( rcountPixel < 15 || dcountPixel < 15 )  //保证出现所要求的折形结构,否则不予判断 
				matchValue = 1000000000; 
			else 
			{ 
				for( m = 0; m <= 5; m++ ) 
					for( n = 0; n < 30; n++ ) 
					{ 
						matchValue = matchValue + (int)fabs( binaryImageData[i + m][j + n] - modelImage[m][n] ); 
					} 
				for( m = 6; m < 30; m++ ) 
					for( n = 0; n <= 5; n++ ) 
					{ 
						matchValue = matchValue + (int)fabs( binaryImageData[i + m][j + n] - modelImage[m][n] ); 
					} 
 
				if( matchValue < minMatchValue ) 
				{ 
					minMatchValue = matchValue; 
					LT_REF_X = j; 
					LT_REF_Y = i; 
				} 
			} 
		} 
	 
	minMatchValue = 1000000000; 
	for( i = RT_REF_TOP; i <= RT_REF_BOTTOM; i++ ) 
		for( j = RT_REF_LEFT; j <= RT_REF_RIGHT; j++ ) 
		{ 
			matchValue = 0; 
 
			//为了减少运算量,只在上面六行和右边六行进行模板匹配,并且为了增强抗干扰性,先判断是否进行模板匹配的计算 
			rcountPixel = 0; 
			dcountPixel = 0; 
			for( m = 0; m <= 2; m++ ) 
				for( n = 5; n < 20; n++ ) 
				{ 
					if( binaryImageData[i + m][j - n] == 0 ) 
						rcountPixel++; 
				} 
			for( m = 5; m < 20; m++ ) 
				for( n = 0; n <= 2; n++ ) 
				{ 
					if( binaryImageData[i + m][j - n] == 0 ) 
						dcountPixel++; 
				} 
			if( rcountPixel < 15 || dcountPixel < 15 )  //保证出现所要求的折形结构,否则不予判断 
				matchValue = 1000000000; 
			else 
			{ 
				for( m = 0; m <= 5; m++ ) 
					for( n = 0; n < 30; n++ ) 
					{ 
						matchValue = matchValue + (int)fabs( binaryImageData[i + m][j - n] - modelImage[m][n] ); //理解算法的精妙 
					} 
				for( m = 6; m < 30; m++ ) 
					for( n = 0; n <= 5; n++ ) 
					{ 
						matchValue = matchValue + (int)fabs( binaryImageData[i + m][j - n] - modelImage[m][n] ); 
					} 
 
				if( matchValue < minMatchValue ) 
				{ 
					minMatchValue = matchValue; 
					RT_REF_X = j; 
					RT_REF_Y = i; 
				} 
			} 
		} 
 
	minMatchValue = 1000000000; 
	for( i = LB_REF_TOP; i <= LB_REF_BOTTOM; i++ ) 
		for( j = LB_REF_LEFT; j <= LB_REF_RIGHT; j++ ) 
		{ 
			matchValue = 0; 
 
			//为了减少运算量,只在上面六行和右边六行进行模板匹配,并且为了增强抗干扰性,先判断是否进行模板匹配的计算 
			rcountPixel = 0; 
			dcountPixel = 0; 
			for( m = 0; m <= 2; m++ ) 
				for( n = 5; n < 20; n++ ) 
				{ 
					if( binaryImageData[i - m][j + n] == 0 ) 
						rcountPixel++; 
				} 
			for( m = 5; m < 20; m++ ) 
				for( n = 0; n <= 2; n++ ) 
				{ 
					if( binaryImageData[i - m][j + n] == 0 ) 
						dcountPixel++; 
				} 
			if( rcountPixel < 15 || dcountPixel < 15 )  //保证出现所要求的折形结构,否则不予判断 
				matchValue = 1000000000; 
			else 
			{ 
				for( m = 0; m <= 5; m++ ) 
					for( n = 0; n < 30; n++ ) 
					{ 
						matchValue = matchValue + (int)fabs( binaryImageData[i - m][j + n] - modelImage[m][n] ); //理解算法的精妙 
					} 
 
				for( m = 6; m < 30; m++ ) 
					for( n = 0; n <= 5; n++ ) 
					{ 
						matchValue = matchValue + (int)fabs( binaryImageData[i - m][j + n] - modelImage[m][n] ); 
					} 
			} 
 
			if( matchValue < minMatchValue ) 
			{ 
				minMatchValue = matchValue; 
				LB_REF_X = j; 
				LB_REF_Y = i; 
			} 
		} 
 
		 
	//旋转校正 
	if( abs( RT_REF_Y - LT_REF_Y ) > 4 ) 
	{ 
		double rotateAngle; 
		double param1,param2; 
		int sourceX,sourceY; 
		BYTE tempImageData[IMAGE_HEIGHT][IMAGE_WIDTH]; 
 
		//先备份图像数据 
		for( i = 0; i < m_InfoHeader.biHeight; i++ ) 
			for( j = 0; j < m_InfoHeader.biWidth; j++ ) 
				tempImageData[i][j] = dataNoRealColor[i][j]; 
 
		rotateAngle = atan( (double)( RT_REF_Y - LT_REF_Y )/( RT_REF_X - LT_REF_X ) ); 
		param1 = LT_REF_X - LT_REF_X * cos( rotateAngle ) + LT_REF_Y * sin( rotateAngle ); 
		param2 = LT_REF_Y - LT_REF_X * sin( rotateAngle ) - LT_REF_Y * cos( rotateAngle ); 
		for( i = 0; i < m_InfoHeader.biHeight; i++ ) 
			for( j = 0; j < m_InfoHeader.biWidth; j++ ) 
			{ 
				sourceX = (int)( j * cos( rotateAngle ) - i * sin( rotateAngle ) + param1 + 0.5 ); 
				sourceY = (int)( i * cos( rotateAngle ) + j * sin( rotateAngle ) + param2 + 0.5 ); 
 
				//判断是否位于图像范围内 
				if( sourceX >= 0 && sourceX < m_InfoHeader.biWidth && sourceY >= 0 && sourceY < m_InfoHeader.biHeight ) 
					dataNoRealColor[i][j] = tempImageData[sourceY][sourceX]; 
				else  //其他部分用白色填充 
					dataNoRealColor[i][j] = 255;   
			} 
	} 
	 
 
	return TRUE; 
} 
 
BOOL CDib::mergeImageFile()  //批处理最大类间方差全局二值化发票图像 
{ 
	CFile cf; 
 
	int lineBytes; 
 
 
 
		if(!cf.Open("D:\\test.bmp",CFile::modeRead)) 
		{ 
			AfxMessageBox("打开图像文件失败!"); 
			return FALSE; 
		} 
 
		if(cf.Read(&m_FileHeader,sizeof(BITMAPFILEHEADER)) != sizeof(BITMAPFILEHEADER)) 
		{ 
			AfxMessageBox("读位图文件头失败!"); 
			return FALSE; 
		} 
 
		if(cf.Read(&m_InfoHeader,sizeof(BITMAPINFOHEADER)) != sizeof(BITMAPINFOHEADER)) 
		{ 
			AfxMessageBox("读位图信息头失败!"); 
			return FALSE; 
		} 
 
		if(cf.Read(m_grayPalette,1024) != 1024) 
		{ 
			AfxMessageBox("读位图调色板失败!"); 
			return FALSE; 
		} 
 
	    lineBytes = WIDTHBYTES( m_InfoHeader.biWidth * 8 ); //这里处理的都是256级灰度图象,所以biBitCount都取8 
 
		if(!cf.Open("D:\\emendationImage.bmp",CFile::modeCreate|CFile::modeWrite)) 
		{ 
			AfxMessageBox("创建图像文件失败!");		 
			return FALSE; 
		} 
 
		cf.Write(&m_FileHeader,sizeof(BITMAPFILEHEADER)); 
		cf.Write(&m_InfoHeader,sizeof(BITMAPINFOHEADER)); 
		cf.Write(m_grayPalette,1024); 
 
		for( int i = m_InfoHeader.biHeight - 1; i >= 0 ; i-- ) 
			cf.Write(dataNoRealColor[i],lineBytes); 
 
		cf.Close(); 
 
 
 
	AfxMessageBox("finished!"); 
 
	return TRUE; 
}