📄 bmpproc.cpp
字号:
//传递灰度值
gray=*lpSrc;
//如果点在图像内、颜色为黑色并且没有被访问过
if(y+1 <lHeight && x+1 <lWidth && 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 <lWidth && 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 && x+1 <lWidth && 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;
}
//如果递归结束,返回false,说明是离散点
return FALSE;
}
void CBmpProc::Adjust(HDIB hDIB)
{
// 指向DIB的指针
LPBYTE lpDIB=(LPBYTE) ::GlobalLock((HGLOBAL)hDIB);
// 指向DIB象素指针
LPBYTE lpDIBBits;
// 找到DIB图像象素起始位置
lpDIBBits = m_clsDIB.FindDIBBits(lpDIB);
// 指向源图像的指针
unsigned char* lpSrc;
// 循环变量
LONG i;
LONG j;
// 图像每行的字节数
LONG lLineBytes;
//图像的长度
LONG lWidth;
//图像的宽度
LONG lHeight;
//获取图像的长度
lWidth= m_clsDIB.DIBWidth (lpDIB);
//获取图像的宽度
lHeight= m_clsDIB.DIBHeight (lpDIB);
// 计算图像每行的字节数
lLineBytes = WIDTHBYTES(lWidth * 8);
//图像左半边的平均高度
double leftaver=0.0;
//图像右半边的平均高度
double rightaver=0.0;
//图像的倾斜度
double slope;
//统计循环变量
LONG counts=0;
//扫描左半边的图像,求黑色象素的平均高度
//行
for (i=0;i<lHeight;i++)
{
//列
for (j=0;j<lWidth/2;j++)
{
//指向第i行第j个象素的指针
lpSrc=(unsigned char*)lpDIBBits + lLineBytes * i + j;
//如果为黑点
if (*lpSrc == 0)
{
//对其高度进行统计叠加
counts +=lWidth/2 -j;
leftaver += i*(lWidth/2 -j);
}
}
}
//计算平均高度
leftaver /= counts;
//将统计循环变量重新赋值
counts =0;
//扫描右半边的图像,求黑色象素的平均高度
//行
for (i =0;i<lHeight;i++)
{
//列
for (j=lWidth/2;j<lWidth;j++)
{
//指向第i行第j个象素的指针
lpSrc=(unsigned char*)lpDIBBits + lLineBytes * i + j;
//如果为黑点
if (*lpSrc == 0)
{
//进行统计叠加
counts +=lWidth -j;
rightaver += i*(lWidth -j);
}
}
}
//计算右半边的平均高度
rightaver /= counts;
//计算斜率
slope = (leftaver - rightaver) / (lWidth/2);
//指向新的图像象素起始位置的指针
LPSTR lpNewDIBBits;
//指向新图像的指针
LPSTR lpDst;
//新图像的句柄
HLOCAL nNewDIBBits=LocalAlloc(LHND,lLineBytes*lHeight);
//锁定内存
lpNewDIBBits=(char*)LocalLock(nNewDIBBits);
//指向新图像象素的指针
lpDst=(char*)lpNewDIBBits;
//为新图像赋初始值
memset(lpDst,(BYTE)255,lLineBytes*lHeight);
//象素点的灰度值
int gray;
//位置映射值
int i_src;
//根据斜率,把当前新图像的点映射到源图像的点
//行
for (i=0;i<lHeight;i++)
{
//列
for (j=0;j<lWidth;j++)
{
//计算映射位置
i_src=int(i - (j-lWidth/2)*slope);
//如果点在图像外,象素置白色
if (i_src <0 || i_src >=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);
}
CRectLink CBmpProc::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;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -