现在有扫描仪能够扫描书本,由此我想到怎样编程实现识别图片中的文字,譬如我如果扫描一页文字,存为jpg格式,请谈谈怎样用VC编写程序来识别这jpg图片中的文字。

解决方案 »

  1.   

    同意 中文hgl 的观点!
      

  2.   

    搜索一下ocr技术吧。很复杂的啊。
      

  3.   

    汉字的智能识:
    就是图像处理的过程,其中具体涉及很多种算法,我以前玩过的一种算法是投影法,将汉字从不同的方向上的投影统计存起来,然后结合图像处理总之,是个慢工程来着。
    OCR
      

  4.   

    VC+XML+DataBase可以慢慢的搞定,嗯!
      

  5.   

    我只要对印刷体能识别就可以了,提供类或dll都可以
      

  6.   

    to kingfire() 
    你的代码能否给我看看?[email protected]
      

  7.   

    只要搞好二值化,印刷体的识别是很简单的。复杂的其实是版面分析、二值化等东西。手写体的OCR识别就更困难一些了。
      

  8.   

    to: duxianghe(简单的人----delphi) 
    看来很难啊,可能要站在巨人的肩膀上--找些他人的类或dll
      

  9.   

    参考汉王的嵌入式OCR(如微普、超星等阅读器)
      

  10.   

    to bright5(星点星) 
    不用老想着别人呀!楼上有一个人说的也不对:是个长期以来大家以为解决了实际上没有解决的问题。 其实这个问题早就解决了的。你能想起手写板吗?对了,它们的工作原理是一样的,有一个相似的算法,只不过手写板是靠算出压力,而字体识别,靠的是图像中像素的RGB,除了这些,这两个程序就一样了,对吧。
    从图像得到字形很容易,只是我不知道由这个字形,如何判断它就是这个汉字,我想可能要有一个汉字库吧,这就是我所不知道的。楼下的go on.
    楼主我们联系联系。
      

  11.   

    从图像得到字形很容易,是啊,但得到的字形仍然是图形格式的东西,难就难在怎样将它与汉字库里的汉字进行最佳匹配
    超星等阅读器的ocr都是一些dll,我如何将它的接口函数调出呢?
      

  12.   

    不一样吧?手写可以记录轨迹,图片怎么记录轨迹?而且手写可以比较明确分离出一个字,图片怎么分离?
    比如说一个图章上面所有的文字,是圆形环绕,通过分离出单个文字识别很困难。
    算法不好通过,当然,印刷体好做,可以简单分离出单个文字识别,这个相信还容易些。
    用softice跟跟看看吧,还有的话老外有一套sdk可以用的,自己找找看看吧。
      

  13.   

    太过复杂,做文字识别的过程太麻烦了,是一项专门的学科
    建议不要希望独自完成这个工程了,工程庞大
    文字识别的过程:采样->提取特征值->建立特征库(这个过程方法很多,但真正有效的却非常复杂,设计许多方面的知识)
    有了特征库后可以根据特征进行查找,以前做毕业设计的时候做过
    感觉要识别汉字几乎不可能,除非你专门做模式识别方面的东西
      

  14.   

    duxianghe(简单的人----delphi)说的有道理,但是有一点需要指出:
    如果是手写板,那么直接可以得到矢量的特征,而如果是印刷体,则只能得到像素值,这也是图像和图形的区别之一。从图像得到能够区别不同汉字的特征是一个很艰难的过程的,如果有了这些特征,那么现在的神经网络和机器学习技术可以很简单的把汉字识别出来的。
      

  15.   

    to: cliff166()
    由图像到矢量也不难呀,还是难在怎么把矢量-->汉字。
      

  16.   

    我觉得两个做好都不容易,现在看来做一个好的识别软件不是一个人的事情啊。
    我看还是考虑如何用用超星的dll吧,谁能帮我?
      

  17.   

    同意duxianghe(简单的人----delphi),矢量化不难,我已经做到了,但是如何建立识别字库很难,要做到一次定位,我的意思是快速查询,而不要使用遍历的办法非常困难,需要很多的测试才可以。
    我的意见仍然是,老外有SDK可用,可以下在用用。
      

  18.   

    建议楼主去微软亚洲研究院看看,也许有很大的收获!http://research.microsoft.com/asia/
      

  19.   

    还是去北邮看看吧,他们的OCR已经有一定水平了,你要是想一个人搞定,一个字“难”!
      

  20.   

    我不认为会有人在这里公布高效的识别算法,做出来都是商业产品的核心技术。至于有人说这个问题已经解决,请问是哪篇论文里面提到的。所谓的手协板,识别率根本不高,特别是字迹潦草的时候。
    我觉得现在唯一可用的是印刷体的识别,但一个人研究,没好的导师+1,2年时间,很难出成果把,我看还是和国内的ocr技术好的公司合作来的见效较快。毕竟,老板也只是让你解决这个问题把。
      

  21.   

    我有加密的DLL,能够进行车牌照识别,在中等图象质量的情况下,识别率可达80%以上。该DLL可以提供给大家,但有一个小小的要求,必须提供解密后的源码给我,有能力的请回贴。
      

  22.   

    我觉得超星的ocr识别印刷体准确率还可以,它的dll文件也不大呀,可想而知其代码行数也不会太多的,为什么一个人就编写不了呢?
      

  23.   

    谁是反编译高手能否看看超星的ocr的dll
      

  24.   

    to horsehorse(老马) 
    我也发现了,还有尚书36也是汉王,汉王确实很牛啊
    如果找到接口了,汉王会不会告我们啊?
      

  25.   

    我都要哭了,真的有点被现实征服的感觉;
    但,谁能帮我征服现实?
    汉王的dll才一两兆啊,能有什么东东?反编译高手都哪儿去了?
      

  26.   

    我来想一个,纯粹为了好玩儿:)
    在图像质量优的情况下: 第一步先将字体的宽度减至1.第二, 由单个汉字的最左、上开始, 记录下每个分岔点.(自己设计一个数据结构,用递归实现应该很简单的.非常类似于扫雷的实现方法.)第三, 同时记录下每个孤立点. 第四, 以分岔点的个数和位置(包括孤立点)为KEY建立结构/或者数据库. 这种方法的效率应该不低的.
    在图像质量差的情况下: 对每一个汉字,从外向内建立四个矩形.每个矩形与汉字相交, 将每条边分成左右两段, 在每段上统计交点的个数. 将交点个数分成多与少两个集合, 用以区分连线与断线. 这样在每个矩形上可以产生16种可能性. 4个矩形可以产生2的16次方的可能性, 也就是65536个. 足够判断所有的汉字了. 如果认为分辨率不够, 还可以增加矩形的数目.呵呵,空想社会主义者.
      

  27.   

    : netxy(netxy) 
    我觉得在图像质量优的情况下的算法不是树了,好象是个图,而且是个弱连通图,可是怎么和字模码联系。
    在图像质量差的情况下的方法我还是不太懂。
    能否由空想社会主义者变成社会主义者?给出code吧!
      

  28.   

    bright5(星点星): 
        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];
    };
      

  29.   

    // Character.h: interface for the CCharacter class.
    //
    //////////////////////////////////////////////////////////////////////
    #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_)
      

  30.   

    // Character.cpp: implementation of the CCharacter class.
    //
    //////////////////////////////////////////////////////////////////////#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;
    }