Skip to content
Merged
Show file tree
Hide file tree
Changes from 19 commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
27 changes: 12 additions & 15 deletions android/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -8,31 +8,30 @@ buildscript {
}

dependencies {
classpath 'com.android.tools.build:gradle:7.1.2'
classpath 'com.android.tools.build:gradle:8.6.0'
}
}

rootProject.allprojects {
repositories {
google()
mavenCentral()
flatDir{
dirs project(":flutter_vision").file("libs")
}
maven {
url 'https://jitpack.io'
}
maven{
name 'ossrh-snapshot'
url 'https://oss.sonatype.org/content/repositories/snapshots'
}

}
}

apply plugin: 'com.android.library'

android {
compileSdkVersion 31
namespace "com.vladih.computer_vision.flutter_vision"
compileSdkVersion 36

compileOptions {
sourceCompatibility JavaVersion.VERSION_1_8
Expand All @@ -41,6 +40,7 @@ android {

defaultConfig {
minSdkVersion 21
targetSdk 36
}
aaptOptions {
noCompress 'tflite'
Expand All @@ -50,17 +50,14 @@ android {
buildFeatures{
mlModelBinding true
}

}
dependencies{
//implementation (files('libs/tesseract4android-release.aar'))
api(name:"tesseract4android-release", ext: "aar")
implementation 'com.github.vladiH:opencv-android:v1.0.0'
implementation 'org.tensorflow:tensorflow-lite:2.10.0'
implementation 'org.tensorflow:tensorflow-lite-api:2.10.0'
implementation 'org.tensorflow:tensorflow-lite-gpu:2.10.0'
implementation 'org.tensorflow:tensorflow-lite-gpu-api:2.10.0'
implementation 'org.tensorflow:tensorflow-lite-gpu-delegate-plugin:0.4.3'
implementation 'org.tensorflow:tensorflow-lite-support:0.4.3'
implementation 'org.tensorflow:tensorflow-lite-metadata:0.4.3'
implementation 'org.tensorflow:tensorflow-lite-select-tf-ops:2.11.0'
implementation 'com.google.ai.edge.litert:litert:1.4.0'
implementation 'com.google.ai.edge.litert:litert-api:1.4.0'
implementation 'com.google.ai.edge.litert:litert-gpu:1.4.0'
implementation 'com.google.ai.edge.litert:litert-gpu-api:1.4.0'
implementation 'com.google.ai.edge.litert:litert-support:1.4.0'
implementation 'com.google.ai.edge.litert:litert-metadata:1.4.0'
}
5 changes: 2 additions & 3 deletions android/gradle/wrapper/gradle-wrapper.properties
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
#Wed Feb 22 11:31:00 CET 2023
distributionBase=GRADLE_USER_HOME
distributionUrl=https\://services.gradle.org/distributions/gradle-7.5-bin.zip
distributionPath=wrapper/dists
zipStorePath=wrapper/dists
zipStoreBase=GRADLE_USER_HOME
zipStorePath=wrapper/dists
distributionUrl=https\://services.gradle.org/distributions/gradle-8.12-all.zip
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
#Sat Jan 25 18:51:17 CET 2025
distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists
distributionUrl=https\://services.gradle.org/distributions/gradle-8.10.2-all.zip
zipStoreBase=GRADLE_USER_HOME
zipStorePath=wrapper/dists
Binary file removed android/libs/tesseract4android-release.aar
Binary file not shown.
3 changes: 1 addition & 2 deletions android/src/main/AndroidManifest.xml
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.vladih.computer_vision.flutter_vision">
<manifest package="com.vladih.computer_vision.flutter_vision">
<!--enable this for storing bitmap-->
<!--<application android:requestLegacyExternalStorage="true">
</application>-->
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,20 +3,16 @@
import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Matrix;

import androidx.annotation.NonNull;

import com.vladih.computer_vision.flutter_vision.models.Tesseract;
import com.vladih.computer_vision.flutter_vision.models.Yolo;
import com.vladih.computer_vision.flutter_vision.models.Yolov8;
import com.vladih.computer_vision.flutter_vision.models.Yolov5;
import com.vladih.computer_vision.flutter_vision.models.Yolov8Seg;
import com.vladih.computer_vision.flutter_vision.utils.utils;

import org.opencv.android.OpenCVLoader;
import org.opencv.android.Utils;
import org.opencv.core.Mat;

import java.nio.ByteBuffer;
import java.util.ArrayList;
Expand All @@ -41,7 +37,6 @@ public class FlutterVisionPlugin implements FlutterPlugin, MethodCallHandler {
private Context context;
private FlutterAssets assets;
private Yolo yolo_model;
private Tesseract tesseract_model;

private ExecutorService executor;

Expand All @@ -61,7 +56,6 @@ public void onDetachedFromEngine(@NonNull FlutterPluginBinding binding) {
this.methodChannel.setMethodCallHandler(null);
this.methodChannel = null;
this.assets = null;
close_tesseract();
close_yolo();
this.executor.shutdownNow();
} catch (Exception e) {
Expand All @@ -84,17 +78,7 @@ private void setupChannel(Context context, FlutterAssets assets, BinaryMessenger
@Override
public void onMethodCall(@NonNull MethodCall call, @NonNull Result result) {
// Handle method calls from Flutter
if (call.method.equals("loadOcrModel")) {
try {
load_ocr_model((Map) call.arguments);
} catch (Exception e) {
result.error("100", "Error on load ocr components", e);
}
} else if (call.method.equals("ocrOnFrame")) {
ocr_on_frame((Map) call.arguments, result);
} else if (call.method.equals("closeOcrModel")) {
close_ocr_model(result);
} else if (call.method.equals("loadYoloModel")) {
if (call.method.equals("loadYoloModel")) {
try {
load_yolo_model((Map) call.arguments);
result.success("ok");
Expand All @@ -107,77 +91,26 @@ public void onMethodCall(@NonNull MethodCall call, @NonNull Result result) {
yolo_on_image((Map) call.arguments, result);
} else if (call.method.equals("closeYoloModel")) {
close_yolo_model(result);
} else if (call.method.equals("loadTesseractModel")) {
try {
load_tesseract_model((Map) call.arguments);
result.success("ok");
} catch (Exception e) {
result.error("100", "Error on load Tesseract model", e);
}
} else if (call.method.equals("tesseractOnImage")) {
tesseract_on_image((Map) call.arguments, result);
} else if (call.method.equals("closeTesseractModel")) {
close_tesseract_model(result);
} else {
}else {
result.notImplemented();
}
}

private void load_ocr_model(Map<String, Object> args) throws Exception {
load_yolo_model(args);
load_tesseract_model(args);
}

private void ocr_on_frame(Map<String, Object> args, Result result) {
try {
List<byte[]> image = (ArrayList) args.get("bytesList");
int image_height = (int) args.get("image_height");
int image_width = (int) args.get("image_width");
float iou_threshold = (float) (double) (args.get("iou_threshold"));
float conf_threshold = (float) (double) (args.get("conf_threshold"));
float class_threshold = (float) (double) (args.get("class_threshold"));
List<Integer> class_is_text = (List<Integer>) args.get("class_is_text");
Bitmap bitmap = utils.feedInputToBitmap(context.getApplicationContext(), image, image_height, image_width, 90);
int[] shape = yolo_model.getInputTensor().shape();
ByteBuffer byteBuffer = utils.feedInputTensor(bitmap, shape[1], shape[2], image_width, image_height, 0, 255);

List<Map<String, Object>> yolo_results = yolo_model.detect_task(byteBuffer, image_height, image_width, iou_threshold, conf_threshold, class_threshold);
for (Map<String, Object> yolo_result : yolo_results) {
float[] box = (float[]) yolo_result.get("box");
if (class_is_text.contains((int) box[5])) {
Bitmap crop = utils.crop_bitmap(bitmap,
box[0], box[1], box[2], box[3]);
//utils.getScreenshotBmp(crop, "crop");
Bitmap tmp = crop.copy(crop.getConfig(), crop.isMutable());
yolo_result.put("text", tesseract_model.predict_text(tmp));
} else {
yolo_result.put("text", "");
}
}
result.success(yolo_results);
} catch (Exception e) {
result.error("100", "Ocr error", e);
}
}

private void close_ocr_model(Result result) {
try {
close_tesseract();
close_yolo();
result.success("OCR model closed succesfully");
} catch (Exception e) {
result.error("100", "Fail closed ocr model", e);
}
}

private void load_yolo_model(Map<String, Object> args) throws Exception {
final String model = this.assets.getAssetFilePathByName(args.get("model_path").toString());
final Object is_asset_obj = args.get("is_asset");
String model = "";
final Object is_asset_obj = args.get("is_asset");
final boolean is_asset = is_asset_obj == null ? false : (boolean) is_asset_obj;
String label_path = "";
if(is_asset){
model = this.assets.getAssetFilePathByName(args.get("model_path").toString());
label_path = this.assets.getAssetFilePathByName(args.get("label_path").toString());
}else{
model = args.get("model_path").toString();
label_path = args.get("label_path").toString();
}
final int num_threads = (int) args.get("num_threads");
final boolean quantization = (boolean) args.get("quantization");
final boolean use_gpu = (boolean) args.get("use_gpu");
final String label_path = this.assets.getAssetFilePathByName(args.get("label_path").toString());
final int rotation = (int) args.get("rotation");
final String version = args.get("model_version").toString();
switch (version) {
Expand Down Expand Up @@ -316,68 +249,6 @@ private void close_yolo_model(Result result) {
}
}

private void load_tesseract_model(Map<String, Object> args) throws Exception {
final String tess_data = args.get("tess_data").toString();
final Map<String, String> arg = (Map<String, String>) args.get("arg");
final String language = args.get("language").toString();
tesseract_model = new Tesseract(tess_data, arg, language);
tesseract_model.initialize_model();
}

class PredictionTask implements Runnable {
private Tesseract tesseract;
private Bitmap bitmap;
private Result result;

public PredictionTask(Tesseract tesseract, Map<String, Object> args, Result result) {
byte[] image = (byte[]) args.get("bytesList");
this.tesseract = tesseract;
this.bitmap = BitmapFactory.decodeByteArray(image, 0, image.length);
this.result = result;
}

@Override
public void run() {
try {
Mat mat = utils.rgbBitmapToMatGray(bitmap);
double angle = utils.computeSkewAngle(mat.clone());
mat = utils.deskew(mat, angle);
mat = utils.filterTextFromImage(mat);
bitmap = Bitmap.createBitmap(mat.width(), mat.height(), Bitmap.Config.ARGB_8888);
Utils.matToBitmap(mat, bitmap);
// utils.getScreenshotBmp(bitmap,"TESSEREACT");
result.success(tesseract.predict_text(bitmap));
} catch (Exception e) {
result.error("100", "Prediction text Error", e);
}
}
}

private void tesseract_on_image(Map<String, Object> args, Result result) {
try {
PredictionTask predictionTask = new PredictionTask(tesseract_model, args, result);
executor.submit(predictionTask);
} catch (Exception e) {
result.error("100", "Prediction Error", e);
}
}

private void close_tesseract_model(Result result) {
try {
close_tesseract();
result.success("Tesseract model closed succesfully");
} catch (Exception e) {
result.error("100", "close_tesseract_model error", e);
}
}

private void close_tesseract(){
if (tesseract_model != null) {
tesseract_model.close();
tesseract_model = null;
}
}

private void close_yolo(){
if (yolo_model != null) {
yolo_model.close();
Expand Down

This file was deleted.

Loading