C++/MFC大漠OCR文字识别原理
参考自:
解密大漠插件文字识别原理(带源码) 展示MFC部分源码:
文字识别原理在很多人面前已经不是什么秘密了,但是通过理解这些原理,我们可以更好的使用大漠插件文字识别功能
事情的起源是我异想天开的想用纯TC代替大漠插件进行文字识别,又懒得自己写一个字库制作工具,就想利用大漠综合工具制作的字库进行文字识别…
于是乎就开始探索大漠字库的奥秘…
402807FF801002$1$0.0.17$11
以上是一个1字的大漠字库信息,我们可以很明显的看到,信息字串用"$"符号,分为4个部分,下面我们就来一一分析这4个部分代表什么,有什么用
第一部分 402807FF801002 很明显是一个十六进制字符串
我们知道电脑显示图也好字也好,都是以像素颜色点来显示的.
那么一个字的组成,就是一个点阵的组合,如下图:
我们可以看到,这是一个二值化点阵,点阵只有两种色块(像素点)组成,黑色(字体色)和灰色(背景色)
大漠插件用1表示黑色(字体色),用0表示灰色(背景色),如下
对了千万不要被下面的数字所欺骗,要像图中一样的读法才能完美解析。
00100
11100
00100
00100
00100
00100
00100
00100
00100
00100
11111
以从上到下,从左到右的顺序排列
那么上面的点阵,就是:0100000000101000000001111111111110000000000100000000001
错误示范:
我们可以看到最后一组多加了一个0,这个0是怎么加的呢?
以字体点阵的最大宽度(例:5)除以4,余数是多少就加多少个0(例:5/4余1)
402807FF801002,我们可以看到字库的点阵信息就还原出来了
那么,字库信息的第一部分就是字体点阵的信息
这下把我两天来研究的解析大漠字库MFC/C++代码贡献给大家
代码:
int CFinndstrExDlg::GetDict(CString str_a)
{
CString str,str1;
int strl = str_a.GetLength();
CString Dict1; //要操作字体的点阵
CString Neam; //要操作的字符名称
CString czs;//有效像数
CString chs;//竖排行数
int strlock = 0;
for (UINT64 i = 0; i < strl; i++)
{
str1 = str_a.Mid(i, 1);
if (str1=="$")
{
strlock++;
}
if (strlock==0 && str1 != "$")
{
Dict1 += str1;
str1 = "";
}
if (strlock == 1 && str1 != "$")
{
Neam += str1;
str1 = "";
}
if (strlock == 2&& str1!="$")
{
czs += str1;
str1 = "";
}
if (strlock == 3 && str1 != "$")
{
chs += str1;
str1 = "";
}
}
if (Dict1.GetLength()<=0|| Neam.GetLength() <= 0|| czs.GetLength() <= 0|| chs.GetLength() <= 0)
{
return 0;//读取错误返回0
}
//下面我们申请一个字库机构体
// 当然这个机构体要放到外面
//struct MyDict
//{
// CString Dict; //要操作字体的点阵
// CString Neam; //要操作的字符名称
// int yxxs;//有效像数
// int spxs;//竖排行数
//};
Dict.Dict=(strToren(Dict1));//转换到二进制
Dict.Neam = Neam; //要找的字符名称
str = czs.Mid(4, czs.GetLength() - 1);
Dict.yxxs = StrToInt(str);//字符转换到整数
Dict.spxs = StrToInt(chs);//这是竖排行数
return 1;
}
第二部分 1 我们制作字库时定义的字
这个就不用再详细解释了吧,这是代表了字库点阵信息的字符,是我们在制作字库时,自己定义的(系统字库自动定义).如下图:
下面贴出部分图片转二值化的代码:
int redToGreen(COLORREF& c,CString color,float sim)//把图片二值化
{
BYTE R = c;// GetRValue(c);//获取c中R的值
int c1 = StrToInt(color);
//获取c1中RGB的值
BYTE R1 = c1;// GetRValue(c);//获取c中R的值
if (R>0)
{
if (R1>=R)
{
if ((R1-R)<=(R/ sim)) {R = 1;}else{ R = 0;}
}
else if (R1 <= R)
{
if ((R - R1) <= (R / sim)) {R = 1;} else{ R = 0;}
}
}
else
{
return 0;
}
return R;
}
以上代码还未经过测试,因为还没写完。
这东西必须写完才能测试。
本帅还编写了了一个:X64||X86通用汇编代码注入器!
下面贴出图片