diff --git a/android/build.gradle b/android/build.gradle index 1a9eaa60e..4aed49550 100644 --- a/android/build.gradle +++ b/android/build.gradle @@ -66,16 +66,16 @@ repositories { } dependencies { - def googlePlayServicesVisionVersion = safeExtGet('googlePlayServicesVisionVersion', safeExtGet('googlePlayServicesVersion', '17.0.2')) - //noinspection GradleDynamicVersion implementation 'com.facebook.react:react-native:+' // From node_modules implementation "com.google.zxing:core:3.3.3" implementation "com.drewnoakes:metadata-extractor:2.11.0" - generalImplementation "com.google.android.gms:play-services-vision:$googlePlayServicesVisionVersion" implementation "androidx.exifinterface:exifinterface:1.3.2" implementation "androidx.annotation:annotation:1.0.0" implementation "androidx.legacy:legacy-support-v4:1.0.0" - mlkitImplementation "com.google.firebase:firebase-ml-vision:${safeExtGet('firebase-ml-vision', '19.0.3')}" - mlkitImplementation "com.google.firebase:firebase-ml-vision-face-model:${safeExtGet('firebase-ml-vision-face-model', '17.0.2')}" + implementation "com.google.android.gms:play-services-mlkit-text-recognition:16.3.0" + generalImplementation "com.google.android.gms:play-services-mlkit-barcode-scanning:16.2.0" + generalImplementation "com.google.android.gms:play-services-mlkit-face-detection:16.2.0" + mlkitImplementation "com.google.mlkit:barcode-scanning:16.2.0" + mlkitImplementation "com.google.mlkit:face-detection:16.1.2" } diff --git a/android/src/general/java/org/reactnative/barcodedetector/BarcodeFormatUtils.java b/android/src/general/java/org/reactnative/barcodedetector/BarcodeFormatUtils.java index 5d90bcd2f..675303702 100644 --- a/android/src/general/java/org/reactnative/barcodedetector/BarcodeFormatUtils.java +++ b/android/src/general/java/org/reactnative/barcodedetector/BarcodeFormatUtils.java @@ -1,7 +1,7 @@ package org.reactnative.barcodedetector; import android.util.SparseArray; -import com.google.android.gms.vision.barcode.Barcode; +import com.google.mlkit.vision.barcode.Barcode; import java.util.Collections; import java.util.HashMap; @@ -18,33 +18,32 @@ public class BarcodeFormatUtils { static { // Initialize integer to string map SparseArray map = new SparseArray<>(); - map.put(Barcode.CODE_128, "CODE_128"); - map.put(Barcode.CODE_39, "CODE_39"); - map.put(Barcode.CODE_93, "CODE_93"); - map.put(Barcode.CODABAR, "CODABAR"); - map.put(Barcode.DATA_MATRIX, "DATA_MATRIX"); - map.put(Barcode.EAN_13, "EAN_13"); - map.put(Barcode.EAN_8, "EAN_8"); - map.put(Barcode.ITF, "ITF"); - map.put(Barcode.QR_CODE, "QR_CODE"); - map.put(Barcode.UPC_A, "UPC_A"); - map.put(Barcode.UPC_E, "UPC_E"); - map.put(Barcode.PDF417, "PDF417"); - map.put(Barcode.AZTEC, "AZTEC"); - map.put(Barcode.ALL_FORMATS, "ALL"); - map.put(Barcode.CALENDAR_EVENT, "CALENDAR_EVENT"); - map.put(Barcode.CONTACT_INFO, "CONTACT_INFO"); - map.put(Barcode.DRIVER_LICENSE, "DRIVER_LICENSE"); - map.put(Barcode.EMAIL, "EMAIL"); - map.put(Barcode.GEO, "GEO"); - map.put(Barcode.ISBN, "ISBN"); - map.put(Barcode.PHONE, "PHONE"); - map.put(Barcode.PRODUCT, "PRODUCT"); - map.put(Barcode.SMS, "SMS"); - map.put(Barcode.TEXT, "TEXT"); - map.put(Barcode.UPC_A, "UPC_A"); - map.put(Barcode.URL, "URL"); - map.put(Barcode.WIFI, "WIFI"); + map.put(Barcode.FORMAT_CODE_128, "CODE_128"); + map.put(Barcode.FORMAT_CODE_39, "CODE_39"); + map.put(Barcode.FORMAT_CODE_93, "CODE_93"); + map.put(Barcode.FORMAT_CODABAR, "CODABAR"); + map.put(Barcode.FORMAT_DATA_MATRIX, "DATA_MATRIX"); + map.put(Barcode.FORMAT_EAN_13, "EAN_13"); + map.put(Barcode.FORMAT_EAN_8, "EAN_8"); + map.put(Barcode.FORMAT_ITF, "ITF"); + map.put(Barcode.FORMAT_QR_CODE, "QR_CODE"); + map.put(Barcode.FORMAT_UPC_A, "UPC_A"); + map.put(Barcode.FORMAT_UPC_E, "UPC_E"); + map.put(Barcode.FORMAT_PDF417, "PDF417"); + map.put(Barcode.FORMAT_AZTEC, "AZTEC"); + map.put(Barcode.FORMAT_ALL_FORMATS, "ALL"); + map.put(Barcode.TYPE_CALENDAR_EVENT, "CALENDAR_EVENT"); + map.put(Barcode.TYPE_CONTACT_INFO, "CONTACT_INFO"); + map.put(Barcode.TYPE_DRIVER_LICENSE, "DRIVER_LICENSE"); + map.put(Barcode.TYPE_EMAIL, "EMAIL"); + map.put(Barcode.TYPE_GEO, "GEO"); + map.put(Barcode.TYPE_ISBN, "ISBN"); + map.put(Barcode.TYPE_PHONE, "PHONE"); + map.put(Barcode.TYPE_PRODUCT, "PRODUCT"); + map.put(Barcode.TYPE_SMS, "SMS"); + map.put(Barcode.TYPE_TEXT, "TEXT"); + map.put(Barcode.TYPE_URL, "URL"); + map.put(Barcode.TYPE_WIFI, "WIFI"); map.put(-1, "None"); FORMATS = map; diff --git a/android/src/general/java/org/reactnative/barcodedetector/RNBarcodeDetector.java b/android/src/general/java/org/reactnative/barcodedetector/RNBarcodeDetector.java index 1424796ce..20aacb5f5 100644 --- a/android/src/general/java/org/reactnative/barcodedetector/RNBarcodeDetector.java +++ b/android/src/general/java/org/reactnative/barcodedetector/RNBarcodeDetector.java @@ -1,27 +1,31 @@ package org.reactnative.barcodedetector; import android.content.Context; -import android.util.SparseArray; -import com.google.android.gms.vision.barcode.Barcode; -import com.google.android.gms.vision.barcode.BarcodeDetector; +import com.google.mlkit.vision.barcode.Barcode; +import com.google.mlkit.vision.barcode.BarcodeScanner; +import com.google.mlkit.vision.barcode.BarcodeScannerOptions; +import com.google.mlkit.vision.barcode.BarcodeScanning; + import org.reactnative.camera.utils.ImageDimensions; import org.reactnative.frame.RNFrame; +import java.util.List; + public class RNBarcodeDetector { public static int NORMAL_MODE = 0; public static int ALTERNATE_MODE = 1; public static int INVERTED_MODE = 2; - public static int ALL_FORMATS = Barcode.ALL_FORMATS; + public static int ALL_FORMATS = Barcode.FORMAT_ALL_FORMATS; - private BarcodeDetector mBarcodeDetector = null; + private BarcodeScanner mBarcodeDetector = null; private ImageDimensions mPreviousDimensions; - private BarcodeDetector.Builder mBuilder; - private int mBarcodeType = Barcode.ALL_FORMATS; + private int mBarcodeType = Barcode.FORMAT_ALL_FORMATS; + private BarcodeScannerOptions.Builder mBuilder; public RNBarcodeDetector(Context context) { - mBuilder = new BarcodeDetector.Builder(context) + mBuilder = new BarcodeScannerOptions.Builder() .setBarcodeFormats(mBarcodeType); } @@ -32,10 +36,10 @@ public boolean isOperational() { createBarcodeDetector(); } - return mBarcodeDetector.isOperational(); + return true; } - public SparseArray detect(RNFrame frame) { + public List detect(RNFrame frame) { // If the frame has different dimensions, create another barcode detector. // Otherwise we will most likely get nasty "inconsistent image dimensions" error from detector // and no barcode will be detected. @@ -48,7 +52,7 @@ public SparseArray detect(RNFrame frame) { mPreviousDimensions = frame.getDimensions(); } - return mBarcodeDetector.detect(frame.getFrame()); + return mBarcodeDetector.process(frame.getFrame()).getResult(); } public void setBarcodeType(int barcodeType) { @@ -69,12 +73,12 @@ public void release() { private void releaseBarcodeDetector() { if (mBarcodeDetector != null) { - mBarcodeDetector.release(); + mBarcodeDetector.close(); mBarcodeDetector = null; } } private void createBarcodeDetector() { - mBarcodeDetector = mBuilder.build(); + mBarcodeDetector = BarcodeScanning.getClient(mBuilder.build()); } } diff --git a/android/src/general/java/org/reactnative/camera/tasks/BarcodeDetectorAsyncTask.java b/android/src/general/java/org/reactnative/camera/tasks/BarcodeDetectorAsyncTask.java index 40505da7f..f528b3fcf 100644 --- a/android/src/general/java/org/reactnative/camera/tasks/BarcodeDetectorAsyncTask.java +++ b/android/src/general/java/org/reactnative/camera/tasks/BarcodeDetectorAsyncTask.java @@ -1,12 +1,11 @@ package org.reactnative.camera.tasks; import android.graphics.Rect; -import android.util.SparseArray; import com.facebook.react.bridge.Arguments; import com.facebook.react.bridge.WritableArray; import com.facebook.react.bridge.WritableMap; -import com.google.android.gms.vision.barcode.Barcode; +import com.google.mlkit.vision.barcode.Barcode; import org.reactnative.barcodedetector.BarcodeFormatUtils; import org.reactnative.camera.utils.ImageDimensions; @@ -14,7 +13,9 @@ import org.reactnative.frame.RNFrameFactory; import org.reactnative.barcodedetector.RNBarcodeDetector; -public class BarcodeDetectorAsyncTask extends android.os.AsyncTask> { +import java.util.List; + +public class BarcodeDetectorAsyncTask extends android.os.AsyncTask> { private byte[] mImageData; private int mWidth; @@ -55,7 +56,7 @@ public BarcodeDetectorAsyncTask( } @Override - protected SparseArray doInBackground(Void... ignored) { + protected List doInBackground(Void... ignored) { if (isCancelled() || mDelegate == null || mBarcodeDetector == null || !mBarcodeDetector.isOperational()) { return null; } @@ -65,7 +66,7 @@ protected SparseArray doInBackground(Void... ignored) { } @Override - protected void onPostExecute(SparseArray barcodes) { + protected void onPostExecute(List barcodes) { super.onPostExecute(barcodes); if (barcodes == null) { @@ -78,16 +79,16 @@ protected void onPostExecute(SparseArray barcodes) { } } - private WritableArray serializeEventData(SparseArray barcodes) { + private WritableArray serializeEventData(List barcodes) { WritableArray barcodesList = Arguments.createArray(); for (int i = 0; i < barcodes.size(); i++) { - Barcode barcode = barcodes.valueAt(i); + Barcode barcode = barcodes.get(i); WritableMap serializedBarcode = Arguments.createMap(); - serializedBarcode.putString("data", barcode.displayValue); - serializedBarcode.putString("rawData", barcode.rawValue); - serializedBarcode.putString("type", BarcodeFormatUtils.get(barcode.format)); + serializedBarcode.putString("data", barcode.getDisplayValue()); + serializedBarcode.putString("rawData", barcode.getRawValue()); + serializedBarcode.putString("type", BarcodeFormatUtils.get(barcode.getFormat())); serializedBarcode.putMap("bounds", processBounds(barcode.getBoundingBox())); barcodesList.pushMap(serializedBarcode); } diff --git a/android/src/general/java/org/reactnative/camera/tasks/FaceDetectorAsyncTask.java b/android/src/general/java/org/reactnative/camera/tasks/FaceDetectorAsyncTask.java index 5432bf696..aace59ab3 100644 --- a/android/src/general/java/org/reactnative/camera/tasks/FaceDetectorAsyncTask.java +++ b/android/src/general/java/org/reactnative/camera/tasks/FaceDetectorAsyncTask.java @@ -1,12 +1,10 @@ package org.reactnative.camera.tasks; -import android.util.SparseArray; - import com.facebook.react.bridge.Arguments; import com.facebook.react.bridge.WritableArray; import com.facebook.react.bridge.WritableMap; import com.google.android.cameraview.CameraView; -import com.google.android.gms.vision.face.Face; +import com.google.mlkit.vision.face.Face; import org.reactnative.camera.utils.ImageDimensions; import org.reactnative.facedetector.FaceDetectorUtils; @@ -14,7 +12,9 @@ import org.reactnative.frame.RNFrameFactory; import org.reactnative.facedetector.RNFaceDetector; -public class FaceDetectorAsyncTask extends android.os.AsyncTask> { +import java.util.List; + +public class FaceDetectorAsyncTask extends android.os.AsyncTask> { private byte[] mImageData; private int mWidth; private int mHeight; @@ -55,7 +55,7 @@ public FaceDetectorAsyncTask( } @Override - protected SparseArray doInBackground(Void... ignored) { + protected List doInBackground(Void... ignored) { if (isCancelled() || mDelegate == null || mFaceDetector == null || !mFaceDetector.isOperational()) { return null; } @@ -65,7 +65,7 @@ protected SparseArray doInBackground(Void... ignored) { } @Override - protected void onPostExecute(SparseArray faces) { + protected void onPostExecute(List faces) { super.onPostExecute(faces); if (faces == null) { @@ -78,11 +78,11 @@ protected void onPostExecute(SparseArray faces) { } } - private WritableArray serializeEventData(SparseArray faces) { + private WritableArray serializeEventData(List faces) { WritableArray facesList = Arguments.createArray(); for(int i = 0; i < faces.size(); i++) { - Face face = faces.valueAt(i); + Face face = faces.get(i); WritableMap serializedFace = FaceDetectorUtils.serializeFace(face, mScaleX, mScaleY, mWidth, mHeight, mPaddingLeft, mPaddingTop); if (mImageDimensions.getFacing() == CameraView.FACING_FRONT) { serializedFace = FaceDetectorUtils.rotateFaceX(serializedFace, mImageDimensions.getWidth(), mScaleX); diff --git a/android/src/general/java/org/reactnative/camera/tasks/TextRecognizerAsyncTask.java b/android/src/general/java/org/reactnative/camera/tasks/TextRecognizerAsyncTask.java index b8c2e9e92..bda5fcdfd 100644 --- a/android/src/general/java/org/reactnative/camera/tasks/TextRecognizerAsyncTask.java +++ b/android/src/general/java/org/reactnative/camera/tasks/TextRecognizerAsyncTask.java @@ -1,5 +1,6 @@ package org.reactnative.camera.tasks; +import android.graphics.Rect; import android.util.SparseArray; import com.facebook.react.bridge.Arguments; @@ -9,18 +10,22 @@ import com.facebook.react.bridge.WritableMap; import com.facebook.react.uimanager.ThemedReactContext; import com.google.android.cameraview.CameraView; -import com.google.android.gms.vision.text.Line; -import com.google.android.gms.vision.text.Text; -import com.google.android.gms.vision.text.TextBlock; -import com.google.android.gms.vision.text.TextRecognizer; +import com.google.mlkit.vision.text.Text; +import com.google.mlkit.vision.text.Text.Line; +import com.google.mlkit.vision.text.Text.TextBlock; +import com.google.mlkit.vision.text.TextRecognizer; +import com.google.mlkit.vision.text.TextRecognizerOptions; +import com.google.mlkit.vision.text.TextRecognition; import org.reactnative.camera.utils.ImageDimensions; import org.reactnative.facedetector.FaceDetectorUtils; import org.reactnative.frame.RNFrame; import org.reactnative.frame.RNFrameFactory; +import java.util.List; -public class TextRecognizerAsyncTask extends android.os.AsyncTask> { + +public class TextRecognizerAsyncTask extends android.os.AsyncTask> { private TextRecognizerAsyncTaskDelegate mDelegate; private ThemedReactContext mThemedReactContext; @@ -63,25 +68,25 @@ public TextRecognizerAsyncTask( } @Override - protected SparseArray doInBackground(Void... ignored) { + protected List doInBackground(Void... ignored) { if (isCancelled() || mDelegate == null) { return null; } - mTextRecognizer = new TextRecognizer.Builder(mThemedReactContext).build(); + mTextRecognizer = TextRecognition.getClient(TextRecognizerOptions.DEFAULT_OPTIONS); RNFrame frame = RNFrameFactory.buildFrame(mImageData, mWidth, mHeight, mRotation); - return mTextRecognizer.detect(frame.getFrame()); + return mTextRecognizer.process(frame.getFrame()).getResult().getTextBlocks(); } @Override - protected void onPostExecute(SparseArray textBlocks) { + protected void onPostExecute(List textBlocks) { super.onPostExecute(textBlocks); if (mTextRecognizer != null) { - mTextRecognizer.release(); + mTextRecognizer.close(); } if (textBlocks != null) { WritableArray textBlocksList = Arguments.createArray(); for (int i = 0; i < textBlocks.size(); ++i) { - TextBlock textBlock = textBlocks.valueAt(i); + TextBlock textBlock = textBlocks.get(i); WritableMap serializedTextBlock = serializeText(textBlock); if (mImageDimensions.getFacing() == CameraView.FACING_FRONT) { serializedTextBlock = rotateTextX(serializedTextBlock); @@ -93,29 +98,74 @@ protected void onPostExecute(SparseArray textBlocks) { mDelegate.onTextRecognizerTaskCompleted(); } - private WritableMap serializeText(Text text) { + private WritableMap serializeText(TextBlock text) { WritableMap encodedText = Arguments.createMap(); WritableArray components = Arguments.createArray(); - for (Text component : text.getComponents()) { + for (Line component : text.getLines()) { components.pushMap(serializeText(component)); } encodedText.putArray("components", components); - encodedText.putString("value", text.getValue()); + encodedText.putString("value", text.getText()); + + WritableMap bounds = serializeBounds(text.getBoundingBox()); + encodedText.putMap("bounds", bounds); + + encodedText.putString("type", "block"); + + return encodedText; + } - int x = text.getBoundingBox().left; - int y = text.getBoundingBox().top; + private WritableMap serializeText(Line text) { + WritableMap encodedText = Arguments.createMap(); - if (text.getBoundingBox().left < mWidth / 2) { + WritableArray components = Arguments.createArray(); + for (Text.Element component : text.getElements()) { + components.pushMap(serializeText(component)); + } + encodedText.putArray("components", components); + + encodedText.putString("value", text.getText()); + + WritableMap bounds = serializeBounds(text.getBoundingBox()); + encodedText.putMap("bounds", bounds); + + encodedText.putString("type", "line"); + + return encodedText; + } + + private WritableMap serializeText(Text.Element text) { + WritableMap encodedText = Arguments.createMap(); + + WritableArray components = Arguments.createArray(); + encodedText.putArray("components", components); + + encodedText.putString("value", text.getText()); + + WritableMap bounds = serializeBounds(text.getBoundingBox()); + encodedText.putMap("bounds", bounds); + + encodedText.putString("type", "element"); + + return encodedText; + } + + private WritableMap serializeBounds(Rect boundingBox) { + int x = boundingBox.left; + int y = boundingBox.top; + int width = boundingBox.width(); + int height = boundingBox.height(); + if (x < mWidth / 2) { x = x + mPaddingLeft / 2; - } else if (text.getBoundingBox().left > mWidth /2) { + } else if (x > mWidth /2) { x = x - mPaddingLeft / 2; } - if (text.getBoundingBox().height() < mHeight / 2) { + if (height < mHeight / 2) { y = y + mPaddingTop / 2; - } else if (text.getBoundingBox().height() > mHeight / 2) { + } else if (height > mHeight / 2) { y = y - mPaddingTop / 2; } @@ -124,26 +174,14 @@ private WritableMap serializeText(Text text) { origin.putDouble("y", y * this.mScaleY); WritableMap size = Arguments.createMap(); - size.putDouble("width", text.getBoundingBox().width() * this.mScaleX); - size.putDouble("height", text.getBoundingBox().height() * this.mScaleY); + size.putDouble("width", width * this.mScaleX); + size.putDouble("height", height * this.mScaleY); WritableMap bounds = Arguments.createMap(); bounds.putMap("origin", origin); bounds.putMap("size", size); - encodedText.putMap("bounds", bounds); - - String type_; - if (text instanceof TextBlock) { - type_ = "block"; - } else if (text instanceof Line) { - type_ = "line"; - } else /*if (text instanceof Element)*/ { - type_ = "element"; - } - encodedText.putString("type", type_); - - return encodedText; + return bounds; } private WritableMap rotateTextX(WritableMap text) { diff --git a/android/src/general/java/org/reactnative/facedetector/FaceDetectorUtils.java b/android/src/general/java/org/reactnative/facedetector/FaceDetectorUtils.java index f6b1985fa..8397beb2d 100644 --- a/android/src/general/java/org/reactnative/facedetector/FaceDetectorUtils.java +++ b/android/src/general/java/org/reactnative/facedetector/FaceDetectorUtils.java @@ -1,12 +1,13 @@ package org.reactnative.facedetector; import android.graphics.PointF; +import android.graphics.Rect; import com.facebook.react.bridge.Arguments; import com.facebook.react.bridge.ReadableMap; import com.facebook.react.bridge.WritableMap; -import com.google.android.gms.vision.face.Face; -import com.google.android.gms.vision.face.Landmark; +import com.google.mlkit.vision.face.Face; +import com.google.mlkit.vision.face.FaceLandmark; public class FaceDetectorUtils { // All the landmarks reported by Google Mobile Vision in constants' order. @@ -24,44 +25,45 @@ public static WritableMap serializeFace(Face face) { public static WritableMap serializeFace(Face face, double scaleX, double scaleY, int width, int height, int paddingLeft, int paddingTop) { WritableMap encodedFace = Arguments.createMap(); - encodedFace.putInt("faceID", face.getId()); - encodedFace.putDouble("rollAngle", face.getEulerZ()); - encodedFace.putDouble("yawAngle", face.getEulerY()); + encodedFace.putInt("faceID", face.getTrackingId()); + encodedFace.putDouble("rollAngle", face.getHeadEulerAngleZ()); + encodedFace.putDouble("yawAngle", face.getHeadEulerAngleY()); - if (face.getIsSmilingProbability() >= 0) { - encodedFace.putDouble("smilingProbability", face.getIsSmilingProbability()); + if (face.getSmilingProbability() >= 0) { + encodedFace.putDouble("smilingProbability", face.getSmilingProbability()); } - if (face.getIsLeftEyeOpenProbability() >= 0) { - encodedFace.putDouble("leftEyeOpenProbability", face.getIsLeftEyeOpenProbability()); + if (face.getLeftEyeOpenProbability() >= 0) { + encodedFace.putDouble("leftEyeOpenProbability", face.getLeftEyeOpenProbability()); } - if (face.getIsRightEyeOpenProbability() >= 0) { - encodedFace.putDouble("rightEyeOpenProbability", face.getIsRightEyeOpenProbability()); + if (face.getRightEyeOpenProbability() >= 0) { + encodedFace.putDouble("rightEyeOpenProbability", face.getRightEyeOpenProbability()); } - for(Landmark landmark : face.getLandmarks()) { - encodedFace.putMap(landmarkNames[landmark.getType()], mapFromPoint(landmark.getPosition(), scaleX, scaleY, width, height, paddingLeft, paddingTop)); + for(FaceLandmark landmark : face.getAllLandmarks()) { + encodedFace.putMap(landmarkNames[landmark.getLandmarkType()], mapFromPoint(landmark.getPosition(), scaleX, scaleY, width, height, paddingLeft, paddingTop)); } WritableMap origin = Arguments.createMap(); - Float x = face.getPosition().x; - Float y = face.getPosition().y; - if (face.getPosition().x < width / 2) { + Rect boundingBox = face.getBoundingBox(); + int x = boundingBox.left; + int y = boundingBox.top; + if (x < width / 2) { x = x + paddingLeft / 2; - } else if (face.getPosition().x > width / 2) { + } else if (x > width / 2) { x = x - paddingLeft / 2; } - if (face.getPosition().y < height / 2) { + if (y < height / 2) { y = y + paddingTop / 2; - } else if (face.getPosition().y > height / 2) { + } else if (y > height / 2) { y = y - paddingTop / 2; } origin.putDouble("x", x * scaleX); origin.putDouble("y", y * scaleY); WritableMap size = Arguments.createMap(); - size.putDouble("width", face.getWidth() * scaleX); - size.putDouble("height", face.getHeight() * scaleY); + size.putDouble("width", boundingBox.width() * scaleX); + size.putDouble("height", boundingBox.height() * scaleY); WritableMap bounds = Arguments.createMap(); bounds.putMap("origin", origin); diff --git a/android/src/general/java/org/reactnative/facedetector/RNFaceDetector.java b/android/src/general/java/org/reactnative/facedetector/RNFaceDetector.java index f114d180f..58b7b7f13 100644 --- a/android/src/general/java/org/reactnative/facedetector/RNFaceDetector.java +++ b/android/src/general/java/org/reactnative/facedetector/RNFaceDetector.java @@ -1,24 +1,27 @@ package org.reactnative.facedetector; import android.content.Context; -import android.util.SparseArray; import org.reactnative.camera.utils.ImageDimensions; -import com.google.android.gms.vision.face.Face; -import com.google.android.gms.vision.face.FaceDetector; +import com.google.mlkit.vision.face.Face; +import com.google.mlkit.vision.face.FaceDetection; +import com.google.mlkit.vision.face.FaceDetector; +import com.google.mlkit.vision.face.FaceDetectorOptions; import org.reactnative.frame.RNFrame; +import java.util.List; + public class RNFaceDetector { - public static int ALL_CLASSIFICATIONS = FaceDetector.ALL_CLASSIFICATIONS; - public static int NO_CLASSIFICATIONS = FaceDetector.NO_CLASSIFICATIONS; - public static int ALL_LANDMARKS = FaceDetector.ALL_LANDMARKS; - public static int NO_LANDMARKS = FaceDetector.NO_LANDMARKS; - public static int ACCURATE_MODE = FaceDetector.ACCURATE_MODE; - public static int FAST_MODE = FaceDetector.FAST_MODE; + public static int ALL_CLASSIFICATIONS = FaceDetectorOptions.CLASSIFICATION_MODE_ALL; + public static int NO_CLASSIFICATIONS = FaceDetectorOptions.CLASSIFICATION_MODE_NONE; + public static int ALL_LANDMARKS = FaceDetectorOptions.LANDMARK_MODE_ALL; + public static int NO_LANDMARKS = FaceDetectorOptions.LANDMARK_MODE_NONE; + public static int ACCURATE_MODE = FaceDetectorOptions.PERFORMANCE_MODE_ACCURATE; + public static int FAST_MODE = FaceDetectorOptions.PERFORMANCE_MODE_FAST; private FaceDetector mFaceDetector = null; private ImageDimensions mPreviousDimensions; - private FaceDetector.Builder mBuilder = null; + private FaceDetectorOptions.Builder mBuilder = null; private int mClassificationType = NO_CLASSIFICATIONS; private int mLandmarkType = NO_LANDMARKS; @@ -26,11 +29,11 @@ public class RNFaceDetector { private int mMode = FAST_MODE; public RNFaceDetector(Context context) { - mBuilder = new FaceDetector.Builder(context); + mBuilder = new FaceDetectorOptions.Builder(); mBuilder.setMinFaceSize(mMinFaceSize); - mBuilder.setMode(mMode); - mBuilder.setLandmarkType(mLandmarkType); - mBuilder.setClassificationType(mClassificationType); + mBuilder.setPerformanceMode(mMode); + mBuilder.setLandmarkMode(mLandmarkType); + mBuilder.setClassificationMode(mClassificationType); } // Public API @@ -40,10 +43,10 @@ public boolean isOperational() { createFaceDetector(); } - return mFaceDetector.isOperational(); + return true; } - public SparseArray detect(RNFrame frame) { + public List detect(RNFrame frame) { // If the frame has different dimensions, create another face detector. // Otherwise we will get nasty "inconsistent image dimensions" error from detector // and no face will be detected. @@ -56,18 +59,20 @@ public SparseArray detect(RNFrame frame) { mPreviousDimensions = frame.getDimensions(); } - return mFaceDetector.detect(frame.getFrame()); + return mFaceDetector.process(frame.getFrame()).getResult(); } public void setTracking(boolean trackingEnabled) { release(); - mBuilder.setTrackingEnabled(trackingEnabled); + if (trackingEnabled) { + mBuilder.enableTracking(); + } } public void setClassificationType(int classificationType) { if (classificationType != mClassificationType) { release(); - mBuilder.setClassificationType(classificationType); + mBuilder.setClassificationMode(classificationType); mClassificationType = classificationType; } } @@ -75,7 +80,7 @@ public void setClassificationType(int classificationType) { public void setLandmarkType(int landmarkType) { if (landmarkType != mLandmarkType) { release(); - mBuilder.setLandmarkType(landmarkType); + mBuilder.setLandmarkMode(landmarkType); mLandmarkType = landmarkType; } } @@ -83,7 +88,7 @@ public void setLandmarkType(int landmarkType) { public void setMode(int mode) { if (mode != mMode) { release(); - mBuilder.setMode(mode); + mBuilder.setPerformanceMode(mode); mMode = mode; } } @@ -97,12 +102,12 @@ public void release() { private void releaseFaceDetector() { if (mFaceDetector != null) { - mFaceDetector.release(); + mFaceDetector.close(); mFaceDetector = null; } } private void createFaceDetector() { - mFaceDetector = mBuilder.build(); + mFaceDetector = FaceDetection.getClient(mBuilder.build()); } } diff --git a/android/src/general/java/org/reactnative/facedetector/tasks/FileFaceDetectionAsyncTask.java b/android/src/general/java/org/reactnative/facedetector/tasks/FileFaceDetectionAsyncTask.java index 1d55af998..f45b2b4cc 100644 --- a/android/src/general/java/org/reactnative/facedetector/tasks/FileFaceDetectionAsyncTask.java +++ b/android/src/general/java/org/reactnative/facedetector/tasks/FileFaceDetectionAsyncTask.java @@ -7,7 +7,6 @@ import android.net.Uri; import android.os.AsyncTask; import android.util.Log; -import android.util.SparseArray; import org.reactnative.facedetector.RNFaceDetector; import org.reactnative.frame.RNFrame; @@ -18,12 +17,13 @@ import com.facebook.react.bridge.ReadableMap; import com.facebook.react.bridge.WritableArray; import com.facebook.react.bridge.WritableMap; -import com.google.android.gms.vision.face.Face; +import com.google.mlkit.vision.face.Face; import java.io.File; import java.io.IOException; +import java.util.List; -public class FileFaceDetectionAsyncTask extends AsyncTask> { +public class FileFaceDetectionAsyncTask extends AsyncTask> { private static final String ERROR_TAG = "E_FACE_DETECTION_FAILED"; private static final String MODE_OPTION_KEY = "mode"; @@ -81,7 +81,7 @@ protected void onPreExecute() { } @Override - protected SparseArray doInBackground(Void... voids) { + protected List doInBackground(Void... voids) { if (isCancelled()) { return null; } @@ -103,13 +103,13 @@ protected SparseArray doInBackground(Void... voids) { } @Override - protected void onPostExecute(SparseArray faces) { + protected void onPostExecute(List faces) { super.onPostExecute(faces); WritableMap result = Arguments.createMap(); WritableArray facesArray = Arguments.createArray(); for(int i = 0; i < faces.size(); i++) { - Face face = faces.valueAt(i); + Face face = faces.get(i); WritableMap encodedFace = FaceDetectorUtils.serializeFace(face); encodedFace.putDouble("yawAngle", (-encodedFace.getDouble("yawAngle") + 360) % 360); encodedFace.putDouble("rollAngle", (-encodedFace.getDouble("rollAngle") + 360) % 360); diff --git a/android/src/main/java/org/reactnative/frame/RNFrame.java b/android/src/main/java/org/reactnative/frame/RNFrame.java index ff66b452e..90a797c5e 100644 --- a/android/src/main/java/org/reactnative/frame/RNFrame.java +++ b/android/src/main/java/org/reactnative/frame/RNFrame.java @@ -1,7 +1,7 @@ package org.reactnative.frame; import org.reactnative.camera.utils.ImageDimensions; -import com.google.android.gms.vision.Frame; +import com.google.mlkit.vision.common.InputImage; /** * Wrapper around Frame allowing us to track Frame dimensions. @@ -10,15 +10,15 @@ */ public class RNFrame { - private Frame mFrame; + private InputImage mFrame; private ImageDimensions mDimensions; - public RNFrame(Frame frame, ImageDimensions dimensions) { + public RNFrame(InputImage frame, ImageDimensions dimensions) { mFrame = frame; mDimensions = dimensions; } - public Frame getFrame() { + public InputImage getFrame() { return mFrame; } diff --git a/android/src/main/java/org/reactnative/frame/RNFrameFactory.java b/android/src/main/java/org/reactnative/frame/RNFrameFactory.java index 9f9b85bab..c452a84e0 100644 --- a/android/src/main/java/org/reactnative/frame/RNFrameFactory.java +++ b/android/src/main/java/org/reactnative/frame/RNFrameFactory.java @@ -1,43 +1,23 @@ package org.reactnative.frame; import android.graphics.Bitmap; -import android.graphics.ImageFormat; import org.reactnative.camera.utils.ImageDimensions; -import com.google.android.gms.vision.Frame; +import com.google.mlkit.vision.common.InputImage; import java.nio.ByteBuffer; public class RNFrameFactory { public static RNFrame buildFrame(byte[] bitmapData, int width, int height, int rotation) { - Frame.Builder builder = new Frame.Builder(); - ByteBuffer byteBuffer = ByteBuffer.wrap(bitmapData); - builder.setImageData(byteBuffer, width, height, ImageFormat.NV21); - - switch (rotation) { - case 90: - builder.setRotation(Frame.ROTATION_90); - break; - case 180: - builder.setRotation(Frame.ROTATION_180); - break; - case 270: - builder.setRotation(Frame.ROTATION_270); - break; - default: - builder.setRotation(Frame.ROTATION_0); - } - ImageDimensions dimensions = new ImageDimensions(width, height, rotation); - - return new RNFrame(builder.build(), dimensions); + InputImage image = InputImage.fromByteBuffer(byteBuffer, width, height, rotation, InputImage.IMAGE_FORMAT_NV21); + return new RNFrame(image, dimensions); } public static RNFrame buildFrame(Bitmap bitmap) { - Frame.Builder builder = new Frame.Builder(); - builder.setBitmap(bitmap); ImageDimensions dimensions = new ImageDimensions(bitmap.getWidth(), bitmap.getHeight()); - return new RNFrame(builder.build(), dimensions); + InputImage image = InputImage.fromBitmap(bitmap, 0); + return new RNFrame(image, dimensions); } } diff --git a/android/src/mlkit/java/org/reactnative/barcodedetector/BarcodeFormatUtils.java b/android/src/mlkit/java/org/reactnative/barcodedetector/BarcodeFormatUtils.java index 84e5ab4b6..93b3ef112 100644 --- a/android/src/mlkit/java/org/reactnative/barcodedetector/BarcodeFormatUtils.java +++ b/android/src/mlkit/java/org/reactnative/barcodedetector/BarcodeFormatUtils.java @@ -1,7 +1,7 @@ package org.reactnative.barcodedetector; import android.util.SparseArray; -import com.google.firebase.ml.vision.barcode.FirebaseVisionBarcode; +import com.google.mlkit.vision.barcode.Barcode; import java.util.Collections; import java.util.HashMap; @@ -14,7 +14,7 @@ public class BarcodeFormatUtils { public static final SparseArray TYPES; public static final Map REVERSE_TYPES; - private static final int UNKNOWN_FORMAT_INT = FirebaseVisionBarcode.FORMAT_UNKNOWN; + private static final int UNKNOWN_FORMAT_INT = Barcode.FORMAT_UNKNOWN; private static final String UNKNOWN_TYPE_STRING = "UNKNOWN_TYPE"; private static final String UNKNOWN_FORMAT_STRING = "UNKNOWN_FORMAT"; @@ -22,21 +22,21 @@ public class BarcodeFormatUtils { static { // Initialize integer to string map SparseArray map = new SparseArray<>(); - map.put(FirebaseVisionBarcode.FORMAT_CODE_128, "CODE_128"); - map.put(FirebaseVisionBarcode.FORMAT_CODE_39, "CODE_39"); - map.put(FirebaseVisionBarcode.FORMAT_CODE_93, "CODE_93"); - map.put(FirebaseVisionBarcode.FORMAT_CODABAR, "CODABAR"); - map.put(FirebaseVisionBarcode.FORMAT_DATA_MATRIX, "DATA_MATRIX"); - map.put(FirebaseVisionBarcode.FORMAT_EAN_13, "EAN_13"); - map.put(FirebaseVisionBarcode.FORMAT_EAN_8, "EAN_8"); - map.put(FirebaseVisionBarcode.FORMAT_ITF, "ITF"); - map.put(FirebaseVisionBarcode.FORMAT_QR_CODE, "QR_CODE"); - map.put(FirebaseVisionBarcode.FORMAT_UPC_A, "UPC_A"); - map.put(FirebaseVisionBarcode.FORMAT_UPC_E, "UPC_E"); - map.put(FirebaseVisionBarcode.FORMAT_PDF417, "PDF417"); - map.put(FirebaseVisionBarcode.FORMAT_AZTEC, "AZTEC"); - map.put(FirebaseVisionBarcode.FORMAT_ALL_FORMATS, "ALL"); - map.put(FirebaseVisionBarcode.FORMAT_UPC_A, "UPC_A"); + map.put(Barcode.FORMAT_CODE_128, "CODE_128"); + map.put(Barcode.FORMAT_CODE_39, "CODE_39"); + map.put(Barcode.FORMAT_CODE_93, "CODE_93"); + map.put(Barcode.FORMAT_CODABAR, "CODABAR"); + map.put(Barcode.FORMAT_DATA_MATRIX, "DATA_MATRIX"); + map.put(Barcode.FORMAT_EAN_13, "EAN_13"); + map.put(Barcode.FORMAT_EAN_8, "EAN_8"); + map.put(Barcode.FORMAT_ITF, "ITF"); + map.put(Barcode.FORMAT_QR_CODE, "QR_CODE"); + map.put(Barcode.FORMAT_UPC_A, "UPC_A"); + map.put(Barcode.FORMAT_UPC_E, "UPC_E"); + map.put(Barcode.FORMAT_PDF417, "PDF417"); + map.put(Barcode.FORMAT_AZTEC, "AZTEC"); + map.put(Barcode.FORMAT_ALL_FORMATS, "ALL"); + map.put(Barcode.FORMAT_UPC_A, "UPC_A"); map.put(-1, "None"); FORMATS = map; @@ -53,18 +53,18 @@ public class BarcodeFormatUtils { static { // Initialize integer to string map SparseArray map = new SparseArray<>(); - map.put(FirebaseVisionBarcode.TYPE_CALENDAR_EVENT, "CALENDAR_EVENT"); - map.put(FirebaseVisionBarcode.TYPE_CONTACT_INFO, "CONTACT_INFO"); - map.put(FirebaseVisionBarcode.TYPE_DRIVER_LICENSE, "DRIVER_LICENSE"); - map.put(FirebaseVisionBarcode.TYPE_EMAIL, "EMAIL"); - map.put(FirebaseVisionBarcode.TYPE_GEO, "GEO"); - map.put(FirebaseVisionBarcode.TYPE_ISBN, "ISBN"); - map.put(FirebaseVisionBarcode.TYPE_PHONE, "PHONE"); - map.put(FirebaseVisionBarcode.TYPE_PRODUCT, "PRODUCT"); - map.put(FirebaseVisionBarcode.TYPE_SMS, "SMS"); - map.put(FirebaseVisionBarcode.TYPE_TEXT, "TEXT"); - map.put(FirebaseVisionBarcode.TYPE_URL, "URL"); - map.put(FirebaseVisionBarcode.TYPE_WIFI, "WIFI"); + map.put(Barcode.TYPE_CALENDAR_EVENT, "CALENDAR_EVENT"); + map.put(Barcode.TYPE_CONTACT_INFO, "CONTACT_INFO"); + map.put(Barcode.TYPE_DRIVER_LICENSE, "DRIVER_LICENSE"); + map.put(Barcode.TYPE_EMAIL, "EMAIL"); + map.put(Barcode.TYPE_GEO, "GEO"); + map.put(Barcode.TYPE_ISBN, "ISBN"); + map.put(Barcode.TYPE_PHONE, "PHONE"); + map.put(Barcode.TYPE_PRODUCT, "PRODUCT"); + map.put(Barcode.TYPE_SMS, "SMS"); + map.put(Barcode.TYPE_TEXT, "TEXT"); + map.put(Barcode.TYPE_URL, "URL"); + map.put(Barcode.TYPE_WIFI, "WIFI"); map.put(-1, "None"); TYPES = map; diff --git a/android/src/mlkit/java/org/reactnative/barcodedetector/RNBarcodeDetector.java b/android/src/mlkit/java/org/reactnative/barcodedetector/RNBarcodeDetector.java index 31b676065..ae0c0d950 100644 --- a/android/src/mlkit/java/org/reactnative/barcodedetector/RNBarcodeDetector.java +++ b/android/src/mlkit/java/org/reactnative/barcodedetector/RNBarcodeDetector.java @@ -3,10 +3,10 @@ import android.content.Context; import android.util.Log; -import com.google.firebase.ml.vision.FirebaseVision; -import com.google.firebase.ml.vision.barcode.FirebaseVisionBarcode; -import com.google.firebase.ml.vision.barcode.FirebaseVisionBarcodeDetector; -import com.google.firebase.ml.vision.barcode.FirebaseVisionBarcodeDetectorOptions; +import com.google.mlkit.vision.barcode.Barcode; +import com.google.mlkit.vision.barcode.BarcodeScanner; +import com.google.mlkit.vision.barcode.BarcodeScanning; +import com.google.mlkit.vision.barcode.BarcodeScannerOptions; public class RNBarcodeDetector { @@ -14,15 +14,15 @@ public class RNBarcodeDetector { public static int NORMAL_MODE = 0; public static int ALTERNATE_MODE = 1; public static int INVERTED_MODE = 2; - public static int ALL_FORMATS = FirebaseVisionBarcode.FORMAT_ALL_FORMATS; + public static int ALL_FORMATS = Barcode.FORMAT_ALL_FORMATS; - private FirebaseVisionBarcodeDetector mBarcodeDetector = null; - private FirebaseVisionBarcodeDetectorOptions.Builder mBuilder; + private BarcodeScanner mBarcodeDetector = null; + private BarcodeScannerOptions.Builder mBuilder; - private int mBarcodeType = FirebaseVisionBarcode.FORMAT_ALL_FORMATS; + private int mBarcodeType = Barcode.FORMAT_ALL_FORMATS; public RNBarcodeDetector(Context context) { - mBuilder = new FirebaseVisionBarcodeDetectorOptions.Builder().setBarcodeFormats(mBarcodeType); + mBuilder = new BarcodeScannerOptions.Builder().setBarcodeFormats(mBarcodeType); } public boolean isOperational() { @@ -30,7 +30,7 @@ public boolean isOperational() { return true; } - public FirebaseVisionBarcodeDetector getDetector() { + public BarcodeScanner getDetector() { if (mBarcodeDetector == null) { createBarcodeDetector(); @@ -59,9 +59,7 @@ public void release() { } private void createBarcodeDetector() { - FirebaseVisionBarcodeDetectorOptions options = mBuilder.build(); - mBarcodeDetector = FirebaseVision.getInstance() - .getVisionBarcodeDetector(options); - + BarcodeScannerOptions options = mBuilder.build(); + mBarcodeDetector = BarcodeScanning.getClient(options); } } diff --git a/android/src/mlkit/java/org/reactnative/camera/tasks/BarcodeDetectorAsyncTask.java b/android/src/mlkit/java/org/reactnative/camera/tasks/BarcodeDetectorAsyncTask.java index bf0f33aaf..c64cd8089 100644 --- a/android/src/mlkit/java/org/reactnative/camera/tasks/BarcodeDetectorAsyncTask.java +++ b/android/src/mlkit/java/org/reactnative/camera/tasks/BarcodeDetectorAsyncTask.java @@ -9,10 +9,9 @@ import com.facebook.react.bridge.WritableMap; import com.google.android.gms.tasks.OnFailureListener; import com.google.android.gms.tasks.OnSuccessListener; -import com.google.firebase.ml.vision.barcode.FirebaseVisionBarcode; -import com.google.firebase.ml.vision.barcode.FirebaseVisionBarcodeDetector; -import com.google.firebase.ml.vision.common.FirebaseVisionImage; -import com.google.firebase.ml.vision.common.FirebaseVisionImageMetadata; +import com.google.mlkit.vision.barcode.Barcode; +import com.google.mlkit.vision.barcode.BarcodeScanner; +import com.google.mlkit.vision.common.InputImage; import org.reactnative.barcodedetector.BarcodeFormatUtils; import org.reactnative.barcodedetector.RNBarcodeDetector; @@ -68,19 +67,13 @@ protected Void doInBackground(Void... ignored) { return null; } - final FirebaseVisionImageMetadata metadata = new FirebaseVisionImageMetadata.Builder() - .setWidth(mWidth) - .setHeight(mHeight) - .setFormat(FirebaseVisionImageMetadata.IMAGE_FORMAT_YV12) - .setRotation(getFirebaseRotation()) - .build(); - FirebaseVisionImage image = FirebaseVisionImage.fromByteArray(mImageData, metadata); + InputImage image = InputImage.fromByteArray(mImageData, mWidth, mHeight, getFirebaseRotation(), InputImage.IMAGE_FORMAT_YV12); - FirebaseVisionBarcodeDetector barcode = mBarcodeDetector.getDetector(); - barcode.detectInImage(image) - .addOnSuccessListener(new OnSuccessListener>() { + BarcodeScanner barcode = mBarcodeDetector.getDetector(); + barcode.process(image) + .addOnSuccessListener(new OnSuccessListener>() { @Override - public void onSuccess(List barcodes) { + public void onSuccess(List barcodes) { WritableArray serializedBarcodes = serializeEventData(barcodes); mDelegate.onBarcodesDetected(serializedBarcodes, mWidth, mHeight, mImageData); mDelegate.onBarcodeDetectingTaskCompleted(); @@ -100,29 +93,30 @@ private int getFirebaseRotation(){ int result; switch (mRotation) { case 0: - result = FirebaseVisionImageMetadata.ROTATION_0; + result = 0; break; case 90: - result = FirebaseVisionImageMetadata.ROTATION_90; + result = 90; break; case 180: - result = FirebaseVisionImageMetadata.ROTATION_180; + result = 180; break; case -90: - result = FirebaseVisionImageMetadata.ROTATION_270; + case 270: + result = 270; break; default: - result = FirebaseVisionImageMetadata.ROTATION_0; + result = 0; Log.e(TAG, "Bad rotation value: " + mRotation); } return result; } - private WritableArray serializeEventData(List barcodes) { + private WritableArray serializeEventData(List barcodes) { WritableArray barcodesList = Arguments.createArray(); - for (FirebaseVisionBarcode barcode: barcodes) { + for (Barcode barcode: barcodes) { // TODO implement position and data from all barcode types Rect bounds = barcode.getBoundingBox(); // Point[] corners = barcode.getCornerPoints(); @@ -135,19 +129,19 @@ private WritableArray serializeEventData(List barcodes) { WritableMap serializedBarcode = Arguments.createMap(); switch (valueType) { - case FirebaseVisionBarcode.TYPE_WIFI: + case Barcode.TYPE_WIFI: String ssid = barcode.getWifi().getSsid(); String password = barcode.getWifi().getPassword(); int type = barcode.getWifi().getEncryptionType(); String typeString = "UNKNOWN"; switch (type) { - case FirebaseVisionBarcode.WiFi.TYPE_OPEN: + case Barcode.WiFi.TYPE_OPEN: typeString = "Open"; break; - case FirebaseVisionBarcode.WiFi.TYPE_WEP: + case Barcode.WiFi.TYPE_WEP: typeString = "WEP"; break; - case FirebaseVisionBarcode.WiFi.TYPE_WPA: + case Barcode.WiFi.TYPE_WPA: typeString = "WPA"; break; } @@ -155,33 +149,33 @@ private WritableArray serializeEventData(List barcodes) { serializedBarcode.putString("password", password); serializedBarcode.putString("ssid", ssid); break; - case FirebaseVisionBarcode.TYPE_URL: + case Barcode.TYPE_URL: String title = barcode.getUrl().getTitle(); String url = barcode.getUrl().getUrl(); serializedBarcode.putString("url", url); serializedBarcode.putString("title", title); break; - case FirebaseVisionBarcode.TYPE_SMS: + case Barcode.TYPE_SMS: String message = barcode.getSms().getMessage(); String phoneNumber = barcode.getSms().getPhoneNumber(); serializedBarcode.putString("message", message); serializedBarcode.putString("title", phoneNumber); break; - case FirebaseVisionBarcode.TYPE_PHONE: + case Barcode.TYPE_PHONE: String number = barcode.getPhone().getNumber(); int typePhone = barcode.getPhone().getType(); serializedBarcode.putString("number", number); String typeStringPhone = getPhoneType(typePhone); serializedBarcode.putString("phoneType", typeStringPhone); break; - case FirebaseVisionBarcode.TYPE_CALENDAR_EVENT: + case Barcode.TYPE_CALENDAR_EVENT: serializedBarcode.putString("description", barcode.getCalendarEvent().getDescription()); serializedBarcode.putString("location", barcode.getCalendarEvent().getLocation()); serializedBarcode.putString("organizer", barcode.getCalendarEvent().getOrganizer()); serializedBarcode.putString("status", barcode.getCalendarEvent().getStatus()); serializedBarcode.putString("summary", barcode.getCalendarEvent().getSummary()); - FirebaseVisionBarcode.CalendarDateTime start = barcode.getCalendarEvent().getStart(); - FirebaseVisionBarcode.CalendarDateTime end = barcode.getCalendarEvent().getEnd(); + Barcode.CalendarDateTime start = barcode.getCalendarEvent().getStart(); + Barcode.CalendarDateTime end = barcode.getCalendarEvent().getEnd(); if (start != null) { serializedBarcode.putString("start", start.getRawValue()); } @@ -189,7 +183,7 @@ private WritableArray serializeEventData(List barcodes) { serializedBarcode.putString("end", start.getRawValue()); } break; - case FirebaseVisionBarcode.TYPE_DRIVER_LICENSE: + case Barcode.TYPE_DRIVER_LICENSE: serializedBarcode.putString("addressCity", barcode.getDriverLicense().getAddressCity()); serializedBarcode.putString("addressState", barcode.getDriverLicense().getAddressState()); serializedBarcode.putString("addressStreet", barcode.getDriverLicense().getAddressStreet()); @@ -205,14 +199,14 @@ private WritableArray serializeEventData(List barcodes) { serializedBarcode.putString("issuingCountry", barcode.getDriverLicense().getIssuingCountry()); serializedBarcode.putString("licenseNumber", barcode.getDriverLicense().getLicenseNumber()); break; - case FirebaseVisionBarcode.TYPE_GEO: + case Barcode.TYPE_GEO: serializedBarcode.putDouble("latitude", barcode.getGeoPoint().getLat()); serializedBarcode.putDouble("longitude", barcode.getGeoPoint().getLng()); break; - case FirebaseVisionBarcode.TYPE_CONTACT_INFO: + case Barcode.TYPE_CONTACT_INFO: serializedBarcode.putString("organization", barcode.getContactInfo().getOrganization()); serializedBarcode.putString("title", barcode.getContactInfo().getTitle()); - FirebaseVisionBarcode.PersonName name = barcode.getContactInfo().getName(); + Barcode.PersonName name = barcode.getContactInfo().getName(); if (name != null) { serializedBarcode.putString("firstName", name.getFirst()); serializedBarcode.putString("lastName", name.getLast()); @@ -222,18 +216,18 @@ private WritableArray serializeEventData(List barcodes) { serializedBarcode.putString("pronunciation", name.getPronunciation()); serializedBarcode.putString("suffix", name.getSuffix()); } - List phones = barcode.getContactInfo().getPhones(); + List phones = barcode.getContactInfo().getPhones(); WritableArray phonesList = Arguments.createArray(); - for (FirebaseVisionBarcode.Phone phone : phones) { + for (Barcode.Phone phone : phones) { WritableMap phoneObject = Arguments.createMap(); phoneObject.putString("number", phone.getNumber()); phoneObject.putString("phoneType", getPhoneType(phone.getType())); phonesList.pushMap(phoneObject); } serializedBarcode.putArray("phones", phonesList); - List addresses = barcode.getContactInfo().getAddresses(); + List addresses = barcode.getContactInfo().getAddresses(); WritableArray addressesList = Arguments.createArray(); - for (FirebaseVisionBarcode.Address address : addresses) { + for (Barcode.Address address : addresses) { WritableMap addressesData = Arguments.createMap(); WritableArray addressesLinesList = Arguments.createArray(); String[] addressesLines = address.getAddressLines(); @@ -245,10 +239,10 @@ private WritableArray serializeEventData(List barcodes) { int addressType = address.getType(); String addressTypeString = "UNKNOWN"; switch(addressType) { - case FirebaseVisionBarcode.Address.TYPE_WORK: + case Barcode.Address.TYPE_WORK: addressTypeString = "Work"; break; - case FirebaseVisionBarcode.Address.TYPE_HOME: + case Barcode.Address.TYPE_HOME: addressTypeString = "Home"; break; } @@ -256,21 +250,21 @@ private WritableArray serializeEventData(List barcodes) { addressesList.pushMap(addressesData); } serializedBarcode.putArray("addresses", addressesList); - List emails = barcode.getContactInfo().getEmails(); + List emails = barcode.getContactInfo().getEmails(); WritableArray emailsList = Arguments.createArray(); - for (FirebaseVisionBarcode.Email email : emails) { + for (Barcode.Email email : emails) { WritableMap emailData = processEmail(email); emailsList.pushMap(emailData); } serializedBarcode.putArray("emails", emailsList); - String[] urls = barcode.getContactInfo().getUrls(); + List urls = barcode.getContactInfo().getUrls(); WritableArray urlsList = Arguments.createArray(); for (String urlContact : urls) { urlsList.pushString(urlContact); } serializedBarcode.putArray("urls", urlsList); break; - case FirebaseVisionBarcode.TYPE_EMAIL: + case Barcode.TYPE_EMAIL: WritableMap emailData = processEmail(barcode.getEmail()); serializedBarcode.putMap("email", emailData); break; @@ -287,7 +281,7 @@ private WritableArray serializeEventData(List barcodes) { return barcodesList; } - private WritableMap processEmail(FirebaseVisionBarcode.Email email) { + private WritableMap processEmail(Barcode.Email email) { WritableMap emailData = Arguments.createMap(); emailData.putString("address", email.getAddress()); emailData.putString("body", email.getBody()); @@ -295,10 +289,10 @@ private WritableMap processEmail(FirebaseVisionBarcode.Email email) { int emailType = email.getType(); String emailTypeString = "UNKNOWN"; switch (emailType) { - case FirebaseVisionBarcode.Email.TYPE_WORK: + case Barcode.Email.TYPE_WORK: emailTypeString = "Work"; break; - case FirebaseVisionBarcode.Email.TYPE_HOME: + case Barcode.Email.TYPE_HOME: emailTypeString = "Home"; break; } @@ -309,16 +303,16 @@ private WritableMap processEmail(FirebaseVisionBarcode.Email email) { private String getPhoneType(int typePhone) { String typeStringPhone = "UNKNOWN"; switch(typePhone) { - case FirebaseVisionBarcode.Phone.TYPE_WORK: + case Barcode.Phone.TYPE_WORK: typeStringPhone = "Work"; break; - case FirebaseVisionBarcode.Phone.TYPE_HOME: + case Barcode.Phone.TYPE_HOME: typeStringPhone = "Home"; break; - case FirebaseVisionBarcode.Phone.TYPE_FAX: + case Barcode.Phone.TYPE_FAX: typeStringPhone = "Fax"; break; - case FirebaseVisionBarcode.Phone.TYPE_MOBILE: + case Barcode.Phone.TYPE_MOBILE: typeStringPhone = "Mobile"; break; } diff --git a/android/src/mlkit/java/org/reactnative/camera/tasks/FaceDetectorAsyncTask.java b/android/src/mlkit/java/org/reactnative/camera/tasks/FaceDetectorAsyncTask.java index a372be384..343ec9ef3 100644 --- a/android/src/mlkit/java/org/reactnative/camera/tasks/FaceDetectorAsyncTask.java +++ b/android/src/mlkit/java/org/reactnative/camera/tasks/FaceDetectorAsyncTask.java @@ -8,10 +8,9 @@ import com.google.android.cameraview.CameraView; import com.google.android.gms.tasks.OnFailureListener; import com.google.android.gms.tasks.OnSuccessListener; -import com.google.firebase.ml.vision.common.FirebaseVisionImage; -import com.google.firebase.ml.vision.common.FirebaseVisionImageMetadata; -import com.google.firebase.ml.vision.face.FirebaseVisionFace; -import com.google.firebase.ml.vision.face.FirebaseVisionFaceDetector; +import com.google.mlkit.vision.common.InputImage; +import com.google.mlkit.vision.face.Face; +import com.google.mlkit.vision.face.FaceDetector; import org.reactnative.camera.utils.ImageDimensions; import org.reactnative.facedetector.FaceDetectorUtils; @@ -65,20 +64,14 @@ protected Void doInBackground(Void... ignored) { if (isCancelled() || mDelegate == null || mFaceDetector == null) { return null; } - FirebaseVisionImageMetadata metadata = new FirebaseVisionImageMetadata.Builder() - .setWidth(mWidth) - .setHeight(mHeight) - .setFormat(FirebaseVisionImageMetadata.IMAGE_FORMAT_YV12) - .setRotation(getFirebaseRotation()) - .build(); - FirebaseVisionImage image = FirebaseVisionImage.fromByteArray(mImageData, metadata); + InputImage image = InputImage.fromByteArray(mImageData, mWidth, mHeight, getFirebaseRotation(), InputImage.IMAGE_FORMAT_YV12); - FirebaseVisionFaceDetector detector = mFaceDetector.getDetector(); - detector.detectInImage(image) + FaceDetector detector = mFaceDetector.getDetector(); + detector.process(image) .addOnSuccessListener( - new OnSuccessListener>() { + new OnSuccessListener>() { @Override - public void onSuccess(List faces) { + public void onSuccess(List faces) { WritableArray facesList = serializeEventData(faces); mDelegate.onFacesDetected(facesList); mDelegate.onFaceDetectingTaskCompleted(); @@ -99,31 +92,29 @@ private int getFirebaseRotation(){ int result; switch (mRotation) { case 0: - result = FirebaseVisionImageMetadata.ROTATION_0; + result = 0; break; case 90: - result = FirebaseVisionImageMetadata.ROTATION_90; + result = 90; break; case 180: - result = FirebaseVisionImageMetadata.ROTATION_180; + result = 180; break; case 270: - result = FirebaseVisionImageMetadata.ROTATION_270; - break; case -90: - result = FirebaseVisionImageMetadata.ROTATION_270; + result = 270; break; default: - result = FirebaseVisionImageMetadata.ROTATION_0; + result = 0; Log.e(TAG, "Bad rotation value: " + mRotation); } return result; } - private WritableArray serializeEventData(List faces) { + private WritableArray serializeEventData(List faces) { WritableArray facesList = Arguments.createArray(); - for (FirebaseVisionFace face : faces) { + for (Face face : faces) { WritableMap serializedFace = FaceDetectorUtils.serializeFace(face, mScaleX, mScaleY, mWidth, mHeight, mPaddingLeft, mPaddingTop); if (mImageDimensions.getFacing() == CameraView.FACING_FRONT) { serializedFace = FaceDetectorUtils.rotateFaceX(serializedFace, mImageDimensions.getWidth(), mScaleX); diff --git a/android/src/mlkit/java/org/reactnative/camera/tasks/TextRecognizerAsyncTask.java b/android/src/mlkit/java/org/reactnative/camera/tasks/TextRecognizerAsyncTask.java index 9a1e5db86..074165366 100644 --- a/android/src/mlkit/java/org/reactnative/camera/tasks/TextRecognizerAsyncTask.java +++ b/android/src/mlkit/java/org/reactnative/camera/tasks/TextRecognizerAsyncTask.java @@ -13,11 +13,11 @@ import com.google.android.cameraview.CameraView; import com.google.android.gms.tasks.OnFailureListener; import com.google.android.gms.tasks.OnSuccessListener; -import com.google.firebase.ml.vision.FirebaseVision; -import com.google.firebase.ml.vision.common.FirebaseVisionImage; -import com.google.firebase.ml.vision.common.FirebaseVisionImageMetadata; -import com.google.firebase.ml.vision.text.FirebaseVisionText; -import com.google.firebase.ml.vision.text.FirebaseVisionTextRecognizer; +import com.google.mlkit.vision.common.InputImage; +import com.google.mlkit.vision.text.Text; +import com.google.mlkit.vision.text.TextRecognizer; +import com.google.mlkit.vision.text.TextRecognition; +import com.google.mlkit.vision.text.TextRecognizerOptions; import org.reactnative.camera.utils.ImageDimensions; @@ -71,20 +71,14 @@ protected Void doInBackground(Void... ignored) { return null; } - FirebaseVisionImageMetadata metadata = new FirebaseVisionImageMetadata.Builder() - .setWidth(mWidth) - .setHeight(mHeight) - .setFormat(FirebaseVisionImageMetadata.IMAGE_FORMAT_YV12) - .setRotation(getFirebaseRotation()) - .build(); - FirebaseVisionTextRecognizer detector = FirebaseVision.getInstance().getOnDeviceTextRecognizer(); - - FirebaseVisionImage image = FirebaseVisionImage.fromByteArray(mImageData, metadata); - detector.processImage(image) - .addOnSuccessListener(new OnSuccessListener() { + TextRecognizer detector = TextRecognition.getClient(TextRecognizerOptions.DEFAULT_OPTIONS); + + InputImage image = InputImage.fromByteArray(mImageData, mWidth, mHeight, getFirebaseRotation(), InputImage.IMAGE_FORMAT_YV12); + detector.process(image) + .addOnSuccessListener(new OnSuccessListener() { @Override - public void onSuccess(FirebaseVisionText firebaseVisionText) { - List textBlocks = firebaseVisionText.getTextBlocks(); + public void onSuccess(Text firebaseVisionText) { + List textBlocks = firebaseVisionText.getTextBlocks(); WritableArray serializedData = serializeEventData(textBlocks); mDelegate.onTextRecognized(serializedData); mDelegate.onTextRecognizerTaskCompleted(); @@ -106,27 +100,28 @@ private int getFirebaseRotation(){ int result; switch (mRotation) { case 0: - result = FirebaseVisionImageMetadata.ROTATION_0; + result = 0; break; case 90: - result = FirebaseVisionImageMetadata.ROTATION_90; + result = 90; break; case 180: - result = FirebaseVisionImageMetadata.ROTATION_180; + result = 180; break; case -90: - result = FirebaseVisionImageMetadata.ROTATION_270; + case 270: + result = 270; break; default: - result = FirebaseVisionImageMetadata.ROTATION_0; + result = 0; Log.e(TAG, "Bad rotation value: " + mRotation); } return result; } - private WritableArray serializeEventData(List textBlocks) { + private WritableArray serializeEventData(List textBlocks) { WritableArray textBlocksList = Arguments.createArray(); - for (FirebaseVisionText.TextBlock block: textBlocks) { + for (Text.TextBlock block: textBlocks) { WritableMap serializedTextBlock = serializeBloc(block); if (mImageDimensions.getFacing() == CameraView.FACING_FRONT) { serializedTextBlock = rotateTextX(serializedTextBlock); @@ -137,10 +132,10 @@ private WritableArray serializeEventData(List text return textBlocksList; } - private WritableMap serializeBloc(FirebaseVisionText.TextBlock block) { + private WritableMap serializeBloc(Text.TextBlock block) { WritableMap encodedText = Arguments.createMap(); WritableArray lines = Arguments.createArray(); - for (FirebaseVisionText.Line line : block.getLines()) { + for (Text.Line line : block.getLines()) { lines.pushMap(serializeLine(line)); } encodedText.putArray("components", lines); @@ -155,10 +150,10 @@ private WritableMap serializeBloc(FirebaseVisionText.TextBlock block) { return encodedText; } - private WritableMap serializeLine(FirebaseVisionText.Line line) { + private WritableMap serializeLine(Text.Line line) { WritableMap encodedText = Arguments.createMap(); WritableArray lines = Arguments.createArray(); - for (FirebaseVisionText.Element element : line.getElements()) { + for (Text.Element element : line.getElements()) { lines.pushMap(serializeElement(element)); } encodedText.putArray("components", lines); @@ -173,7 +168,7 @@ private WritableMap serializeLine(FirebaseVisionText.Line line) { return encodedText; } - private WritableMap serializeElement(FirebaseVisionText.Element element) { + private WritableMap serializeElement(Text.Element element) { WritableMap encodedText = Arguments.createMap(); encodedText.putString("value", element.getText()); diff --git a/android/src/mlkit/java/org/reactnative/facedetector/FaceDetectorUtils.java b/android/src/mlkit/java/org/reactnative/facedetector/FaceDetectorUtils.java index 316c0875f..4b7d2e912 100644 --- a/android/src/mlkit/java/org/reactnative/facedetector/FaceDetectorUtils.java +++ b/android/src/mlkit/java/org/reactnative/facedetector/FaceDetectorUtils.java @@ -1,11 +1,12 @@ package org.reactnative.facedetector; +import android.graphics.PointF; + import com.facebook.react.bridge.Arguments; import com.facebook.react.bridge.ReadableMap; import com.facebook.react.bridge.WritableMap; -import com.google.firebase.ml.vision.common.FirebaseVisionPoint; -import com.google.firebase.ml.vision.face.FirebaseVisionFace; -import com.google.firebase.ml.vision.face.FirebaseVisionFaceLandmark; +import com.google.mlkit.vision.face.Face; +import com.google.mlkit.vision.face.FaceLandmark; public class FaceDetectorUtils { private static final String[] landmarkNames = { @@ -14,16 +15,16 @@ public class FaceDetectorUtils { "rightEarPosition", "rightEyePosition", "rightMouthPosition" }; - public static WritableMap serializeFace(FirebaseVisionFace face) { + public static WritableMap serializeFace(Face face) { return serializeFace(face, 1, 1, 0, 0, 0, 0); } - public static WritableMap serializeFace(FirebaseVisionFace face, double scaleX, double scaleY, int width, int height, int paddingLeft, int paddingTop) { + public static WritableMap serializeFace(Face face, double scaleX, double scaleY, int width, int height, int paddingLeft, int paddingTop) { WritableMap encodedFace = Arguments.createMap(); int id = 0; // If face tracking was enabled: - if (face.getTrackingId() != FirebaseVisionFace.INVALID_ID) { + if (face.getTrackingId() != null) { id = face.getTrackingId(); } @@ -33,29 +34,29 @@ public static WritableMap serializeFace(FirebaseVisionFace face, double scaleX, encodedFace.putDouble("yawAngle", face.getHeadEulerAngleY()); // If classification was enabled: - if (face.getSmilingProbability() != FirebaseVisionFace.UNCOMPUTED_PROBABILITY) { + if (face.getSmilingProbability() != null) { encodedFace.putDouble("smilingProbability", face.getSmilingProbability()); } - if (face.getLeftEyeOpenProbability() != FirebaseVisionFace.UNCOMPUTED_PROBABILITY) { + if (face.getLeftEyeOpenProbability() != null) { encodedFace.putDouble("leftEyeOpenProbability", face.getLeftEyeOpenProbability()); } - if (face.getRightEyeOpenProbability() != FirebaseVisionFace.UNCOMPUTED_PROBABILITY) { + if (face.getRightEyeOpenProbability() != null) { encodedFace.putDouble("rightEyeOpenProbability", face.getRightEyeOpenProbability()); } int[] landmarks = { - FirebaseVisionFaceLandmark.MOUTH_BOTTOM, - FirebaseVisionFaceLandmark.LEFT_CHEEK, - FirebaseVisionFaceLandmark.LEFT_EAR, - FirebaseVisionFaceLandmark.LEFT_EYE, - FirebaseVisionFaceLandmark.MOUTH_LEFT, - FirebaseVisionFaceLandmark.NOSE_BASE, - FirebaseVisionFaceLandmark.RIGHT_CHEEK, - FirebaseVisionFaceLandmark.RIGHT_EAR, - FirebaseVisionFaceLandmark.RIGHT_EYE, - FirebaseVisionFaceLandmark.MOUTH_RIGHT}; + FaceLandmark.MOUTH_BOTTOM, + FaceLandmark.LEFT_CHEEK, + FaceLandmark.LEFT_EAR, + FaceLandmark.LEFT_EYE, + FaceLandmark.MOUTH_LEFT, + FaceLandmark.NOSE_BASE, + FaceLandmark.RIGHT_CHEEK, + FaceLandmark.RIGHT_EAR, + FaceLandmark.RIGHT_EYE, + FaceLandmark.MOUTH_RIGHT}; for (int i = 0; i < landmarks.length; ++i) { - FirebaseVisionFaceLandmark landmark = face.getLandmark(landmarks[i]); + FaceLandmark landmark = face.getLandmark(landmarks[i]); if (landmark != null) { encodedFace.putMap(landmarkNames[i], mapFromPoint(landmark.getPosition(), scaleX, scaleY, width, height, paddingLeft, paddingTop)); } @@ -124,19 +125,19 @@ public static WritableMap changeAnglesDirection(WritableMap face) { return face; } - public static WritableMap mapFromPoint(FirebaseVisionPoint point, double scaleX, double scaleY, int width, int height, int paddingLeft, int paddingTop) { + public static WritableMap mapFromPoint(PointF point, double scaleX, double scaleY, int width, int height, int paddingLeft, int paddingTop) { WritableMap map = Arguments.createMap(); - Float x = point.getX(); - Float y = point.getY(); - if (point.getX() < width / 2) { + Float x = point.x; + Float y = point.y; + if (point.x < width / 2) { x = (x + paddingLeft / 2); - } else if (point.getX() > width / 2) { + } else if (point.x > width / 2) { x = (x - paddingLeft / 2); } - if (point.getY() < height / 2) { + if (point.y < height / 2) { y = (y + paddingTop / 2); - } else if (point.getY() > height / 2) { + } else if (point.y > height / 2) { y = (y - paddingTop / 2); } map.putDouble("x", x * scaleX); diff --git a/android/src/mlkit/java/org/reactnative/facedetector/RNFaceDetector.java b/android/src/mlkit/java/org/reactnative/facedetector/RNFaceDetector.java index 9df38ce5b..722b32053 100644 --- a/android/src/mlkit/java/org/reactnative/facedetector/RNFaceDetector.java +++ b/android/src/mlkit/java/org/reactnative/facedetector/RNFaceDetector.java @@ -3,24 +3,24 @@ import android.content.Context; import android.util.Log; -import com.google.firebase.ml.vision.FirebaseVision; -import com.google.firebase.ml.vision.face.FirebaseVisionFaceDetector; -import com.google.firebase.ml.vision.face.FirebaseVisionFaceDetectorOptions; +import com.google.mlkit.vision.face.FaceDetector; +import com.google.mlkit.vision.face.FaceDetection; +import com.google.mlkit.vision.face.FaceDetectorOptions; public class RNFaceDetector { - public static int ALL_CLASSIFICATIONS = FirebaseVisionFaceDetectorOptions.ALL_CLASSIFICATIONS; - public static int NO_CLASSIFICATIONS = FirebaseVisionFaceDetectorOptions.NO_CLASSIFICATIONS; - public static int ALL_LANDMARKS = FirebaseVisionFaceDetectorOptions.ALL_LANDMARKS; - public static int NO_LANDMARKS = FirebaseVisionFaceDetectorOptions.NO_LANDMARKS; - public static int ACCURATE_MODE = FirebaseVisionFaceDetectorOptions.ACCURATE; - public static int FAST_MODE = FirebaseVisionFaceDetectorOptions.FAST; + public static int ALL_CLASSIFICATIONS = FaceDetectorOptions.CLASSIFICATION_MODE_ALL; + public static int NO_CLASSIFICATIONS = FaceDetectorOptions.CLASSIFICATION_MODE_NONE; + public static int ALL_LANDMARKS = FaceDetectorOptions.LANDMARK_MODE_ALL; + public static int NO_LANDMARKS = FaceDetectorOptions.LANDMARK_MODE_NONE; + public static int ACCURATE_MODE = FaceDetectorOptions.PERFORMANCE_MODE_ACCURATE; + public static int FAST_MODE = FaceDetectorOptions.PERFORMANCE_MODE_FAST; // TODO contours detection is possible for MLKit-based face detector, implement this feature - public static int ALL_CONTOURS = FirebaseVisionFaceDetectorOptions.ALL_CONTOURS; - public static int NO_CONTOURS = FirebaseVisionFaceDetectorOptions.NO_CONTOURS; + public static int ALL_CONTOURS = FaceDetectorOptions.CONTOUR_MODE_ALL; + public static int NO_CONTOURS = FaceDetectorOptions.CONTOUR_MODE_NONE; - private FirebaseVisionFaceDetector mFaceDetector = null; - private FirebaseVisionFaceDetectorOptions.Builder mBuilder; + private FaceDetector mFaceDetector = null; + private FaceDetectorOptions.Builder mBuilder; private int mClassificationType = NO_CLASSIFICATIONS; private int mLandmarkType = NO_LANDMARKS; @@ -28,7 +28,7 @@ public class RNFaceDetector { private int mMode = FAST_MODE; public RNFaceDetector(Context context) { - mBuilder = new FirebaseVisionFaceDetectorOptions.Builder() + mBuilder = new FaceDetectorOptions.Builder() .setPerformanceMode(mMode) .setLandmarkMode(mLandmarkType) .setClassificationMode(mClassificationType) @@ -40,7 +40,7 @@ public boolean isOperational() { return true; } - public FirebaseVisionFaceDetector getDetector() { + public FaceDetector getDetector() { if (mFaceDetector == null) { createFaceDetector(); @@ -91,7 +91,7 @@ public void release() { } private void createFaceDetector() { - FirebaseVisionFaceDetectorOptions options = mBuilder.build(); - mFaceDetector = FirebaseVision.getInstance().getVisionFaceDetector(options); + FaceDetectorOptions options = mBuilder.build(); + mFaceDetector = FaceDetection.getClient(options); } } diff --git a/android/src/mlkit/java/org/reactnative/facedetector/tasks/FileFaceDetectionAsyncTask.java b/android/src/mlkit/java/org/reactnative/facedetector/tasks/FileFaceDetectionAsyncTask.java index ca5521f7f..073138afd 100644 --- a/android/src/mlkit/java/org/reactnative/facedetector/tasks/FileFaceDetectionAsyncTask.java +++ b/android/src/mlkit/java/org/reactnative/facedetector/tasks/FileFaceDetectionAsyncTask.java @@ -15,9 +15,9 @@ import com.facebook.react.bridge.WritableMap; import com.google.android.gms.tasks.OnFailureListener; import com.google.android.gms.tasks.OnSuccessListener; -import com.google.firebase.ml.vision.common.FirebaseVisionImage; -import com.google.firebase.ml.vision.face.FirebaseVisionFace; -import com.google.firebase.ml.vision.face.FirebaseVisionFaceDetector; +import com.google.mlkit.vision.common.InputImage; +import com.google.mlkit.vision.face.Face; +import com.google.mlkit.vision.face.FaceDetector; import java.io.File; import java.io.IOException; @@ -96,13 +96,13 @@ protected Void doInBackground(Void... voids) { } try { - FirebaseVisionImage image = FirebaseVisionImage.fromFilePath(mContext, Uri.parse(mUri)); - FirebaseVisionFaceDetector detector = mRNFaceDetector.getDetector(); - detector.detectInImage(image) + InputImage image = InputImage.fromFilePath(mContext, Uri.parse(mUri)); + FaceDetector detector = mRNFaceDetector.getDetector(); + detector.process(image) .addOnSuccessListener( - new OnSuccessListener>() { + new OnSuccessListener>() { @Override - public void onSuccess(List faces) { + public void onSuccess(List faces) { serializeEventData(faces); } }) @@ -122,11 +122,11 @@ public void onFailure(Exception e) { return null; } - private void serializeEventData(List faces) { + private void serializeEventData(List faces) { WritableMap result = Arguments.createMap(); WritableArray facesArray = Arguments.createArray(); - for(FirebaseVisionFace face : faces) { + for(Face face : faces) { WritableMap encodedFace = FaceDetectorUtils.serializeFace(face); encodedFace.putDouble("yawAngle", (-encodedFace.getDouble("yawAngle") + 360) % 360); encodedFace.putDouble("rollAngle", (-encodedFace.getDouble("rollAngle") + 360) % 360); diff --git a/docs/installation.md b/docs/installation.md index fd6141908..dee120ce7 100644 --- a/docs/installation.md +++ b/docs/installation.md @@ -161,14 +161,13 @@ allprojects { # Additional installation steps Follow these optional steps if you want to use Face Detection/Text Recognition/BarCode with [MLKit](https://developers.google.com/ml-kit). -You will need to set-up Firebase project for your app (detailed steps below). - -_Note:_ Installing [react-native-firebase](https://github.com/invertase/react-native-firebase) package is NOT necessary. ## iOS If you want any of these optional features, you will need to use CocoaPods. +> MLKit for iOS runs on arm64/x86_64 devices only; armv7/x86 is not supported + ### Modifying Podfile Add dependency towards `react-native-camera` in your `Podfile` with `subspecs` using one of the following: @@ -209,33 +208,11 @@ pod 'react-native-camera', path: '../node_modules/react-native-camera', subspecs Then run `cd ios && pod install && cd ..` -### Setting up Firebase - -Text/Face recognition for iOS uses Firebase MLKit which requires setting up Firebase project for your app. -If you have not already added Firebase to your app, please follow the steps described in [getting started guide](https://firebase.google.com/docs/ios/setup). -In short, you would need to - -1. Register your app in Firebase console. -2. Download `GoogleService-Info.plist` and add it to your project -3. Add `pod 'Firebase/Core'` to your podfile -4. In your `AppDelegate.m` file add the following lines: - -```objective-c -#import // <--- add this -... - -- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions -{ - [FIRApp configure]; // <--- add this - ... -} -```
Additional information in case of problems -- If you have issues with duplicate symbols you will need to enable dead code stripping option in your Xcode (Target > Build Settings > search for "Dead code stripping") [see here](https://github.com/firebase/quickstart-ios/issues/487#issuecomment-415313053). -- If you are using `pod Firebase/Core` with a version set below 5.13 you might want to add `pod 'GoogleAppMeasurement', '~> 5.3.0'` to your podfile +- If you see build errors like `ld: symbol(s) not found for architecture armv7` you will need to exclude armv7 arch in your Xcode (Xcode -> Build Setting -> Excluded Architectures -> Add 'armv7' for 'Any iOS SDK' ).
## Android @@ -254,39 +231,44 @@ android { } ``` -### Setting up Firebase +### Setting up MLKit -Using Firebase MLKit requires seting up Firebase project for your app. If you have not already added Firebase to your app, please follow the steps described in [getting started guide](https://firebase.google.com/docs/android/setup). -In short, you would need to +**If you don't use any other Firebase component in your project** -1. Register your app in Firebase console. -2. Download google-services.json and place it in `android/app/` -3. Add the folowing to project level `build.gradle`: +1. Add the folowing to project level `build.gradle`: ```gradle buildscript { dependencies { // Add this line - classpath 'com.google.gms:google-services:4.0.1' // <--- you might want to use different version + classpath 'com.google.android.gms:strict-version-matcher-plugin:1.2.1' // <--- you might want to use different version } } ``` -4. add to the bottom of `android/app/build.gradle` file +2. add to the bottom of `android/app/build.gradle` file ```gradle -apply plugin: 'com.google.gms.google-services' +apply plugin: 'com.google.android.gms.strict-version-matcher-plugin' ``` -5. Configure your app to automatically download the ML model to the device after your app is installed from the Play Store. If you do not enable install-time model downloads, the model will be downloaded the first time you run the on-device detector. Requests you make before the download has completed will produce no results. +**If you have Firebase integrated already** -```xml - -... - - +1. Add the folowing to project level `build.gradle`: + +```gradle +buildscript { + dependencies { + // Add this line + classpath 'com.google.gms:google-services:4.3.3' // Google Services plugin(you might want to use different version) + } +} +``` + +2. add to the bottom of `android/app/build.gradle` file + +```gradle +apply plugin: 'com.google.gms.google-services' // Google Services plugin ```
@@ -297,7 +279,6 @@ apply plugin: 'com.google.gms.google-services' def DEFAULT_COMPILE_SDK_VERSION = 29 def DEFAULT_BUILD_TOOLS_VERSION = "29.0.2" def DEFAULT_TARGET_SDK_VERSION = 29 -def DEFAULT_GOOGLE_PLAY_SERVICES_VERSION = "12.0.1" def DEFAULT_SUPPORT_LIBRARY_VERSION = "27.1.0" ``` @@ -317,114 +298,12 @@ ext { compileSdkVersion = 29 targetSdkVersion = 29 buildToolsVersion = "29.0.2" - googlePlayServicesVersion = "12.0.1" - googlePlayServicesVisionVersion = "15.0.2" supportLibVersion = "27.1.0" } ``` The above settings in the ReactNative project over-rides the values present in the `react-native-camera` -module. For your reference below is the `android/build.gradle` file of the module. - -```gradle -def safeExtGet(prop, fallback) { - rootProject.ext.has(prop) ? rootProject.ext.get(prop) : fallback -} - -buildscript { - repositories { - google() - maven { - url 'https://maven.google.com' - } - jcenter() - } - - dependencies { - classpath 'com.android.tools.build:gradle:4.1.0' - } -} - -apply plugin: 'com.android.library' - -android { - compileSdkVersion safeExtGet('compileSdkVersion', 28) - buildToolsVersion safeExtGet('buildToolsVersion', '28.0.3') - - defaultConfig { - minSdkVersion safeExtGet('minSdkVersion', 16) - targetSdkVersion safeExtGet('targetSdkVersion', 28) - } - - flavorDimensions "react-native-camera" - - productFlavors { - general { - dimension "react-native-camera" - } - mlkit { - dimension "react-native-camera" - } - } - - sourceSets { - main { - java.srcDirs = ['src/main/java'] - } - general { - java.srcDirs = ['src/general/java'] - } - mlkit { - java.srcDirs = ['src/mlkit/java'] - } - } - - lintOptions { - abortOnError false - warning 'InvalidPackage' - } -} - -repositories { - google() - jcenter() - maven { - url 'https://maven.google.com' - } - maven { url "https://jitpack.io" } - maven { - // All of React Native (JS, Obj-C sources, Android binaries) is installed from npm - url "$rootDir/../node_modules/react-native/android" - } -} - -dependencies { - def googlePlayServicesVisionVersion = safeExtGet('googlePlayServicesVisionVersion', safeExtGet('googlePlayServicesVersion', '17.0.2')) - - implementation 'com.facebook.react:react-native:+' - implementation "com.google.zxing:core:3.3.3" - implementation "com.drewnoakes:metadata-extractor:2.11.0" - generalImplementation "com.google.android.gms:play-services-vision:$googlePlayServicesVisionVersion" - implementation "com.android.support:exifinterface:${safeExtGet('supportLibVersion', '28.0.0')}" - implementation "com.android.support:support-annotations:${safeExtGet('supportLibVersion', '28.0.0')}" - implementation "com.android.support:support-v4:${safeExtGet('supportLibVersion', '28.0.0')}" - mlkitImplementation "com.google.firebase:firebase-ml-vision:${safeExtGet('firebase-ml-vision', '19.0.3')}" - mlkitImplementation "com.google.firebase:firebase-ml-vision-face-model:${safeExtGet('firebase-ml-vision-face-model', '17.0.2')}" -} -``` - -If you are using a version of `googlePlayServicesVersion` that does not have `play-services-vision`, you can specify a different version of `play-services-vision` by adding `googlePlayServicesVisionVersion` to the project-wide properties - -```gradle -ext { - compileSdkVersion = 29 - targetSdkVersion = 29 - buildToolsVersion = "29.0.2" - googlePlayServicesVersion = "16.0.1" - googlePlayServicesVisionVersion = "15.0.2" - supportLibVersion = "27.1.0" -} -``` +module. For your reference please check [android/build.gradle](android/build.gradle) file of the module.
diff --git a/docs/migrationV4.md b/docs/migrationV4.md new file mode 100644 index 000000000..4fad9e90c --- /dev/null +++ b/docs/migrationV4.md @@ -0,0 +1,67 @@ +--- +id: migrationv4 +title: Migrating from version 2.x/3.x to 4.x +sidebar_label: Migrating from version 2.x/3.x to 4.x +--- + +Version 3.x of react-native-camera replaces `MLKit for Firebase`(which has been deprecated) with `Google MLKit`, allowing you to use advanced features such as text/face recognition without Firebase. You can learn more at [MLKit](https://developers.google.com/ml-kit/migration) + +## Required steps + +> Skip this if you need Firebase in your project + +### Remove Firebase project + +#### Android + +1. Remove the Firebase configuration file by deleting the google-services.json config file at `android/app/`. + +2. Replace the Google Services Gradle plugin classpath in `android/app/build.gradle` with the one for the Strict Version Matcher plugin: + +```diff + buildscript { + dependencies { + // Add this line +- classpath 'com.google.gms:google-services:4.0.1' <-- you might want to use different version ++ classpath 'com.google.android.gms:strict-version-matcher-plugin:1.2.1' + } + } +``` + +3. Replace the Google Services Gradle plugin in `android/build.gradle` with the Strict Version Matcher plugin: + +```diff +- apply plugin: 'com.google.gms.google-services' ++ apply plugin: 'com.google.android.gms.strict-version-matcher-plugin' +``` + +4. Remove meta fron `android/app/Manifest.xml`(MLKit use bundled models) + +```diff + +... +- +- + +``` + +#### iOS + +1. Remove `GoogleService-Info.plist` from your project + +2. Remove `pod 'Firebase/Core'` from your Podfile + +1\3. Remove Firebase code from `AppDelegate.m` + +```diff +-#import // <--- add this +... + +\- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions +{ +- [FIRApp configure]; // <--- add this + ... +} +``` diff --git a/examples/mlkit/android/app/build.gradle b/examples/mlkit/android/app/build.gradle index 234bd0d4c..ffaec7c00 100644 --- a/examples/mlkit/android/app/build.gradle +++ b/examples/mlkit/android/app/build.gradle @@ -165,4 +165,4 @@ task downloadDependencies() { } } -apply plugin: 'com.google.gms.google-services' +apply plugin: 'com.google.android.gms.strict-version-matcher-plugin' diff --git a/examples/mlkit/android/build.gradle b/examples/mlkit/android/build.gradle index 754d4b9ed..75dd2eaac 100644 --- a/examples/mlkit/android/build.gradle +++ b/examples/mlkit/android/build.gradle @@ -14,7 +14,7 @@ buildscript { } dependencies { classpath 'com.android.tools.build:gradle:4.1.0' - classpath 'com.google.gms:google-services:4.0.1' + classpath 'com.google.android.gms:strict-version-matcher-plugin:1.2.1' // NOTE: Do not place your application dependencies here; they belong // in the individual module build.gradle files diff --git a/website/i18n/en.json b/website/i18n/en.json index b2e9d3dd1..c8cb7d59b 100644 --- a/website/i18n/en.json +++ b/website/i18n/en.json @@ -34,6 +34,10 @@ "title": "Migrating from version 1.x to 2.x", "sidebar_label": "Migrating from version 1.x to 2.x" }, + "migrationv4": { + "title": "Migrating from version 2.x/3.x to 4.x", + "sidebar_label": "Migrating from version 2.x/3.x to 4.x" + }, "qa": { "title": "Q & A", "sidebar_label": "Q & A" diff --git a/website/sidebars.json b/website/sidebars.json index 825da3e36..e244da606 100644 --- a/website/sidebars.json +++ b/website/sidebars.json @@ -1,7 +1,7 @@ { "docs": { "Getting Started": ["installation", "contributing"], - "Guides": ["expo_usage", "GradleUpgradeGuide", "migration", "migrationv2", "react-navigation", "recipes", "rncamera", "tests"], + "Guides": ["expo_usage", "GradleUpgradeGuide", "migration", "migrationv2", "migrationv4", "react-navigation", "recipes", "rncamera", "tests"], "API": ["api"], "Help": ["qa"], "Enterprise": ["Tidelift"]