www.pudn.com > Photodeal.rar > PointTrans.cpp
/************************************************************************** * 文件名:PointTrans.cpp * * 图像点运算API函数库: * * LinerTrans() - 图像线性变换 * WindowTrans() - 图像窗口变换 * GrayStretch() - 图像灰度拉伸 * InteEqualize() -直方图均衡 * *************************************************************************/ #include#include #include "stdafx.h" #include "PointTrans.h" //#include "DIBAPI.h" #include #include /************************************************************************* * * 函数名称: * ThresholdTrans() * * 参数: * LPSTR lpDIBBits - 指向源DIB图像指针 * LONG lWidth - 源图像宽度(象素数) * LONG lHeight - 源图像高度(象素数) * BYTE bThre - 阈值 * * 返回值: * BOOL - 成功返回TRUE,否则返回FALSE。 * * 说明: * 该函数用来对图像进行阈值变换。对于灰度值小于阈值的象素直接设置 * 灰度值为0;灰度值大于阈值的象素直接设置为255。 * ************************************************************************/ BOOL WINAPI ThresholdTrans(LPSTR lpDIBBits, LONG lWidth, LONG lHeight, BYTE bThre) { // 指向源图像的指针 unsigned char* lpSrc; // 循环变量 LONG i; LONG j; // 图像每行的字节数 LONG lLineBytes; // 计算图像每行的字节数 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; // 判断是否小于阈值 if ((*lpSrc) < bThre) { // 直接赋值为0 *lpSrc = 0; } else { // 直接赋值为255 *lpSrc = 255; } } } // 返回 return TRUE; } /************************************************************************* * * 函数名称: * GetMedianNum() * * 参数: * unsigned char * bpArray - 指向要获取中值的数组指针 * int iFilterLen - 数组长度 * * 返回值: * unsigned char - 返回指定数组的中值。 * * 说明: * 该函数用冒泡法对一维数组进行排序,并返回数组元素的中值。 * ************************************************************************/ unsigned char WINAPI GetMedianNum(unsigned char * bArray, int iFilterLen) { // 循环变量 int i; int j; // 中间变量 unsigned char bTemp; // 用冒泡法对数组进行排序 for (j = 0; j < iFilterLen - 1; j ++) { for (i = 0; i < iFilterLen - j - 1; i ++) { if (bArray[i] > bArray[i + 1]) { // 互换 bTemp = bArray[i]; bArray[i] = bArray[i + 1]; bArray[i + 1] = bTemp; } } } // 计算中值 if ((iFilterLen & 1) > 0) { // 数组有奇数个元素,返回中间一个元素 bTemp = bArray[(iFilterLen + 1) / 2]; } else { // 数组有偶数个元素,返回中间两个元素平均值 bTemp = (bArray[iFilterLen / 2] + bArray[iFilterLen / 2 + 1]) / 2; } // 返回中值 return bTemp; } /************************************************************************* * * 函数名称: * GrayStretch() * * 参数: * LPSTR lpDIBBits - 指向源DIB图像指针 * LONG lWidth - 源图像宽度(象素数) * LONG lHeight - 源图像高度(象素数) * BYTE bX1 - 灰度拉伸第一个点的X坐标 * BYTE bY1 - 灰度拉伸第一个点的Y坐标 * BYTE bX2 - 灰度拉伸第二个点的X坐标 * BYTE bY2 - 灰度拉伸第二个点的Y坐标 * * 返回值: * BOOL - 成功返回TRUE,否则返回FALSE。 * * 说明: * 该函数用来对图像进行灰度拉伸。 * ************************************************************************/ BOOL WINAPI GrayStretch(LPSTR lpDIBBits, LONG lWidth, LONG lHeight, BYTE bX1, BYTE bY1, BYTE bX2, BYTE bY2) { // 指向源图像的指针 unsigned char* lpSrc; // 循环变量 LONG i; LONG j; // 灰度映射表 BYTE bMap[256]; // 图像每行的字节数 LONG lLineBytes; // 计算图像每行的字节数 lLineBytes = WIDTHBYTES(lWidth * 8); // 计算灰度映射表 for (i = 0; i <= bX1; i++) { // 判断bX1是否大于0(防止分母为0) if (bX1 > 0) { // 线性变换 bMap[i] = (BYTE) bY1 * i / bX1; } else { // 直接赋值为0 bMap[i] = 0; } } for (; i <= bX2; i++) { // 判断bX1是否等于bX2(防止分母为0) if (bX2 != bX1) { // 线性变换 bMap[i] = bY1 + (BYTE) ((bY2 - bY1) * (i - bX1) / (bX2 - bX1)); } else { // 直接赋值为bY1 bMap[i] = bY1; } } for (; i < 256; i++) { // 判断bX2是否等于255(防止分母为0) if (bX2 != 255) { // 线性变换 bMap[i] = bY2 + (BYTE) ((255 - bY2) * (i - bX2) / (255 - bX2)); } else { // 直接赋值为255 bMap[i] = 255; } } // 每行 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]; } } // 返回 return TRUE; } /************************************************************************* * * 函数名称: * ReplaceColorPal() * * 参数: * LPSTR lpDIB - 指向源DIB图像指针 * BYTE * bpColorsTable - 伪彩色编码表 * * 返回值: * BOOL - 成功返回TRUE,否则返回FALSE。 * * 说明: * 该函数用指定的伪彩色编码表来替换图像的调试板,参数bpColorsTable * 指向要替换的伪彩色编码表。 * ************************************************************************/ BOOL WINAPI ReplaceColorPal(LPSTR lpDIB, BYTE * bpColorsTable) { // 循环变量 int i; // 颜色表中的颜色数目 WORD wNumColors; // 指向BITMAPINFO结构的指针(Win3.0) LPBITMAPINFO lpbmi; // 指向BITMAPCOREINFO结构的指针 LPBITMAPCOREINFO lpbmc; // 表明是否是Win3.0 DIB的标记 BOOL bWinStyleDIB; // 创建结果 BOOL bResult = FALSE; // 获取指向BITMAPINFO结构的指针(Win3.0) lpbmi = (LPBITMAPINFO)lpDIB; // 获取指向BITMAPCOREINFO结构的指针 lpbmc = (LPBITMAPCOREINFO)lpDIB; // 获取DIB中颜色表中的颜色数目 wNumColors = ::DIBNumColors(lpDIB); // 判断颜色数目是否是256色 if (wNumColors == 256) { // 判断是否是WIN3.0的DIB bWinStyleDIB = IS_WIN30_DIB(lpDIB); // 读取伪彩色编码,更新DIB调色板 for (i = 0; i < (int)wNumColors; i++) { if (bWinStyleDIB) { // 更新DIB调色板红色分量 lpbmi->bmiColors[i].rgbRed = bpColorsTable[i * 4]; // 更新DIB调色板绿色分量 lpbmi->bmiColors[i].rgbGreen = bpColorsTable[i * 4 + 1]; // 更新DIB调色板蓝色分量 lpbmi->bmiColors[i].rgbBlue = bpColorsTable[i * 4 + 2]; // 更新DIB调色板保留位 lpbmi->bmiColors[i].rgbReserved = 0; } else { // 更新DIB调色板红色分量 lpbmc->bmciColors[i].rgbtRed = bpColorsTable[i * 4]; // 更新DIB调色板绿色分量 lpbmc->bmciColors[i].rgbtGreen = bpColorsTable[i * 4 + 1]; // 更新DIB调色板蓝色分量 lpbmc->bmciColors[i].rgbtBlue = bpColorsTable[i * 4 + 2]; } } } // 返回 return bResult; } /************************************************************************* * * 函数名称: * MedianFilter() * * 参数: * LPSTR lpDIBBits - 指向源DIB图像指针 * LONG lWidth - 源图像宽度(象素数) * LONG lHeight - 源图像高度(象素数) * int iFilterH - 滤波器的高度 * int iFilterW - 滤波器的宽度 * int iFilterMX - 滤波器的中心元素X坐标 * int iFilterMY - 滤波器的中心元素Y坐标 * * 返回值: * BOOL - 成功返回TRUE,否则返回FALSE。 * * 说明: * 该函数对DIB图像进行中值滤波。 * ************************************************************************/ BOOL WINAPI MedianFilter(LPSTR lpDIBBits, LONG lWidth, LONG lHeight, int iFilterH, int iFilterW, int iFilterMX, int iFilterMY) { // 指向源图像的指针 unsigned char* lpSrc; // 指向要复制区域的指针 unsigned char* lpDst; // 指向复制图像的指针 LPSTR lpNewDIBBits; HLOCAL hNewDIBBits; // 指向滤波器数组的指针 unsigned char * aValue; HLOCAL hArray; // 循环变量 LONG i; LONG j; LONG k; LONG l; // 图像每行的字节数 LONG lLineBytes; // 计算图像每行的字节数 lLineBytes = WIDTHBYTES(lWidth * 8); // 暂时分配内存,以保存新图像 hNewDIBBits = LocalAlloc(LHND, lLineBytes * lHeight); // 判断是否内存分配失败 if (hNewDIBBits == NULL) { // 分配内存失败 return FALSE; } // 锁定内存 lpNewDIBBits = (char * )LocalLock(hNewDIBBits); // 初始化图像为原始图像 memcpy(lpNewDIBBits, lpDIBBits, lLineBytes * lHeight); // 暂时分配内存,以保存滤波器数组 hArray = LocalAlloc(LHND, iFilterH * iFilterW); // 判断是否内存分配失败 if (hArray == NULL) { // 释放内存 LocalUnlock(hNewDIBBits); LocalFree(hNewDIBBits); // 分配内存失败 return FALSE; } // 锁定内存 aValue = (unsigned char * )LocalLock(hArray); // 开始中值滤波 // 行(除去边缘几行) for(i = iFilterMY; i < lHeight - iFilterH + iFilterMY + 1; i++) { // 列(除去边缘几列) for(j = iFilterMX; j < lWidth - iFilterW + iFilterMX + 1; j++) { // 指向新DIB第i行,第j个象素的指针 lpDst = (unsigned char*)lpNewDIBBits + lLineBytes * (lHeight - 1 - i) + j; // 读取滤波器数组 for (k = 0; k < iFilterH; k++) { for (l = 0; l < iFilterW; l++) { // 指向DIB第i - iFilterMY + k行,第j - iFilterMX + l个象素的指针 lpSrc = (unsigned char*)lpDIBBits + lLineBytes * (lHeight - 1 - i + iFilterMY - k) + j - iFilterMX + l; // 保存象素值 aValue[k * iFilterW + l] = *lpSrc; } } // 获取中值 * lpDst = GetMedianNum(aValue, iFilterH * iFilterW); } } // 复制变换后的图像 memcpy(lpDIBBits, lpNewDIBBits, lLineBytes * lHeight); // 释放内存 LocalUnlock(hNewDIBBits); LocalFree(hNewDIBBits); LocalUnlock(hArray); LocalFree(hArray); // 返回 return TRUE; } /************************************************************************* * * 函数名称: * HoughDIB() * * 参数: * LPSTR lpDIBBits - 指向源DIB图像指针 * LONG lWidth - 源图像宽度(象素数,必须是4的倍数) * LONG lHeight - 源图像高度(象素数) * 返回值: * BOOL - 运算成功返回TRUE,否则返回FALSE。 * * 说明: * 该函数用于对检测图像中的平行直线。如果图像中有两条平行的直线,则将这两条平行直线 * 提取出来。 * * 要求目标图像为只有0和255两个灰度值的灰度图像。 ************************************************************************/ float HoughDIB(LPSTR lpDIBBits, LONG lWidth, LONG lHeight) { int Anglenumber; #define pi 3.1415926 // 指向源图像的指针 LPSTR lpSrc; // 指向缓存图像的指针 LPSTR lpDst; // 指向变换域的指针 LPSTR lpTrans; // 图像每行的字节数 LONG lLineBytes; // 指向缓存DIB图像的指针 LPSTR lpNewDIBBits; HLOCAL hNewDIBBits; //指向变换域的指针 LPSTR lpTransArea; HLOCAL hTransArea; //变换域的尺寸 int iMaxDist; int iMaxAngleNumber; //变换域的坐标 int iDist; int iAngleNumber; //循环变量 long i; long j; //像素值 unsigned char pixel; //存储变换域中的两个最大值 MaxValue MaxValue1; MaxValue MaxValue2; // 暂时分配内存,以保存新图像 hNewDIBBits = LocalAlloc(LHND, lWidth * lHeight); if (hNewDIBBits == NULL) { // 分配内存失败 return FALSE; } // 锁定内存 lpNewDIBBits = (char * )LocalLock(hNewDIBBits); // 初始化新分配的内存,设定初始值为255 lpDst = (char *)lpNewDIBBits; memset(lpDst, (BYTE)255, lWidth * lHeight); //计算变换域的尺寸 //最大距离 iMaxDist = (int) sqrt(lWidth*lWidth + lHeight*lHeight); //角度从0-180,每格2度 iMaxAngleNumber = 180; //为变换域分配内存 hTransArea = LocalAlloc(LHND, lWidth * lHeight * sizeof(int)); if (hNewDIBBits == NULL) { // 分配内存失败 return FALSE; } // 锁定内存 lpTransArea = (char * )LocalLock(hTransArea); // 初始化新分配的内存,设定初始值为0 lpTrans = (char *)lpTransArea; memset(lpTrans, 0, lWidth * lHeight * sizeof(int)); // 计算图像每行的字节数 lLineBytes = WIDTHBYTES(lWidth * 8); for(j = 0; j MaxValue1.Value) { MaxValue1.Value = (int)*(lpTransArea+iDist*iMaxAngleNumber+iAngleNumber); MaxValue1.Dist = iDist; MaxValue1.AngleNumber = iAngleNumber; } } } //将第一个最大值点附近清零 for (iDist = -9;iDist < 10;iDist++) { for(iAngleNumber=-1; iAngleNumber<2; iAngleNumber++) { if(iDist+MaxValue1.Dist>=0 && iDist+MaxValue1.Dist =0 && iAngleNumber+MaxValue1.AngleNumber<=iMaxAngleNumber) { *(lpTransArea+(iDist+MaxValue1.Dist)*iMaxAngleNumber+\ (iAngleNumber+MaxValue1.AngleNumber))=0; } } } //找到第二个最大值点 for (iDist=0; iDist MaxValue2.Value) { MaxValue2.Value = (int)*(lpTransArea+iDist*iMaxAngleNumber+iAngleNumber); MaxValue2.Dist = iDist; MaxValue2.AngleNumber = iAngleNumber; } } } Anglenumber=MaxValue1.AngleNumber; // } // 释放内存 LocalUnlock(hNewDIBBits); LocalFree(hNewDIBBits); // 释放内存 LocalUnlock(hTransArea); LocalFree(hTransArea); if(Anglenumber>0) { // 返回 //MessageBox("ok",0,0); return Anglenumber+90; } else { return 90-abs(Anglenumber); } } /************************************************* * * 函数名称: * CharSegment() * * 参数: * HDIB hDIB -原图像的句柄 * * 返回值: * CRectLink -存放被分割的各个字符位置信息的链表 * * 功能: * 将图像中待识别的字符逐个分离出来并返回存放各个字符的位置信息的链表 * * 说明: * 此函数只能对2值化后的图像进行处理 * *********************************************************/ CRectLink CharSegment(HANDLE hDIB) { //清空用来保存每个字符区域的链表 CRectLink charRect1,charRect2; charRect1.clear(); charRect2.clear(); // 指向DIB的指针 LPSTR lpDIB=(LPSTR) ::GlobalLock((HGLOBAL)hDIB); // 指向DIB象素指针 LPSTR lpDIBBits; // 找到DIB图像象素起始位置 lpDIBBits = ::FindDIBBits(lpDIB); //指向象素的的指针 BYTE* lpSrc; //图像的长度和宽度 int height,width; //获取图像的宽度 width=(int)::DIBWidth(lpDIB); //获取图像的长度 height=(int)::DIBHeight(lpDIB); //计算图像每行的字节数 LONG lLineBytes = WIDTHBYTES(width * 8); //定义上下边界两个变量 int top,bottom; //象素的灰度值 int gray; //设置循环变量 int i,j; //用来统计图像中字符个数的计数器 int digicount=0; //从上往下扫描,找到上边界 //行 for (i=0;i =0;i--) { //列 for (j=0;j =rect.top ;i--) { //列 for(j=rect.left ;j m_hDC,rcDest,hDIB,rcDIB,NULL); ::GlobalUnlock((HGLOBAL)hDIB); } /*****************绘制数字字符外面的矩形框*******************/ 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); } ///////////////////////////////// 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); }