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