1
This commit is contained in:
Binary file not shown.
|
After Width: | Height: | Size: 445 KiB |
Binary file not shown.
|
After Width: | Height: | Size: 1.2 MiB |
Binary file not shown.
|
After Width: | Height: | Size: 372 KiB |
@@ -0,0 +1,20 @@
|
||||
## 1.0.8(2025-08-17)
|
||||
* 兼容鸿蒙原生
|
||||
## 1.0.7(2025-02-14)
|
||||
* 增加对web的支持,web使用时需要网络加载模型数据
|
||||
## 1.0.6(2024-12-18)
|
||||
* ios,安卓添加本地路径识别函数localFilePathImageBuilder,可自己循环批量处理.
|
||||
## 1.0.5(2024-11-01)
|
||||
* 修复ios可能的兼容问题
|
||||
## 1.0.4(2024-10-31)
|
||||
* ios没对齐安卓,失败不会返回回调.
|
||||
## 1.0.3(2024-10-27)
|
||||
升级了调用方式,使得安卓,ios用同样的方式调用,不再区别,统一使用callback,并且在回调中携带回了坐标,以便让大家通过坐标计算识别比例或者绘制位置
|
||||
.并且文本块统一为行返回(之前是文本块返回,但在源始数据中还是块和坐标)
|
||||
## 1.0.2(2024-09-24)
|
||||
* 各个函数追回了个参数language:string|null,可以是zh,ja,两种语言中文和日文识别。
|
||||
## 1.0.1(2024-05-04)
|
||||
* 更新支持IOS端,需要IOS12.0(含)+
|
||||
## 1.0.0(2024-04-10)
|
||||
* ocr文本识别,ai模型识别,离线识别。
|
||||
* tmui4.0种子用户,可免费赠送源码,无需购买
|
||||
@@ -0,0 +1,97 @@
|
||||
{
|
||||
"id": "x-ocr-s",
|
||||
"displayName": "Ocr文本识别ai模型离线本机识别无需服务端 支持ios,andriod,鸿蒙Next安卓",
|
||||
"version": "1.0.8",
|
||||
"description": "支持中文,日语,韩语,英语识别,支持本地,远程图片,相机相机选取识别文本",
|
||||
"keywords": [
|
||||
"ocr,文本识别,tmui4.0,uts"
|
||||
],
|
||||
"repository": "",
|
||||
"engines": {
|
||||
"HBuilderX": "^3.99",
|
||||
"uni-app": "",
|
||||
"uni-app-x": "^4.75"
|
||||
},
|
||||
"dcloudext": {
|
||||
"type": "uts",
|
||||
"sale": {
|
||||
"regular": {
|
||||
"price": "99.00"
|
||||
},
|
||||
"sourcecode": {
|
||||
"price": "0.00"
|
||||
}
|
||||
},
|
||||
"contact": {
|
||||
"qq": "369986563"
|
||||
},
|
||||
"declaration": {
|
||||
"ads": "无",
|
||||
"data": "无",
|
||||
"permissions": "本地相机/相册选取权限,需要征得同意。"
|
||||
},
|
||||
"npmurl": "",
|
||||
"darkmode": "x",
|
||||
"i18n": "x",
|
||||
"widescreen": "x"
|
||||
},
|
||||
"uni_modules": {
|
||||
"dependencies": [],
|
||||
"encrypt": [],
|
||||
"platforms": {
|
||||
"cloud": {
|
||||
"tcb": "√",
|
||||
"aliyun": "√",
|
||||
"alipay": "√"
|
||||
},
|
||||
"client": {
|
||||
"uni-app": {
|
||||
"vue": {
|
||||
"vue2": "-",
|
||||
"vue3": "-"
|
||||
},
|
||||
"web": {
|
||||
"safari": "-",
|
||||
"chrome": "-"
|
||||
},
|
||||
"app": {
|
||||
"vue": "-",
|
||||
"nvue": "-",
|
||||
"android": "-",
|
||||
"ios": "-",
|
||||
"harmony": "-"
|
||||
},
|
||||
"mp": {
|
||||
"weixin": "-",
|
||||
"alipay": "-",
|
||||
"toutiao": "-",
|
||||
"baidu": "-",
|
||||
"kuaishou": "-",
|
||||
"jd": "-",
|
||||
"harmony": "-",
|
||||
"qq": "-",
|
||||
"lark": "-"
|
||||
},
|
||||
"quickapp": {
|
||||
"huawei": "-",
|
||||
"union": "-"
|
||||
}
|
||||
},
|
||||
"uni-app-x": {
|
||||
"web": {
|
||||
"safari": "√",
|
||||
"chrome": "√"
|
||||
},
|
||||
"app": {
|
||||
"android": "√",
|
||||
"ios": "√",
|
||||
"harmony": "√"
|
||||
},
|
||||
"mp": {
|
||||
"weixin": "x"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,156 @@
|
||||
# x-ocr-s
|
||||
### 开发文档
|
||||
[TMUI4.0文档](https://xui.tmui.design/)
|
||||
[TMUI4.0组件库](https://ext.dcloud.net.cn/plugin?id=16369)
|
||||
|
||||
**如果需要查看效果请[下载TMUI4.0组件库应用demo](https://ext.dcloud.net.cn/plugin?id=16369),导航到原生插件栏目体验。**
|
||||
|
||||
**本插件会让你的安卓应用增加大约8.7mb体积**
|
||||
**本插件会让你的IOS应用增加大约38mb(估算)体积**
|
||||
**web端需要网络加载模型文件,因为web无法离线,也不是调用api就是本地模型加载一次后,就不需要网络了**
|
||||
|
||||
### UniApp 适配的版本
|
||||
[oc离线识别uniapp版本](https://ext.dcloud.net.cn/plugin?name=tm-ocr)
|
||||
|
||||
### 功能
|
||||
|
||||
支持以下特殊的ocr文本识别。**离线识别,不需要联网**
|
||||
|
||||
注意:鸿蒙使用本插件时第二参数语言类型不会起作用,它会自适应识别语言。
|
||||
|
||||
- 支持中文
|
||||
- 支持英文
|
||||
- 支持韩文
|
||||
- 支持日文
|
||||
|
||||
### 兼容性
|
||||
|
||||
| Harmony | IOS | Android | WEB | 小程序 |
|
||||
| --- | --- | --- | --- | --- |
|
||||
| 支持 | 支持 | 支持 | 支持 | x |
|
||||
|
||||
### 说明
|
||||
这是tmui4.0|XUI的原生插件附赠插件。种子用户可免于购买。
|
||||
|
||||
非种子用户:
|
||||
|
||||
普通授权:99元
|
||||
源码授权:299元
|
||||
|
||||
### 使用
|
||||
|
||||
如果是安卓请务必打自定义基座,如果ios:你在mac环境下配置好了环境无需打包本地编译,如果win开发ios需要打包基座。
|
||||
|
||||
安卓:
|
||||
|
||||
如果你需要32位系统和模拟器x86上运行,需要自行配置打包cpu 支持类型,配置abis
|
||||
需要自定义基座运行,且安卓5.0+(含5.0)以上支持
|
||||
|
||||
Ios:
|
||||
同样按照官方文档配置所需CPU类型,默认是arm64
|
||||
|
||||
WEB:
|
||||
请复制插件目录中的static目录到低的根目录static目录中即可。
|
||||
|
||||
### API说明
|
||||
|
||||
插件提供了三个主要的API函数用于OCR文本识别:
|
||||
|
||||
#### 1. chooseImageBuilder
|
||||
从相册或相机选择图片进行文字识别
|
||||
|
||||
```ts
|
||||
|
||||
chooseImageBuilder(
|
||||
callback: (str: string[], source: string[]) => void,
|
||||
langs: string|null
|
||||
)
|
||||
```
|
||||
|
||||
参数说明:
|
||||
- callback:识别结果回调函数
|
||||
- str: 识别出的文本数组
|
||||
- source: 包含文本位置信息的数组,每个元素为JSON字符串,格式为:`{boundingBox:[left,top,width,height], text:string}`
|
||||
- langs:识别语言,可选值:
|
||||
- 'zh':中文识别
|
||||
- 'ja':日文识别
|
||||
- null:默认中文zh
|
||||
|
||||
#### 2. downloadUrlImageBuilder
|
||||
下载网络图片进行文字识别
|
||||
|
||||
```ts
|
||||
|
||||
downloadUrlImageBuilder(
|
||||
url: string,
|
||||
callback: (str: string[], source: string[]) => void,
|
||||
langs: string|null
|
||||
)
|
||||
```
|
||||
|
||||
参数说明:
|
||||
- url:网络图片地址
|
||||
- callback:识别结果回调函数,参数同chooseImageBuilder
|
||||
- langs:识别语言,可选值同chooseImageBuilder
|
||||
|
||||
#### 3. localFilePathImageBuilder
|
||||
识别本地图片文件
|
||||
|
||||
```ts
|
||||
|
||||
localFilePathImageBuilder(
|
||||
pathfile: string,
|
||||
callback: (str: string[], source: string[]) => void,
|
||||
langs: string|null
|
||||
)
|
||||
```
|
||||
|
||||
参数说明:
|
||||
- pathfile:本地图片文件路径
|
||||
- callback:识别结果回调函数,参数同chooseImageBuilder
|
||||
- langs:识别语言,可选值同chooseImageBuilder
|
||||
|
||||
### 使用示例
|
||||
|
||||
```ts
|
||||
|
||||
import {chooseImageBuilder,downloadUrlImageBuilder,localFilePathImageBuilder} from "@/uni_modules/x-ocr-s"
|
||||
|
||||
// 从相册/相机选择图片识别
|
||||
chooseImageBuilder((txt:string[], sour:string[])=>{
|
||||
// txt为识别出的文本数组
|
||||
// sour为包含位置信息的JSON字符串数组,需要JSON.parse转换
|
||||
sour.forEach(item => {
|
||||
const info = JSON.parse(item)
|
||||
console.log('文本:', info.text)
|
||||
console.log('位置:', info.boundingBox)
|
||||
})
|
||||
}, 'zh')
|
||||
|
||||
// 识别网络图片
|
||||
downloadUrlImageBuilder(
|
||||
'https://example.com/test.jpg',
|
||||
(txt:string[], sour:string[])=>{
|
||||
console.log('识别文本:', txt)
|
||||
console.log('详细信息:', sour)
|
||||
},
|
||||
'ja' // 日文识别
|
||||
)
|
||||
|
||||
// 识别本地图片
|
||||
localFilePathImageBuilder(
|
||||
'/static/test.png',
|
||||
(txt:string[], sour:string[])=>{
|
||||
console.log('识别文本:', txt)
|
||||
console.log('详细信息:', sour)
|
||||
},
|
||||
'zh' // 中文识别
|
||||
)
|
||||
```
|
||||
|
||||
### 注意事项
|
||||
|
||||
1. 识别置信度默认设置为0.50,只返回置信度大于等于0.50的识别结果
|
||||
2. 回调函数中的source参数需要通过JSON.parse解析才能获取位置信息
|
||||
3. 建议图片清晰度较高,避免模糊、反光等影响识别效果
|
||||
4. Web端首次使用需要下载模型文件,请确保网络环境良好
|
||||
@@ -0,0 +1,7 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<manifest xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools"
|
||||
package="io.dcloud.uni_modules.xVibrateS">
|
||||
<uses-permission android:name="android.permission.VIBRATE" />
|
||||
<!-- <uses-permission android:name="android.permission.MANAGE_EXTERNAL_STORAGE" /> -->
|
||||
|
||||
</manifest>
|
||||
@@ -0,0 +1,11 @@
|
||||
{
|
||||
"minSdkVersion": "20",
|
||||
"dependencies":[
|
||||
"com.google.mlkit:text-recognition:16.0.0",
|
||||
"com.google.mlkit:text-recognition-chinese:16.0.0",
|
||||
"com.google.mlkit:text-recognition-devanagari:16.0.0",
|
||||
"com.google.mlkit:text-recognition-japanese:16.0.0",
|
||||
"com.google.mlkit:text-recognition-korean:16.0.0"
|
||||
],
|
||||
"abis": ["armeabi-v7a", "arm64-v8a"]
|
||||
}
|
||||
@@ -0,0 +1,260 @@
|
||||
import Text from "com.google.mlkit.vision.text.Text"
|
||||
import TextRecognition from "com.google.mlkit.vision.text.TextRecognition"
|
||||
import TextRecognizer from "com.google.mlkit.vision.text.TextRecognizer"
|
||||
import TextRecognizerOptionsInterface from "com.google.mlkit.vision.text.TextRecognizerOptionsInterface"
|
||||
import ChineseTextRecognizerOptions from "com.google.mlkit.vision.text.chinese.ChineseTextRecognizerOptions"
|
||||
import JapaneseTextRecognizerOptions from "com.google.mlkit.vision.text.japanese.JapaneseTextRecognizerOptions"
|
||||
|
||||
import Context from 'android.content.Context'
|
||||
import IOException from 'java.io.IOException'
|
||||
import InputStream from 'java.io.InputStream'
|
||||
import Uri from 'android.net.Uri';
|
||||
import File from 'java.io.File'
|
||||
import Bitmap from "android.graphics.Bitmap"
|
||||
import BarcodeScanner from "com.google.mlkit.vision.barcode.BarcodeScanner"
|
||||
import BarcodeScannerOptions from "com.google.mlkit.vision.barcode.BarcodeScannerOptions"
|
||||
import BarcodeScanning from "com.google.mlkit.vision.barcode.BarcodeScanning"
|
||||
import ZoomSuggestionOptions from "com.google.mlkit.vision.barcode.ZoomSuggestionOptions"
|
||||
import ZoomCallback from "com.google.mlkit.vision.barcode.ZoomSuggestionOptions.ZoomCallback"
|
||||
import Barcode from "com.google.mlkit.vision.barcode.common.Barcode"
|
||||
import InputImage from "com.google.mlkit.vision.common.InputImage"
|
||||
import Task from "com.google.android.gms.tasks.Task"
|
||||
import List from "java.util.List"
|
||||
import ByteBuffer from 'java.nio.ByteBuffer'
|
||||
import ImageFormat from 'android.graphics.ImageFormat'
|
||||
|
||||
import Vibrator from "android.os.Vibrator"
|
||||
|
||||
|
||||
import ContentValues from "android.content.ContentValues"
|
||||
import ContentUris from "android.content.ContentUris"
|
||||
import JSONObject from "org.json.JSONObject"
|
||||
import TimeZone from "java.util.TimeZone"
|
||||
import Cursor from "android.database.Cursor"
|
||||
import MediaStore from "android.provider.MediaStore"
|
||||
import SimpleDateFormat from "java.text.SimpleDateFormat"
|
||||
import Locale from "java.util.Locale"
|
||||
import MediaScannerConnection from "android.media.MediaScannerConnection"
|
||||
|
||||
|
||||
type callType = (list:any)=> void;
|
||||
|
||||
/**
|
||||
* 震动
|
||||
* @param {number} duriation 震动时间单位ms
|
||||
*/
|
||||
export function vibrator(duriation : number) : boolean {
|
||||
try {
|
||||
const context = UTSAndroid.getAppContext() as Context
|
||||
let vb = context.getSystemService(Context.VIBRATOR_SERVICE) as Vibrator;
|
||||
if (vb!.hasVibrator()) {
|
||||
vb!.vibrate(duriation.toLong());
|
||||
} else {
|
||||
return false
|
||||
}
|
||||
} catch (e) {
|
||||
console.error(e)
|
||||
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 从相册/相机中选取图片进行识别
|
||||
*/
|
||||
export function chooseImageBuilder(language:string|null) : Promise<string[]> {
|
||||
// 置信度
|
||||
let zxd = 0.50
|
||||
let local = language == null?'zh':language!
|
||||
return new Promise((res, rej) => {
|
||||
uni.chooseImage({
|
||||
count: 1,
|
||||
success(evt : ChooseImageSuccess) {
|
||||
uni.showLoading({ title: '...', mask: true })
|
||||
if (evt.tempFilePaths.length > 0) {
|
||||
const imgs = evt.tempFilePaths[0] as string;
|
||||
try {
|
||||
const decodedPath = Uri.decode(imgs).substring(7)
|
||||
const file = File(decodedPath)
|
||||
let image = InputImage.fromFilePath(UTSAndroid.getAppContext() as Context, Uri.fromFile(file));
|
||||
let opts = new ChineseTextRecognizerOptions().Builder()
|
||||
// if(local == 'ja'){
|
||||
// opts = new JapaneseTextRecognizerOptions().Builder()
|
||||
// }
|
||||
const recognizer = TextRecognition.getClient(opts.build()) as TextRecognizer;
|
||||
recognizer.process(image!)
|
||||
.addOnSuccessListener((TextList) => {
|
||||
let str = [] as string[]
|
||||
for (block in TextList.textBlocks) {
|
||||
for (line in block.lines) {
|
||||
// let lineText = line.text
|
||||
// let lineCornerPoints = line.cornerPoints
|
||||
// let lineFrame = line.boundingBox
|
||||
for (element in line.elements) {
|
||||
if (element.getConfidence() >= zxd) {
|
||||
let elementText = element.text as string;
|
||||
// let elementCornerPoints = element.cornerPoints
|
||||
// let elementFrame = element.boundingBox
|
||||
str.push(elementText as string)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
uni.hideLoading()
|
||||
vibrator(100)
|
||||
res(str as string[])
|
||||
})
|
||||
.addOnFailureListener((e) => {
|
||||
uni.hideLoading()
|
||||
rej(["识别失败"] as string[])
|
||||
})
|
||||
|
||||
|
||||
} catch (e : IOException) {
|
||||
uni.hideLoading()
|
||||
rej(["图片选取失败"] as string[])
|
||||
}
|
||||
}
|
||||
},
|
||||
fail() {
|
||||
rej(["图片选择失败"] as string[])
|
||||
}
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
/**
|
||||
* 提供一个远程图片地址进行识别
|
||||
*/
|
||||
export function downloadUrlImageBuilder(url : string,language:string|null) : Promise<string[]> {
|
||||
// 置信度
|
||||
let zxd = 0.50
|
||||
let local = language == null?'zh':language!
|
||||
uni.showLoading({ title: '...', mask: true })
|
||||
return new Promise((res, rej) => {
|
||||
uni.downloadFile({
|
||||
url,
|
||||
success(evt) {
|
||||
const contentResolver = UTSAndroid.getAppContext()!.contentResolver
|
||||
let decodedPath = evt.tempFilePath
|
||||
if (evt.tempFilePath.indexOf('file://') > -1) {
|
||||
decodedPath = Uri.decode(evt.tempFilePath).substring(7)
|
||||
}
|
||||
|
||||
try {
|
||||
const file = File(decodedPath)
|
||||
let image = InputImage.fromFilePath(UTSAndroid.getAppContext() as Context, Uri.fromFile(file));
|
||||
console.log(typeof ChineseTextRecognizerOptions)
|
||||
let opts = new ChineseTextRecognizerOptions().Builder()
|
||||
// if(local == 'ja'){
|
||||
// opts = new JapaneseTextRecognizerOptions().Builder()
|
||||
// }
|
||||
|
||||
const recognizer = TextRecognition.getClient(opts.build()) as TextRecognizer;
|
||||
if (image != null) {
|
||||
const result = recognizer.process(image!)
|
||||
.addOnSuccessListener((TextList) => {
|
||||
let str = [] as string[]
|
||||
for (block in TextList.textBlocks) {
|
||||
for (line in block.lines) {
|
||||
// let lineText = line.text
|
||||
// let lineCornerPoints = line.cornerPoints
|
||||
// let lineFrame = line.boundingBox
|
||||
for (element in line.elements) {
|
||||
if (element.getConfidence() >= zxd) {
|
||||
let elementText = element.text as string;
|
||||
// let elementCornerPoints = element.cornerPoints
|
||||
// let elementFrame = element.boundingBox
|
||||
str.push(elementText as string)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
uni.hideLoading()
|
||||
vibrator(100)
|
||||
res(str as string[])
|
||||
})
|
||||
.addOnFailureListener((e) => {
|
||||
uni.hideLoading()
|
||||
rej(["识别失败"] as string[])
|
||||
})
|
||||
} else {
|
||||
uni.hideLoading()
|
||||
rej(["图片下载失败"])
|
||||
}
|
||||
} catch (e : IOException) {
|
||||
uni.hideLoading()
|
||||
rej(["图片下载失败"])
|
||||
}
|
||||
|
||||
},
|
||||
fail() {
|
||||
uni.hideLoading()
|
||||
rej(["图片下载失败"])
|
||||
}
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
/**
|
||||
* 给定图片路径进行识别
|
||||
*/
|
||||
export function localFilePathImageBuilder(pathfile : string,language:string|null) : Promise<string[]> {
|
||||
// 置信度
|
||||
let zxd = 0.50
|
||||
let local = language == null?'zh':language!
|
||||
uni.showLoading({ title: '...', mask: true })
|
||||
return new Promise((res, rej) => {
|
||||
try {
|
||||
let decodedPath = pathfile
|
||||
if (pathfile.indexOf('file://') > -1) {
|
||||
decodedPath = Uri.decode(pathfile).substring(7)
|
||||
}
|
||||
const file = File(decodedPath)
|
||||
let image = InputImage.fromFilePath(UTSAndroid.getAppContext() as Context, Uri.fromFile(file));
|
||||
let opts = new ChineseTextRecognizerOptions().Builder()
|
||||
// if(local == 'ja'){
|
||||
// opts = new JapaneseTextRecognizerOptions().Builder()
|
||||
// }
|
||||
const recognizer = TextRecognition.getClient(opts.build()) as TextRecognizer;
|
||||
if (image != null) {
|
||||
const result = recognizer.process(image!)
|
||||
.addOnSuccessListener((TextList) => {
|
||||
let str = [] as string[]
|
||||
for (block in TextList.textBlocks) {
|
||||
for (line in block.lines) {
|
||||
// let lineText = line.text
|
||||
// let lineCornerPoints = line.cornerPoints
|
||||
// let lineFrame = line.boundingBox
|
||||
for (element in line.elements) {
|
||||
if (element.getConfidence() >= zxd) {
|
||||
let elementText = element.text as string;
|
||||
// let elementCornerPoints = element.cornerPoints
|
||||
// let elementFrame = element.boundingBox
|
||||
str.push(elementText as string)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
uni.hideLoading()
|
||||
vibrator(100)
|
||||
res(str as string[])
|
||||
})
|
||||
.addOnFailureListener((e) => {
|
||||
uni.hideLoading()
|
||||
rej(["识别失败"] as string[])
|
||||
})
|
||||
} else {
|
||||
uni.hideLoading()
|
||||
rej(["图片地址解析失败"])
|
||||
}
|
||||
} catch (e : IOException) {
|
||||
uni.hideLoading()
|
||||
rej(["图片地址解析失败"])
|
||||
}
|
||||
|
||||
|
||||
})
|
||||
}
|
||||
|
||||
@@ -0,0 +1,258 @@
|
||||
import Text from "com.google.mlkit.vision.text.Text"
|
||||
import TextRecognition from "com.google.mlkit.vision.text.TextRecognition"
|
||||
import TextRecognizer from "com.google.mlkit.vision.text.TextRecognizer"
|
||||
import TextRecognizerOptionsInterface from "com.google.mlkit.vision.text.TextRecognizerOptionsInterface"
|
||||
import ChineseTextRecognizerOptions from "com.google.mlkit.vision.text.chinese.ChineseTextRecognizerOptions"
|
||||
import JapaneseTextRecognizerOptions from "com.google.mlkit.vision.text.japanese.JapaneseTextRecognizerOptions"
|
||||
|
||||
import Context from 'android.content.Context'
|
||||
import IOException from 'java.io.IOException'
|
||||
import InputStream from 'java.io.InputStream'
|
||||
import Uri from 'android.net.Uri';
|
||||
import File from 'java.io.File'
|
||||
import Bitmap from "android.graphics.Bitmap"
|
||||
import BarcodeScanner from "com.google.mlkit.vision.barcode.BarcodeScanner"
|
||||
import BarcodeScannerOptions from "com.google.mlkit.vision.barcode.BarcodeScannerOptions"
|
||||
import BarcodeScanning from "com.google.mlkit.vision.barcode.BarcodeScanning"
|
||||
import ZoomSuggestionOptions from "com.google.mlkit.vision.barcode.ZoomSuggestionOptions"
|
||||
import ZoomCallback from "com.google.mlkit.vision.barcode.ZoomSuggestionOptions.ZoomCallback"
|
||||
import Barcode from "com.google.mlkit.vision.barcode.common.Barcode"
|
||||
import InputImage from "com.google.mlkit.vision.common.InputImage"
|
||||
import Task from "com.google.android.gms.tasks.Task"
|
||||
import List from "java.util.List"
|
||||
import ByteBuffer from 'java.nio.ByteBuffer'
|
||||
import ImageFormat from 'android.graphics.ImageFormat'
|
||||
|
||||
import Vibrator from "android.os.Vibrator"
|
||||
|
||||
|
||||
import ContentValues from "android.content.ContentValues"
|
||||
import ContentUris from "android.content.ContentUris"
|
||||
import JSONObject from "org.json.JSONObject"
|
||||
import TimeZone from "java.util.TimeZone"
|
||||
import Cursor from "android.database.Cursor"
|
||||
import MediaStore from "android.provider.MediaStore"
|
||||
import SimpleDateFormat from "java.text.SimpleDateFormat"
|
||||
import Locale from "java.util.Locale"
|
||||
import MediaScannerConnection from "android.media.MediaScannerConnection"
|
||||
import Rect from 'android.graphics.Rect';
|
||||
|
||||
|
||||
type callType = (list:any)=> void;
|
||||
|
||||
/**
|
||||
* 震动
|
||||
* @param {number} duriation 震动时间单位ms
|
||||
*/
|
||||
export function vibrator(duriation : number) : boolean {
|
||||
try {
|
||||
const context = UTSAndroid.getAppContext() as Context
|
||||
let vb = context.getSystemService(Context.VIBRATOR_SERVICE) as Vibrator;
|
||||
if (vb!.hasVibrator()) {
|
||||
vb!.vibrate(duriation.toLong());
|
||||
} else {
|
||||
return false
|
||||
}
|
||||
} catch (e) {
|
||||
console.error(e)
|
||||
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 从相册/相机中选取图片进行识别
|
||||
* @param callback {(string[],any[])=>{}} 回调参数:第一个是识别的文本数组,第二个是源数据{boundingBox:[x,y,width,height],text:elementText}[]字符串,需要JSON.pare,携带了坐标等详细资料
|
||||
* @param language {string} 需要识别的语言 zh中文,ja日文
|
||||
*/
|
||||
export function chooseImageBuilder(callback:(str:string[],source:string[])=>void,langs:string|null){
|
||||
// 置信度
|
||||
let zxd = 0.50
|
||||
|
||||
uni.chooseImage({
|
||||
count: 1,
|
||||
success(evt : ChooseImageSuccess) {
|
||||
uni.showLoading({ title: '...', mask: true })
|
||||
if (evt.tempFilePaths.length > 0) {
|
||||
const imgs = evt.tempFilePaths[0] as string;
|
||||
try {
|
||||
const decodedPath = UTSAndroid.convert2AbsFullPath(imgs)
|
||||
const file = new File(decodedPath)
|
||||
let image = InputImage.fromFilePath(UTSAndroid.getAppContext() as Context, Uri.fromFile(file));
|
||||
|
||||
let recognizer = TextRecognition.getClient(new ChineseTextRecognizerOptions.Builder().build()) as TextRecognizer;
|
||||
if(langs=='ja'){
|
||||
recognizer = TextRecognition.getClient(new JapaneseTextRecognizerOptions.Builder().build()) as TextRecognizer;
|
||||
}
|
||||
recognizer.process(image!)
|
||||
.addOnSuccessListener((TextList) => {
|
||||
let str = [] as string[]
|
||||
let sour = [] as string[]
|
||||
for (block in TextList.textBlocks) {
|
||||
for (line in block.lines) {
|
||||
// let lineText = line.text
|
||||
// let lineCornerPoints = line.cornerPoints
|
||||
// let lineFrame = line.getBoundingBox
|
||||
let texts = ''
|
||||
for (element in line.elements) {
|
||||
if (element.getConfidence() >= zxd) {
|
||||
let elementText = element.text as string;
|
||||
|
||||
let elementFrame = element.getBoundingBox()
|
||||
let rect = elementFrame as Rect
|
||||
sour.push(JSON.stringify({boundingBox:[rect.left,rect.top,rect.width(),rect.height()],text:elementText} as UTSJSONObject))
|
||||
texts+=elementText
|
||||
|
||||
}
|
||||
}
|
||||
if(texts!=''){
|
||||
str.push(texts)
|
||||
}
|
||||
}
|
||||
}
|
||||
uni.hideLoading()
|
||||
vibrator(100)
|
||||
callback(str as string[],sour as string[])
|
||||
})
|
||||
.addOnFailureListener((e) => {
|
||||
|
||||
callback([] as string[],[] as string[])
|
||||
})
|
||||
|
||||
|
||||
} catch (e : IOException) {
|
||||
callback([] as string[],[] as string[])
|
||||
}
|
||||
}
|
||||
},
|
||||
fail() {
|
||||
callback([] as string[],[] as string[])
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
/**
|
||||
* 从相册/相机中选取图片进行识别
|
||||
* @param url {string} 图片地址.
|
||||
* @param callback {(string[],any[])=>{}} 回调参数:第一个是识别的文本数组,第二个是源数据{boundingBox:[x,y,width,height],text:elementText}[]字符串,需要JSON.pare,携带了坐标等详细资料
|
||||
* @param language {string} 需要识别的语言 zh中文,ja日文
|
||||
*/
|
||||
export function downloadUrlImageBuilder(url : string,callback:(str:string[],source:string[])=>void,langs:string|null) {
|
||||
// 置信度
|
||||
let zxd = 0.50
|
||||
uni.downloadFile({
|
||||
url,
|
||||
success(evt) {
|
||||
const contentResolver = UTSAndroid.getAppContext()!.contentResolver
|
||||
let decodedPath = UTSAndroid.convert2AbsFullPath(evt.tempFilePath)
|
||||
|
||||
try {
|
||||
const file = new File(decodedPath)
|
||||
let image = InputImage.fromFilePath(UTSAndroid.getAppContext() as Context, Uri.fromFile(file));
|
||||
let recognizer = TextRecognition.getClient(new ChineseTextRecognizerOptions.Builder().build()) as TextRecognizer;
|
||||
if(langs=='ja'){
|
||||
recognizer = TextRecognition.getClient(new JapaneseTextRecognizerOptions.Builder().build()) as TextRecognizer;
|
||||
}
|
||||
if (image != null) {
|
||||
const result = recognizer.process(image!)
|
||||
.addOnSuccessListener((TextList) => {
|
||||
let str = [] as string[]
|
||||
let sour = [] as string[]
|
||||
for (block in TextList.textBlocks) {
|
||||
for (line in block.lines) {
|
||||
let texts = ''
|
||||
for (element in line.elements) {
|
||||
if (element.getConfidence() >= zxd) {
|
||||
let elementText = element.text as string;
|
||||
|
||||
let elementFrame = element.getBoundingBox()
|
||||
let rect = elementFrame as Rect
|
||||
sour.push(JSON.stringify({boundingBox:[rect.left,rect.top,rect.width(),rect.height()],text:elementText} as UTSJSONObject))
|
||||
texts+=elementText
|
||||
|
||||
}
|
||||
}
|
||||
if(texts!=''){
|
||||
str.push(texts)
|
||||
}
|
||||
}
|
||||
}
|
||||
uni.hideLoading()
|
||||
vibrator(100)
|
||||
callback(str as string[],sour)
|
||||
})
|
||||
.addOnFailureListener((e) => {
|
||||
callback([] as string[],[] as string[])
|
||||
})
|
||||
} else {
|
||||
callback([] as string[],[] as string[])
|
||||
}
|
||||
} catch (e : IOException) {
|
||||
callback([] as string[],[] as string[])
|
||||
}
|
||||
|
||||
},
|
||||
fail() {
|
||||
callback([] as string[],[] as string[])
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 从相册/相机中选取图片进行识别
|
||||
* @param pathfile {string} 图片地址.
|
||||
* @param callback {(string[],any[])=>{}} 回调参数:第一个是识别的文本数组,第二个是源数据{boundingBox:[x,y,width,height],text:elementText}[]字符串,需要JSON.pare,携带了坐标等详细资料
|
||||
* @param language {string} 需要识别的语言 zh中文,ja日文
|
||||
*/
|
||||
export function localFilePathImageBuilder(pathfile : string,callback:(str:string[],source:string[])=>void,langs:string|null){
|
||||
// 置信度
|
||||
let zxd = 0.50
|
||||
try {
|
||||
let decodedPath = UTSAndroid.convert2AbsFullPath(pathfile)
|
||||
|
||||
const file = new File(decodedPath)
|
||||
let image = InputImage.fromFilePath(UTSAndroid.getAppContext() as Context, Uri.fromFile(file));
|
||||
let recognizer = TextRecognition.getClient(new ChineseTextRecognizerOptions.Builder().build()) as TextRecognizer;
|
||||
if(langs=='ja'){
|
||||
recognizer = TextRecognition.getClient(new JapaneseTextRecognizerOptions.Builder().build()) as TextRecognizer;
|
||||
}
|
||||
|
||||
if (image != null) {
|
||||
const result = recognizer.process(image!)
|
||||
.addOnSuccessListener((TextList) => {
|
||||
let str = [] as string[]
|
||||
let sour = [] as string[]
|
||||
for (block in TextList.textBlocks) {
|
||||
for (line in block.lines) {
|
||||
let texts = ''
|
||||
for (element in line.elements) {
|
||||
if (element.getConfidence() >= zxd) {
|
||||
let elementText = element.text as string;
|
||||
|
||||
let elementFrame = element.getBoundingBox()
|
||||
let rect = elementFrame as Rect
|
||||
sour.push(JSON.stringify({boundingBox:[rect.left,rect.top,rect.width(),rect.height()],text:elementText} as UTSJSONObject))
|
||||
texts+=elementText
|
||||
|
||||
}
|
||||
}
|
||||
if(texts!=''){
|
||||
str.push(texts)
|
||||
}
|
||||
}
|
||||
}
|
||||
callback(str as string[],sour)
|
||||
})
|
||||
.addOnFailureListener((e) => {
|
||||
callback([] as string[],[] as string[])
|
||||
})
|
||||
} else {
|
||||
callback([] as string[],[] as string[])
|
||||
}
|
||||
} catch (e : IOException) {
|
||||
callback([] as string[],[] as string[])
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,5 @@
|
||||
{
|
||||
"dependencies": {
|
||||
"x_ocr_s": "./lib/x_ocr_s.har"
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,36 @@
|
||||
import { x_ocrDecode } from "x_ocr_s"
|
||||
|
||||
export function chooseImageBuilder(callback : (str : string[], source : string[]) => void, langs : string | null) {
|
||||
uni.chooseImage({
|
||||
count: 1,
|
||||
success(evt : ChooseImageSuccess) {
|
||||
uni.showLoading({ title: '', mask: true })
|
||||
if (evt.tempFilePaths.length > 0) {
|
||||
const imgs = UTSHarmony.convert2AbsFullPath(evt.tempFilePaths[0] as string);
|
||||
x_ocrDecode(imgs, (arg1 : string[], arg2 : string[]) => {
|
||||
callback(arg1, arg2)
|
||||
uni.hideLoading()
|
||||
})
|
||||
}
|
||||
},
|
||||
fail() {
|
||||
callback([] as string[], [] as string[])
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
export function downloadUrlImageBuilder(url : string,callback:(str:string[],source:string[])=>void,langs:string|null) {
|
||||
uni.downloadFile({
|
||||
url,
|
||||
success(evt) {
|
||||
x_ocrDecode(UTSHarmony.convert2AbsFullPath(evt.tempFilePath), callback)
|
||||
},
|
||||
fail() {
|
||||
callback([] as string[],[] as string[])
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
export function localFilePathImageBuilder(pathfile : string,callback:(str:string[],source:string[])=>void,langs:string|null){
|
||||
x_ocrDecode(UTSHarmony.convert2AbsFullPath(pathfile), callback)
|
||||
}
|
||||
Binary file not shown.
@@ -0,0 +1,14 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
||||
<plist version="1.0">
|
||||
<dict>
|
||||
<key>NSPrivacyAccessedAPITypes</key>
|
||||
<array/>
|
||||
<key>NSPrivacyCollectedDataTypes</key>
|
||||
<array/>
|
||||
<key>NSPrivacyTracking</key>
|
||||
<false/>
|
||||
<key>NSPrivacyTrackingDomains</key>
|
||||
<array/>
|
||||
</dict>
|
||||
</plist>
|
||||
@@ -0,0 +1,17 @@
|
||||
{
|
||||
"deploymentTarget": "12",
|
||||
"dependencies-pods": [
|
||||
{
|
||||
"name": "GoogleMLKit/TextRecognition",
|
||||
"version": "3.2.0"
|
||||
},
|
||||
{
|
||||
"name": "GoogleMLKit/TextRecognitionChinese",
|
||||
"version": "3.2.0"
|
||||
},
|
||||
{
|
||||
"name": "GoogleMLKit/TextRecognitionJapanese",
|
||||
"version": "3.2.0"
|
||||
}
|
||||
]
|
||||
}
|
||||
@@ -0,0 +1,222 @@
|
||||
import {ChineseTextRecognizerOptions,JapaneseTextRecognizerOptions,TextRecognizer,VisionImage,TextBlock,Text} from "MLKit"
|
||||
import * as UIKit from "UIKit"
|
||||
import { UIAlertController , UIAlertAction , UITextField,UIImage } from "UIKit"
|
||||
import { UTSiOS } from "DCloudUTSFoundation"
|
||||
import {String} from "Swift"
|
||||
import { PHPhotoLibrary } from "Photos"
|
||||
import { CGPoint , CGRect } from 'CoreFoundation';
|
||||
|
||||
|
||||
/**
|
||||
* 从相册/相机中选取图片进行识别
|
||||
* @param callback {(string[],string[])=>{}} 回调参数:第一个是识别的文本数组,第二个是源数据{boundingBox:[x,y,width,height],text:elementText}[]字符串,需要JSON.pare,携带了坐标等详细资料
|
||||
* @param language {string} 需要识别的语言 zh中文,ja日文
|
||||
*/
|
||||
export function chooseImageBuilder(callback:(str:string[],source:string[])=>void,langs:string|null){
|
||||
// 置信度
|
||||
let zxd = 0.50
|
||||
let local = 'zh'
|
||||
if(langs=='ja'){
|
||||
local = 'ja'
|
||||
}
|
||||
uni.chooseImage({
|
||||
count: 1,
|
||||
success:(evt : ChooseImageSuccess)=> {
|
||||
uni.showLoading({title:'...',mask:true})
|
||||
let chineseOptions = new ChineseTextRecognizerOptions()
|
||||
|
||||
let chineseTextRecognizer = TextRecognizer.textRecognizer(options=chineseOptions)
|
||||
if(local == 'ja'){
|
||||
chineseTextRecognizer = TextRecognizer.textRecognizer(options=new JapaneseTextRecognizerOptions())
|
||||
}
|
||||
if (evt.tempFilePaths.length > 0) {
|
||||
let imgs = evt.tempFilePaths[0] as string;
|
||||
try {
|
||||
let realImgPath = UTSiOS.convert2AbsFullPath(imgs)
|
||||
|
||||
let img = new UIImage(contentsOfFile = realImgPath);
|
||||
if(img!=null){
|
||||
let image = new VisionImage(image = img!);
|
||||
chineseTextRecognizer.process(image as VisionImage,completion=(TextList,error)=>{
|
||||
if(error!=null||TextList==null){
|
||||
uni.hideLoading()
|
||||
uni.showToast({title:"失败",icon:'none'})
|
||||
return;
|
||||
}
|
||||
let str = [] as string[]
|
||||
let sour = [] as string[]
|
||||
for(block in TextList!.blocks){
|
||||
let lines = block.lines
|
||||
if(lines!=null){
|
||||
for(line in lines) {
|
||||
let elements = line.elements
|
||||
|
||||
if(elements!=null){
|
||||
let texts = ''
|
||||
for(element in elements) {
|
||||
let elementText = element.text;
|
||||
let rect = element.frame as CGRect
|
||||
let elementFrame = [rect.origin.x,rect.origin.y,rect.size.width,rect.size.height] as number[]
|
||||
sour.push(JSON.stringify({boundingBox:elementFrame,text:elementText})!)
|
||||
texts+=elementText
|
||||
}
|
||||
if(texts!=''){
|
||||
str.push(texts)
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
uni.hideLoading()
|
||||
callback(str as string[],sour)
|
||||
})
|
||||
|
||||
}
|
||||
|
||||
} catch (e) {
|
||||
console.warn("图片选择失败")
|
||||
uni.hideLoading()
|
||||
callback([] as string[],[] as string[])
|
||||
|
||||
}
|
||||
}
|
||||
},
|
||||
fail() {
|
||||
console.warn("图片选择失败")
|
||||
uni.showToast({title:"图片选择失败",icon:'none'})
|
||||
callback([] as string[],[] as string[])
|
||||
}
|
||||
})
|
||||
|
||||
}
|
||||
/**
|
||||
* 从相册/相机中选取图片进行识别
|
||||
* @param url {string} 图片地址.
|
||||
* @param callback {(string[],string[])=>{}} 回调参数:第一个是识别的文本数组,第二个是源数据{boundingBox:[x,y,width,height],text:elementText}[]字符串,需要JSON.pare,携带了坐标等详细资料
|
||||
* @param language {string} 需要识别的语言 zh中文,ja日文
|
||||
*/
|
||||
export function downloadUrlImageBuilder(url : string,callback:(str:string[],source:string[])=>void,langs:string|null){
|
||||
uni.showLoading({title:'...',mask:true})
|
||||
let local = langs == null?'zh':(langs! as string)
|
||||
uni.downloadFile({
|
||||
url,
|
||||
success:(evt)=> {
|
||||
let chineseOptions = new ChineseTextRecognizerOptions()
|
||||
let chineseTextRecognizer = TextRecognizer.textRecognizer(options=chineseOptions)
|
||||
|
||||
if(local == 'ja'){
|
||||
chineseTextRecognizer = TextRecognizer.textRecognizer(options=new JapaneseTextRecognizerOptions())
|
||||
}
|
||||
let imgs = evt.tempFilePath as string;
|
||||
|
||||
try {
|
||||
let realImgPath = UTSiOS.convert2AbsFullPath(imgs)
|
||||
let img = new UIImage(contentsOfFile = realImgPath);
|
||||
|
||||
if(img!=null){
|
||||
let image = new VisionImage(image = img!);
|
||||
chineseTextRecognizer.process(image as VisionImage,completion=(TextList,error)=>{
|
||||
if(error!=null||TextList==null){
|
||||
uni.hideLoading()
|
||||
uni.showToast({title:"失败",icon:'none'})
|
||||
return;
|
||||
}
|
||||
let str = [] as string[]
|
||||
let sour = [] as string[]
|
||||
for(block in TextList!.blocks){
|
||||
let lines = block.lines
|
||||
if(lines!=null){
|
||||
for(line in lines) {
|
||||
let elements = line.elements
|
||||
if(elements!=null){
|
||||
let texts = ''
|
||||
for(element in elements) {
|
||||
let elementText = element.text;
|
||||
let rect = element.frame as CGRect
|
||||
let elementFrame = [rect.origin.x,rect.origin.y,rect.size.width,rect.size.height] as number[]
|
||||
sour.push(JSON.stringify({boundingBox:elementFrame,text:elementText})!)
|
||||
|
||||
texts+=elementText
|
||||
}
|
||||
if(texts!=''){
|
||||
str.push(texts)
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
uni.hideLoading()
|
||||
callback(str as string[],sour)
|
||||
})
|
||||
|
||||
}
|
||||
|
||||
} catch (e) {
|
||||
console.warn("下载失败")
|
||||
uni.hideLoading()
|
||||
uni.showToast({title:"下载失败",icon:'none'})
|
||||
callback([] as string[],[] as string[])
|
||||
}
|
||||
|
||||
},
|
||||
fail() {
|
||||
uni.hideLoading()
|
||||
uni.showToast({title:"下载失败",icon:'none'})
|
||||
callback([] as string[],[] as string[])
|
||||
}
|
||||
})
|
||||
}
|
||||
export function localFilePathImageBuilder(pathfile : string,callback:(str:string[],source:string[])=>void,langs:string|null){
|
||||
let local = langs == null?'zh':(langs! as string)
|
||||
let chineseOptions = new ChineseTextRecognizerOptions()
|
||||
let chineseTextRecognizer = TextRecognizer.textRecognizer(options=chineseOptions)
|
||||
|
||||
if(local == 'ja'){
|
||||
chineseTextRecognizer = TextRecognizer.textRecognizer(options=new JapaneseTextRecognizerOptions())
|
||||
}
|
||||
let realImgPath = UTSiOS.convert2AbsFullPath(pathfile)
|
||||
let img = new UIImage(contentsOfFile = realImgPath);
|
||||
|
||||
if(img!=null){
|
||||
let image = new VisionImage(image = img!);
|
||||
chineseTextRecognizer.process(image as VisionImage,completion=(TextList,error)=>{
|
||||
if(error!=null||TextList==null){
|
||||
callback([] as string[],[] as string[])
|
||||
return;
|
||||
}
|
||||
let str = [] as string[]
|
||||
let sour = [] as string[]
|
||||
for(block in TextList!.blocks){
|
||||
let lines = block.lines
|
||||
if(lines!=null){
|
||||
for(line in lines) {
|
||||
let elements = line.elements
|
||||
if(elements!=null){
|
||||
let texts = ''
|
||||
for(element in elements) {
|
||||
let elementText = element.text;
|
||||
let rect = element.frame as CGRect
|
||||
let elementFrame = [rect.origin.x,rect.origin.y,rect.size.width,rect.size.height] as number[]
|
||||
sour.push(JSON.stringify({boundingBox:elementFrame,text:elementText})!)
|
||||
|
||||
texts+=elementText
|
||||
}
|
||||
if(texts!=''){
|
||||
str.push(texts)
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
callback(str as string[],sour)
|
||||
})
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,8 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
||||
<plist version="1.0">
|
||||
<dict>
|
||||
<key>NSPhotoLibraryUsageDescription</key>
|
||||
<string>读取您的相册图片,用来识别图片中的文字功能,如果拒绝将无法使用相关识别功能.</string>
|
||||
</dict>
|
||||
</plist>
|
||||
@@ -0,0 +1,103 @@
|
||||
async function loadScript(url) {
|
||||
return new Promise(res=>{
|
||||
var script = document.createElement('script');
|
||||
script.type = 'text/javascript';
|
||||
script.src = url;
|
||||
|
||||
// 当脚本加载完成后,执行回调
|
||||
script.onload = function() {
|
||||
res()
|
||||
};
|
||||
|
||||
// 处理旧版浏览器的onreadystatechange事件
|
||||
script.onreadystatechange = function() {
|
||||
if (this.readyState === 'loaded' || this.readyState === 'complete') {
|
||||
script.onload();
|
||||
}
|
||||
};
|
||||
|
||||
// 将脚本添加到head中,开始加载
|
||||
document.head.appendChild(script);
|
||||
})
|
||||
}
|
||||
|
||||
async function loadScripts(scripts) {
|
||||
await (async function loadNextScript(i) {
|
||||
if (i < scripts.length) {
|
||||
await loadScript(scripts[i]);
|
||||
await loadNextScript(i + 1)
|
||||
}
|
||||
})(0);
|
||||
|
||||
}
|
||||
let ocr = window?.paddlejs?.ocr??null;
|
||||
let jsFiles = [
|
||||
'/static/tmui4xLibs/lib/ocrLib.js'
|
||||
];
|
||||
const decoderText =async (imgpath:string,callback)=>{
|
||||
if(!window?.paddlejs){
|
||||
await loadScripts(jsFiles)
|
||||
ocr = paddlejs.ocr
|
||||
await ocr.init()
|
||||
}
|
||||
let img = new Image()
|
||||
img.src = imgpath
|
||||
img.onload = async function(){
|
||||
const canvas = document.createElement('canvas')
|
||||
canvas.width = 800;
|
||||
canvas.height = 800
|
||||
const res = await ocr.recognize(img, { canvas });
|
||||
let texts = res.text
|
||||
let bounds = []
|
||||
for(let i=0;i<res.points.length;i++){
|
||||
let item = res.points[i]
|
||||
bounds.push({
|
||||
x:item[0][0],
|
||||
y:item[0][1],
|
||||
width:item[1][0]-item[0][0],
|
||||
height:item[3][1]+item[0][1]
|
||||
})
|
||||
}
|
||||
|
||||
callback(texts,JSON.stringify(bounds))
|
||||
}
|
||||
|
||||
}
|
||||
export async function chooseImageBuilder(callback : (str : string[], source : string[]) => void, langs : string | null) {
|
||||
|
||||
uni.chooseImage({
|
||||
count: 1,
|
||||
success:async (evt : ChooseImageSuccess)=> {
|
||||
uni.showLoading({title:'...',mask:true})
|
||||
if (evt.tempFilePaths.length > 0) {
|
||||
let imgpath = evt.tempFilePaths[0] as string;
|
||||
try {
|
||||
await decoderText(imgpath,callback)
|
||||
} catch (error) {
|
||||
console.error(error)
|
||||
callback([] as string[],[] as string[])
|
||||
}
|
||||
}
|
||||
uni.hideLoading()
|
||||
},
|
||||
fail() {
|
||||
console.warn("图片选择失败")
|
||||
callback([] as string[],[] as string[])
|
||||
}
|
||||
})
|
||||
|
||||
|
||||
}
|
||||
export async function downloadUrlImageBuilder(url : string, callback : (str : string[], source : string[]) => void, langs : string | null) {
|
||||
uni.showLoading({title:'...',mask:true})
|
||||
try {
|
||||
await decoderText(url,callback)
|
||||
} catch (error) {
|
||||
console.error(error)
|
||||
callback([] as string[],[] as string[])
|
||||
}
|
||||
uni.hideLoading()
|
||||
}
|
||||
export async function localFilePathImageBuilder(pathfile : string, callback : (str : string[], source : string[]) => void, langs : string | null) {
|
||||
downloadUrlImageBuilder(pathfile,callback)
|
||||
}
|
||||
Reference in New Issue
Block a user