點擊藍字 ╳ 關注我們
開源項目 OpenHarmony是每個人的 OpenHarmony郭岳峰
深圳開鴻數字產業發展有限公司
OS框架開發工程師
以下內容來自嘉賓分享,不代表開放原子開源基金會觀點1.簡介
Tesseract(Apache 2.0 License)是一個可以進行圖像OCR識別的C++庫,可以跨平臺運行 。本樣例基于Tesseract庫進行適配,使其可以運行在OpenAtom OpenHarmony(以下簡稱“OpenHarmony”)上,并新增N-API接口供上層應用調用,這樣上層應用就可以使用Tesseract提供的相關功能。2.效果展示
識別文字 身份信息識別 ? 提取文字信息到本地文件 ? ? ?相關代碼已經上傳至SIG倉庫,鏈接如下:
https://gitee.com/openharmony-sig/knowledge_demo_temp/tree/master/FA/OCRDemo
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;
/**
* 銷毀資源
*/
exportconstdestroyOCR:()=>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集成OCR三方庫實現文字提取
文章出處:【微信公眾號:OpenAtom OpenHarmony】歡迎添加關注!文章轉載請注明出處。
聲明:本文內容及配圖由入駐作者撰寫或者入駐合作網站授權轉載。文章觀點僅代表作者本人,不代表電子發燒友網立場。文章及其配圖僅供工程師學習之用,如有內容侵權或者其他違規問題,請聯系本站處理。
舉報投訴
-
鴻蒙
+關注
關注
57文章
2351瀏覽量
42850 -
OpenHarmony
+關注
關注
25文章
3722瀏覽量
16313
原文標題:OpenHarmony集成OCR三方庫實現文字提取
文章出處:【微信號:gh_e4f28cfa3159,微信公眾號:OpenAtom OpenHarmony】歡迎添加關注!文章轉載請注明出處。
發布評論請先 登錄
相關推薦
三方庫移植OpenHarmony過程
戰碼先鋒,PR征集令(以下簡稱“戰碼先鋒”)第二期正如火如荼地進行中,涉及OpenAtom OpenHarmony(以下簡稱“OpenHarmony”)主干倉、SIG倉、三方庫,共計1
使用OpenHarmonyNDK移植三方庫Speexdsp
大家好,我是一名即將本科畢業的OpenHarmony開發者,去年暑假利用了兩個月時間移植了一個語音處理的三方庫Speexdsp到OpenHarmony標準系統。主要為其編寫了`buil
快速移植OpenHarmony到三方芯片平臺的方法
移植概述本文面向希望將OpenHarmony移植到三方芯片平臺硬件的開發者,介紹一種借助三方芯片平臺自帶Linux內核的現有能力,快速移植OpenHarmony到
發表于 04-12 11:08
【PIMF】OpenHarmony啃論文俱樂部—盤點開源鴻蒙三方庫【1】
OpenHarmony third_party三方庫:三方開源庫是封裝的軟件功能,可以避免重復造輪子、提升軟件開發效率。
發表于 06-17 19:48
【PIMF】OpenHarmony啃論文俱樂部—盤點開源鴻蒙三方庫【2】
OpenHarmony third_party三方庫:三方庫(開源庫)是封裝的軟件功能,可以避免
發表于 06-29 16:44
4步成功將三方庫——speexdsp移植到OpenHarmony
歸)進行分享,他在完成了一個三方庫在OpenHarmony標準系統上的移植工作后,總結了以下經驗。四步實現三方
發表于 09-27 12:02
OpenHarmony集成OCR三方庫實現文字提取
;#125;這個功能首先通過接口識別出圖片中的文字,然后再通過fileio的能力將文字寫入文件中。6. 總結樣例通過Native的方式將C++的三方庫
發表于 11-15 12:09
OpenHarmony三方庫適配指南
本文以OpenHarmony-3.2-Beta4上適配modbus編譯動態庫為例。獲取三方庫使用之前要做好代碼溯源,確認可用的版本,開源許可和發布方式等。通過正確的路徑獲取源碼,可以是
發表于 04-07 09:12
OpenAtom OpenHarmony 三方庫創建發布及安全隱私檢測
的三方庫進行功能性測試,如果三方庫沒有真正的功能實現或其功能無法在OpenHarmony上驗證,
發表于 11-13 17:27
openharmony第三方組件適配移植的文字組合拆分庫
項目介紹 項目名稱: MatchView 所屬系列: openharmony的第三方組件適配移植 功能: 是一款由進度條來控制文字的組合和拆分的庫 項目移植狀態: 主功能完成 調用差異
發表于 03-30 10:59
?0次下載
基于openharmony實現綁定ability和fraction頁面切換的三方庫
項目介紹 項目名稱:Alligator 所屬系列:openharmony的第三方組件適配移植 功能:通過注解處理器實現一套綁定ability和fraction頁面切換的三方
發表于 04-08 10:21
?1次下載
總結移植三方庫到OpenHarmony的經驗
三方庫主要是基于標準 Linux 系統的 c/c++ 開源庫,所以三方庫的移植工作,首先是在標準 Linux 系統搭建環境、編譯與驗證,然后
鴻蒙三方庫適配指南
本文以 OpenHarmony-3.2-Beta4 上適配 modbus 編譯動態庫為例。 獲取三方庫 使用之前要做好代碼溯源,確認可用的版本,開源許可和發布方式等。 通過正確的路徑獲
【開源三方庫】bignumber.js:一個大數數學庫
點擊藍字 ╳ 關注我們 開源項目 OpenHarmony 是每個人的 OpenHarmony OpenAtom OpenHarmony (以下簡稱“OpenHarmony”)
【開源三方庫】crypto-js加密算法庫的使用方法
點擊藍字 ╳ 關注我們 開源項目 OpenHarmony 是每個人的 OpenHarmony OpenAtom OpenHarmony(簡稱“OpenHarmony”)
評論