From c21de5c3dd46de47a41647409106d79b1458477a Mon Sep 17 00:00:00 2001 From: Maurice Parrish Date: Thu, 25 Oct 2018 16:24:25 -0700 Subject: [PATCH 01/35] Make it possible to pass bytes --- .../lib/firebase_ml_vision.dart | 1 + .../lib/src/barcode_detector.dart | 4 ++- .../lib/src/face_detector.dart | 4 ++- .../lib/src/firebase_vision.dart | 34 ++++++++++++++++--- .../lib/src/label_detector.dart | 8 +++-- .../lib/src/text_recognizer.dart | 4 ++- 6 files changed, 45 insertions(+), 10 deletions(-) diff --git a/packages/firebase_ml_vision/lib/firebase_ml_vision.dart b/packages/firebase_ml_vision/lib/firebase_ml_vision.dart index 8e228bb65229..e7194589acf4 100644 --- a/packages/firebase_ml_vision/lib/firebase_ml_vision.dart +++ b/packages/firebase_ml_vision/lib/firebase_ml_vision.dart @@ -7,6 +7,7 @@ library firebase_ml_vision; import 'dart:async'; import 'dart:io'; import 'dart:math'; +import 'dart:typed_data'; import 'package:flutter/foundation.dart'; import 'package:flutter/services.dart'; diff --git a/packages/firebase_ml_vision/lib/src/barcode_detector.dart b/packages/firebase_ml_vision/lib/src/barcode_detector.dart index 8ceedbbe475a..04236c8cce48 100644 --- a/packages/firebase_ml_vision/lib/src/barcode_detector.dart +++ b/packages/firebase_ml_vision/lib/src/barcode_detector.dart @@ -189,7 +189,9 @@ class BarcodeDetector extends FirebaseVisionDetector { final List reply = await FirebaseVision.channel.invokeMethod( 'BarcodeDetector#detectInImage', { - 'path': visionImage.imageFile.path, + 'type': _enumToString(visionImage._type), + 'path': visionImage._imageFile.path, + 'bytes': visionImage._bytes, 'options': { 'barcodeFormats': options.barcodeFormats.value, }, diff --git a/packages/firebase_ml_vision/lib/src/face_detector.dart b/packages/firebase_ml_vision/lib/src/face_detector.dart index 560f2a7448cf..a12597dee2c0 100644 --- a/packages/firebase_ml_vision/lib/src/face_detector.dart +++ b/packages/firebase_ml_vision/lib/src/face_detector.dart @@ -44,7 +44,9 @@ class FaceDetector extends FirebaseVisionDetector { final List reply = await FirebaseVision.channel.invokeMethod( 'FaceDetector#detectInImage', { - 'path': visionImage.imageFile.path, + 'type': _enumToString(visionImage._type), + 'path': visionImage._imageFile.path, + 'bytes': visionImage._bytes, 'options': { 'enableClassification': options.enableClassification, 'enableLandmarks': options.enableLandmarks, diff --git a/packages/firebase_ml_vision/lib/src/firebase_vision.dart b/packages/firebase_ml_vision/lib/src/firebase_vision.dart index 31bd400494b4..385e07fff1dd 100644 --- a/packages/firebase_ml_vision/lib/src/firebase_vision.dart +++ b/packages/firebase_ml_vision/lib/src/firebase_vision.dart @@ -4,6 +4,8 @@ part of firebase_ml_vision; +enum _FirebaseVisionImageType { file, bytes } + /// The Firebase machine learning vision API. /// /// You can get an instance by calling [FirebaseVision.instance] and then get @@ -56,22 +58,44 @@ class FirebaseVision { /// /// Create an instance by calling one of the factory constructors. class FirebaseVisionImage { - FirebaseVisionImage._(this.imageFile); + FirebaseVisionImage._({ + @required _FirebaseVisionImageType type, + File imageFile, + Uint8List bytes, + }) : _imageFile = imageFile, + _bytes = bytes, + _type = type; /// Construct a [FirebaseVisionImage] from a file. factory FirebaseVisionImage.fromFile(File imageFile) { assert(imageFile != null); - return FirebaseVisionImage._(imageFile); + return FirebaseVisionImage._( + type: _FirebaseVisionImageType.file, + imageFile: imageFile, + ); } /// Construct a [FirebaseVisionImage] from a file path. factory FirebaseVisionImage.fromFilePath(String imagePath) { assert(imagePath != null); - return FirebaseVisionImage._(File(imagePath)); + return FirebaseVisionImage._( + type: _FirebaseVisionImageType.file, + imageFile: File(imagePath), + ); + } + + /// Construct a [FirebaseVisionImage] from a list of bytes. + factory FirebaseVisionImage.fromBytes(Uint8List bytes) { + assert(bytes != null); + return FirebaseVisionImage._( + type: _FirebaseVisionImageType.bytes, + bytes: bytes, + ); } - /// The file location of the image. - final File imageFile; + final File _imageFile; + final Uint8List _bytes; + final _FirebaseVisionImageType _type; } /// Abstract class for detectors in [FirebaseVision] API. diff --git a/packages/firebase_ml_vision/lib/src/label_detector.dart b/packages/firebase_ml_vision/lib/src/label_detector.dart index 8511724406d0..f24d2eaa9734 100644 --- a/packages/firebase_ml_vision/lib/src/label_detector.dart +++ b/packages/firebase_ml_vision/lib/src/label_detector.dart @@ -34,7 +34,9 @@ class LabelDetector extends FirebaseVisionDetector { final List reply = await FirebaseVision.channel.invokeMethod( 'LabelDetector#detectInImage', { - 'path': visionImage.imageFile.path, + 'type': _enumToString(visionImage._type), + 'path': visionImage._imageFile.path, + 'bytes': visionImage._bytes, 'options': { 'confidenceThreshold': options.confidenceThreshold, }, @@ -80,7 +82,9 @@ class CloudLabelDetector extends FirebaseVisionDetector { final List reply = await FirebaseVision.channel.invokeMethod( 'CloudLabelDetector#detectInImage', { - 'path': visionImage.imageFile.path, + 'type': _enumToString(visionImage._type), + 'path': visionImage._imageFile.path, + 'bytes': visionImage._bytes, 'options': options._toMap(), }, ); diff --git a/packages/firebase_ml_vision/lib/src/text_recognizer.dart b/packages/firebase_ml_vision/lib/src/text_recognizer.dart index b65aa95fec09..c2a587ed9bc8 100644 --- a/packages/firebase_ml_vision/lib/src/text_recognizer.dart +++ b/packages/firebase_ml_vision/lib/src/text_recognizer.dart @@ -22,7 +22,9 @@ class TextRecognizer implements FirebaseVisionDetector { await FirebaseVision.channel.invokeMethod( 'TextRecognizer#processImage', { - 'path': visionImage.imageFile.path, + 'type': _enumToString(visionImage._type), + 'path': visionImage._imageFile.path, + 'bytes': visionImage._bytes, 'options': {}, }, ); From 671b66c3deed7e38112bfe19f89869ec87095cd4 Mon Sep 17 00:00:00 2001 From: Maurice Parrish Date: Thu, 25 Oct 2018 17:26:50 -0700 Subject: [PATCH 02/35] Add metadata for images --- .../lib/firebase_ml_vision.dart | 1 + .../lib/src/barcode_detector.dart | 5 +-- .../lib/src/cloud_detector_options.dart | 2 +- .../lib/src/face_detector.dart | 5 +-- .../lib/src/firebase_vision.dart | 39 +++++++++++++++++-- .../lib/src/label_detector.dart | 12 ++---- .../lib/src/text_recognizer.dart | 5 +-- 7 files changed, 44 insertions(+), 25 deletions(-) diff --git a/packages/firebase_ml_vision/lib/firebase_ml_vision.dart b/packages/firebase_ml_vision/lib/firebase_ml_vision.dart index e7194589acf4..00f85da5bfe7 100644 --- a/packages/firebase_ml_vision/lib/firebase_ml_vision.dart +++ b/packages/firebase_ml_vision/lib/firebase_ml_vision.dart @@ -8,6 +8,7 @@ import 'dart:async'; import 'dart:io'; import 'dart:math'; import 'dart:typed_data'; +import 'dart:ui'; import 'package:flutter/foundation.dart'; import 'package:flutter/services.dart'; diff --git a/packages/firebase_ml_vision/lib/src/barcode_detector.dart b/packages/firebase_ml_vision/lib/src/barcode_detector.dart index 04236c8cce48..d8705aaeaad6 100644 --- a/packages/firebase_ml_vision/lib/src/barcode_detector.dart +++ b/packages/firebase_ml_vision/lib/src/barcode_detector.dart @@ -189,13 +189,10 @@ class BarcodeDetector extends FirebaseVisionDetector { final List reply = await FirebaseVision.channel.invokeMethod( 'BarcodeDetector#detectInImage', { - 'type': _enumToString(visionImage._type), - 'path': visionImage._imageFile.path, - 'bytes': visionImage._bytes, 'options': { 'barcodeFormats': options.barcodeFormats.value, }, - }, + }..addAll(visionImage._serialize()), ); final List barcodes = []; diff --git a/packages/firebase_ml_vision/lib/src/cloud_detector_options.dart b/packages/firebase_ml_vision/lib/src/cloud_detector_options.dart index 4a4144ecd014..58c7c8885fe5 100644 --- a/packages/firebase_ml_vision/lib/src/cloud_detector_options.dart +++ b/packages/firebase_ml_vision/lib/src/cloud_detector_options.dart @@ -29,7 +29,7 @@ class CloudDetectorOptions { /// The type of model to use for the detection. final CloudModelType modelType; - Map _toMap() => { + Map _serialize() => { 'maxResults': maxResults, 'modelType': _enumToString(modelType), }; diff --git a/packages/firebase_ml_vision/lib/src/face_detector.dart b/packages/firebase_ml_vision/lib/src/face_detector.dart index a12597dee2c0..7d87377d840f 100644 --- a/packages/firebase_ml_vision/lib/src/face_detector.dart +++ b/packages/firebase_ml_vision/lib/src/face_detector.dart @@ -44,9 +44,6 @@ class FaceDetector extends FirebaseVisionDetector { final List reply = await FirebaseVision.channel.invokeMethod( 'FaceDetector#detectInImage', { - 'type': _enumToString(visionImage._type), - 'path': visionImage._imageFile.path, - 'bytes': visionImage._bytes, 'options': { 'enableClassification': options.enableClassification, 'enableLandmarks': options.enableLandmarks, @@ -54,7 +51,7 @@ class FaceDetector extends FirebaseVisionDetector { 'minFaceSize': options.minFaceSize, 'mode': _enumToString(options.mode), }, - }, + }..addAll(visionImage._serialize()), ); final List faces = []; diff --git a/packages/firebase_ml_vision/lib/src/firebase_vision.dart b/packages/firebase_ml_vision/lib/src/firebase_vision.dart index 385e07fff1dd..4a026d009a02 100644 --- a/packages/firebase_ml_vision/lib/src/firebase_vision.dart +++ b/packages/firebase_ml_vision/lib/src/firebase_vision.dart @@ -58,11 +58,13 @@ class FirebaseVision { /// /// Create an instance by calling one of the factory constructors. class FirebaseVisionImage { - FirebaseVisionImage._({ + const FirebaseVisionImage._({ @required _FirebaseVisionImageType type, + FirebaseVisionImageMetadata metadata, File imageFile, Uint8List bytes, }) : _imageFile = imageFile, + _metadata = metadata, _bytes = bytes, _type = type; @@ -85,17 +87,48 @@ class FirebaseVisionImage { } /// Construct a [FirebaseVisionImage] from a list of bytes. - factory FirebaseVisionImage.fromBytes(Uint8List bytes) { + factory FirebaseVisionImage.fromBytes( + Uint8List bytes, + FirebaseVisionImageMetadata metadata, + ) { assert(bytes != null); return FirebaseVisionImage._( type: _FirebaseVisionImageType.bytes, bytes: bytes, + metadata: metadata, ); } - final File _imageFile; final Uint8List _bytes; + final File _imageFile; + final FirebaseVisionImageMetadata _metadata; final _FirebaseVisionImageType _type; + + Map _serialize() => { + 'type': _enumToString(_type), + 'bytes': _bytes, + 'path': _imageFile?.path, + 'metadata': _type == _FirebaseVisionImageType.bytes + ? _metadata._serialize() + : null, + }; +} + +/// Image metadata used by [FirebaseVision] detectors. +class FirebaseVisionImageMetadata { + const FirebaseVisionImageMetadata({ + @required this.size, + @required this.orientation, + }); + + final Size size; + final DeviceOrientation orientation; + + Map _serialize() => { + 'width': size.width, + 'height': size.height, + 'orientation': _enumToString(orientation), + }; } /// Abstract class for detectors in [FirebaseVision] API. diff --git a/packages/firebase_ml_vision/lib/src/label_detector.dart b/packages/firebase_ml_vision/lib/src/label_detector.dart index f24d2eaa9734..9adaaae80b43 100644 --- a/packages/firebase_ml_vision/lib/src/label_detector.dart +++ b/packages/firebase_ml_vision/lib/src/label_detector.dart @@ -34,13 +34,10 @@ class LabelDetector extends FirebaseVisionDetector { final List reply = await FirebaseVision.channel.invokeMethod( 'LabelDetector#detectInImage', { - 'type': _enumToString(visionImage._type), - 'path': visionImage._imageFile.path, - 'bytes': visionImage._bytes, 'options': { 'confidenceThreshold': options.confidenceThreshold, }, - }, + }..addAll(visionImage._serialize()), ); final List