Skip to content

Commit

Permalink
Add barcode detector for ML Vision (flutter#646)
Browse files Browse the repository at this point in the history
  • Loading branch information
azihsoyn authored and bparrishMines committed Jul 13, 2018
1 parent 5c96c41 commit 72ab756
Show file tree
Hide file tree
Showing 9 changed files with 1,667 additions and 22 deletions.
Original file line number Diff line number Diff line change
@@ -1,12 +1,205 @@
package io.flutter.plugins.firebasemlvision;

import android.graphics.Point;
import android.graphics.Rect;
import android.support.annotation.NonNull;
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.barcode.FirebaseVisionBarcode;
import com.google.firebase.ml.vision.barcode.FirebaseVisionBarcodeDetector;
import com.google.firebase.ml.vision.common.FirebaseVisionImage;
import io.flutter.plugin.common.MethodChannel;
import java.io.IOException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

class BarcodeDetector implements Detector {
public static final BarcodeDetector instance = new BarcodeDetector();
private static FirebaseVisionBarcodeDetector barcodeDetector;

private BarcodeDetector() {}

@Override
public void handleDetection(FirebaseVisionImage image, MethodChannel.Result result) {}
public void handleDetection(FirebaseVisionImage image, final MethodChannel.Result result) {
if (barcodeDetector == null)
barcodeDetector = FirebaseVision.getInstance().getVisionBarcodeDetector();
barcodeDetector
.detectInImage(image)
.addOnSuccessListener(
new OnSuccessListener<List<FirebaseVisionBarcode>>() {
@Override
public void onSuccess(List<FirebaseVisionBarcode> firebaseVisionBarcodes) {
List<Map<String, Object>> barcodes = new ArrayList<>();

for (FirebaseVisionBarcode barcode : firebaseVisionBarcodes) {
Map<String, Object> barcodeMap = new HashMap<>();

Rect bounds = barcode.getBoundingBox();
barcodeMap.put("left", bounds.left);
barcodeMap.put("top", bounds.top);
barcodeMap.put("width", bounds.width());
barcodeMap.put("height", bounds.height());

List<int[]> points = new ArrayList<>();
if (barcode.getCornerPoints() != null) {
for (Point point : barcode.getCornerPoints()) {
points.add(new int[] {point.x, point.y});
}
}
barcodeMap.put("points", points);

barcodeMap.put("raw_value", barcode.getRawValue());
barcodeMap.put("display_value", barcode.getDisplayValue());
barcodeMap.put("format", barcode.getFormat());
barcodeMap.put("value_type", barcode.getValueType());

Map<String, Object> typeValue = new HashMap<>();
switch (barcode.getValueType()) {
case FirebaseVisionBarcode.TYPE_EMAIL:
typeValue.put("type", barcode.getEmail().getType());
typeValue.put("address", barcode.getEmail().getAddress());
typeValue.put("body", barcode.getEmail().getBody());
typeValue.put("subject", barcode.getEmail().getSubject());
barcodeMap.put("email", typeValue);
break;
case FirebaseVisionBarcode.TYPE_PHONE:
typeValue.put("number", barcode.getPhone().getNumber());
typeValue.put("type", barcode.getPhone().getType());
barcodeMap.put("phone", typeValue);
break;
case FirebaseVisionBarcode.TYPE_SMS:
typeValue.put("message", barcode.getSms().getMessage());
typeValue.put("phone_number", barcode.getSms().getPhoneNumber());
barcodeMap.put("sms", typeValue);
break;
case FirebaseVisionBarcode.TYPE_URL:
typeValue.put("title", barcode.getUrl().getTitle());
typeValue.put("url", barcode.getUrl().getUrl());
barcodeMap.put("url", typeValue);
break;
case FirebaseVisionBarcode.TYPE_WIFI:
typeValue.put("ssid", barcode.getWifi().getSsid());
typeValue.put("password", barcode.getWifi().getPassword());
typeValue.put("encryption_type", barcode.getWifi().getEncryptionType());
barcodeMap.put("wifi", typeValue);
break;
case FirebaseVisionBarcode.TYPE_GEO:
typeValue.put("latitude", barcode.getGeoPoint().getLat());
typeValue.put("longitude", barcode.getGeoPoint().getLng());
barcodeMap.put("geo_point", typeValue);
break;
case FirebaseVisionBarcode.TYPE_CONTACT_INFO:
List<Map<String, Object>> addresses = new ArrayList<>();
for (FirebaseVisionBarcode.Address address :
barcode.getContactInfo().getAddresses()) {
Map<String, Object> addressMap = new HashMap();
addressMap.put("address_lines", address.getAddressLines());
addressMap.put("type", address.getType());
addresses.add(addressMap);
}
typeValue.put("addresses", addresses);

List<Map<String, Object>> emails = new ArrayList<>();
for (FirebaseVisionBarcode.Email email :
barcode.getContactInfo().getEmails()) {
Map<String, Object> emailMap = new HashMap();
emailMap.put("address", email.getAddress());
emailMap.put("type", email.getType());
emailMap.put("body", email.getBody());
emailMap.put("subject", email.getSubject());
emails.add(emailMap);
}
typeValue.put("emails", emails);

Map<String, Object> name = new HashMap();
name.put(
"formatted_name", barcode.getContactInfo().getName().getFormattedName());
name.put("first", barcode.getContactInfo().getName().getFirst());
name.put("last", barcode.getContactInfo().getName().getLast());
name.put("middle", barcode.getContactInfo().getName().getMiddle());
name.put("prefix", barcode.getContactInfo().getName().getPrefix());
name.put(
"pronounciation", barcode.getContactInfo().getName().getPronunciation());
name.put("suffix", barcode.getContactInfo().getName().getSuffix());
typeValue.put("name", name);

List<Map<String, Object>> phones = new ArrayList<>();
for (FirebaseVisionBarcode.Phone phone :
barcode.getContactInfo().getPhones()) {
Map<String, Object> phoneMap = new HashMap();
phoneMap.put("number", phone.getNumber());
phoneMap.put("type", phone.getType());
phones.add(phoneMap);
}
typeValue.put("phones", phones);

typeValue.put("urls", barcode.getContactInfo().getUrls());
typeValue.put("job_title", barcode.getContactInfo().getTitle());
typeValue.put("organization", barcode.getContactInfo().getOrganization());

barcodeMap.put("contact_info", typeValue);
break;
case FirebaseVisionBarcode.TYPE_CALENDAR_EVENT:
typeValue.put(
"event_description", barcode.getCalendarEvent().getDescription());
typeValue.put("location", barcode.getCalendarEvent().getLocation());
typeValue.put("organizer", barcode.getCalendarEvent().getOrganizer());
typeValue.put("status", barcode.getCalendarEvent().getStatus());
typeValue.put("summary", barcode.getCalendarEvent().getSummary());
typeValue.put("start", barcode.getCalendarEvent().getStart().getRawValue());
typeValue.put("end", barcode.getCalendarEvent().getEnd().getRawValue());
typeValue.put("calendar_event", typeValue);
break;
case FirebaseVisionBarcode.TYPE_DRIVER_LICENSE:
typeValue.put("first_name", barcode.getDriverLicense().getFirstName());
typeValue.put("middle_name", barcode.getDriverLicense().getMiddleName());
typeValue.put("last_name", barcode.getDriverLicense().getLastName());
typeValue.put("gender", barcode.getDriverLicense().getGender());
typeValue.put("address_city", barcode.getDriverLicense().getAddressCity());
typeValue.put(
"address_street", barcode.getDriverLicense().getAddressStreet());
typeValue.put("address_state", barcode.getDriverLicense().getAddressState());
typeValue.put("address_zip", barcode.getDriverLicense().getAddressZip());
typeValue.put("birth_date", barcode.getDriverLicense().getBirthDate());
typeValue.put("document_type", barcode.getDriverLicense().getDocumentType());
typeValue.put(
"license_number", barcode.getDriverLicense().getLicenseNumber());
typeValue.put("expiry_date", barcode.getDriverLicense().getExpiryDate());
typeValue.put("issuing_date", barcode.getDriverLicense().getIssueDate());
typeValue.put(
"issuing_country", barcode.getDriverLicense().getIssuingCountry());
barcodeMap.put("calendar_event", typeValue);
break;
}

barcodes.add(barcodeMap);
}
result.success(barcodes);
}
})
.addOnFailureListener(
new OnFailureListener() {
@Override
public void onFailure(@NonNull Exception exception) {
result.error("barcodeDetectorError", exception.getLocalizedMessage(), null);
}
});
}

@Override
public void close(MethodChannel.Result result) {}
public void close(MethodChannel.Result result) {
if (barcodeDetector != null) {
try {
barcodeDetector.close();
result.success(null);
} catch (IOException exception) {
result.error("barcodeDetectorError", exception.getLocalizedMessage(), null);
}

barcodeDetector = null;
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -27,10 +27,14 @@ public static void registerWith(Registrar registrar) {

@Override
public void onMethodCall(MethodCall call, Result result) {
FirebaseVisionImage image;
switch (call.method) {
case "BarcodeDetector#detectInImage":
image = filePathToVisionImage((String) call.arguments, result);
if (image != null) BarcodeDetector.instance.handleDetection(image, result);
break;
case "BarcodeDetector#close":
BarcodeDetector.instance.close(result);
break;
case "FaceDetector#detectInImage":
break;
Expand All @@ -41,7 +45,7 @@ public void onMethodCall(MethodCall call, Result result) {
case "LabelDetector#close":
break;
case "TextDetector#detectInImage":
FirebaseVisionImage image = filePathToVisionImage((String) call.arguments, result);
image = filePathToVisionImage((String) call.arguments, result);
if (image != null) TextDetector.instance.handleDetection(image, result);
break;
case "TextDetector#close":
Expand Down
31 changes: 25 additions & 6 deletions packages/firebase_ml_vision/example/lib/detector_painters.dart
Original file line number Diff line number Diff line change
Expand Up @@ -8,20 +8,39 @@ import 'package:flutter/material.dart';
enum Detector { barcode, face, label, text }

class BarcodeDetectorPainter extends CustomPainter {
BarcodeDetectorPainter(this.absoluteImageSize, this.results);
BarcodeDetectorPainter(this.absoluteImageSize, this.barcodeLocations);

final Size absoluteImageSize;
final List<dynamic> results;
final List<Barcode> barcodeLocations;

@override
void paint(Canvas canvas, Size size) {
// TODO: implement paint
final double scaleX = size.width / absoluteImageSize.width;
final double scaleY = size.height / absoluteImageSize.height;

Rect scaleRect(Barcode barcode) {
return new Rect.fromLTRB(
barcode.boundingBox.left * scaleX,
barcode.boundingBox.top * scaleY,
barcode.boundingBox.right * scaleX,
barcode.boundingBox.bottom * scaleY,
);
}

final Paint paint = new Paint()
..style = PaintingStyle.stroke
..strokeWidth = 2.0;

for (Barcode barcode in barcodeLocations) {
paint.color = Colors.green;
canvas.drawRect(scaleRect(barcode), paint);
}
}

@override
bool shouldRepaint(CustomPainter oldDelegate) {
// TODO: implement shouldRepaint
return false;
bool shouldRepaint(BarcodeDetectorPainter oldDelegate) {
return oldDelegate.absoluteImageSize != absoluteImageSize ||
oldDelegate.barcodeLocations != barcodeLocations;
}
}

Expand Down
4 changes: 2 additions & 2 deletions packages/firebase_ml_vision/example/lib/main.dart
Original file line number Diff line number Diff line change
Expand Up @@ -5,10 +5,10 @@
import 'dart:async';
import 'dart:io';

import 'package:firebase_ml_vision/firebase_ml_vision.dart';
import 'package:firebase_ml_vision_example/detector_painters.dart';
import 'package:flutter/material.dart';
import 'package:image_picker/image_picker.dart';
import 'package:firebase_ml_vision/firebase_ml_vision.dart';

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

Expand Down Expand Up @@ -72,7 +72,7 @@ class _MyHomePageState extends State<_MyHomePage> {
FirebaseVisionDetector detector;
switch (_currentDetector) {
case Detector.barcode:
detector = FirebaseVision.instance.barcodeDetector(null);
detector = FirebaseVision.instance.barcodeDetector();
break;
case Detector.face:
detector = FirebaseVision.instance.faceDetector(null);
Expand Down
Loading

0 comments on commit 72ab756

Please sign in to comment.