to: duxianghe(简单的人----delphi) 看来很难啊,可能要站在巨人的肩膀上--找些他人的类或dll
参考汉王的嵌入式OCR(如微普、超星等阅读器)
to bright5(星点星) 不用老想着别人呀!楼上有一个人说的也不对:是个长期以来大家以为解决了实际上没有解决的问题。 其实这个问题早就解决了的。你能想起手写板吗?对了,它们的工作原理是一样的,有一个相似的算法,只不过手写板是靠算出压力,而字体识别,靠的是图像中像素的RGB,除了这些,这两个程序就一样了,对吧。 从图像得到字形很容易,只是我不知道由这个字形,如何判断它就是这个汉字,我想可能要有一个汉字库吧,这就是我所不知道的。楼下的go on. 楼主我们联系联系。
就是图像处理的过程,其中具体涉及很多种算法,我以前玩过的一种算法是投影法,将汉字从不同的方向上的投影统计存起来,然后结合图像处理总之,是个慢工程来着。
OCR
你的代码能否给我看看?[email protected]
看来很难啊,可能要站在巨人的肩膀上--找些他人的类或dll
不用老想着别人呀!楼上有一个人说的也不对:是个长期以来大家以为解决了实际上没有解决的问题。 其实这个问题早就解决了的。你能想起手写板吗?对了,它们的工作原理是一样的,有一个相似的算法,只不过手写板是靠算出压力,而字体识别,靠的是图像中像素的RGB,除了这些,这两个程序就一样了,对吧。
从图像得到字形很容易,只是我不知道由这个字形,如何判断它就是这个汉字,我想可能要有一个汉字库吧,这就是我所不知道的。楼下的go on.
楼主我们联系联系。
超星等阅读器的ocr都是一些dll,我如何将它的接口函数调出呢?
比如说一个图章上面所有的文字,是圆形环绕,通过分离出单个文字识别很困难。
算法不好通过,当然,印刷体好做,可以简单分离出单个文字识别,这个相信还容易些。
用softice跟跟看看吧,还有的话老外有一套sdk可以用的,自己找找看看吧。
建议不要希望独自完成这个工程了,工程庞大
文字识别的过程:采样->提取特征值->建立特征库(这个过程方法很多,但真正有效的却非常复杂,设计许多方面的知识)
有了特征库后可以根据特征进行查找,以前做毕业设计的时候做过
感觉要识别汉字几乎不可能,除非你专门做模式识别方面的东西
如果是手写板,那么直接可以得到矢量的特征,而如果是印刷体,则只能得到像素值,这也是图像和图形的区别之一。从图像得到能够区别不同汉字的特征是一个很艰难的过程的,如果有了这些特征,那么现在的神经网络和机器学习技术可以很简单的把汉字识别出来的。
由图像到矢量也不难呀,还是难在怎么把矢量-->汉字。
我看还是考虑如何用用超星的dll吧,谁能帮我?
我的意见仍然是,老外有SDK可用,可以下在用用。
我觉得现在唯一可用的是印刷体的识别,但一个人研究,没好的导师+1,2年时间,很难出成果把,我看还是和国内的ocr技术好的公司合作来的见效较快。毕竟,老板也只是让你解决这个问题把。
我也发现了,还有尚书36也是汉王,汉王确实很牛啊
如果找到接口了,汉王会不会告我们啊?
但,谁能帮我征服现实?
汉王的dll才一两兆啊,能有什么东东?反编译高手都哪儿去了?
在图像质量优的情况下: 第一步先将字体的宽度减至1.第二, 由单个汉字的最左、上开始, 记录下每个分岔点.(自己设计一个数据结构,用递归实现应该很简单的.非常类似于扫雷的实现方法.)第三, 同时记录下每个孤立点. 第四, 以分岔点的个数和位置(包括孤立点)为KEY建立结构/或者数据库. 这种方法的效率应该不低的.
在图像质量差的情况下: 对每一个汉字,从外向内建立四个矩形.每个矩形与汉字相交, 将每条边分成左右两段, 在每段上统计交点的个数. 将交点个数分成多与少两个集合, 用以区分连线与断线. 这样在每个矩形上可以产生16种可能性. 4个矩形可以产生2的16次方的可能性, 也就是65536个. 足够判断所有的汉字了. 如果认为分辨率不够, 还可以增加矩形的数目.呵呵,空想社会主义者.
我觉得在图像质量优的情况下的算法不是树了,好象是个图,而且是个弱连通图,可是怎么和字模码联系。
在图像质量差的情况下的方法我还是不太懂。
能否由空想社会主义者变成社会主义者?给出code吧!
Yes, the algorithm of searching connection points is a graph, but the ADT for storing characters is a tree. I think the algorithm is something like this:// Character.htypedef enum {left, upperleft, up, upperright, right, downright, down, downleft, inside, outside} PositionDescriptor;class CCharacter {
public:
CCharacter(){}
void SetBMP(unsigned char source[][]);
BOOL operator==(CCharacter &in);
BOOL operator<(CCharacter &in);
protected:
void TrimBMP(unsigned char source[][]);
CCharacterBlock * pFirstBlock;
};class CCharacterBlock {
public:
CCharacterBlock() {}
BOOL operator==(CCharacterBlock &in);
BOOL operator<(CCharacterBlock &in);
protected:
CCharacterBlock * neighbours[10];
CConnectionPoint * pFirstPoint;
};class CConnectionPoint {
public:
CConnectionPoint() {}
BOOL operator==(CConnectionPoint &in);
BOOL operator<(CConnectionPoint &in);
private:
CConnectionPoint * neightbours[8];
};
//
//////////////////////////////////////////////////////////////////////
#include <stdio.h>
#include <windows.h>#if !defined(AFX_CHARACTER_H__E3F2F298_003F_442F_BD3A_4546CDE28FBC__INCLUDED_)
#define AFX_CHARACTER_H__E3F2F298_003F_442F_BD3A_4546CDE28FBC__INCLUDED_#if _MSC_VER > 1000
#pragma once
#endif // _MSC_VER > 1000typedef enum {left, upperleft, up, upperright, right, lowerright, down,
lowerleft, inside, outside} PositionDescriptor;const int width = 255, height = 255;class CConnectionPoint {
public:
CConnectionPoint();
BOOL operator==(CConnectionPoint &in);
BOOL operator<(CConnectionPoint &in);
virtual ~CConnectionPoint();
CConnectionPoint * neighbours[8];
protected:
};class CCharacterBlock {
public:
CCharacterBlock();
BOOL operator==(CCharacterBlock &in);
BOOL operator<(CCharacterBlock &in);
inline int GetPoints() { return _points;}
CConnectionPoint * GetNextPoint();
virtual ~CCharacterBlock();
protected:
void SetPoints();
CConnectionPoint * pFirstPoint, * pPoint;
CCharacterBlock * neighbours[10];
int _points;
};class CCharacter
{
public:
CCharacter();
void SetBMP(unsigned char source[][width]);
BOOL operator==(CCharacter &in);
BOOL operator<(CCharacter &in);
inline int GetBlocks() { return _blocks;}
CCharacterBlock * GetNextBlock();
virtual ~CCharacter();
protected:
void TrimBMP(unsigned char source[][width]);
void SetBlocks();
CCharacterBlock * pFirstBlock, *pBlock;
int _blocks;
};#endif // !defined(AFX_CHARACTER_H__E3F2F298_003F_442F_BD3A_4546CDE28FBC__INCLUDED_)
//
//////////////////////////////////////////////////////////////////////#include "Character.h"//////////////////////////////////////////////////////////////////////
// Construction/Destruction
//////////////////////////////////////////////////////////////////////CCharacter::CCharacter()
{
pFirstBlock = NULL;
pBlock = NULL;
_blocks = 0;
}CCharacter::~CCharacter()
{
}void CCharacter::SetBMP(unsigned char source[][width])
{
TrimBMP(source);
SetBlocks(); // The pFirstBlock should be available by now.
}BOOL CCharacter::operator ==(CCharacter &in)
{
pBlock = GetNextBlock();
CCharacterBlock * tmpBlock;
int direction = left;
if(GetBlocks() != in.GetBlocks())
return FALSE;
// Now the number of blocks is equal.
tmpBlock = in.GetNextBlock();
while(pBlock == tmpBlock)
{
pBlock = GetNextBlock();
tmpBlock = in.GetNextBlock();
}
if(pBlock == NULL || tmpBlock == NULL)
{
if(pBlock != tmpBlock) return FALSE;
}
// Now we can say the two characters are equal;
return TRUE;
}BOOL CCharacterBlock::operator ==(CCharacterBlock &in)
{
pPoint = in.GetNextPoint();
CConnectionPoint * tmpPoint;
int direction = left; if(GetPoints() != in.GetPoints())
return FALSE;
tmpPoint = in.GetNextPoint();
while(pPoint == tmpPoint)
{
pPoint = GetNextPoint();
tmpPoint = in.GetNextPoint();
}
if(pPoint == NULL || tmpPoint == NULL)
{
if(pPoint != tmpPoint) return FALSE;
}
// Now we can say the two blocks are equal.
return TRUE;
}BOOL CConnectionPoint::operator ==(CConnectionPoint &in)
{
for(int i=left; i<8; ++i)
{
if(neighbours[i] != in.neighbours[i])
return FALSE;
} return TRUE;
}