From 31a77957adc8059ffe002f3a68f555d489241810 Mon Sep 17 00:00:00 2001 From: tongtongstudio Date: Wed, 4 Jun 2025 15:41:06 +0800 Subject: [PATCH] =?UTF-8?q?version:=20bugfixes:=20update:=E5=8E=BB?= =?UTF-8?q?=E6=8E=89ocr=E7=9B=AE=E5=BD=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../selecttospeak/SelectToSpeakService.java | 6 +- .../callwechat/CallWechatActivity.java | 2 + .../os/ocr/paddle/OCRPredictorNative.java | 105 ------- .../vscool/os/ocr/paddle/OcrResultModel.java | 79 ----- .../com/vscool/os/ocr/paddle/Predictor.java | 283 ------------------ .../java/com/vscool/os/ocr/paddle/Utils.java | 165 ---------- 6 files changed, 5 insertions(+), 635 deletions(-) delete mode 100644 app/src/main/java/com/vscool/os/ocr/paddle/OCRPredictorNative.java delete mode 100644 app/src/main/java/com/vscool/os/ocr/paddle/OcrResultModel.java delete mode 100644 app/src/main/java/com/vscool/os/ocr/paddle/Predictor.java delete mode 100644 app/src/main/java/com/vscool/os/ocr/paddle/Utils.java diff --git a/app/src/main/java/com/google/android/accessibility/selecttospeak/SelectToSpeakService.java b/app/src/main/java/com/google/android/accessibility/selecttospeak/SelectToSpeakService.java index 55cf898..564b32b 100644 --- a/app/src/main/java/com/google/android/accessibility/selecttospeak/SelectToSpeakService.java +++ b/app/src/main/java/com/google/android/accessibility/selecttospeak/SelectToSpeakService.java @@ -147,14 +147,14 @@ public class SelectToSpeakService extends AccessibilityService { if (mCurrentStep != Step.FIND_CONTACT) { mCurrentStep = Step.CLICK_CONTACT; } - break; - case "com.tencent.mm.plugin.label.ui.ContactLabelManagerUI": - break; case "com.tencent.mm.plugin.account.ui.WelcomeActivity": case "com.tencent.mm.plugin.account.ui.LoginPasswordUI": Toaster.showLong("请先登录微信"); mCurrentStep = Step.WAITING; + break; + case "com.tencent.mm.plugin.label.ui.ContactLabelManagerUI": + break; default: } diff --git a/app/src/main/java/com/vscool/os/activity/callwechat/CallWechatActivity.java b/app/src/main/java/com/vscool/os/activity/callwechat/CallWechatActivity.java index 8a7b00d..9d1c4e2 100644 --- a/app/src/main/java/com/vscool/os/activity/callwechat/CallWechatActivity.java +++ b/app/src/main/java/com/vscool/os/activity/callwechat/CallWechatActivity.java @@ -137,6 +137,7 @@ public class CallWechatActivity extends BaseMvvmActivity runImage(Bitmap originalImage, int max_size_len, int run_det, int run_cls, int run_rec) { - Log.i("OCRPredictorNative", "begin to run image "); - float[] rawResults = forward(nativePointer, originalImage, max_size_len, run_det, run_cls, run_rec); - ArrayList results = postprocess(rawResults); - return results; - } - - public static class Config { - public int useOpencl; - public int cpuThreadNum; - public String cpuPower; - public String detModelFilename; - public String recModelFilename; - public String clsModelFilename; - - } - - public void destroy() { - if (nativePointer != 0) { - release(nativePointer); - nativePointer = 0; - } - } - - protected native long init(String detModelPath, String recModelPath, String clsModelPath, int useOpencl, int threadNum, String cpuMode); - - protected native float[] forward(long pointer, Bitmap originalImage, int max_size_len, int run_det, int run_cls, int run_rec); - - protected native void release(long pointer); - - private ArrayList postprocess(float[] raw) { - ArrayList results = new ArrayList(); - int begin = 0; - - while (begin < raw.length) { - int point_num = Math.round(raw[begin]); - int word_num = Math.round(raw[begin + 1]); - OcrResultModel res = parse(raw, begin + 2, point_num, word_num); - begin += 2 + 1 + point_num * 2 + word_num + 2; - results.add(res); - } - - return results; - } - - private OcrResultModel parse(float[] raw, int begin, int pointNum, int wordNum) { - int current = begin; - OcrResultModel res = new OcrResultModel(); - res.setConfidence(raw[current]); - current++; - for (int i = 0; i < pointNum; i++) { - res.addPoints(Math.round(raw[current + i * 2]), Math.round(raw[current + i * 2 + 1])); - } - current += (pointNum * 2); - for (int i = 0; i < wordNum; i++) { - int index = Math.round(raw[current + i]); - res.addWordIndex(index); - } - current += wordNum; - res.setClsIdx(raw[current]); - res.setClsConfidence(raw[current + 1]); - Log.i("OCRPredictorNative", "word finished " + wordNum); - return res; - } - - -} diff --git a/app/src/main/java/com/vscool/os/ocr/paddle/OcrResultModel.java b/app/src/main/java/com/vscool/os/ocr/paddle/OcrResultModel.java deleted file mode 100644 index c1a2fc3..0000000 --- a/app/src/main/java/com/vscool/os/ocr/paddle/OcrResultModel.java +++ /dev/null @@ -1,79 +0,0 @@ -package com.vscool.os.ocr.paddle; - -import android.graphics.Point; - -import java.util.ArrayList; -import java.util.List; - -public class OcrResultModel { - private List points; - private List wordIndex; - private String label; - private float confidence; - private float cls_idx; - private String cls_label; - private float cls_confidence; - - public OcrResultModel() { - super(); - points = new ArrayList<>(); - wordIndex = new ArrayList<>(); - } - - public void addPoints(int x, int y) { - Point point = new Point(x, y); - points.add(point); - } - - public void addWordIndex(int index) { - wordIndex.add(index); - } - - public List getPoints() { - return points; - } - - public List getWordIndex() { - return wordIndex; - } - - public String getLabel() { - return label; - } - - public void setLabel(String label) { - this.label = label; - } - - public float getConfidence() { - return confidence; - } - - public void setConfidence(float confidence) { - this.confidence = confidence; - } - - public float getClsIdx() { - return cls_idx; - } - - public void setClsIdx(float idx) { - this.cls_idx = idx; - } - - public String getClsLabel() { - return cls_label; - } - - public void setClsLabel(String label) { - this.cls_label = label; - } - - public float getClsConfidence() { - return cls_confidence; - } - - public void setClsConfidence(float confidence) { - this.cls_confidence = confidence; - } -} diff --git a/app/src/main/java/com/vscool/os/ocr/paddle/Predictor.java b/app/src/main/java/com/vscool/os/ocr/paddle/Predictor.java deleted file mode 100644 index 212c8f5..0000000 --- a/app/src/main/java/com/vscool/os/ocr/paddle/Predictor.java +++ /dev/null @@ -1,283 +0,0 @@ -package com.vscool.os.ocr.paddle; - -import android.content.Context; -import android.graphics.Bitmap; -import android.graphics.Canvas; -import android.graphics.Color; -import android.graphics.Paint; -import android.graphics.Path; -import android.graphics.Point; -import android.util.Log; - -import java.io.File; -import java.io.InputStream; -import java.util.ArrayList; -import java.util.Date; -import java.util.List; -import java.util.Vector; - -public class Predictor { - private static final String TAG = Predictor.class.getSimpleName(); - public boolean isLoaded = false; - public int warmupIterNum = 1; - public int inferIterNum = 1; - public int cpuThreadNum = 6; - public String cpuPowerMode = "LITE_POWER_HIGH"; - public String modelPath = ""; - public String modelName = ""; - protected OCRPredictorNative paddlePredictor = null; - protected float inferenceTime = 0; - // Only for object detection - protected Vector wordLabels = new Vector(); - protected int detLongSize = 960; - protected float scoreThreshold = 0.1f; - protected Bitmap inputImage = null; - protected Bitmap outputImage = null; - protected volatile String outputResult = ""; - protected float postprocessTime = 0; - protected ArrayList mOcrResultModels; - - public Predictor() { - } - - public boolean init(Context appCtx, String modelPath, String labelPath, int useOpencl, int cpuThreadNum, String cpuPowerMode) { - isLoaded = loadModel(appCtx, modelPath, useOpencl, cpuThreadNum, cpuPowerMode); - if (!isLoaded) { - return false; - } - isLoaded = loadLabel(appCtx, labelPath); - return isLoaded; - } - - - public boolean init(Context appCtx, String modelPath, String labelPath, int useOpencl, int cpuThreadNum, String cpuPowerMode, - int detLongSize, float scoreThreshold) { - boolean isLoaded = init(appCtx, modelPath, labelPath, useOpencl, cpuThreadNum, cpuPowerMode); - if (!isLoaded) { - return false; - } - this.detLongSize = detLongSize; - this.scoreThreshold = scoreThreshold; - return true; - } - - protected boolean loadModel(Context appCtx, String modelPath, int useOpencl, int cpuThreadNum, String cpuPowerMode) { - // Release model if exists - releaseModel(); - - // Load model - if (modelPath.isEmpty()) { - return false; - } - String realPath = modelPath; - if (!modelPath.substring(0, 1).equals("/")) { - // Read model files from custom path if the first character of mode path is '/' - // otherwise copy model to cache from assets - realPath = appCtx.getCacheDir() + "/" + modelPath; - Utils.copyDirectoryFromAssets(appCtx, modelPath, realPath); - } - if (realPath.isEmpty()) { - return false; - } - - OCRPredictorNative.Config config = new OCRPredictorNative.Config(); - config.useOpencl = useOpencl; - config.cpuThreadNum = cpuThreadNum; - config.cpuPower = cpuPowerMode; - config.detModelFilename = realPath + File.separator + "det_db.nb"; - config.recModelFilename = realPath + File.separator + "rec_crnn.nb"; - config.clsModelFilename = realPath + File.separator + "cls.nb"; - Log.i("Predictor", "model path" + config.detModelFilename + " ; " + config.recModelFilename + ";" + config.clsModelFilename); - paddlePredictor = new OCRPredictorNative(config); - - this.cpuThreadNum = cpuThreadNum; - this.cpuPowerMode = cpuPowerMode; - this.modelPath = realPath; - this.modelName = realPath.substring(realPath.lastIndexOf("/") + 1); - return true; - } - - public void releaseModel() { - if (paddlePredictor != null) { - paddlePredictor.destroy(); - paddlePredictor = null; - } - isLoaded = false; - cpuThreadNum = 1; - cpuPowerMode = "LITE_POWER_HIGH"; - modelPath = ""; - modelName = ""; - } - - protected boolean loadLabel(Context appCtx, String labelPath) { - wordLabels.clear(); - wordLabels.add("black"); - // Load word labels from file - try { - InputStream assetsInputStream = appCtx.getAssets().open(labelPath); - int available = assetsInputStream.available(); - byte[] lines = new byte[available]; - assetsInputStream.read(lines); - assetsInputStream.close(); - String words = new String(lines); - String[] contents = words.split("\n"); - for (String content : contents) { - wordLabels.add(content); - } - wordLabels.add(" "); - Log.i(TAG, "Word label size: " + wordLabels.size()); - } catch (Exception e) { - Log.e(TAG, e.getMessage()); - return false; - } - return true; - } - - - public boolean runModel(int run_det, int run_cls, int run_rec) { - if (inputImage == null || !isLoaded()) { - return false; - } - Log.d(TAG, "runModel: " + inputImage.getWidth() + "x" + inputImage.getHeight()); - // Warm up - for (int i = 0; i < warmupIterNum; i++) { - paddlePredictor.runImage(inputImage, detLongSize, run_det, run_cls, run_rec); - } - warmupIterNum = 0; // do not need warm - // Run inference - Date start = new Date(); - ArrayList results = paddlePredictor.runImage(inputImage, detLongSize, run_det, run_cls, run_rec); - Date end = new Date(); - inferenceTime = (end.getTime() - start.getTime()) / (float) inferIterNum; - - results = postprocess(results); - mOcrResultModels = results; - Log.i(TAG, "[stat] Inference Time: " + inferenceTime + " ;Box Size " + results.size()); - drawResults(results); - - return true; - } - - public ArrayList getOcrResultModels() { - return mOcrResultModels; - } - - public boolean isLoaded() { - return paddlePredictor != null && isLoaded; - } - - public String modelPath() { - return modelPath; - } - - public String modelName() { - return modelName; - } - - public int cpuThreadNum() { - return cpuThreadNum; - } - - public String cpuPowerMode() { - return cpuPowerMode; - } - - public float inferenceTime() { - return inferenceTime; - } - - public Bitmap inputImage() { - return inputImage; - } - - public Bitmap outputImage() { - return outputImage; - } - - public String outputResult() { - return outputResult; - } - - public float postprocessTime() { - return postprocessTime; - } - - - public void setInputImage(Bitmap image) { - if (image == null) { - return; - } - this.inputImage = image.copy(Bitmap.Config.ARGB_8888, true); - } - - private ArrayList postprocess(ArrayList results) { - for (OcrResultModel r : results) { - StringBuffer word = new StringBuffer(); - for (int index : r.getWordIndex()) { - if (index >= 0 && index < wordLabels.size()) { - word.append(wordLabels.get(index)); - } else { - Log.e(TAG, "Word index is not in label list:" + index); - word.append("×"); - } - } - r.setLabel(word.toString()); - r.setClsLabel(r.getClsIdx() == 1 ? "180" : "0"); - } - return results; - } - - private void drawResults(ArrayList results) { - StringBuffer outputResultSb = new StringBuffer(""); - for (int i = 0; i < results.size(); i++) { - OcrResultModel result = results.get(i); - StringBuilder sb = new StringBuilder(""); - if (result.getPoints().size() > 0) { - sb.append("Det: "); - for (Point p : result.getPoints()) { - sb.append("(").append(p.x).append(",").append(p.y).append(") "); - } - } - if (result.getLabel().length() > 0) { - sb.append("\n Rec: ").append(result.getLabel()); - sb.append(",").append(result.getConfidence()); - } - if (result.getClsIdx() != -1) { - sb.append(" Cls: ").append(result.getClsLabel()); - sb.append(",").append(result.getClsConfidence()); - } - Log.i(TAG, sb.toString()); // show LOG in Logcat panel - outputResultSb.append(i + 1).append(": ").append(sb.toString()).append("\n"); - } - outputResult = outputResultSb.toString(); - outputImage = inputImage; - Canvas canvas = new Canvas(outputImage); - Paint paintFillAlpha = new Paint(); - paintFillAlpha.setStyle(Paint.Style.FILL); - paintFillAlpha.setColor(Color.parseColor("#3B85F5")); - paintFillAlpha.setAlpha(50); - - Paint paint = new Paint(); - paint.setColor(Color.parseColor("#3B85F5")); - paint.setStrokeWidth(5); - paint.setStyle(Paint.Style.STROKE); - - for (OcrResultModel result : results) { - Path path = new Path(); - List points = result.getPoints(); - if (points.size() == 0) { - continue; - } - path.moveTo(points.get(0).x, points.get(0).y); - for (int i = points.size() - 1; i >= 0; i--) { - Point p = points.get(i); - path.lineTo(p.x, p.y); - } - canvas.drawPath(path, paint); - canvas.drawPath(path, paintFillAlpha); - } - Log.d(TAG, "drawResults: " + outputImage.getWidth() + "x" + outputImage.getHeight()); - - } - -} diff --git a/app/src/main/java/com/vscool/os/ocr/paddle/Utils.java b/app/src/main/java/com/vscool/os/ocr/paddle/Utils.java deleted file mode 100644 index 0921281..0000000 --- a/app/src/main/java/com/vscool/os/ocr/paddle/Utils.java +++ /dev/null @@ -1,165 +0,0 @@ -package com.vscool.os.ocr.paddle; - -import android.content.Context; -import android.graphics.Bitmap; -import android.graphics.Matrix; -import android.media.ExifInterface; -import android.os.Environment; - -import java.io.BufferedInputStream; -import java.io.BufferedOutputStream; -import java.io.File; -import java.io.FileNotFoundException; -import java.io.FileOutputStream; -import java.io.IOException; -import java.io.InputStream; -import java.io.OutputStream; - -public class Utils { - private static final String TAG = Utils.class.getSimpleName(); - - public static void copyFileFromAssets(Context appCtx, String srcPath, String dstPath) { - if (srcPath.isEmpty() || dstPath.isEmpty()) { - return; - } - InputStream is = null; - OutputStream os = null; - try { - is = new BufferedInputStream(appCtx.getAssets().open(srcPath)); - os = new BufferedOutputStream(new FileOutputStream(new File(dstPath))); - byte[] buffer = new byte[1024]; - int length = 0; - while ((length = is.read(buffer)) != -1) { - os.write(buffer, 0, length); - } - } catch (FileNotFoundException e) { - e.printStackTrace(); - } catch (IOException e) { - e.printStackTrace(); - } finally { - try { - os.close(); - is.close(); - } catch (IOException e) { - e.printStackTrace(); - } - } - } - - public static void copyDirectoryFromAssets(Context appCtx, String srcDir, String dstDir) { - if (srcDir.isEmpty() || dstDir.isEmpty()) { - return; - } - try { - if (!new File(dstDir).exists()) { - new File(dstDir).mkdirs(); - } - for (String fileName : appCtx.getAssets().list(srcDir)) { - String srcSubPath = srcDir + File.separator + fileName; - String dstSubPath = dstDir + File.separator + fileName; - if (new File(srcSubPath).isDirectory()) { - copyDirectoryFromAssets(appCtx, srcSubPath, dstSubPath); - } else { - copyFileFromAssets(appCtx, srcSubPath, dstSubPath); - } - } - } catch (Exception e) { - e.printStackTrace(); - } - } - - public static float[] parseFloatsFromString(String string, String delimiter) { - String[] pieces = string.trim().toLowerCase().split(delimiter); - float[] floats = new float[pieces.length]; - for (int i = 0; i < pieces.length; i++) { - floats[i] = Float.parseFloat(pieces[i].trim()); - } - return floats; - } - - public static long[] parseLongsFromString(String string, String delimiter) { - String[] pieces = string.trim().toLowerCase().split(delimiter); - long[] longs = new long[pieces.length]; - for (int i = 0; i < pieces.length; i++) { - longs[i] = Long.parseLong(pieces[i].trim()); - } - return longs; - } - - public static String getSDCardDirectory() { - return Environment.getExternalStorageDirectory().getAbsolutePath(); - } - - public static boolean isSupportedNPU() { - return false; - // String hardware = android.os.Build.HARDWARE; - // return hardware.equalsIgnoreCase("kirin810") || hardware.equalsIgnoreCase("kirin990"); - } - - public static Bitmap resizeWithStep(Bitmap bitmap, int maxLength, int step) { - int width = bitmap.getWidth(); - int height = bitmap.getHeight(); - int maxWH = Math.max(width, height); - float ratio = 1; - int newWidth = width; - int newHeight = height; - if (maxWH > maxLength) { - ratio = maxLength * 1.0f / maxWH; - newWidth = (int) Math.floor(ratio * width); - newHeight = (int) Math.floor(ratio * height); - } - - newWidth = newWidth - newWidth % step; - if (newWidth == 0) { - newWidth = step; - } - newHeight = newHeight - newHeight % step; - if (newHeight == 0) { - newHeight = step; - } - return Bitmap.createScaledBitmap(bitmap, newWidth, newHeight, true); - } - - public static Bitmap rotateBitmap(Bitmap bitmap, int orientation) { - - Matrix matrix = new Matrix(); - switch (orientation) { - case ExifInterface.ORIENTATION_NORMAL: - return bitmap; - case ExifInterface.ORIENTATION_FLIP_HORIZONTAL: - matrix.setScale(-1, 1); - break; - case ExifInterface.ORIENTATION_ROTATE_180: - matrix.setRotate(180); - break; - case ExifInterface.ORIENTATION_FLIP_VERTICAL: - matrix.setRotate(180); - matrix.postScale(-1, 1); - break; - case ExifInterface.ORIENTATION_TRANSPOSE: - matrix.setRotate(90); - matrix.postScale(-1, 1); - break; - case ExifInterface.ORIENTATION_ROTATE_90: - matrix.setRotate(90); - break; - case ExifInterface.ORIENTATION_TRANSVERSE: - matrix.setRotate(-90); - matrix.postScale(-1, 1); - break; - case ExifInterface.ORIENTATION_ROTATE_270: - matrix.setRotate(-90); - break; - default: - return bitmap; - } - try { - Bitmap bmRotated = Bitmap.createBitmap(bitmap, 0, 0, bitmap.getWidth(), bitmap.getHeight(), matrix, true); - bitmap.recycle(); - return bmRotated; - } catch (OutOfMemoryError e) { - e.printStackTrace(); - return null; - } - } -}