blob: 14e51daf935605eb8818b0c0a416270b6266ee81 [file] [log] [blame]
// Copyright 2018 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
import 'dart:async';
import 'dart:io';
import 'package:firebase_ml_vision/firebase_ml_vision.dart';
import 'package:flutter/material.dart';
import 'package:image_picker/image_picker.dart';
import 'detector_painters.dart';
void main() => runApp(new MaterialApp(home: _MyHomePage()));
class _MyHomePage extends StatefulWidget {
@override
_MyHomePageState createState() => new _MyHomePageState();
}
class _MyHomePageState extends State<_MyHomePage> {
File _imageFile;
Size _imageSize;
List<dynamic> _scanResults;
Detector _currentDetector = Detector.text;
Future<void> _getAndScanImage() async {
setState(() {
_imageFile = null;
_imageSize = null;
});
final File imageFile =
await ImagePicker.pickImage(source: ImageSource.gallery);
if (imageFile != null) {
_getImageSize(imageFile);
_scanImage(imageFile);
}
setState(() {
_imageFile = imageFile;
});
}
Future<void> _getImageSize(File imageFile) async {
final Completer<Size> completer = new Completer<Size>();
final Image image = new Image.file(imageFile);
image.image.resolve(const ImageConfiguration()).addListener(
(ImageInfo info, bool _) {
completer.complete(Size(
info.image.width.toDouble(),
info.image.height.toDouble(),
));
},
);
final Size imageSize = await completer.future;
setState(() {
_imageSize = imageSize;
});
}
Future<void> _scanImage(File imageFile) async {
setState(() {
_scanResults = null;
});
final FirebaseVisionImage visionImage =
FirebaseVisionImage.fromFile(imageFile);
FirebaseVisionDetector detector;
switch (_currentDetector) {
case Detector.barcode:
detector = FirebaseVision.instance.barcodeDetector();
break;
case Detector.face:
detector = FirebaseVision.instance.faceDetector();
break;
case Detector.label:
detector = FirebaseVision.instance.labelDetector();
break;
case Detector.text:
detector = FirebaseVision.instance.textDetector();
break;
default:
return;
}
final List<dynamic> results =
await detector.detectInImage(visionImage) ?? <dynamic>[];
setState(() {
_scanResults = results;
});
}
CustomPaint _buildResults(Size imageSize, List<dynamic> results) {
CustomPainter painter;
switch (_currentDetector) {
case Detector.barcode:
painter = new BarcodeDetectorPainter(_imageSize, results);
break;
case Detector.face:
painter = new FaceDetectorPainter(_imageSize, results);
break;
case Detector.label:
painter = new LabelDetectorPainter(_imageSize, results);
break;
case Detector.text:
painter = new TextDetectorPainter(_imageSize, results);
break;
default:
break;
}
return new CustomPaint(
painter: painter,
);
}
Widget _buildImage() {
return new Container(
constraints: const BoxConstraints.expand(),
decoration: new BoxDecoration(
image: new DecorationImage(
image: Image.file(_imageFile).image,
fit: BoxFit.fill,
),
),
child: _imageSize == null || _scanResults == null
? const Center(
child: Text(
'Scanning...',
style: TextStyle(
color: Colors.green,
fontSize: 30.0,
),
),
)
: _buildResults(_imageSize, _scanResults),
);
}
@override
Widget build(BuildContext context) {
return new Scaffold(
appBar: new AppBar(
title: const Text('ML Vision Example'),
actions: <Widget>[
new PopupMenuButton<Detector>(
onSelected: (Detector result) {
_currentDetector = result;
if (_imageFile != null) _scanImage(_imageFile);
},
itemBuilder: (BuildContext context) => <PopupMenuEntry<Detector>>[
const PopupMenuItem<Detector>(
child: Text('Detect Barcode'),
value: Detector.barcode,
),
const PopupMenuItem<Detector>(
child: Text('Detect Face'),
value: Detector.face,
),
const PopupMenuItem<Detector>(
child: Text('Detect Label'),
value: Detector.label,
),
const PopupMenuItem<Detector>(
child: Text('Detect Text'),
value: Detector.text,
),
],
),
],
),
body: _imageFile == null
? const Center(child: Text('No image selected.'))
: _buildImage(),
floatingActionButton: new FloatingActionButton(
onPressed: _getAndScanImage,
tooltip: 'Pick Image',
child: const Icon(Icons.add_a_photo),
),
);
}
}