openharmony集成ocr三方库实现文字提取(代码片段)

author author     2022-12-08     127

关键词:

作者:郭岳峰

一、简介

Tesseract (Apache 2.0 License)是一个可以进行图像OCR识别的C++库,可以跨平台运行 。本样例基于Tesseract 库进行适配,使其可以运行在 OpenAtom OpenHarmony(以下简称“OpenHarmony”)上,并新增N-API接口供上层应用调用,这样上层应用就可以使用Tesseract提供的相关功能。

二、效果展示

动物图片识别文字

身份信息识别

提取文字信息到本地文件

相关代码已经上传至SIG仓库,链接如下:
https://gitee.com/openharmony-sig/knowledge_demo_temp/tree/master/FA/OCRDemo

三、目录结构

四、调用流程

调用过程主要涉及到三方面,首先应用层实现样例的效果,包括页面的布局和业务逻辑代码;中间层主要起桥梁的作用,提供N-API接口给应用调用,再通过三方库的接口去调用具体的实现;Native层使用了三方库Tesseract提供具体的实现功能。

五、源码分析

本样例源码的分析主要涉及到两个方面,一方面是N-API接口的实现,另一方面是应用层的页面布局和业务逻辑。

N-API实现

1. 首先在index.d.ts文件中定义好接口

/**
 * 初始化文字识别引擎
 * @param lang 识别的语言, eg:eng、chi_sim、 eng+chi_sim,为Null或不传则为中英文(eng+chi_sim)
 * @param trainDir 训练模型目录,为Null或不传则为默认目录
 *
 * @return 初始化是否成功 0=>成功,-1=>失败
 */
export const initOCR: (lang: string, trainDir: string) => Promise<number>;

export const initOCR: (lang: string, trainDir: string, callback: AsyncCallback<number>) => void;

/**
 * 开始识别
 * @param imagePath 图片路径(当前支持的图片格式为png, jpg, tiff)
 *
 * @return 识别结果
 */
export const startOCR: (imagePath: string) => Promise<string>;
export const startOCR: (imagePath: string, callback: AsyncCallback<string>) => void;


/**
 * 销毁资源
 */
export const destroyOCR: () => void;

代码中可以看出N-API接口initOCR和startOCR都采用了两种方式,一种是Promise,一种是Callback的方式。在样例的应用层,使用的是它们的Callback方式。

2 注册N-API模块和接口

EXTERN_C_START
static napi_value Init(napi_env env, napi_value exports) 
napi_property_descriptor desc[] = 

"initOCR", nullptr, InitOCR, nullptr, nullptr, nullptr, napi_default, nullptr
,

"startOCR", nullptr, StartOCR, nullptr, nullptr, nullptr, napi_default, nullptr
,

"destroyOCR", nullptr, DestroyOCR, nullptr, nullptr, nullptr, napi_default, nullptr
,

;
napi_define_properties(env, exports, sizeof(desc) / sizeof(desc[0]), desc);
return exports;

EXTERN_C_END

static napi_module demoModule = 
.nm_version = 1,
.nm_flags = 0,
.nm_filename = nullptr,
.nm_register_func = Init,
.nm_modname = "tesseract",
.nm_priv = ((void *)0),
.reserved = 
0
,
;

extern "C" __attribute__((constructor)) void RegisterHelloModule(void) 
napi_module_register(& demoModule);

通过nm_modname定义模块名,nm_register_func注册接口函数,在Init函数中指定了JS中initOCR,startOCR,destroyOCR对应的本地实现函数,这样就可以在对应的本地实现函数中调用三方库Tesseract的具体实现了。

3 以startOCR的Callback方式为例介绍N-API中的具体实现

static napi_value StartOCR(napi_env env, napi_callback_info info) 
    OH_LOG_ERROR(LogType::LOG_APP, "OCR StartOCR 111");
    size_t argc = 2;
    napi_value args[2] =  nullptr ;
	//1. 获取参数
    napi_get_cb_info(env, info, &argc, args, nullptr, nullptr);


    //2. 共享数据
    auto addonData = new StartOCRAddOnData
        .asyncWork = nullptr,
    ;
    //3. N-API类型转成C/C++类型
    char imagePath[1024] =  0 ;
    size_t length = 0;
    napi_get_value_string_utf8(env, args[0], imagePath, 1024, &length);

    addonData->args0 = string(imagePath);

    napi_create_reference(env, args[1], 1, &addonData->callback);

    //4. 创建async work
    napi_value resourceName = nullptr;
    napi_create_string_utf8(env, "startOCR", NAPI_AUTO_LENGTH, &resourceName);
    napi_create_async_work(env, nullptr, resourceName, executeStartOCR, completeStartOCRForCallback, (void *)addonData, &addonData->asyncWork);

    //将创建的async work加到队列中,由底层调度执行
    napi_queue_async_work(env, addonData->asyncWork);

    napi_value result = 0;
    napi_get_null(env, &result);

    return result;

首先通过napi_get_cb_info方法获取JS侧传入的参数信息,将参数转成C++对应的类型,然后创建异步工作,异步工作的方法参数中包含,执行的函数以及函数执行完成的回调函数。 我们看一下执行函数

static void executeStartOCR(napi_env env, void* data) 
    //通过data来获取数据
    StartOCRAddOnData * addonData = (StartOCRAddOnData *)data;
    napi_value resultValue;
    try 
        if (api != nullptr) 
            //调用具体的实现,读取图片像素
            PIX * pix = pixRead((const char*)addonData->args0.c_str());
            //设置api的图片像素
            api->SetImage(pix);

            //调用文字提取接口,获取图片中的文字
            char * result = api->GetUTF8Text();
            addonData->result = result;

            //释放资源
            pixDestroy (& pix);
            delete[] result;
        
     catch (std::exception e) 
        std::string error = "Error: ";
        if (initResult != 0) 
            error += "please first init tesseractocr.";
         else 
            error += e.what();
        
        addonData->result = error;
    

这个方法中通过data获取JS传入的参数,然后调用Tesseract库中提供的接口,调用具体的文字提取功能,获取图片中的文字。

执行完成后,会回调到completeStartOCRForCallback,在这个方法中会将执行函数中返回的结果转换为JS的对应类型,然后通过Callback的方式返回。

static void completeStartOCRForCallback(napi_env env, napi_status status, void * data) 
    StartOCRAddOnData * addonData = (StartOCRAddOnData *)data;
    napi_value callback = nullptr;
    napi_get_reference_value(env, addonData->callback, &callback);
    napi_value undefined = nullptr;
    napi_get_undefined(env, &undefined);
    napi_value result = nullptr;
    napi_create_string_utf8(env, addonData->result.c_str(), addonData->result.length(), &result);

    //执行回调函数
    napi_value returnVal = nullptr;
    napi_call_function(env, undefined, callback, 1, &result, &returnVal);

    //删除napi_ref对象
    if (addonData->callback != nullptr) 
        napi_delete_reference(env, addonData->callback);
    

    //删除异步工作项
    napi_delete_async_work(env, addonData->asyncWork);
    delete addonData;

应用层实现

应用层主要分为三个模块:动物图片文字识别,身份信息识别,提取文字到本地文件

1.动物图片文字识别

build() 
    Column() 
      Row() 
        Text(点击图片进行文字提取  提取结果 : ).fontSize(30fp).fontColor(Color.Blue)
        Text(this.ocrResult).fontSize(50fp).fontColor(Color.Red)
      .margin(10vp).height(10%).alignItems(VerticalAlign.Center)

      Grid() 
        ForEach(this.images, (item, index) => 
          GridItem() 
            AnimalItem(
              path1: item[0],
              path2: item[1]
            );
          
        )
      
      .padding(left: this.columnSpace, right: this.columnSpace)
      .columnsTemplate("1fr 1fr 1fr")      // Grid宽度均分成3份
      .rowsTemplate("1fr 1fr")     // Grid高度均分成2份
      .rowsGap(this.rowSpace)                  // 设置行间距
      .columnsGap(this.columnSpace)            // 设置列间距
      .width(100%)
      .height(90%)
    
    .backgroundColor(Color.Pink)
  

布局主要使用了Grid的网格布局,每个Item都是对应的图片,通过点击图片可以对点击图片进行文字提取,将提取出的文字显示在标题栏。

2.身份信息识别

build() 
    Row() 
      Column() 
        Image(/common/idImages/aobamao.jpg)
          .onClick(() => 
            //点击图片进行信息识别
            console.log(OCR begin dialog open 111);
            this.ocrDialog.open();
            ToolUtils.ocrResult(ToolUtils.aobamao, (result) => 
              console.log(111 OCR result =  + result);
              this.result = result;
              this.ocrDialog.close();
            );
          )
          .margin(10vp)
          .objectFit(ImageFit.Auto)
          .height(50%)

        Image(/common/idImages/weixiaobao.jpg)
          .onClick(() => 
            //点击图片进行信息识别
            this.ocrDialog.open();
            ToolUtils.ocrResult(ToolUtils.weixiaobao, (result) => 
              console.log(111 OCR result =  + result);
              this.result = result;
              this.ocrDialog.close();
            );
          )
          .margin(10vp)
          .objectFit(ImageFit.Auto)
          .height(50%)
      
      .width(this.screenWidth/2)
      .padding(20vp)

      Column() 
        Text(this.title).height(10%).fontSize(30fp).fontColor(this.titleColor)

        Column() 
          Text(this.result)
            .fontColor(#0000FF)
            .fontSize(50fp)
        .justifyContent(FlexAlign.Center).alignItems(HorizontalAlign.Center).height(90%)
      
      .justifyContent(FlexAlign.Start)
      .width(50%)

    
    .width(100%)
    .height(100%)
  

身份信息识别的布局最外层是一个水平布局,分为左右两部分,左边的子布局是垂直布局,里面是两张不同的身份证图片,右边子布局也是垂直布局,主要是标题区和识别结果的内容显示区。

3.提取文字到本地文件

Row() 
      Column() 
        Image(/common/save2FileImages/testImage1.png)
          .onClick(() => 
            //点击图片进行信息识别
            ToolUtils.ocrResult(ToolUtils.testImage1, (result) => 
              let path = this.dir + ocrresult1.txt;
              try 
                let fd = fileio.openSync(path, 0o100 | 0o2, 0o666);
                fileio.writeSync(fd, result);
                fileio.closeSync(fd);
                this.displayText = 文件写入 + path;
               catch (e) 
                console.log(OCR fileio error =  + e);
              
            );
          )
        Image(/common/save2FileImages/testImage2.png)
          .onClick(() => 
            //点击图片进行信息识别
            ToolUtils.ocrResult(ToolUtils.testImage2, (result) => 
              let path = this.dir + ocrresult2.txt;
              let fd = fileio.openSync(path, 0o100 | 0o2, 0o666);
              fileio.writeSync(fd, result);
              fileio.closeSync(fd);
              this.displayText = 文件写入 + path;
            );
          )
      
      Column() 
        Text(this.title)
        Column() 
          Text(this.displayText)
        
      
    

这个功能首先通过接口识别出图片中的文字,然后再通过fileio的能力将文字写入文件中。

6. 总结

样例通过Native的方式将C++的三方库集成到应用中,通过N-API方式提供接口给上层应用调用。对于依赖三方库能力的应用,都可以使用这种方式来进行,移植三方库到Native,通过N-API提供接口给应用调用。

关于样例开发,我之前还分享过《如何利用OpenHarmony ArkUI的Canvas组件实现涂鸦功能?》、《如何通过OpenHarmony的音频模块实现录音变速功能?》 欢迎感兴趣的开发者进行了解并与我交流样例开发经验。

更多原创内容请关注:深开鸿技术团队

入门到精通、技巧到案例,系统化分享OpenHarmony开发技术,欢迎投稿和订阅,让我们一起携手前行共建生态。

想了解更多关于开源的内容,请访问:​

​51CTO 开源基础软件社区​

​https://ost.51cto.com/#bkwz​

4步成功将三方库——speexdsp移植到openharmony

4步成功将三方库——speexdsp移植到OpenHarmony​战码先锋,PR征集令(以下简称“战码先锋”)第二期正如火如荼地进行中,涉及OpenAtomOpenHarmony(以下简称“OpenHarmony”)主干仓、SIG仓、三方库,共计1000+代码仓任君挑战。在战码先... 查看详情

python提取图片中的文字(代码片段)

Python提取图片中的文字相关依赖库安装OCR工具安装识别代码相关依赖库安装pipinstallPILpipinstallpytesseractOCR工具安装下载链接修改pytesseract源码中的路径,将tesseract_cmd的值改为安装Tesseract-OCR应用程序路径安装识别中文所需依赖... 查看详情

如何使用迅捷ocr文字识别软件识别提取图中文字

...由:软件采用先进的OCR识别技术,识别精度高,能够轻松实现文档数字化,操作 查看详情

将图片局部文字提取出来的小技巧

...面,我们都是借助相关OCR文字识别请添加链接描述工具来实现,下面就是具体的操作方法,有需要的朋友可以来学习一下。  步骤一、为了实现文字局部识别功能,我们需要借助百度搜索下载相关OCR文字识别工具,小编在这里... 查看详情

用python写一个图像文字识别ocr工具(代码片段)

...现。创建或者选择一个虚拟环境,安装需要用到的第三方库。condacreate-nocrcondaactivateocr①安装框架如果你没有NVIDIAGPU,或GPU不支持CUDA,可以安装CPU 查看详情

使用ocr文字识别软件将图中文字识别提取出来的方法

有时候我们上网看见了一些文字图片,上面的内容自己很喜欢,想要将文字保存下来,但是大家都知道图片上面的文字是不可以直接进行复制粘贴的,那这时候就需要识别提取图中文字了,具体怎样去操作呢?下面小编将在文字... 查看详情

如何通过迅捷ocr文字识别软件识别提取图中文字

工作中识别提取图中文字的问题,也是时常会发生的,就比如说你的领导给了你一些图片文件让你将上面的文字录入到文档里面,这时候你该不会傻傻的手动录入吧,这种方法工作效率太低了,下面小编将教大家一种通过使用文... 查看详情

python案例ocr提取图片中的文字(代码片段)

很多软件内置了OCR功能,即图片提取文字功能。有些是免费提供给大家使用,但有些是收费的。不管是免费的还是收费的,终究逃离不了隐私问题。用别人的OCR,总得把图片传到对方的服务器。今天我们使用Python... 查看详情

python案例ocr提取图片中的文字(代码片段)

很多软件内置了OCR功能,即图片提取文字功能。有些是免费提供给大家使用,但有些是收费的。不管是免费的还是收费的,终究逃离不了隐私问题。用别人的OCR,总得把图片传到对方的服务器。今天我们使用Python... 查看详情

python开发文字点选验证码,有啥推荐的方法?

...其中指定的字符或单词,以验证用户身份。在Python开发中实现文字点选验证码,一种常用的方法是使用图像处理库和机器学习库,以下是一些常用的库和方法:PIL库:PythonImagingLibrary(PIL)是一个Python图像处理库,提供了丰富的... 查看详情

python案例ocr提取图片中的文字(代码片段)

很多软件内置了OCR功能,即图片提取文字功能。有些是免费提供给大家使用,但有些是收费的。不管是免费的还是收费的,终究逃离不了隐私问题。用别人的OCR,总得把图片传到对方的服务器。今天我们使用Python... 查看详情

对图片中的局部文字提取的教程

...的文字进行提取,则我们需要借助相关OCR文字识别软件来实现,你可以搜索迅捷办公找到迅捷OCR文字识别软件将其下载安装下来。  步骤二、打开软件,接着切换到图片局部识别板块选项,点击添加文件按钮将对应的图片添加... 查看详情

有道词典中的ocr功能:第三方库的变化

  之前有点好奇有道词典中的OCR功能,具体来说就是强力取词功能。我知道的最有名的OCR库是tesseract,这个库是惠普在早些年前开源的。  在用python做爬虫处理验证码的时候,就会用到这个库,对应的python封装版本名字叫pyt... 查看详情

怎么把word2016中,大量图片里的文字提取出来?

...里的文字提取出来?求助,求助楼主您好,把大量的图片实现文字提取,建议使用ocr文字识别软件,因为ocr可以批量提取图片中的文字,使用起来方便省心;1、打开cor文字识别软件,选择上面的极速识别功能;2、通过左上角的... 查看详情

如何将 Tesseract OCR 库集成到 C++ 程序中

】如何将TesseractOCR库集成到C++程序中【英文标题】:HowtointegrateTesseractOCRLibrarytoaC++program【发布时间】:2012-02-2711:55:03【问题描述】:我正在尝试使用TesseractOCRLibrary来创建一个程序来读取电梯楼层号的图片。我还没有找到任何关... 查看详情

有没有一些电脑上能用的ocr识别,像手机上的qq提取文字,电脑上的ayy识别率还是太低了

...识别技术称为OCR(OpticalCharacterRecognition)。OCR技术的出现,实现了将印刷文字扫描得到的图片转化为文本文字的功能,提供了一种全新的文字输入手段,大大提高了用户工作的效率。二、OCR适合对象  1.印刷行业、文印店:经常... 查看详情

爬虫之简单验证码处理(代码片段)

...一般被称为光学文字识别(OpticalCharacterRecognition,OCR)。可以实现OCR的底层库并不多,目前很多库都是使用共同的几个底层OCR库,或者是在上面进行定制。在这里我们只重点介绍:Tesseract  Tesseract是一个OCR库,目前由Google赞助(Goo 查看详情

基于深度学习和语言模型的印刷文字ocr系统

...:3.特征提取(1)OCR技术浅探:3.特征提取(2)OCR技术浅探:4.文字定位OCR技术浅探:5.文本切割OCR技术浅探:6.光学识别OCR技术浅探:7.语言模型OCR技术浅探:8.综合评估OCR技术浅探:9.代码共享(完)泰迪杯:基于深度学习和语言模型的... 查看详情