Skip to content

Commit 3edd01b

Browse files
azihsoynbparrishMines
authored andcommitted
Add barcode detector for ML Vision (flutter#646)
1 parent cd4829a commit 3edd01b

File tree

9 files changed

+1667
-22
lines changed

9 files changed

+1667
-22
lines changed
Lines changed: 195 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,205 @@
11
package io.flutter.plugins.firebasemlvision;
22

3+
import android.graphics.Point;
4+
import android.graphics.Rect;
5+
import android.support.annotation.NonNull;
6+
import com.google.android.gms.tasks.OnFailureListener;
7+
import com.google.android.gms.tasks.OnSuccessListener;
8+
import com.google.firebase.ml.vision.FirebaseVision;
9+
import com.google.firebase.ml.vision.barcode.FirebaseVisionBarcode;
10+
import com.google.firebase.ml.vision.barcode.FirebaseVisionBarcodeDetector;
311
import com.google.firebase.ml.vision.common.FirebaseVisionImage;
412
import io.flutter.plugin.common.MethodChannel;
13+
import java.io.IOException;
14+
import java.util.ArrayList;
15+
import java.util.HashMap;
16+
import java.util.List;
17+
import java.util.Map;
518

619
class BarcodeDetector implements Detector {
20+
public static final BarcodeDetector instance = new BarcodeDetector();
21+
private static FirebaseVisionBarcodeDetector barcodeDetector;
22+
23+
private BarcodeDetector() {}
24+
725
@Override
8-
public void handleDetection(FirebaseVisionImage image, MethodChannel.Result result) {}
26+
public void handleDetection(FirebaseVisionImage image, final MethodChannel.Result result) {
27+
if (barcodeDetector == null)
28+
barcodeDetector = FirebaseVision.getInstance().getVisionBarcodeDetector();
29+
barcodeDetector
30+
.detectInImage(image)
31+
.addOnSuccessListener(
32+
new OnSuccessListener<List<FirebaseVisionBarcode>>() {
33+
@Override
34+
public void onSuccess(List<FirebaseVisionBarcode> firebaseVisionBarcodes) {
35+
List<Map<String, Object>> barcodes = new ArrayList<>();
36+
37+
for (FirebaseVisionBarcode barcode : firebaseVisionBarcodes) {
38+
Map<String, Object> barcodeMap = new HashMap<>();
39+
40+
Rect bounds = barcode.getBoundingBox();
41+
barcodeMap.put("left", bounds.left);
42+
barcodeMap.put("top", bounds.top);
43+
barcodeMap.put("width", bounds.width());
44+
barcodeMap.put("height", bounds.height());
45+
46+
List<int[]> points = new ArrayList<>();
47+
if (barcode.getCornerPoints() != null) {
48+
for (Point point : barcode.getCornerPoints()) {
49+
points.add(new int[] {point.x, point.y});
50+
}
51+
}
52+
barcodeMap.put("points", points);
53+
54+
barcodeMap.put("raw_value", barcode.getRawValue());
55+
barcodeMap.put("display_value", barcode.getDisplayValue());
56+
barcodeMap.put("format", barcode.getFormat());
57+
barcodeMap.put("value_type", barcode.getValueType());
58+
59+
Map<String, Object> typeValue = new HashMap<>();
60+
switch (barcode.getValueType()) {
61+
case FirebaseVisionBarcode.TYPE_EMAIL:
62+
typeValue.put("type", barcode.getEmail().getType());
63+
typeValue.put("address", barcode.getEmail().getAddress());
64+
typeValue.put("body", barcode.getEmail().getBody());
65+
typeValue.put("subject", barcode.getEmail().getSubject());
66+
barcodeMap.put("email", typeValue);
67+
break;
68+
case FirebaseVisionBarcode.TYPE_PHONE:
69+
typeValue.put("number", barcode.getPhone().getNumber());
70+
typeValue.put("type", barcode.getPhone().getType());
71+
barcodeMap.put("phone", typeValue);
72+
break;
73+
case FirebaseVisionBarcode.TYPE_SMS:
74+
typeValue.put("message", barcode.getSms().getMessage());
75+
typeValue.put("phone_number", barcode.getSms().getPhoneNumber());
76+
barcodeMap.put("sms", typeValue);
77+
break;
78+
case FirebaseVisionBarcode.TYPE_URL:
79+
typeValue.put("title", barcode.getUrl().getTitle());
80+
typeValue.put("url", barcode.getUrl().getUrl());
81+
barcodeMap.put("url", typeValue);
82+
break;
83+
case FirebaseVisionBarcode.TYPE_WIFI:
84+
typeValue.put("ssid", barcode.getWifi().getSsid());
85+
typeValue.put("password", barcode.getWifi().getPassword());
86+
typeValue.put("encryption_type", barcode.getWifi().getEncryptionType());
87+
barcodeMap.put("wifi", typeValue);
88+
break;
89+
case FirebaseVisionBarcode.TYPE_GEO:
90+
typeValue.put("latitude", barcode.getGeoPoint().getLat());
91+
typeValue.put("longitude", barcode.getGeoPoint().getLng());
92+
barcodeMap.put("geo_point", typeValue);
93+
break;
94+
case FirebaseVisionBarcode.TYPE_CONTACT_INFO:
95+
List<Map<String, Object>> addresses = new ArrayList<>();
96+
for (FirebaseVisionBarcode.Address address :
97+
barcode.getContactInfo().getAddresses()) {
98+
Map<String, Object> addressMap = new HashMap();
99+
addressMap.put("address_lines", address.getAddressLines());
100+
addressMap.put("type", address.getType());
101+
addresses.add(addressMap);
102+
}
103+
typeValue.put("addresses", addresses);
104+
105+
List<Map<String, Object>> emails = new ArrayList<>();
106+
for (FirebaseVisionBarcode.Email email :
107+
barcode.getContactInfo().getEmails()) {
108+
Map<String, Object> emailMap = new HashMap();
109+
emailMap.put("address", email.getAddress());
110+
emailMap.put("type", email.getType());
111+
emailMap.put("body", email.getBody());
112+
emailMap.put("subject", email.getSubject());
113+
emails.add(emailMap);
114+
}
115+
typeValue.put("emails", emails);
116+
117+
Map<String, Object> name = new HashMap();
118+
name.put(
119+
"formatted_name", barcode.getContactInfo().getName().getFormattedName());
120+
name.put("first", barcode.getContactInfo().getName().getFirst());
121+
name.put("last", barcode.getContactInfo().getName().getLast());
122+
name.put("middle", barcode.getContactInfo().getName().getMiddle());
123+
name.put("prefix", barcode.getContactInfo().getName().getPrefix());
124+
name.put(
125+
"pronounciation", barcode.getContactInfo().getName().getPronunciation());
126+
name.put("suffix", barcode.getContactInfo().getName().getSuffix());
127+
typeValue.put("name", name);
128+
129+
List<Map<String, Object>> phones = new ArrayList<>();
130+
for (FirebaseVisionBarcode.Phone phone :
131+
barcode.getContactInfo().getPhones()) {
132+
Map<String, Object> phoneMap = new HashMap();
133+
phoneMap.put("number", phone.getNumber());
134+
phoneMap.put("type", phone.getType());
135+
phones.add(phoneMap);
136+
}
137+
typeValue.put("phones", phones);
138+
139+
typeValue.put("urls", barcode.getContactInfo().getUrls());
140+
typeValue.put("job_title", barcode.getContactInfo().getTitle());
141+
typeValue.put("organization", barcode.getContactInfo().getOrganization());
142+
143+
barcodeMap.put("contact_info", typeValue);
144+
break;
145+
case FirebaseVisionBarcode.TYPE_CALENDAR_EVENT:
146+
typeValue.put(
147+
"event_description", barcode.getCalendarEvent().getDescription());
148+
typeValue.put("location", barcode.getCalendarEvent().getLocation());
149+
typeValue.put("organizer", barcode.getCalendarEvent().getOrganizer());
150+
typeValue.put("status", barcode.getCalendarEvent().getStatus());
151+
typeValue.put("summary", barcode.getCalendarEvent().getSummary());
152+
typeValue.put("start", barcode.getCalendarEvent().getStart().getRawValue());
153+
typeValue.put("end", barcode.getCalendarEvent().getEnd().getRawValue());
154+
typeValue.put("calendar_event", typeValue);
155+
break;
156+
case FirebaseVisionBarcode.TYPE_DRIVER_LICENSE:
157+
typeValue.put("first_name", barcode.getDriverLicense().getFirstName());
158+
typeValue.put("middle_name", barcode.getDriverLicense().getMiddleName());
159+
typeValue.put("last_name", barcode.getDriverLicense().getLastName());
160+
typeValue.put("gender", barcode.getDriverLicense().getGender());
161+
typeValue.put("address_city", barcode.getDriverLicense().getAddressCity());
162+
typeValue.put(
163+
"address_street", barcode.getDriverLicense().getAddressStreet());
164+
typeValue.put("address_state", barcode.getDriverLicense().getAddressState());
165+
typeValue.put("address_zip", barcode.getDriverLicense().getAddressZip());
166+
typeValue.put("birth_date", barcode.getDriverLicense().getBirthDate());
167+
typeValue.put("document_type", barcode.getDriverLicense().getDocumentType());
168+
typeValue.put(
169+
"license_number", barcode.getDriverLicense().getLicenseNumber());
170+
typeValue.put("expiry_date", barcode.getDriverLicense().getExpiryDate());
171+
typeValue.put("issuing_date", barcode.getDriverLicense().getIssueDate());
172+
typeValue.put(
173+
"issuing_country", barcode.getDriverLicense().getIssuingCountry());
174+
barcodeMap.put("calendar_event", typeValue);
175+
break;
176+
}
177+
178+
barcodes.add(barcodeMap);
179+
}
180+
result.success(barcodes);
181+
}
182+
})
183+
.addOnFailureListener(
184+
new OnFailureListener() {
185+
@Override
186+
public void onFailure(@NonNull Exception exception) {
187+
result.error("barcodeDetectorError", exception.getLocalizedMessage(), null);
188+
}
189+
});
190+
}
9191

10192
@Override
11-
public void close(MethodChannel.Result result) {}
193+
public void close(MethodChannel.Result result) {
194+
if (barcodeDetector != null) {
195+
try {
196+
barcodeDetector.close();
197+
result.success(null);
198+
} catch (IOException exception) {
199+
result.error("barcodeDetectorError", exception.getLocalizedMessage(), null);
200+
}
201+
202+
barcodeDetector = null;
203+
}
204+
}
12205
}

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

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -27,10 +27,14 @@ public static void registerWith(Registrar registrar) {
2727

2828
@Override
2929
public void onMethodCall(MethodCall call, Result result) {
30+
FirebaseVisionImage image;
3031
switch (call.method) {
3132
case "BarcodeDetector#detectInImage":
33+
image = filePathToVisionImage((String) call.arguments, result);
34+
if (image != null) BarcodeDetector.instance.handleDetection(image, result);
3235
break;
3336
case "BarcodeDetector#close":
37+
BarcodeDetector.instance.close(result);
3438
break;
3539
case "FaceDetector#detectInImage":
3640
break;
@@ -41,7 +45,7 @@ public void onMethodCall(MethodCall call, Result result) {
4145
case "LabelDetector#close":
4246
break;
4347
case "TextDetector#detectInImage":
44-
FirebaseVisionImage image = filePathToVisionImage((String) call.arguments, result);
48+
image = filePathToVisionImage((String) call.arguments, result);
4549
if (image != null) TextDetector.instance.handleDetection(image, result);
4650
break;
4751
case "TextDetector#close":

packages/firebase_ml_vision/example/lib/detector_painters.dart

Lines changed: 25 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -8,20 +8,39 @@ import 'package:flutter/material.dart';
88
enum Detector { barcode, face, label, text }
99

1010
class BarcodeDetectorPainter extends CustomPainter {
11-
BarcodeDetectorPainter(this.absoluteImageSize, this.results);
11+
BarcodeDetectorPainter(this.absoluteImageSize, this.barcodeLocations);
1212

1313
final Size absoluteImageSize;
14-
final List<dynamic> results;
14+
final List<Barcode> barcodeLocations;
1515

1616
@override
1717
void paint(Canvas canvas, Size size) {
18-
// TODO: implement paint
18+
final double scaleX = size.width / absoluteImageSize.width;
19+
final double scaleY = size.height / absoluteImageSize.height;
20+
21+
Rect scaleRect(Barcode barcode) {
22+
return new Rect.fromLTRB(
23+
barcode.boundingBox.left * scaleX,
24+
barcode.boundingBox.top * scaleY,
25+
barcode.boundingBox.right * scaleX,
26+
barcode.boundingBox.bottom * scaleY,
27+
);
28+
}
29+
30+
final Paint paint = new Paint()
31+
..style = PaintingStyle.stroke
32+
..strokeWidth = 2.0;
33+
34+
for (Barcode barcode in barcodeLocations) {
35+
paint.color = Colors.green;
36+
canvas.drawRect(scaleRect(barcode), paint);
37+
}
1938
}
2039

2140
@override
22-
bool shouldRepaint(CustomPainter oldDelegate) {
23-
// TODO: implement shouldRepaint
24-
return false;
41+
bool shouldRepaint(BarcodeDetectorPainter oldDelegate) {
42+
return oldDelegate.absoluteImageSize != absoluteImageSize ||
43+
oldDelegate.barcodeLocations != barcodeLocations;
2544
}
2645
}
2746

packages/firebase_ml_vision/example/lib/main.dart

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,10 +5,10 @@
55
import 'dart:async';
66
import 'dart:io';
77

8+
import 'package:firebase_ml_vision/firebase_ml_vision.dart';
89
import 'package:firebase_ml_vision_example/detector_painters.dart';
910
import 'package:flutter/material.dart';
1011
import 'package:image_picker/image_picker.dart';
11-
import 'package:firebase_ml_vision/firebase_ml_vision.dart';
1212

1313
void main() => runApp(new MaterialApp(home: _MyHomePage()));
1414

@@ -72,7 +72,7 @@ class _MyHomePageState extends State<_MyHomePage> {
7272
FirebaseVisionDetector detector;
7373
switch (_currentDetector) {
7474
case Detector.barcode:
75-
detector = FirebaseVision.instance.barcodeDetector(null);
75+
detector = FirebaseVision.instance.barcodeDetector();
7676
break;
7777
case Detector.face:
7878
detector = FirebaseVision.instance.faceDetector(null);

0 commit comments

Comments
 (0)