OpenHarmony整合OCR三方庫實現文字提取
1. 簡介
Tesseract(Apache 2.0 License)是一個可以進行影像OCR識別的C++庫,可以跨平臺執行 。本樣例基於Tesseract庫進行適配,使其可以執行在OpenAtom OpenHarmony(以下簡稱“OpenHarmony”)上,並新增N-API介面供上層應用呼叫,這樣上層應用就可以使用Tesseract提供的相關功能。
2. 效果展示
動物圖片識別文字
身份資訊識別
提取文字資訊到本地檔案
相關程式碼已經上傳至SIG倉庫,連結如下:
3. 目錄結構
4. 呼叫流程
呼叫過程主要涉及到三方面,首先應用層實現樣例的效果,包括頁面的佈局和業務邏輯程式碼;中間層主要起橋樑的作用,提供N-API介面給應用呼叫,再透過三方庫的介面去呼叫具體的實現;Native層使用了三方庫Tesseract提供具體的實現功能。
5. 原始碼分析
本樣例原始碼的分析主要涉及到兩個方面,一方面是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 = { }, }; 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的音訊模組實現錄音變速功能? 》歡迎感興趣的開發者進行了解並交流樣例開發經驗。
來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/70011554/viewspace-2923390/,如需轉載,請註明出處,否則將追究法律責任。
相關文章
- excel表格文字識別-ocr表格文字提取api介面整合ExcelAPI
- 表格轉文字如何實現-表格文字識別介面整合示例-快速提取表格中的文字
- OCR圖片文字提取工具:Initiater for Mac中文版Mac
- 如何精準實現OCR文字識別?
- Java也能做OCR!SpringBoot 整合 Tess4J 實現圖片文字識別JavaSpring Boot
- C#呼叫DLL實現影像文字識別(OCR)C#
- Java 實現OCR掃描/識別圖片文字Java
- Initiater 中文最新安裝包:Mac電腦好用的ocr文字提取軟體Mac
- mac上如何提取圖片上的文字?幾款不錯的OCR文字識別工具推薦Mac
- 如何通過OpenHarmony系統中整合的ffmpeg庫和NAPI機制,實現更多的多媒體功能?API
- 如何透過OpenHarmony系統中整合的ffmpeg庫和NAPI機制,實現更多的多媒體功能?API
- 3.基於LSTM+CTC實現不定長文字圖片OCR
- 達觀OCR首創無錨點文字提取演算法,攻克行業難點演算法行業
- CGO入門和OCR文字識別(非第三方API,有原始碼,效果好)實戰GoAPI原始碼
- 如何實現OpenHarmony的OTA升級
- OpenAtom OpenHarmony三方庫建立釋出及安全隱私檢測
- webpack提取第三方庫的正確姿勢Web
- ocr文字識別技術
- Byakuren:一個 C 實現的主題色提取庫
- vim技巧--提取文字與文字替換
- PHP OCR實戰:用Tesseract從影像中讀取文字PHP
- 整合ExtJS和第三方類庫JS
- OCR技術-文字影像識別
- python 網頁文字提取Python網頁
- 達觀OCR文字識別賦能公積金中心實現業務辦理再提速
- 中安OCR文字識別系統
- TH-OCR文字識別技術
- Text Scanner for Mac ocr文字識別工具Mac
- OCR文字識別工具:OCRKit Pro中文
- OCR 文字檢測(Differentiable Binarization --- DB)
- OCRKit Pro for mac (OCR文字識別工具)Mac
- OCR文字識別工具:OCRKit Pro macMac
- kaarbe/html-extractor:從HTML中提取文字的簡單Java庫HTMLJava
- 文字實現ftpFTP
- 高效的PDF文字提取技術
- Python提取文字指定內容Python
- OpenHarmony Docker移植實踐Docker
- 錄音內容如何轉成文字?從音訊中提取文字的實用方法音訊