跳转到主要内容
名片包含有关公司或个人的商务信息。名片可包括个人姓名、公司名称、电话号码、传真、电子邮件、网站地址以及类似信息。您可能需要从纸质名片中提取这些信息,并将其保存为电子格式。例如,可以保存到手机的电子通讯录、电子邮件客户端或任何其他数据存储系统中。比如,名片通常会以 vCard 格式通过电子邮件或网络传送。 在此场景中,您需要执行的主要步骤:
  1. 获取名片的数字副本
您可以扫描名片,也可以为名片拍照。使用移动设备数码相机拍摄的照片可能分辨率较低、质量较差。因此,可能需要对图像进行额外预处理。
  1. 识别名片
扫描得到的页面中每页可能包含多张名片。识别质量必须足够高,确保准确提取所有信息。
  1. 以合适的格式保存识别后的数据
您可以将识别后的数据保存到不同的数据存储系统中,或者将其导出为 vCard 格式并通过电子邮件发送。

场景实现

本主题中提供的代码示例仅适用于 Windows。
下文将详细介绍在此场景中使用 ABBYY FineReader Engine 的推荐方法。
要开始使用 ABBYY FineReader Engine,您需要创建 Engine 对象。Engine 对象是 ABBYY FineReader Engine 对象层次结构中的顶层对象,提供各种全局设置、部分处理方法,以及用于创建其他对象的方法。要创建 Engine 对象,您可以使用 InitializeEngine 函数。另请参阅加载 Engine 对象的其他方法 (Win) 。

C#

public class EngineLoader : IDisposable
{
    public EngineLoader()
    {
        // 使用 FREngine.dll 的完整路径、您的 Customer Project ID,
        // 以及(如适用)Online License 令牌文件的路径和 Online License 密码来初始化这些变量
        string enginePath = "";
        string customerProjectId = "";
        string licensePath = "";
        string licensePassword = "";
        // 加载 FREngine.dll 库
        dllHandle = LoadLibraryEx(enginePath, IntPtr.Zero, LOAD_WITH_ALTERED_SEARCH_PATH);
           
        try
        {
            if (dllHandle == IntPtr.Zero)
            {
                throw new Exception("Can't load " + enginePath);
            }
            IntPtr initializeEnginePtr = GetProcAddress(dllHandle, "InitializeEngine");
            if (initializeEnginePtr == IntPtr.Zero)
            {
                throw new Exception("Can't find InitializeEngine function");
            }
            IntPtr deinitializeEnginePtr = GetProcAddress(dllHandle, "DeinitializeEngine");
            if (deinitializeEnginePtr == IntPtr.Zero)
            {
                throw new Exception("Can't find DeinitializeEngine function");
            }
            IntPtr dllCanUnloadNowPtr = GetProcAddress(dllHandle, "DllCanUnloadNow");
            if (dllCanUnloadNowPtr == IntPtr.Zero)
            {
                throw new Exception("Can't find DllCanUnloadNow function");
            }
            // 将指针转换为委托
            initializeEngine = (InitializeEngine)Marshal.GetDelegateForFunctionPointer(
                initializeEnginePtr, typeof(InitializeEngine));
            deinitializeEngine = (DeinitializeEngine)Marshal.GetDelegateForFunctionPointer(
                deinitializeEnginePtr, typeof(DeinitializeEngine));
            dllCanUnloadNow = (DllCanUnloadNow)Marshal.GetDelegateForFunctionPointer(
                dllCanUnloadNowPtr, typeof(DllCanUnloadNow));
            // 调用 InitializeEngine 函数 
            // 传入 Online License 文件路径和 Online License 密码
            int hresult = initializeEngine(customerProjectId, licensePath, licensePassword, 
                "", "", false, ref engine);
            Marshal.ThrowExceptionForHR(hresult);
        }
        catch (Exception)
        {
            // 释放 FREngine.dll 库
            engine = null;
            // 在调用 FreeLibrary 之前删除所有对象
            GC.Collect();
            GC.WaitForPendingFinalizers();
            GC.Collect();
            FreeLibrary(dllHandle);
            dllHandle = IntPtr.Zero;
            initializeEngine = null;
            deinitializeEngine = null;
            dllCanUnloadNow = null;
            throw;
        }
    }
    // Kernel32.dll 函数
    [DllImport("kernel32.dll")]
    private static extern IntPtr LoadLibraryEx(string dllToLoad, IntPtr reserved, uint flags);
    private const uint LOAD_WITH_ALTERED_SEARCH_PATH = 0x00000008;
    [DllImport("kernel32.dll")]
    private static extern IntPtr GetProcAddress(IntPtr hModule, string procedureName);
    [DllImport("kernel32.dll")]
    private static extern bool FreeLibrary(IntPtr hModule);
    // FREngine.dll 函数
    [UnmanagedFunctionPointer(CallingConvention.StdCall, CharSet = CharSet.Unicode)]
    private delegate int InitializeEngine(string customerProjectId, string licensePath, 
        string licensePassword, string tempFolder, string dataFolder, bool isSharedCPUCoresMode, 
        ref FREngine.IEngine engine);
    [UnmanagedFunctionPointer(CallingConvention.StdCall)]
    private delegate int DeinitializeEngine();
    [UnmanagedFunctionPointer(CallingConvention.StdCall)]
    private delegate int DllCanUnloadNow();
    // 私有变量
    private FREngine.IEngine engine = null;
    // FREngine.dll 句柄
    private IntPtr dllHandle = IntPtr.Zero;
    private InitializeEngine initializeEngine = null;
    private DeinitializeEngine deinitializeEngine = null;
    private DllCanUnloadNow dllCanUnloadNow = null;
}
您可以使用 Engine 对象的 LoadPredefinedProfile 方法加载适用于此场景的处理设置。此方法将设置配置文件的名称作为输入 Parameter。更多信息,请参阅 使用配置文件此场景的设置可在预定义的 BusinessCardsProcessing 配置文件中找到:
  • 仅检测名片 (将 SynthesisParamsForPage 对象的 SynthesizeBusinessCards 属性设置为 TRUE) 。
  • 启用对图像中所有文本的检测,包括质量较低的小文本区域 (不检测图片和表格) 。
  • 执行分辨率校正。
  • 不执行文档逻辑结构的完整合成。

C#

// 加载预定义配置文件
engine.LoadPredefinedProfile("BusinessCardsProcessing");
如果您希望更改处理设置,请使用相应的 Parameter 对象。更多信息,请参阅下面的 特定任务的附加优化
要将图像加载到 FineReader Engine,您可以使用以下对象的方法:
Linux 和 Windows 用户可以在 使用 ABBYY FineReader Engine 进行并行处理 中了解每种方法的优缺点。当前主题重点介绍 FRDocument。
要将图像加载到 FRDocument 对象,请执行以下任一操作:所有这些方法都将 PrepareImageMode 对象用作参数,该对象允许您指定不同的图像预处理参数。调用 IEngine::CreatePrepareImageMode 函数创建此对象,然后根据需要更改其属性,再将其传递给需要它的函数。

C#

FREngine.IEngine engine;
string imagePath;
FREngine.IPrepareImageMode pim = engine.CreatePrepareImageMode();
pim.DocumentType = FREngine.DocumentTypeEnum.DT_BusinessCard;
FREngine.IFRDocument frDoc = engine.CreateFRDocument();
frDoc.AddImageFile(imagePath, pim, null);
要识别名片,请执行以下操作:
  1. 使用 RecognizerParams object 的 SetPredefinedTextLanguage 方法 指定名片所用的语言。有关可用于名片识别的语言,请参阅预定义语言列表
  2. 如有必要,设置其他处理参数。请参阅页面预处理、分析、识别和合成的调优参数
  3. 将这些参数传递给任意处理 方法 (例如,FRDocument object 的 Process 方法) 。该 方法 会填充文档及其页面的名片集合 (IFRDocument::BusinessCardsIFRPage::BusinessCards) 。
您还可以使用 FRPage object 的 SynthesizeBusinessCardSynthesizeBusinessCardEx 方法,从整个页面或每个页面上的某个区域合成名片。该 方法 会返回一个 BusinessCard object。请注意,在这种情况下,名片不会添加到页面的名片集合中。如果您选择使用 Batch Processor 的处理方式,此方法尤其有用。

C#

// 创建文档处理参数
FREngine.IDocumentProcessingParams dpp = engine.CreateDocumentProcessingParams();
// 使用指定参数执行识别
frDoc.Process( dpp );
// 访问名片
FREngine.IBusinessCard card = frDoc.BusinessCards[0];
已识别的名片 (BusinessCard 对象) 可包含以下字段:

BusinessCard_pict

  • 姓名
  • 公司名称
  • 公司职位
  • 公司地址
  • 电话号码
  • 传真
  • 手机号码
  • 电子邮件
  • 网站
您可以按类型访问每个字段 (FieldByType 属性) ,也可以按其在字段集合中的索引访问 (Field 属性) 。每个字段都有 Value 属性,可用于以 string 格式访问字段值。对于字段中的每个字符,都可以获取其识别变体 (GetCharParams 方法) 。某些字段可能由多个组成部分构成。例如,地址字段可包含邮政编码、国家、USA 的州、城市和街道地址。要访问字段的组成部分,您可以使用 Component 属性或 FindComponent 方法。前者允许您按索引访问组成部分;后者则按类型查找组成部分。对于每个组成部分,您都可以查看其类型和值,并获取每个字符的参数和识别变体 (GetCharParams 方法) 。

C#

// 获取姓名字段
FREngine.IBusinessCardField nameField = card.FieldByType( FREngine.BusinessCardFieldTypeEnum.BCFT_Name, 0 );
// 获取包含名字的组成部分
FREngine.IBusinessCardFieldComponent firstNameComponent =
  nameField.FindComponent( FREngine.BusinessCardFieldComponentTypeEnum.BCFCT_FirstName );
// 识别出的名字
string firstName = firstNameComponent.Value;
BusinessCard 对象提供了专用的 ExportToVCard 方法,用于将名片保存为 vCard 格式。文件路径作为参数传入。您也可以将名片保存为任何其他可用的导出格式,例如 XML。

C#

// 以 vCard 格式保存识别出的数据
card.ExportToVCard("D:\\sample.vcf");
// 保存为 XML
frDoc.Export("D:\\Demo.xml", FREngine.FileExportFormatEnum.FEF_XML, null);
使用完 ABBYY FineReader Engine 后,您需要卸载 Engine 对象。为此,请使用导出的 DeinitializeEngine 函数。

C#

public class EngineLoader : IDisposable
{
    // 卸载 FineReader Engine
    public void Dispose()
    {
        if (engine == null)
        {
            // Engine 尚未加载
            return;
        }
        engine = null;
        // 在调用 FreeLibrary 之前删除所有对象
        GC.Collect();
        GC.WaitForPendingFinalizers();
        GC.Collect();
        int hresult = deinitializeEngine();
 
        hresult = dllCanUnloadNow();
        if (hresult == 0)
        {
            FreeLibrary(dllHandle);
        }
        dllHandle = IntPtr.Zero;
        initializeEngine = null;
        deinitializeEngine = null;
        dllCanUnloadNow = null;
        // 清理完成后抛出异常
        Marshal.ThrowExceptionForHR(hresult);
    }
    // Kernel32.dll 函数
    [DllImport("kernel32.dll")]
    private static extern IntPtr LoadLibraryEx(string dllToLoad, IntPtr reserved, uint flags);
    private const uint LOAD_WITH_ALTERED_SEARCH_PATH = 0x00000008;
    [DllImport("kernel32.dll")]
    private static extern IntPtr GetProcAddress(IntPtr hModule, string procedureName);
    [DllImport("kernel32.dll")]
    private static extern bool FreeLibrary(IntPtr hModule);
    // FREngine.dll 函数
    [UnmanagedFunctionPointer(CallingConvention.StdCall, CharSet = CharSet.Unicode)]
    private delegate int InitializeEngine( string customerProjectId, string LicensePath, string LicensePassword, , , , ref FREngine.IEngine engine);
    [UnmanagedFunctionPointer(CallingConvention.StdCall)]
    private delegate int DeinitializeEngine();
    [UnmanagedFunctionPointer(CallingConvention.StdCall)]
    private delegate int DllCanUnloadNow();
    // 私有变量
    private FREngine.IEngine engine = null;
    // FREngine.dll 的句柄
    private IntPtr dllHandle = IntPtr.Zero;
    private InitializeEngine initializeEngine = null;
    private DeinitializeEngine deinitializeEngine = null;
    private DllCanUnloadNow dllCanUnloadNow = null;
}

所需资源

您可以使用 FREngineDistribution.csv 文件,自动生成应用程序运行所需文件的列表。对于此处理场景,请在第 5 列 (RequiredByModule) 中选择以下值: Core Core.Resources Opening Opening, Processing Processing Processing.BCR Processing.OCR Processing.OCR, Processing.ICR Processing.OCR.NaturalLanguages Processing.OCR.NaturalLanguages, Processing.ICR.NaturalLanguages Export Export, Processing 如果您修改了标准场景,请相应调整所需模块。您还需要指定应用程序使用的界面语言、识别语言以及任何附加功能 (例如,如果您需要打开 PDF 文件,则指定 Opening.PDF;如果您需要识别 CJK 语言中的文本,则指定 Processing.OCR.CJK) 。更多详细信息,请参阅 Working with the FREngineDistribution.csv File

其他优化

以下是帮助文件中的相关章节,您可以在其中找到有关为各个处理阶段设置Parameter的更多信息:

另请参见

基本使用场景实现