Skip to content

Commit 1949fe4

Browse files
committed
updating code to latest version in flutter/plugins
1 parent 801a7fd commit 1949fe4

31 files changed

+1262
-847
lines changed

android/src/main/java/io/flutter/plugins/firebasemlvision/BarcodeDetector.java

Lines changed: 17 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -13,40 +13,20 @@
1313
import io.flutter.plugin.common.MethodChannel;
1414
import java.io.IOException;
1515
import java.util.ArrayList;
16+
import java.util.Arrays;
1617
import java.util.HashMap;
1718
import java.util.List;
1819
import java.util.Map;
1920

2021
class BarcodeDetector implements Detector {
21-
static final BarcodeDetector instance = new BarcodeDetector();
22+
private final FirebaseVisionBarcodeDetector detector;
2223

23-
private BarcodeDetector() {}
24-
25-
private FirebaseVisionBarcodeDetector detector;
26-
private Map<String, Object> lastOptions;
24+
BarcodeDetector(FirebaseVision vision, Map<String, Object> options) {
25+
detector = vision.getVisionBarcodeDetector(parseOptions(options));
26+
}
2727

2828
@Override
29-
public void handleDetection(
30-
FirebaseVisionImage image, Map<String, Object> options, final MethodChannel.Result result) {
31-
32-
// Use instantiated detector if the options are the same. Otherwise, close and instantiate new
33-
// options.
34-
35-
if (detector == null) {
36-
lastOptions = options;
37-
detector = FirebaseVision.getInstance().getVisionBarcodeDetector(parseOptions(lastOptions));
38-
} else if (!options.equals(lastOptions)) {
39-
try {
40-
detector.close();
41-
} catch (IOException e) {
42-
result.error("barcodeDetectorIOError", e.getLocalizedMessage(), null);
43-
return;
44-
}
45-
46-
lastOptions = options;
47-
detector = FirebaseVision.getInstance().getVisionBarcodeDetector(parseOptions(lastOptions));
48-
}
49-
29+
public void handleDetection(final FirebaseVisionImage image, final MethodChannel.Result result) {
5030
detector
5131
.detectInImage(image)
5232
.addOnSuccessListener(
@@ -138,7 +118,9 @@ public void onSuccess(List<FirebaseVisionBarcode> firebaseVisionBarcodes) {
138118
List<Map<String, Object>> addresses = new ArrayList<>();
139119
for (FirebaseVisionBarcode.Address address : contactInfo.getAddresses()) {
140120
Map<String, Object> addressMap = new HashMap<>();
141-
addressMap.put("addressLines", address.getAddressLines());
121+
if (address.getAddressLines() != null) {
122+
addressMap.put("addressLines", Arrays.asList(address.getAddressLines()));
123+
}
142124
addressMap.put("type", address.getType());
143125

144126
addresses.add(addressMap);
@@ -180,7 +162,9 @@ public void onSuccess(List<FirebaseVisionBarcode> firebaseVisionBarcodes) {
180162
}
181163
typeValue.put("phones", phones);
182164

183-
typeValue.put("urls", contactInfo.getUrls());
165+
if (contactInfo.getUrls() != null) {
166+
typeValue.put("urls", Arrays.asList(contactInfo.getUrls()));
167+
}
184168
typeValue.put("jobTitle", contactInfo.getTitle());
185169
typeValue.put("organization", contactInfo.getOrganization());
186170

@@ -242,10 +226,14 @@ public void onFailure(@NonNull Exception exception) {
242226
}
243227

244228
private FirebaseVisionBarcodeDetectorOptions parseOptions(Map<String, Object> optionsData) {
245-
@SuppressWarnings("unchecked")
246229
Integer barcodeFormats = (Integer) optionsData.get("barcodeFormats");
247230
return new FirebaseVisionBarcodeDetectorOptions.Builder()
248231
.setBarcodeFormats(barcodeFormats)
249232
.build();
250233
}
234+
235+
@Override
236+
public void close() throws IOException {
237+
detector.close();
238+
}
251239
}

android/src/main/java/io/flutter/plugins/firebasemlvision/FaceDetector.java

Lines changed: 64 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,9 @@
55
import com.google.android.gms.tasks.OnSuccessListener;
66
import com.google.firebase.ml.vision.FirebaseVision;
77
import com.google.firebase.ml.vision.common.FirebaseVisionImage;
8+
import com.google.firebase.ml.vision.common.FirebaseVisionPoint;
89
import com.google.firebase.ml.vision.face.FirebaseVisionFace;
10+
import com.google.firebase.ml.vision.face.FirebaseVisionFaceContour;
911
import com.google.firebase.ml.vision.face.FirebaseVisionFaceDetector;
1012
import com.google.firebase.ml.vision.face.FirebaseVisionFaceDetectorOptions;
1113
import com.google.firebase.ml.vision.face.FirebaseVisionFaceLandmark;
@@ -17,35 +19,14 @@
1719
import java.util.Map;
1820

1921
class FaceDetector implements Detector {
20-
static final FaceDetector instance = new FaceDetector();
22+
private final FirebaseVisionFaceDetector detector;
2123

22-
private FaceDetector() {}
23-
24-
private FirebaseVisionFaceDetector detector;
25-
private Map<String, Object> lastOptions;
24+
FaceDetector(FirebaseVision vision, Map<String, Object> options) {
25+
detector = vision.getVisionFaceDetector(parseOptions(options));
26+
}
2627

2728
@Override
28-
public void handleDetection(
29-
FirebaseVisionImage image, Map<String, Object> options, final MethodChannel.Result result) {
30-
31-
// Use instantiated detector if the options are the same. Otherwise, close and instantiate new
32-
// options.
33-
34-
if (detector == null) {
35-
lastOptions = options;
36-
detector = FirebaseVision.getInstance().getVisionFaceDetector(parseOptions(lastOptions));
37-
} else if (!options.equals(lastOptions)) {
38-
try {
39-
detector.close();
40-
} catch (IOException e) {
41-
result.error("faceDetectorIOError", e.getLocalizedMessage(), null);
42-
return;
43-
}
44-
45-
lastOptions = options;
46-
detector = FirebaseVision.getInstance().getVisionFaceDetector(parseOptions(lastOptions));
47-
}
48-
29+
public void handleDetection(final FirebaseVisionImage image, final MethodChannel.Result result) {
4930
detector
5031
.detectInImage(image)
5132
.addOnSuccessListener(
@@ -84,6 +65,8 @@ public void onSuccess(List<FirebaseVisionFace> firebaseVisionFaces) {
8465

8566
faceData.put("landmarks", getLandmarkData(face));
8667

68+
faceData.put("contours", getContourData(face));
69+
8770
faces.add(faceData);
8871
}
8972

@@ -116,6 +99,34 @@ private Map<String, double[]> getLandmarkData(FirebaseVisionFace face) {
11699
return landmarks;
117100
}
118101

102+
private Map<String, List<double[]>> getContourData(FirebaseVisionFace face) {
103+
Map<String, List<double[]>> contours = new HashMap<>();
104+
105+
contours.put("allPoints", contourPosition(face, FirebaseVisionFaceContour.ALL_POINTS));
106+
contours.put("face", contourPosition(face, FirebaseVisionFaceContour.FACE));
107+
contours.put("leftEye", contourPosition(face, FirebaseVisionFaceContour.LEFT_EYE));
108+
contours.put(
109+
"leftEyebrowBottom", contourPosition(face, FirebaseVisionFaceContour.LEFT_EYEBROW_BOTTOM));
110+
contours.put(
111+
"leftEyebrowTop", contourPosition(face, FirebaseVisionFaceContour.LEFT_EYEBROW_TOP));
112+
contours.put(
113+
"lowerLipBottom", contourPosition(face, FirebaseVisionFaceContour.LOWER_LIP_BOTTOM));
114+
contours.put("lowerLipTop", contourPosition(face, FirebaseVisionFaceContour.LOWER_LIP_TOP));
115+
contours.put("noseBottom", contourPosition(face, FirebaseVisionFaceContour.NOSE_BOTTOM));
116+
contours.put("noseBridge", contourPosition(face, FirebaseVisionFaceContour.NOSE_BRIDGE));
117+
contours.put("rightEye", contourPosition(face, FirebaseVisionFaceContour.RIGHT_EYE));
118+
contours.put(
119+
"rightEyebrowBottom",
120+
contourPosition(face, FirebaseVisionFaceContour.RIGHT_EYEBROW_BOTTOM));
121+
contours.put(
122+
"rightEyebrowTop", contourPosition(face, FirebaseVisionFaceContour.RIGHT_EYEBROW_TOP));
123+
contours.put(
124+
"upperLipBottom", contourPosition(face, FirebaseVisionFaceContour.UPPER_LIP_BOTTOM));
125+
contours.put("upperLipTop", contourPosition(face, FirebaseVisionFaceContour.UPPER_LIP_TOP));
126+
127+
return contours;
128+
}
129+
119130
private double[] landmarkPosition(FirebaseVisionFace face, int landmarkInt) {
120131
FirebaseVisionFaceLandmark landmark = face.getLandmark(landmarkInt);
121132
if (landmark != null) {
@@ -125,6 +136,22 @@ private double[] landmarkPosition(FirebaseVisionFace face, int landmarkInt) {
125136
return null;
126137
}
127138

139+
private List<double[]> contourPosition(FirebaseVisionFace face, int contourInt) {
140+
FirebaseVisionFaceContour contour = face.getContour(contourInt);
141+
if (contour != null) {
142+
List<FirebaseVisionPoint> contourPoints = contour.getPoints();
143+
List<double[]> result = new ArrayList<double[]>();
144+
145+
for (int i = 0; i < contourPoints.size(); i++) {
146+
result.add(new double[] {contourPoints.get(i).getX(), contourPoints.get(i).getY()});
147+
}
148+
149+
return result;
150+
}
151+
152+
return null;
153+
}
154+
128155
private FirebaseVisionFaceDetectorOptions parseOptions(Map<String, Object> options) {
129156
int classification =
130157
(boolean) options.get("enableClassification")
@@ -136,6 +163,11 @@ private FirebaseVisionFaceDetectorOptions parseOptions(Map<String, Object> optio
136163
? FirebaseVisionFaceDetectorOptions.ALL_LANDMARKS
137164
: FirebaseVisionFaceDetectorOptions.NO_LANDMARKS;
138165

166+
int contours =
167+
(boolean) options.get("enableContours")
168+
? FirebaseVisionFaceDetectorOptions.ALL_CONTOURS
169+
: FirebaseVisionFaceDetectorOptions.NO_CONTOURS;
170+
139171
int mode;
140172
switch ((String) options.get("mode")) {
141173
case "accurate":
@@ -152,6 +184,7 @@ private FirebaseVisionFaceDetectorOptions parseOptions(Map<String, Object> optio
152184
new FirebaseVisionFaceDetectorOptions.Builder()
153185
.setClassificationMode(classification)
154186
.setLandmarkMode(landmark)
187+
.setContourMode(contours)
155188
.setMinFaceSize((float) ((double) options.get("minFaceSize")))
156189
.setPerformanceMode(mode);
157190

@@ -161,4 +194,9 @@ private FirebaseVisionFaceDetectorOptions parseOptions(Map<String, Object> optio
161194

162195
return builder.build();
163196
}
197+
198+
@Override
199+
public void close() throws IOException {
200+
detector.close();
201+
}
164202
}

android/src/main/java/io/flutter/plugins/firebasemlvision/FirebaseMlVisionPlugin.java

Lines changed: 95 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,9 @@
44
import android.graphics.BitmapFactory;
55
import android.graphics.Matrix;
66
import android.net.Uri;
7+
import android.util.SparseArray;
78
import androidx.exifinterface.media.ExifInterface;
9+
import com.google.firebase.ml.vision.FirebaseVision;
810
import com.google.firebase.ml.vision.common.FirebaseVisionImage;
911
import com.google.firebase.ml.vision.common.FirebaseVisionImageMetadata;
1012
import io.flutter.plugin.common.MethodCall;
@@ -18,6 +20,8 @@
1820

1921
/** FirebaseMlVisionPlugin */
2022
public class FirebaseMlVisionPlugin implements MethodCallHandler {
23+
private final SparseArray<Detector> detectors = new SparseArray<>();
24+
2125
private Registrar registrar;
2226

2327
private FirebaseMlVisionPlugin(Registrar registrar) {
@@ -33,47 +37,97 @@ public static void registerWith(Registrar registrar) {
3337

3438
@Override
3539
public void onMethodCall(MethodCall call, Result result) {
36-
Map<String, Object> options = call.argument("options");
3740
String modelName = call.argument("model");
38-
FirebaseVisionImage image;
39-
Map<String, Object> imageData = call.arguments();
40-
try {
41-
image = dataToVisionImage(imageData);
42-
} catch (IOException exception) {
43-
result.error("MLVisionDetectorIOError", exception.getLocalizedMessage(), null);
44-
return;
45-
}
46-
4741
switch (call.method) {
48-
case "BarcodeDetector#detectInImage":
49-
BarcodeDetector.instance.handleDetection(image, options, result);
42+
case "ModelManager#setupLocalModel":
43+
SetupLocalModel.instance.setup(modelName, result);
5044
break;
51-
case "FaceDetector#processImage":
52-
FaceDetector.instance.handleDetection(image, options, result);
45+
case "ModelManager#setupRemoteModel":
46+
SetupRemoteModel.instance.setup(modelName, result);
5347
break;
48+
case "BarcodeDetector#detectInImage":
49+
case "FaceDetector#processImage":
5450
case "ImageLabeler#processImage":
55-
ImageLabeler.instance.handleDetection(image, options, result);
56-
break;
5751
case "TextRecognizer#processImage":
58-
TextRecognizer.instance.handleDetection(image, options, result);
59-
break;
60-
case "VisionEdgeImageLabeler#processLocalImage":
61-
LocalVisionEdgeDetector.instance.handleDetection(image, options, result);
62-
break;
52+
case "VisionEdgeImageLabeler#processLocalImage":
6353
case "VisionEdgeImageLabeler#processRemoteImage":
64-
RemoteVisionEdgeDetector.instance.handleDetection(image, options, result);
54+
handleDetection(call, result);
6555
break;
66-
case "ModelManager#setupLocalModel":
67-
SetupLocalModel.instance.setup(modelName, result);
68-
break;
69-
case "ModelManager#setupRemoteModel":
70-
SetupRemoteModel.instance.setup(modelName, result);
56+
case "BarcodeDetector#close":
57+
case "FaceDetector#close":
58+
case "ImageLabeler#close":
59+
case "TextRecognizer#close":
60+
case "VisionEdgeImageLabeler#close":
61+
closeDetector(call, result);
7162
break;
7263
default:
7364
result.notImplemented();
7465
}
7566
}
7667

68+
private void handleDetection(MethodCall call, Result result) {
69+
Map<String, Object> options = call.argument("options");
70+
71+
FirebaseVisionImage image;
72+
Map<String, Object> imageData = call.arguments();
73+
try {
74+
image = dataToVisionImage(imageData);
75+
} catch (IOException exception) {
76+
result.error("MLVisionDetectorIOError", exception.getLocalizedMessage(), null);
77+
return;
78+
}
79+
80+
Detector detector = getDetector(call);
81+
if (detector == null) {
82+
switch (call.method) {
83+
case "BarcodeDetector#detectInImage":
84+
detector = new BarcodeDetector(FirebaseVision.getInstance(), options);
85+
break;
86+
case "FaceDetector#processImage":
87+
detector = new FaceDetector(FirebaseVision.getInstance(), options);
88+
break;
89+
case "ImageLabeler#processImage":
90+
detector = new ImageLabeler(FirebaseVision.getInstance(), options);
91+
break;
92+
case "TextRecognizer#processImage":
93+
detector = new TextRecognizer(FirebaseVision.getInstance(), options);
94+
break;
95+
case "VisionEdgeImageLabeler#processLocalImage":
96+
detector = new LocalVisionEdgeDetector(FirebaseVision.getInstance(), options);
97+
break;
98+
case "VisionEdgeImageLabeler#processRemoteImage":
99+
detector = new RemoteVisionEdgeDetector(FirebaseVision.getInstance(), options);
100+
break;
101+
}
102+
103+
final Integer handle = call.argument("handle");
104+
addDetector(handle, detector);
105+
}
106+
107+
detector.handleDetection(image, result);
108+
}
109+
110+
private void closeDetector(final MethodCall call, final Result result) {
111+
final Detector detector = getDetector(call);
112+
113+
if (detector == null) {
114+
final Integer handle = call.argument("handle");
115+
final String message = String.format("Object for handle does not exists: %s", handle);
116+
throw new IllegalArgumentException(message);
117+
}
118+
119+
try {
120+
detector.close();
121+
result.success(null);
122+
} catch (IOException e) {
123+
final String code = String.format("%sIOError", detector.getClass().getSimpleName());
124+
result.error(code, e.getLocalizedMessage(), null);
125+
} finally {
126+
final Integer handle = call.argument("handle");
127+
detectors.remove(handle);
128+
}
129+
}
130+
77131
private FirebaseVisionImage dataToVisionImage(Map<String, Object> imageData) throws IOException {
78132
String imageType = (String) imageData.get("type");
79133
assert imageType != null;
@@ -148,4 +202,18 @@ private int getRotation(int rotation) {
148202
throw new IllegalArgumentException(String.format("No rotation for: %d", rotation));
149203
}
150204
}
205+
206+
private void addDetector(final int handle, final Detector detector) {
207+
if (detectors.get(handle) != null) {
208+
final String message = String.format("Object for handle already exists: %s", handle);
209+
throw new IllegalArgumentException(message);
210+
}
211+
212+
detectors.put(handle, detector);
213+
}
214+
215+
private Detector getDetector(final MethodCall call) {
216+
final Integer handle = call.argument("handle");
217+
return detectors.get(handle);
218+
}
151219
}

0 commit comments

Comments
 (0)