Skip to content

Commit

Permalink
Implement Android
Browse files Browse the repository at this point in the history
  • Loading branch information
aarongrider committed Feb 21, 2022
1 parent dd88556 commit a6a2d35
Show file tree
Hide file tree
Showing 4 changed files with 113 additions and 27 deletions.
3 changes: 2 additions & 1 deletion android/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ android {
compileSdkVersion getExtOrIntegerDefault('compileSdkVersion')
buildToolsVersion getExtOrDefault('buildToolsVersion')
defaultConfig {
minSdkVersion 16
minSdkVersion 21
targetSdkVersion getExtOrIntegerDefault('targetSdkVersion')
versionCode 1
versionName "1.0"
Expand Down Expand Up @@ -129,5 +129,6 @@ dependencies {
implementation "org.jetbrains.kotlin:kotlin-stdlib:$kotlin_version"

implementation project(':react-native-vision-camera')
implementation 'com.google.android.gms:play-services-mlkit-text-recognition:18.0.0'
implementation "androidx.camera:camera-core:1.1.0-alpha08"
}
113 changes: 107 additions & 6 deletions android/src/main/java/com/visioncameraocr/OCRFrameProcessorPlugin.kt
Original file line number Diff line number Diff line change
@@ -1,23 +1,124 @@
package com.visioncameraocr

import android.annotation.SuppressLint
import android.graphics.Point
import android.graphics.Rect
import android.media.Image
import androidx.camera.core.ImageProxy
import com.facebook.react.bridge.WritableNativeArray
import com.facebook.react.bridge.WritableNativeMap
import com.google.android.gms.tasks.Task
import com.google.android.gms.tasks.Tasks
import com.google.mlkit.vision.common.InputImage
import com.google.mlkit.vision.text.Text
import com.google.mlkit.vision.text.TextRecognition
import com.google.mlkit.vision.text.latin.TextRecognizerOptions
import com.mrousavy.camera.frameprocessor.FrameProcessorPlugin


class OCRFrameProcessorPlugin: FrameProcessorPlugin("scanOCR") {

override fun callback(image: ImageProxy, params: Array<Any>): Any? {
private fun getBlockArray(blocks: MutableList<Text.TextBlock>): WritableNativeArray {
val blockArray = WritableNativeArray()

for (block in blocks) {
val blockMap = WritableNativeMap()

blockMap.putString("text", block.text)
blockMap.putArray("recognizedLanguages", getRecognizedLanguages(block.recognizedLanguage))
blockMap.putArray("cornerPoints", block.cornerPoints?.let { getCornerPoints(it) })
blockMap.putMap("frame", getFrame(block.boundingBox))
blockMap.putArray("lines", getLineArray(block.lines))

blockArray.pushMap(blockMap)
}
return blockArray
}

private fun getLineArray(lines: MutableList<Text.Line>): WritableNativeArray {
val lineArray = WritableNativeArray()

for (line in lines) {
val lineMap = WritableNativeMap()

lineMap.putString("text", line.text)
lineMap.putArray("recognizedLanguages", getRecognizedLanguages(line.recognizedLanguage))
lineMap.putArray("cornerPoints", line.cornerPoints?.let { getCornerPoints(it) })
lineMap.putMap("frame", getFrame(line.boundingBox))
lineMap.putArray("elements", getElementArray(line.elements))

lineArray.pushMap(lineMap)
}
return lineArray
}

private fun getElementArray(elements: MutableList<Text.Element>): WritableNativeArray {
val elementArray = WritableNativeArray()

for (element in elements) {
val elementMap = WritableNativeMap()

elementMap.putString("text", element.text)
elementMap.putArray("cornerPoints", element.cornerPoints?.let { getCornerPoints(it) })
elementMap.putMap("frame", getFrame(element.boundingBox))
}
return elementArray
}

private fun getRecognizedLanguages(recognizedLanguage: String): WritableNativeArray {
val recognizedLanguages = WritableNativeArray()
recognizedLanguages.pushString(recognizedLanguage)
return recognizedLanguages
}

private fun getCornerPoints(points: Array<Point>): WritableNativeArray {
val cornerPoints = WritableNativeArray()

for (point in points) {
val pointMap = WritableNativeMap()
pointMap.putInt("x", point.x)
pointMap.putInt("y", point.y)
cornerPoints.pushMap(pointMap)
}
return cornerPoints
}

private fun getFrame(boundingBox: Rect?): WritableNativeMap {
val frame = WritableNativeMap()

if (boundingBox != null) {
frame.putDouble("x", boundingBox.exactCenterX().toDouble())
frame.putDouble("y", boundingBox.exactCenterY().toDouble())
frame.putInt("width", boundingBox.width())
frame.putInt("height", boundingBox.height())
frame.putInt("boundingCenterX", boundingBox.centerX())
frame.putInt("boundingCenterY", boundingBox.centerY())
}
return frame
}

override fun callback(frame: ImageProxy, params: Array<Any>): Any? {

val result = WritableNativeMap()
result.putString("text", "Test Text")

val blocks = WritableNativeArray()
result.putArray("blocks", blocks)
val recognizer = TextRecognition.getClient(TextRecognizerOptions.DEFAULT_OPTIONS)

@SuppressLint("UnsafeOptInUsageError")
val mediaImage: Image? = frame.getImage()

if (mediaImage != null) {
val image = InputImage.fromMediaImage(mediaImage, frame.imageInfo.rotationDegrees)
val task: Task<Text> = recognizer.process(image)
try {
val text: Text = Tasks.await<Text>(task)
result.putString("text", text.text)
result.putArray("blocks", getBlockArray(text.textBlocks))
} catch (e: Exception) {
return null
}
}

val data = WritableNativeMap()
data.putMap("result", result)

return data
}
}
4 changes: 4 additions & 0 deletions example/android/app/src/main/AndroidManifest.xml
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,10 @@
<uses-permission android:name="android.permission.CAMERA" />
<uses-permission android:name="android.permission.RECORD_AUDIO" />

<meta-data
android:name="com.google.mlkit.vision.DEPENDENCIES"
android:value="ocr" />

<application
android:name=".MainApplication"
android:label="@string/app_name"
Expand Down
20 changes: 0 additions & 20 deletions ios/VisionCameraOcr.swift
Original file line number Diff line number Diff line change
Expand Up @@ -87,26 +87,6 @@ public class OCRFrameProcessorPlugin: NSObject, FrameProcessorPluginBase {
return cornerPointArray
}

/*
private static func getFrame(_ frameRect: CGRect) -> [String: CGFloat] {

let offsetX = (frameRect.midX - ceil(frameRect.width)) / 2.0
let offsetY = (frameRect.midY - ceil(frameRect.height)) / 2.0

let x = frameRect.maxX + offsetX
let y = frameRect.minY + offsetY

return [
"x": frameRect.origin.x,
"y": frameRect.origin.y,
"width": frameRect.width,
"height": frameRect.height,
"boundingCenterX": frameRect.midX,
"boundingCenterY": frameRect.midY
]
}
*/

private static func getFrame(_ frameRect: CGRect) -> [String: CGFloat] {

let offsetX = (frameRect.midX - ceil(frameRect.width)) / 2.0
Expand Down

0 comments on commit a6a2d35

Please sign in to comment.