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

📄 dib.cpp

📁 这是树上的代码
💻 CPP
字号:
// Dib.cpp: implementation of the CDib class.
//
//////////////////////////////////////////////////////////////////////

#include "stdafx.h"
#include "INVCR.h"
#include "Dib.h"
#include <math.h>

#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;
}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -