Coder Social home page Coder Social logo

cap-ml's Introduction

Cap-ML

Machine Learning Plugin for Capacitor. Currently offered implementations include -

  • Text Detector: Text Detection in still images.

    On the ios side, we're using Apple's Vision Framework and MLKit's Vision Framework on the Android side. Both have some limitations like not being able to detect cursive/handwriting font etc.

    TextDetector expects the image to be sent in portrait mode only, i.e. with text facing up. It will try to process even otherwise, but note that it might result in gibberish.

Compatibility Chart

Feature ios android
ML Framework CoreML Vision Firebase MLKit
Text Detection with Still Images Yes Yes
Detects lines of text Yes Yes
Bounding Coordinates for Text Yes Yes
Image Orientation Yes (Up, Left, Right, Down) Yes (Up, Left, Right, Down)
Skewed Text Yes Unreliable
Rotated Text (<~ 45deg) Yes Yes (but with noise)
On-Device Yes Yes
SDK/ios Version ios 13.0 or newer Targets API level >= 16
Uses Gradle >= 4.1
com.android.tools.build:gradle >= v3.2.1
compileSdkVersion >= 28

Installation

npm install cap-ml

Usage

TextDetector exposes only one method detectText that returns a Promise with an array of text detections -

// Orientation here is not the current orientation of the image, but the direction in which the image should be turned to make it upright
detectText(filename: string, orientation?: ImageOrientation): Promise<TextDetection[]>

TextDetection looks like -

interface TextDetection {
  bottomLeft: [number, number]; // [x-coordinate, y-coordinate]
  bottomRight: [number, number]; // [x-coordinate, y-coordinate]
  topLeft: [number, number]; // [x-coordinate, y-coordinate]
  topRight: [number, number]; // [x-coordinate, y-coordinate]
  text: string;
}

ImageOrientation is an enum -

enum ImageOrientation {
  Up = "UP",
  Down = "DOWN",
  Left = "LEFT",
  Right = "RIGHT",
}

bottomLeft[x,y], bottomRight[x,y], topLeft[x,y], topRight[x,y] provide the coordinates for the bounding quadrangle for the detected 'text'. Often, this would be a rectangle, but the text might be skewed.

Example Usage

import { Plugins } from '@capacitor/core';
const { Camera } = Plugins;
import { TextDetector, TextDetection } from 'cap-ml';

and used like:

 # prompt the user to select a picture
  const imageFile = await Camera.getPhoto({
    resultType: CameraResultType.Uri,
    source: CameraSource.Photos,
  })

  # pass in the picture to 'CapML' plugin
  const td = new TextDetector();
  const textDetections = await td.detectText(imageFile.path!)

  # or with orientation -
  # const textDetections = await td.detectText(imageFile.path!, ImageOrientation.Up)

  # textDetections is an array of detected texts and corresponding bounding box coordinates
  # which can be accessed like -
  textDetections.forEach((detection: TextDetection) => {
    text = detection.text
    bottomLeft = detection.bottomLeft
    bottomRight = detection.bottomRight
    topLeft = detection.topLeft
    topRight = detection.topRight
  })

If you're using it in an Android app (generated through Ionic), there is an additional step. Make sure to register the plugin in the app's MainActivity.java - Import the Plugin: import com.bendyworks.capML.CapML - Register the Plugin: On the same file, inside OnCreate's init, add - add(CapML.class)

A complete example can be found in the examples folder - examples/text-detection/ImageReader

If you're planning to use the Camera Plugin like in the example project or use an image from the Photo Library -

For ios:

  • Open the app in XCode by running npx cap open ios from the sample app's root directory. ie here, at examples/text-detection/ImageReader
  • Open info.plist
  • Add the corresponding permissions to the app -
    • Privacy - Camera Usage Description: To Take Photos and Video
    • Privacy - Photo Library Additions Usage Description: Store camera photos to camera
    • Privacy - Photo Library Usage Description: To Pick Photos from Library

For Android:

  • Open the app in Android Studio by running npx cap open android from the sample app's root directory. ie here, at examples/text-detection/ImageReader

  • Open app/manifests/AndroidManifest.xml

  • Add the corresponding permissions to the app -

    • android.permission.INTERNET
    • android.permission.READ_EXTERNAL_STORAGE
    • android.permission.WRITE_EXTERNAL_STORAGE
    • android.permission.CAMERA
  • Note: Sample App is set up to download Firebase's OCR model for Text Detection upon installing the app. If the app errors out with something like - Considering local module com.google.android.gms.vision.ocr:0 and remote module com.google.android.gms.vision.ocr:0. E/Vision: Error loading module com.google.android.gms.vision.ocr optional module true: com.google.android.gms.dynamite.DynamiteModule$LoadingException: No acceptable module found. Local version is 0 and remote version is 0..

    This is a known bug with Google Play Services.

    Follow these steps -

    1. Uninstall app from the device/emulator.
    2. Update 'Google Play Services' - make sure you have the latest version.
    3. Clear cache and store for 'Google Play Services'
    4. Restart the device/emulator
    5. Install and run the app.

Development

After checking out the repo,

  • run npm install to install dependencies. Plugin should be ready at this point. To test it out -
  • navigate to examples/text-detection/ImageReader
  • run npm install to install dependencies
  • run npm run build && npx cap sync to sync the project with ios and android

ios Development

  • run npx capacitor open ios to open up an XCode project.
  • Run the XCode project either on a simulator or a device.
  • For each change in the javascript part of the app, run npm run build && npx cap sync ios to deploy the corresponding changes to ios app (or)
  • (recommended) Enable live reload of the app, using ionic capacitor run ios --livereload Plugin code is located at Pods/DevelopmentPods/CapML
  • Plugin.swift is the entry point to the Plugin.

Android Development

Step 1: Open Android Project

  • run npx capacitor open android to open up an Android Studio project.

Step 2: Create Firebase Project and App

  • Naviagte to https://console.firebase.google.com/ and sign-in

  • Click on 'Add Project' and follow through the steps (Enable Google Analytics if you like but the project doesn't particularly need it)

  • Once the project is created, click on 'android' icon to create an android app.

  • Register App:

    • Enter the package name - this should be the same as the package name of your app. For example - package name in the example project here is com.bendyworks.CapML.ImageReader. Enter that if you wish to run the sample project. If you're setting up a new project, enter the package name of that app. (Tip: You can find it in app/AndroidManifest.xml). Click 'Register App'
    • Download google-services.json
    • Place the downloaded google-services.json in your project's app directory.
  • Add Firebase SDK: Example project should already this is place, but if you're setting up a new project, follow the instructions to modify build.gradle to use the downloaded google-services.json

  • Once the build changes are in place, perform a Gradle sync at this point. (Android Studio will prompt for a gradle sync as soon as a change is made to build files)

Step 3: Making changes and running the app

  • The example project is already setup to use the plugin, but if you're setting up a new project - In the project's MainActivity.java - - Import the Plugin: import com.bendyworks.capML.CapML - Register the Plugin: On the same file, inside OnCreate's init, add - add(CapML.class)

  • Build and Run the project either on a simulator or a device.

  • For each change in the javascript part of the app, run npm run build && npx cap sync android to deploy the corresponding changes to android app

    (or)

  • (recommended) Enable live reload of the app, using ionic capacitor run android --livereload

  • Plugin code is located at android-cap-ml/java/com.bendyworks.capML

  • CapML.java is the entry point to the Plugin. (Note: When plugin code is updated, make sure to rebuild the project before running it.)

Contributing

Bug reports and pull requests are welcome on GitHub at https://github.com/bendyworks/cap-ml.

If you're curious about the implementation, here's an extensive blog post series - https://bendyworks.com/blog/capacitor-plugin-for-text-detection-part1

License

Hippocratic License Version 2.0.

For more information, refer to LICENSE file

cap-ml's People

Contributors

abraham avatar dependabot[bot] avatar vennelakodali avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

cap-ml's Issues

Capacitor 3 support

Thanks for this awesome plugin, it's been really useful. Do you have any plans to add support for Capacitor 3? It seems they've changed the plugin interface a bit (cap plugin migration guide at https://capacitorjs.com/docs/updating/plugins/3-0).

Apparently Android apps need to target Android 11 / APK 30 by November 2021, and Capacitor 3 now supports APK 30.

Plugin failing to initialize with default firebase error at TextDetector.detectText

Android Studio Logcat error message:

E/Capacitor/Plugin: Default FirebaseApp is not initialized in this process io.ionic.starter. Make sure to call FirebaseApp.initializeApp(Context) first.
java.lang.IllegalStateException: Default FirebaseApp is not initialized in this process io.ionic.starter. Make sure to call FirebaseApp.initializeApp(Context) first.
at com.google.firebase.FirebaseApp.getInstance(com.google.firebase:firebase-common@@19.3.0:184)
at com.google.firebase.ml.vision.FirebaseVision.getInstance(com.google.firebase:firebase-ml-vision@@24.0.1:1)
at com.bendyworks.capML.TextDetector.detectText(TextDetector.kt:23)
at com.bendyworks.capML.CapML.detectText(CapML.java:47)
at java.lang.reflect.Method.invoke(Native Method)
at com.getcapacitor.PluginHandle.invoke(PluginHandle.java:99)
at com.getcapacitor.Bridge$1.run(Bridge.java:521)
at android.os.Handler.handleCallback(Handler.java:938)
at android.os.Handler.dispatchMessage(Handler.java:99)
at android.os.Looper.loop(Looper.java:223)
at android.os.HandlerThread.run(HandlerThread.java:67)

CapML version is ^1.0.1

Can't start with browser: "Ionic server" "Error cannot set/"

These Imports don't work. I can't implement from "node_modules"
If i change the Import of
import { CameraSource, CameraResultType, Photo } from '@capacitor/core';
to
import { CameraSource, CameraResultType, Photo } from '@capacitor/camera'; this will work.

The following import:
import { TextDetector, TextDetection, ImageOrientation } from 'cap-ml';
doesn't work either, im not sure why!? I also tried: "npm install cap-ml". But it doesn't change my error.

Error message:

Cannot find module 'cap-ml' or its corresponding type declarations.ts(2307)


The last thing that doesn't work is:
import { Plugins } from '@capacitor/core';
const { Camera } = Plugins;

Error message:

'Plugins' is deprecated.ts(6385)
global.d.ts(5, 4): The declaration was marked as deprecated here.


Versions:

Angular CLI: 12.1.0
Node: 14.17.1
Package Manager: npm 6.14.13
OS: win32 x64

Angular:
...

Package Version

@angular-devkit/architect 0.1201.0 (cli-only)
@angular-devkit/core 12.1.0 (cli-only)
@angular-devkit/schematics 12.1.0 (cli-only)
@schematics/angular 12.1.0 (cli-only)

Potential issue? [coreml] Failed to get the home directory when checking model path

Hi,

This is a great plugin that I've found very promising to be used in my project. But when I was trying the ImageReader app, it could not recognize any string from image. And Xcode shows error messages like this:

[coreml] Failed to get the home directory when checking model path

Did you see such issue before? Wondering if there is configuration incorrect on my side. But I did not do anything except following the README file.

Thanks!

Appendix: the full log:

2022-11-28 11:36:26.575162-0800 App[46081:18346803] [AXRuntimeCommon] Unknown client: App
⚡️ TO JS {"exif":{"PixelYDimension":2532,"PixelXDimension":1170,"ColorSpace":1},"webPath":"capacitor://localhost/capacitor_file/Users/yanling/Library/Developer/CoreSimulator/Devices/E2544E30-426D-4546-B07A-7C38FB6D13E3/data/Containers/Data/Applicati
⚡️ To Native -> CapML detectText 19700326
2022-11-28 11:36:28.991429-0800 App[46081:18347629] [coreml] Failed to get the home directory when checking model path.
2022-11-28 11:36:29.140541-0800 App[46081:18347629] Metal API Validation Enabled
2022-11-28 11:36:30.076851-0800 App[46081:18347629] [coreml] Failed to get the home directory when checking model path.
⚡️ TO JS {"textDetections":[]}

Module was compiled with an incompatible version of Kotlin. The binary version of its metadata is 1.5.1, expected version is 1.1.16.

C:/Users/Owner/.gradle/caches/transforms-2/files-2.1/63b9624e223db8a9498b6b0cc83627dd/jetified-kotlin-stdlib-common-1.5.21.jar!/META-INF/kotlin-stdlib-common.kotlin_module: Module was compiled with an incompatible version of Kotlin. The binary version of its metadata is 1.5.1, expected version is 1.1.16.

ionic info

Ionic:

  Ionic CLI                     : 6.16.3 (C:\Users\Owner\AppData\Roaming\npm\node_modules\@ionic\cli)
  Ionic Framework               : @ionic/angular 5.3.4
  @angular-devkit/build-angular : 0.1000.8
  @angular-devkit/schematics    : 10.0.8
  @angular/cli                  : 10.0.8
  @ionic/angular-toolkit        : 2.3.3

Capacitor:

  Capacitor CLI      : 2.4.2
  @capacitor/android : 2.4.2
  @capacitor/core    : 2.4.2
  @capacitor/ios     : 2.4.2

Utility:

  cordova-res : 0.15.3
  native-run  : 1.3.1

System:

  NodeJS : v14.16.0 (C:\Program Files\nodejs\node.exe)
  npm    : 6.14.11
  OS     : Windows 10

image

Help Request

REPO : msadal
got error Argument labels '(call:, KClientID:, kGraphURI:, kAuthority:, redirectUri:)' do not match any available overloads

in file MSALiOS.swift

line 32 ->XCODE ERROR

ADAuthentication(call: call, KClientID:String,kGraphURI: String,kAuthority: String,redirectUri: String).initADAL()

ImageOrientation required on detectText call (Android)

Thanks for this wonderful plugin! It's been a great time saver.

While implementing on Android (with Ionic 4 / Capacitor), the plugin was crashing if I called detectText(filename) without specifying orientation. After passing in ImageOrientation.Up as a second parameter, like in your example project, things worked smoothly. This may be just a documentation issue.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.