📄 mydiblib.h
字号:
}
}
for(i=0; i<lx; i++)
{
for(j=0; j<ly; j++)
{
kk = i*ly + j;
f[kk] = g[kk];
}
}
}
}while(shori);
free(g);
}
/*************************************************
*
* 函数名称:
* 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;
//用来统计图像中字符个数的计数器
digicount=0;
//从上往下扫描,找到上边界
//行
for (i=0;i<height;i++)
{
//列
for (j=0;j<width;j++)
{
// 指向图像第i行,第j个象素的指针
lpSrc = (unsigned char*)lpDIBBits + lLineBytes * i + j;
//获得该点的灰度值
gray = *(lpSrc);
//看是否为黑点
if (gray == 0)
{
//若为黑点,把此点作为字符大致的最高点
top = i;
//对i强行赋值以中断循环
i=height;
//跳出循环
break;
}
//如果该点不是黑点,继续循环
}
}
//从下往上扫描,找下边界
//行
for (i = height-1;i>=0;i--)
{
//列
for (j=0;j<width;j++)
{
// 指向图像第i行,第j个象素的指针
lpSrc = (unsigned char*)lpDIBBits + lLineBytes * i + j;
//获取该点的灰度值
gray = *(lpSrc);
//判断是否为黑点
if (gray == 0)
{
//若为黑点,把此点作为字符大致的最低点
bottom = i;
//对i强行赋值以中断循环
i=-1;
//跳出循环
break;
}
//如果该点不是黑点,继续循环
}
}
//lab 用作是否进入一个字符分割的标志
bool lab = false;
//表明扫描一列中是否发现黑色点
bool black = false;
//存放位置信息的结构体
CRect rect;
//计数器置零
digicount=0;
//行
for (i=0;i<width;i++)
{
//开始扫描一列
black=false;
for (j=0;j<height;j++)
{
// 指向图像第i行,第j个象素的指针
lpSrc = (unsigned char*)lpDIBBits + lLineBytes * j + i;
//获取该点的灰度值
gray = *(lpSrc);
//判断是否为黑点
if (gray == 0)
{
//如果发现黑点,设置标志位
black=true;
//如果还没有进入一个字符的分割
if(lab==false)
{
//设置左侧边界
rect.left = i;
//字符分割开始
lab = true;
}
//如果字符分割已经开始了
else
//跳出循环
break;
}
}
//如果已经扫到了最右边那列,说明整副图像扫描完毕。退出
if(i==(width-1))
//退出整个循环
break;
//如果到此black仍为false,说明扫描了一列,都没有发现黑点。表明当前字符分割结束
if(lab==true&&black==false)
{
//将位置信息存入结构体中
//设置右边界
rect.right =i;
//设置上边界
rect.top =top;
//设置下边界
rect.bottom =bottom;
//将框外括一个象素,以免压到字符
rect.InflateRect (1,1);
//将这个结构体插入存放位置信息的链表1的后面
charRect1.push_back (rect);
//设置标志位,开始下一次的字符分割
lab=false;
//字符个数统计计数器加1
digicount++;
}
//进入下一列的扫描
}
//再将矩形轮廓矩形的top和bottom精确化
//将链表1赋值给链表2
charRect2=charRect1;
//将链表2的内容清空
charRect2.clear ();
//建立一个新的存放位置信息的结构体
CRect rectnew;
//对于链表1从头至尾逐个进行扫描
while(!charRect1.empty())
{
//从链表1头上得到一个矩形
rect= charRect1.front();
//从链表1头上面删掉一个
charRect1.pop_front();
//计算更加精确的矩形区域
//获得精确的左边界
rectnew.left =rect.left-1 ;
//获得精确的右边界
rectnew.right =rect.right+1 ;
//通过获得的精确左右边界对上下边境重新进行精确定位
// 由下而上扫描计算上边界
//行
for(i=rect.top ;i<rect.bottom ;i++)
{
//列
for(j=rect.left ;j<rect.right ;j++)
{
// 指向图像第i行,第j个象素的指针
lpSrc = (unsigned char*)lpDIBBits + lLineBytes * i + j;
//如果这个象素是黑点
if (*lpSrc == 0)
{
//设置上边界
rectnew.top = i-1;
//对i进行强制定义以跳出循环
i=rect.bottom ;
//跳出循环
break;
}
}
}
//由下而上扫描计算下边界
//行
for(i=rect.bottom-1 ;i>=rect.top ;i--)
{
//列
for(j=rect.left ;j<rect.right ;j++)
{
// 指向图像第i行,第j个象素的指针
lpSrc = (unsigned char*)lpDIBBits + lLineBytes * i + j;
//该点如果为黑点
if (*lpSrc == 0)
{
//设置下边界
rectnew.bottom = i+1;
//对i进行强制定义以跳出循环
i=-1;
//跳出循环
break;
}
}
}
//将得到的新的准确的位置信息从后面插到链表2的尾上
charRect2.push_back (rectnew);
}
//将链表2 传递给链表1
charRect1=charRect2;
//解除锁定
::GlobalUnlock(hDIB);
//将链表1返回
return charRect1;
}
/****************************************************************
* 函数名称:
* Convert256toGray()
*
* 参数:
* HDIB hDIB -图像的句柄
*
* 返回值:
* 无
*
* 功能:
* 将256色位图转化为灰度图
*
***************************************************************/
void Convert256toGray(HDIB hDIB)
{
LPSTR lpDIB;
// 由DIB句柄得到DIB指针并锁定DIB
lpDIB = (LPSTR) ::GlobalLock((HGLOBAL)hDIB);
// 指向DIB象素数据区的指针
LPSTR lpDIBBits;
// 指向DIB象素的指针
BYTE * lpSrc;
// 图像宽度
LONG lWidth;
// 图像高度
LONG lHeight;
// 图像每行的字节数
LONG lLineBytes;
// 指向BITMAPINFO结构的指针(Win3.0)
LPBITMAPINFO lpbmi;
// 指向BITMAPCOREINFO结构的指针
LPBITMAPCOREINFO lpbmc;
// 获取指向BITMAPINFO结构的指针(Win3.0)
lpbmi = (LPBITMAPINFO)lpDIB;
// 获取指向BITMAPCOREINFO结构的指针
lpbmc = (LPBITMAPCOREINFO)lpDIB;
// 灰度映射表
BYTE bMap[256];
// 计算灰度映射表(保存各个颜色的灰度值),并更新DIB调色板
int i,j;
for (i = 0; i < 256; i ++)
{
// 计算该颜色对应的灰度值
bMap[i] = (BYTE)(0.299 * lpbmi->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)
//进行递归处理
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -