6.7.0 - Alpha11 - 修复 ocr.detect 异常及 ocr 部分重载方法异常

This commit is contained in:
SuperMonster003
2025-11-19 14:41:16 +08:00
parent 28f7dbe129
commit 9b72e0deea
7 changed files with 182 additions and 242 deletions

View File

@@ -36,7 +36,7 @@ class OcrRapid {
// 创建 OcrResult 对象
OcrResult(
label = block.text,
text = block.text,
confidence = block.boxScore,
bounds = rect,
)

View File

@@ -8,11 +8,14 @@ import kotlin.math.abs
/**
* Represents a result from Optical Character Recognition (OCR) processing.
*
* @property label The recognized text label.
* @property text The recognized text.
* @property confidence The confidence score of the recognition, ranging from 0 (least confident) to 1 (most confident).
* @property bounds The bounding box coordinates of the recognized text region.
*/
class OcrResult(@JvmField val label: String, @JvmField val confidence: Float, @JvmField val bounds: Rect) : Comparable<OcrResult> {
class OcrResult(@JvmField val text: String, @JvmField val confidence: Float, @JvmField val bounds: Rect) : Comparable<OcrResult> {
@JvmField
val label: String = text
override fun compareTo(other: OcrResult): Int {
// 上下差距小于二分之一的高度 判定为同一行
@@ -27,6 +30,6 @@ class OcrResult(@JvmField val label: String, @JvmField val confidence: Float, @J
override fun toString() =
"${OcrResult::class.java.simpleName}@${Integer.toHexString(hashCode())}" +
"{label=$label, confidence=$confidence, bounds=$bounds}"
"{text=$text, confidence=$confidence, bounds=$bounds}"
}

View File

@@ -7,23 +7,27 @@ import org.autojs.autojs.extension.AnyExtensions.isJsString
import org.autojs.autojs.extension.AnyExtensions.jsBrief
import org.autojs.autojs.extension.AnyExtensions.jsSpecies
import org.autojs.autojs.extension.ArrayExtensions.toNativeArray
import org.autojs.autojs.extension.ScriptableExtensions.prop
import org.autojs.autojs.extension.FlexibleArray.Companion.component1
import org.autojs.autojs.extension.FlexibleArray.Companion.component2
import org.autojs.autojs.extension.FlexibleArray.Companion.component3
import org.autojs.autojs.extension.ScriptableExtensions.defineProp
import org.autojs.autojs.extension.ScriptableExtensions.prop
import org.autojs.autojs.extension.ScriptableObjectExtensions.inquire
import org.autojs.autojs.runtime.ScriptRuntime
import org.autojs.autojs.runtime.api.OcrResult
import org.autojs.autojs.runtime.api.augment.Augmentable
import org.autojs.autojs.runtime.api.augment.Invokable
import org.autojs.autojs.runtime.api.augment.images.Images
import org.autojs.autojs.runtime.exception.WrappedIllegalArgumentException
import org.autojs.autojs.runtime.exception.ShouldNeverHappenException
import org.autojs.autojs.util.RhinoUtils
import org.autojs.autojs.util.RhinoUtils.UNDEFINED
import org.autojs.autojs.util.RhinoUtils.newNativeArray
import org.autojs.autojs.util.RhinoUtils.coerceString
import org.autojs.autojs.util.RhinoUtils.newNativeObject
import org.mozilla.javascript.NativeArray
import org.mozilla.javascript.NativeObject
import org.mozilla.javascript.ScriptableObject
import org.mozilla.javascript.Undefined
import java.util.function.Consumer
import java.util.function.Supplier
import kotlin.reflect.full.declaredMemberProperties
import android.graphics.Rect as AndroidRect
import org.autojs.autojs.runtime.api.augment.images.Images as AugmentableImages
import org.opencv.core.Rect as OpencvRect
@@ -46,187 +50,25 @@ class Ocr(private val scriptRuntime: ScriptRuntime) : Augmentable(scriptRuntime)
companion object {
enum class OcrMode(val value: String) {
MLKIT("mlkit"),
PADDLE("paddle"),
RAPID("rapid"),
UNKNOWN("unknown")
}
@JvmStatic
@RhinoRuntimeFunctionInterface
fun tap(scriptRuntime: ScriptRuntime, args: Array<out Any?>): Undefined = ensureArgumentsOnlyOne(args) { mode ->
scriptRuntime.ocr.mode = when (mode) {
scriptRuntime.augmentedOcrMLKit -> OcrMode.MLKIT
scriptRuntime.augmentedOcrPaddle -> OcrMode.PADDLE
scriptRuntime.augmentedOcrRapid -> OcrMode.RAPID
else -> when (RhinoUtils.coerceStringLowercase(mode, "")) {
OcrMode.MLKIT.value -> OcrMode.MLKIT
OcrMode.PADDLE.value -> OcrMode.PADDLE
OcrMode.RAPID.value -> OcrMode.RAPID
else -> null
}
} ?: OcrMode.MLKIT.also { throw WrappedIllegalArgumentException("Unknown mode ${mode.jsSpecies()} for ocr.tap") }
scriptRuntime.ocr.mode = mode.toOcrModeOrNull(scriptRuntime) ?: OcrMode.MLKIT.also {
throw WrappedIllegalArgumentException("Unknown mode ${mode.jsSpecies()} for ocr.tap")
}
return@ensureArgumentsOnlyOne UNDEFINED
}
@JvmStatic
@RhinoRuntimeFunctionInterface
fun recognizeText(scriptRuntime: ScriptRuntime, args: Array<out Any?>): NativeArray = ensureArgumentsAtMost(args, 3) { argList ->
val (arg0, arg1, arg2) = argList
when {
arg0.isJsString() -> {
// @Signature
// recognizeText(imgPath: string, options?: DetectOptionsMLKit | DetectOptionsPaddle): string[];
// recognizeText(imgPath: string, region: OmniRegion): string[];
val imgPath = arg0
val img = AugmentableImages.read(scriptRuntime, arrayOf(imgPath)) ?: throw WrappedIllegalArgumentException(
"Invalid image of path \"$imgPath\" for ocr.recognizeText(img, options?)",
)
// @Overload
// recognizeText(img: ImageWrapper, options?: DetectOptionsMLKit | DetectOptionsPaddle): string[];
// recognizeText(img: ImageWrapper, region: OmniRegion): string[];
recognizeText(scriptRuntime, arrayOf(img.oneShot(), arg1, arg2))
}
arg0 !is ImageWrapper -> {
// @Signature
// recognizeText(options?: DetectOptionsMLKit | DetectOptionsPaddle): string[];
// recognizeText(region: OmniRegion): string[];
// @Overload
// recognizeText(img: ImageWrapper, options?: DetectOptionsMLKit | DetectOptionsPaddle): string[];
// recognizeText(img: ImageWrapper, region: OmniRegion): string[];
val capt = AugmentableImages.captureScreen(scriptRuntime, emptyArray())
recognizeText(scriptRuntime, arrayOf(capt, arg0, arg1))
}
shouldTakenAsRegion(arg1) -> {
// @Signature recognizeText(img: ImageWrapper, region: OmniRegion): string[];
val region = arg1
val options = newNativeObject().also { o ->
o.defineProp("region", region)
}
// @Overload recognizeText(img: ImageWrapper, options: DetectOptionsMLKit | DetectOptionsPaddle): string[];
recognizeText(scriptRuntime, arrayOf(arg0, options))
}
else -> {
// @Signature recognizeText(img: ImageWrapper, options?: DetectOptionsMLKit | DetectOptionsPaddle): string[];
val img = arg0
val opt = arg1 as? NativeObject ?: newNativeObject()
when (val region = opt.prop("region")) {
null -> newNativeArray()
else -> {
var shouldShoot = false
val (image, options) = when {
region.isJsNullish() -> img to opt
else -> {
val clip = AugmentableImages.clip(scriptRuntime, arrayOf(img, region))
shouldShoot = true
clip.oneShot() to opt
}
}
val results = when (opt.prop("mode").takeIf { it is OcrMode } ?: scriptRuntime.ocr.mode) {
OcrMode.MLKIT -> OcrMLKit.recognizeTextInternal(scriptRuntime, image, options)
OcrMode.PADDLE -> OcrPaddle.recognizeTextInternal(scriptRuntime, image, options)
OcrMode.RAPID -> OcrRapid.recognizeTextInternal(scriptRuntime, image, options)
else -> throw WrappedIllegalArgumentException("Cannot call ocr.recognizeText with an unknown mode")
}
if (shouldShoot) img.shoot()
results.toNativeArray()
}
}
}
}
recognizeTextWith(scriptRuntime, null, argList)
}
@JvmStatic
@RhinoRuntimeFunctionInterface
fun detect(scriptRuntime: ScriptRuntime, args: Array<out Any?>): NativeArray = ensureArgumentsAtMost(args, 3) { argList ->
val (arg0, arg1, arg2) = argList
when {
arg0.isJsString() -> {
// @Signature
// detect(imgPath: string, options?: DetectOptionsMLKit | DetectOptionsPaddle): org.autojs.autojs.runtime.api.OcrResult[];
// detect(imgPath: string, region: OmniRegion): org.autojs.autojs.runtime.api.OcrResult[];
val imgPath = arg0
val img = AugmentableImages.read(scriptRuntime, arrayOf(imgPath)) ?: throw WrappedIllegalArgumentException(
"Invalid image of path \"$imgPath\" for ocr.detect(img, options?)",
)
// @Overload
// detect(img: ImageWrapper, options?: DetectOptionsMLKit | DetectOptionsPaddle): org.autojs.autojs.runtime.api.OcrResult[];
// detect(img: ImageWrapper, region: OmniRegion): org.autojs.autojs.runtime.api.OcrResult[];
detect(scriptRuntime, arrayOf(img.oneShot(), arg1, arg2))
}
arg0 !is ImageWrapper -> {
// @Signature
// detect(options?: DetectOptionsMLKit | DetectOptionsPaddle): org.autojs.autojs.runtime.api.OcrResult[];
// detect(region: OmniRegion): org.autojs.autojs.runtime.api.OcrResult[];
// @Overload
// detect(img: ImageWrapper, options?: DetectOptionsMLKit | DetectOptionsPaddle): org.autojs.autojs.runtime.api.OcrResult[];
// detect(img: ImageWrapper, region: OmniRegion): org.autojs.autojs.runtime.api.OcrResult[];
val capt = AugmentableImages.captureScreen(scriptRuntime, emptyArray())
detect(scriptRuntime, arrayOf(capt, arg0, arg1))
}
shouldTakenAsRegion(arg1) -> {
// @Signature detect(img: ImageWrapper, region: OmniRegion): org.autojs.autojs.runtime.api.OcrResult[];
val region = arg1
val options = newNativeObject().also { o ->
o.defineProp("region", region)
}
// @Overload detect(img: ImageWrapper, options: DetectOptionsMLKit | DetectOptionsPaddle): org.autojs.autojs.runtime.api.OcrResult[];
detect(scriptRuntime, arrayOf(arg0, options))
}
else -> {
// @Signature detect(img: ImageWrapper, options?: DetectOptionsMLKit | DetectOptionsPaddle): org.autojs.autojs.runtime.api.OcrResult[];
val img = arg0
val opt = arg1 as? NativeObject ?: newNativeObject()
when (val region = opt.prop("region")) {
null -> newNativeArray()
else -> {
var shouldShoot = false
val (image, options) = when {
region.isJsNullish() -> img to opt
else -> {
val clip = AugmentableImages.clip(scriptRuntime, arrayOf(img, region))
shouldShoot = true
clip.oneShot() to opt
}
}
val results = when (scriptRuntime.ocr.mode) {
OcrMode.MLKIT -> OcrMLKit.detectInternal(scriptRuntime, image, options)
OcrMode.PADDLE -> OcrPaddle.detectInternal(scriptRuntime, image, options)
OcrMode.RAPID -> OcrRapid.detectInternal(scriptRuntime, image, options)
else -> throw WrappedIllegalArgumentException("Cannot call ocr.detect with an unknown mode")
}.also {
val rect = Images.buildRegion(scriptRuntime, arrayOf(img, region))
it.forEach { result -> result.bounds.offset(rect.x, rect.y) }
}
if (shouldShoot) img.shoot()
results.toNativeArray()
}
}
}
}
detectWith(scriptRuntime, null, argList)
}
@Suppress("EnumValuesSoftDeprecate")
@@ -246,58 +88,131 @@ class Ocr(private val scriptRuntime: ScriptRuntime) : Augmentable(scriptRuntime)
summary(scriptRuntime, args)
}
fun commonRecognizeText(scriptRuntime: ScriptRuntime, mode: OcrMode, vararg args: Any?): NativeArray = ensureArgumentsAtMost(args, 2) { argList ->
commonInvoker(scriptRuntime, mode, ::recognizeText, *argList)
internal fun recognizeTextWith(scriptRuntime: ScriptRuntime, overrideMode: OcrMode?, unwrappedArgs: Array<out Any?>): NativeArray {
return dispatchOcrWith<String>(scriptRuntime, ::recognizeText.name, unwrappedArgs, overrideMode).toNativeArray()
}
fun commonDetect(scriptRuntime: ScriptRuntime, mode: OcrMode, vararg args: Any?): NativeArray = ensureArgumentsAtMost(args, 2) { argList ->
commonInvoker(scriptRuntime, mode, ::detect, *argList)
internal fun detectWith(scriptRuntime: ScriptRuntime, overrideMode: OcrMode?, unwrappedArgs: Array<out Any?>): NativeArray {
return dispatchOcrWith<OcrResult>(scriptRuntime, ::detect.name, unwrappedArgs, overrideMode) { results, rect ->
results.apply { forEach { it.bounds.offset(rect.x, rect.y) } }
}.toNativeArray()
}
private fun commonInvoker(
@Suppress("UNCHECKED_CAST")
internal fun <T> dispatchOcrWith(
scriptRuntime: ScriptRuntime,
mode: OcrMode,
invoker: (ScriptRuntime, Array<out Any?>) -> NativeArray,
vararg args: Any?,
): NativeArray = ensureArgumentsAtMost(args, 2) { argList ->
val (arg0, arg1) = argList
when (argList.size) {
2 -> when {
shouldTakenAsRegion(arg1) -> newNativeObject().let { options ->
options.defineProp("region", arg1)
options.defineProp("mode", mode)
invoker(scriptRuntime, arrayOf(arg0, options))
}
arg1 is NativeObject -> arg1.let { options ->
options.defineProp("mode", mode)
invoker(scriptRuntime, arrayOf(arg0, options))
}
else -> throw WrappedIllegalArgumentException("Unknown argument[1] ${arg1.jsBrief()} for ${mode.value}")
funcName: String,
unwrappedArgs: Array<out Any?>,
overrideMode: OcrMode? = null,
resultsHandler: ((results: List<T>, rect: OpencvRect) -> List<T>)? = null,
): List<T> {
val (arg0, arg1, arg2) = unwrappedArgs
return when {
arg0.isJsString() -> {
// @Signature
// funcName(imgPath: string, options?: DetectOptionsMLKit | DetectOptionsPaddle): org.autojs.autojs.runtime.api.OcrResult[];
// funcName(imgPath: string, region: OmniRegion): org.autojs.autojs.runtime.api.OcrResult[];
val imgPath = arg0
val img = AugmentableImages.read(scriptRuntime, arrayOf(imgPath)) ?: throw WrappedIllegalArgumentException(
"Invalid image of path \"$imgPath\" for ocr.$funcName(img, options?)",
)
// @Overload
// funcName(img: ImageWrapper, options?: DetectOptionsMLKit | DetectOptionsPaddle): org.autojs.autojs.runtime.api.OcrResult[];
// funcName(img: ImageWrapper, region: OmniRegion): org.autojs.autojs.runtime.api.OcrResult[];
dispatchOcrWith(scriptRuntime, funcName, arrayOf(img.oneShot(), arg1, arg2))
}
1 -> when {
arg0 is NativeObject -> invoker(scriptRuntime, arrayOf(arg0.also { options ->
options.defineProp("mode", mode)
}))
arg0 is ImageWrapper -> invoker(scriptRuntime, arrayOf(arg0, newNativeObject().also { options ->
options.defineProp("mode", mode)
}))
shouldTakenAsRegion(arg0) -> newNativeObject().let { options ->
options.defineProp("region", arg0)
options.defineProp("mode", mode)
invoker(scriptRuntime, arrayOf(arg0, options))
arg0 !is ImageWrapper -> {
// @Signature
// funcName(options?: DetectOptionsMLKit | DetectOptionsPaddle): org.autojs.autojs.runtime.api.OcrResult[];
// funcName(region: OmniRegion): org.autojs.autojs.runtime.api.OcrResult[];
// @Overload
// funcName(img: ImageWrapper, options?: DetectOptionsMLKit | DetectOptionsPaddle): org.autojs.autojs.runtime.api.OcrResult[];
// funcName(img: ImageWrapper, region: OmniRegion): org.autojs.autojs.runtime.api.OcrResult[];
val capt = AugmentableImages.captureScreen(scriptRuntime, emptyArray())
dispatchOcrWith(scriptRuntime, funcName, arrayOf(capt, arg0, arg1))
}
shouldTakenAsRegion(arg1) -> {
// @Signature funcName(img: ImageWrapper, region: OmniRegion): org.autojs.autojs.runtime.api.OcrResult[];
val region = arg1
val options = newNativeObject().also { o ->
o.defineProp("region", region)
}
else -> throw WrappedIllegalArgumentException("Unknown argument[0] ${arg0.jsBrief()} for ${mode.value}")
// @Overload funcName(img: ImageWrapper, options: DetectOptionsMLKit | DetectOptionsPaddle): org.autojs.autojs.runtime.api.OcrResult[];
dispatchOcrWith(scriptRuntime, funcName, arrayOf(arg0, options))
}
0 -> newNativeObject().let { options ->
options.defineProp("mode", mode)
invoker(scriptRuntime, arrayOf(options))
else -> {
// @Signature funcName(img: ImageWrapper, options?: DetectOptionsMLKit | DetectOptionsPaddle): org.autojs.autojs.runtime.api.OcrResult[];
val img = arg0
val opt = arg1 as? NativeObject ?: newNativeObject()
val region = opt.prop("region") ?: return emptyList()
var shouldShoot = false
val (image, options) = when {
region.isJsNullish() -> img to opt
else -> {
val clip = AugmentableImages.clip(scriptRuntime, arrayOf(img, region))
shouldShoot = true
clip.oneShot() to opt
}
}
val optMode = overrideMode ?: opt.inquire("mode", scriptRuntime.ocr.mode)
val ocrMode = optMode.toOcrModeOrNull(scriptRuntime)
?: throw WrappedIllegalArgumentException("Cannot call ocr.$funcName with an unknown mode: ${optMode.jsBrief()}")
val prop = OcrMode::class.declaredMemberProperties.firstOrNull { it.name.contentEquals(funcName, true) }
?: throw WrappedIllegalArgumentException("Cannot find ocr dispatcher property for $funcName")
val fn = prop.get(ocrMode) as? (ScriptRuntime, ImageWrapper, NativeObject) -> List<T>
?: throw WrappedIllegalArgumentException("Dispatcher type mismatch for $funcName")
var results = fn.invoke(scriptRuntime, image, options)
resultsHandler?.let {
val rect = AugmentableImages.buildRegion(scriptRuntime, arrayOf(img, region))
results = resultsHandler(results, rect)
}
if (shouldShoot) img.shoot()
results
}
else -> throw ShouldNeverHappenException()
}
}
private fun shouldTakenAsRegion(o: Any?) = o is OpencvRect || o is AndroidRect || o is NativeArray
private fun Any?.toOcrModeOrNull(scriptRuntime: ScriptRuntime? = null) = when (this) {
is ScriptableObject -> when (this) {
scriptRuntime?.augmentedOcrMLKit -> OcrMode.MLKIT
scriptRuntime?.augmentedOcrPaddle -> OcrMode.PADDLE
scriptRuntime?.augmentedOcrRapid -> OcrMode.RAPID
else -> null
}
else -> {
val modeValue = coerceString(this, "")
OcrMode.entries.find { it.value.contentEquals(modeValue, true) }
}
}
@Suppress("unused")
private fun <T> nullImpl(scriptRuntime: ScriptRuntime, image: ImageWrapper, options: NativeObject) = emptyList<T>()
enum class OcrMode(
val value: String,
val recognizeText: ((ScriptRuntime, ImageWrapper, NativeObject) -> List<String>)?,
val detect: ((ScriptRuntime, ImageWrapper, NativeObject) -> List<OcrResult>)?,
) {
MLKIT("mlkit", OcrMLKit::recognizeTextImpl, OcrMLKit::detectImpl),
PADDLE("paddle", OcrPaddle::recognizeTextImpl, OcrPaddle::detectImpl),
RAPID("rapid", OcrRapid::recognizeTextImpl, OcrRapid::detectImpl),
UNKNOWN("unknown", ::nullImpl, ::nullImpl);
}
}
}
}

View File

@@ -22,24 +22,25 @@ class OcrMLKit(private val scriptRuntime: ScriptRuntime) : Augmentable(scriptRun
override fun invoke(vararg args: Any?): NativeArray = recognizeText(scriptRuntime, args)
@Suppress("unused")
companion object {
@JvmStatic
@RhinoRuntimeFunctionInterface
fun recognizeText(scriptRuntime: ScriptRuntime, args: Array<out Any?>): NativeArray = ensureArgumentsAtMost(args, 3) {
Ocr.commonRecognizeText(scriptRuntime, OcrMode.MLKIT, *it)
fun recognizeText(scriptRuntime: ScriptRuntime, args: Array<out Any?>): NativeArray = ensureArgumentsAtMost(args, 3) { argList ->
Ocr.recognizeTextWith(scriptRuntime, OcrMode.MLKIT, argList)
}
@JvmStatic
@RhinoRuntimeFunctionInterface
fun detect(scriptRuntime: ScriptRuntime, args: Array<out Any?>): NativeArray = ensureArgumentsAtMost(args, 3) {
Ocr.commonDetect(scriptRuntime, OcrMode.MLKIT, *it)
fun detect(scriptRuntime: ScriptRuntime, args: Array<out Any?>): NativeArray = ensureArgumentsAtMost(args, 3) { argList ->
Ocr.detectWith(scriptRuntime, OcrMode.MLKIT, argList)
}
// @Hint by SuperMonster003 on Nov 1, 2024.
// ! Reserved param `options`.
// ! zh-CN: 预留参数 `options`.
fun recognizeTextInternal(scriptRuntime: ScriptRuntime, image: ImageWrapper, @Suppress("UNUSED_PARAMETER") options: NativeObject): List<String> {
fun recognizeTextImpl(scriptRuntime: ScriptRuntime, image: ImageWrapper, options: NativeObject): List<String> {
ApkBuilder.Libs.MLKIT_OCR.ensureLibFiles(OcrMode.MLKIT.value)
return scriptRuntime.ocrMLKit.recognizeText(image)
}
@@ -47,7 +48,7 @@ class OcrMLKit(private val scriptRuntime: ScriptRuntime) : Augmentable(scriptRun
// @Hint by SuperMonster003 on Nov 1, 2024.
// ! Reserved param `options`.
// ! zh-CN: 预留参数 `options`.
fun detectInternal(scriptRuntime: ScriptRuntime, image: ImageWrapper, @Suppress("UNUSED_PARAMETER") options: NativeObject): List<OcrResult> {
fun detectImpl(scriptRuntime: ScriptRuntime, image: ImageWrapper, options: NativeObject): List<OcrResult> {
ApkBuilder.Libs.MLKIT_OCR.ensureLibFiles(OcrMode.MLKIT.value)
return scriptRuntime.ocrMLKit.detect(image)
}

View File

@@ -1,19 +1,23 @@
package org.autojs.autojs.runtime.api.augment.ocr
import kotlinx.coroutines.runBlocking
import org.autojs.autojs.annotation.RhinoRuntimeFunctionInterface
import org.autojs.autojs.apkbuilder.ApkBuilder
import org.autojs.autojs.core.image.ImageWrapper
import org.autojs.autojs.core.plugin.ocr.OcrPluginHost
import org.autojs.autojs.extension.ScriptableObjectExtensions.inquire
import org.autojs.autojs.runtime.ScriptRuntime
import org.autojs.autojs.runtime.api.OcrResult
import org.autojs.autojs.runtime.api.augment.Augmentable
import org.autojs.autojs.runtime.api.augment.Invokable
import org.autojs.autojs.runtime.api.augment.ocr.Ocr.Companion.OcrMode
import org.autojs.autojs.runtime.exception.WrappedIllegalArgumentException
import org.autojs.autojs.util.RhinoUtils.coerceBoolean
import org.autojs.autojs.util.RhinoUtils.coerceIntNumber
import org.mozilla.javascript.NativeArray
import org.mozilla.javascript.NativeObject
@Suppress("unused")
class OcrPaddle(private val scriptRuntime: ScriptRuntime) : Augmentable(scriptRuntime), Invokable {
override val key = OcrMode.PADDLE.value
@@ -29,40 +33,55 @@ class OcrPaddle(private val scriptRuntime: ScriptRuntime) : Augmentable(scriptRu
private const val DEFAULT_CPU_THREAD_NUM = 4
private const val DEFAULT_USE_SLIM = true
private const val DEFAULT_USE_OPENCL = false
@JvmStatic
@RhinoRuntimeFunctionInterface
fun recognizeText(scriptRuntime: ScriptRuntime, args: Array<out Any?>): NativeArray = ensureArgumentsAtMost(args, 3) {
Ocr.commonRecognizeText(scriptRuntime, OcrMode.PADDLE, *it)
fun recognizeText(scriptRuntime: ScriptRuntime, args: Array<out Any?>): NativeArray = ensureArgumentsAtMost(args, 3) { argList ->
Ocr.recognizeTextWith(scriptRuntime, OcrMode.PADDLE, argList)
}
@JvmStatic
@RhinoRuntimeFunctionInterface
fun detect(scriptRuntime: ScriptRuntime, args: Array<out Any?>): NativeArray = ensureArgumentsAtMost(args, 3) {
Ocr.commonDetect(scriptRuntime, OcrMode.PADDLE, *it)
fun detect(scriptRuntime: ScriptRuntime, args: Array<out Any?>): NativeArray = ensureArgumentsAtMost(args, 3) { argList ->
Ocr.detectWith(scriptRuntime, OcrMode.PADDLE, argList)
}
fun recognizeTextInternal(scriptRuntime: ScriptRuntime, image: ImageWrapper, options: NativeObject): List<String> {
ApkBuilder.Libs.PADDLE_OCR.ensureLibFiles(OcrMode.PADDLE.value)
val (cpuThreadNum, useSlim) = getOcrOptions(options)
return scriptRuntime.ocrPaddle.recognizeText(image, cpuThreadNum, useSlim)
fun recognizeTextImpl(scriptRuntime: ScriptRuntime, image: ImageWrapper, options: NativeObject): List<String> {
return performOcr(scriptRuntime, image, options).map {
it.text
}
}
fun detectInternal(scriptRuntime: ScriptRuntime, image: ImageWrapper, options: NativeObject): List<OcrResult> {
fun detectImpl(scriptRuntime: ScriptRuntime, image: ImageWrapper, options: NativeObject): List<OcrResult> {
return performOcr(scriptRuntime, image, options).map {
OcrResult(it.text, it.confidence, it.bounds)
}
}
private fun performOcr(scriptRuntime: ScriptRuntime, image: ImageWrapper, options: NativeObject): List<org.autojs.plugin.ocr.OcrResult> {
ApkBuilder.Libs.PADDLE_OCR.ensureLibFiles(OcrMode.PADDLE.value)
val (cpuThreadNum, useSlim) = getOcrOptions(options)
return scriptRuntime.ocrPaddle.detect(image, cpuThreadNum, useSlim).map { result ->
OcrResult(result.label, result.confidence, result.bounds)
val (cpuThreadNum, useSlim, useOpenCL) = getOcrOptions(options)
val ocrOptions = org.autojs.plugin.ocr.OcrOptions().apply {
this.threads = cpuThreadNum
this.useSlim = useSlim
this.useOpenCL = useOpenCL
}
return runBlocking(scriptRuntime.coroutineContext) {
val target = OcrPluginHost.select(globalContext)
?: throw WrappedIllegalArgumentException("No Paddle OCR plugin matched")
OcrPluginHost.detect(globalContext, target, image.bitmap, ocrOptions)
}
}
private fun getOcrOptions(options: NativeObject): OcrOptions {
val cpuThreadNum = options.inquire("cpuThreadNum", ::coerceIntNumber, DEFAULT_CPU_THREAD_NUM)
val useSlim = options.inquire("useSlim", ::coerceBoolean, DEFAULT_USE_SLIM)
return OcrOptions(cpuThreadNum, useSlim)
val useOpenCL = options.inquire("useOpenCL", ::coerceBoolean, DEFAULT_USE_OPENCL)
return OcrOptions(cpuThreadNum, useSlim, useOpenCL)
}
data class OcrOptions(val cpuThreadNum: Int, val useSlim: Boolean)
private data class OcrOptions(val cpuThreadNum: Int, val useSlim: Boolean, val useOpenCL: Boolean)
}

View File

@@ -26,20 +26,20 @@ class OcrRapid(private val scriptRuntime: ScriptRuntime) : Augmentable(scriptRun
@JvmStatic
@RhinoRuntimeFunctionInterface
fun recognizeText(scriptRuntime: ScriptRuntime, args: Array<out Any?>): NativeArray = ensureArgumentsAtMost(args, 3) {
Ocr.commonRecognizeText(scriptRuntime, OcrMode.RAPID, *it)
fun recognizeText(scriptRuntime: ScriptRuntime, args: Array<out Any?>): NativeArray = ensureArgumentsAtMost(args, 3) { argList ->
Ocr.recognizeTextWith(scriptRuntime, OcrMode.RAPID, argList)
}
@JvmStatic
@RhinoRuntimeFunctionInterface
fun detect(scriptRuntime: ScriptRuntime, args: Array<out Any?>): NativeArray = ensureArgumentsAtMost(args, 3) {
Ocr.commonDetect(scriptRuntime, OcrMode.RAPID, *it)
fun detect(scriptRuntime: ScriptRuntime, args: Array<out Any?>): NativeArray = ensureArgumentsAtMost(args, 3) { argList ->
Ocr.detectWith(scriptRuntime, OcrMode.RAPID, argList)
}
// @Hint by SuperMonster003 on Nov 1, 2024.
// ! Reserved param `options`.
// ! zh-CN: 预留参数 `options`.
fun recognizeTextInternal(scriptRuntime: ScriptRuntime, image: ImageWrapper, @Suppress("UNUSED_PARAMETER") options: NativeObject): List<String> {
fun recognizeTextImpl(scriptRuntime: ScriptRuntime, image: ImageWrapper, @Suppress("UNUSED_PARAMETER") options: NativeObject): List<String> {
ApkBuilder.Libs.RAPID_OCR.ensureLibFiles(OcrMode.RAPID.value)
return scriptRuntime.ocrRapid.recognizeText(image)
}
@@ -47,7 +47,7 @@ class OcrRapid(private val scriptRuntime: ScriptRuntime) : Augmentable(scriptRun
// @Hint by SuperMonster003 on Nov 1, 2024.
// ! Reserved param `options`.
// ! zh-CN: 预留参数 `options`.
fun detectInternal(scriptRuntime: ScriptRuntime, image: ImageWrapper, @Suppress("UNUSED_PARAMETER") options: NativeObject): List<OcrResult> {
fun detectImpl(scriptRuntime: ScriptRuntime, image: ImageWrapper, @Suppress("UNUSED_PARAMETER") options: NativeObject): List<OcrResult> {
ApkBuilder.Libs.RAPID_OCR.ensureLibFiles(OcrMode.RAPID.value)
return scriptRuntime.ocrRapid.detect(image)
}