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;i 0) { 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 ;j bmiColors[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;m temp[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); }