6.7.0 - Alpha11 - 修复 ocr.detect 异常及 ocr 部分重载方法异常
This commit is contained in:
@@ -36,7 +36,7 @@ class OcrRapid {
|
||||
|
||||
// 创建 OcrResult 对象
|
||||
OcrResult(
|
||||
label = block.text,
|
||||
text = block.text,
|
||||
confidence = block.boxScore,
|
||||
bounds = rect,
|
||||
)
|
||||
|
||||
@@ -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}"
|
||||
|
||||
}
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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)
|
||||
}
|
||||
|
||||
@@ -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)
|
||||
|
||||
}
|
||||
|
||||
|
||||
@@ -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)
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user