Flutterでカメラ撮影から矩形選択からOCRのAndroid、iPhone動作確認
Flutter で、カメラ撮影から、画像の切り抜き し、Cloud Vision API で OCR の結果を表示する。
/lib/main.dart
import 'dart:io';
import 'package:firebase_ml_vision/firebase_ml_vision.dart';
import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';
import 'package:cloud_firestore/cloud_firestore.dart';
import 'package:image_picker/image_picker.dart';
import 'package:image_cropper/image_cropper.dart';
void main() => runApp(MyApp());
class MyApp extends StatelessWidget {
final message = "Initial Message.";
@override
Widget build(BuildContext context) {
return new MaterialApp(
title: 'Flutter Sample',
home: MyPage(message:this.message),
);
}
}
class MyPageState extends State<MyPage>{
String _time;
File _image;
final _stateController = TextEditingController();
final _visionTextController = TextEditingController();
//final TextRecognizer textRecognizer = FirebaseVision.instance.textRecognizer();
final TextRecognizer textRecognizer = FirebaseVision.instance.cloudTextRecognizer();
@override
void initState() {
super.initState();
this._time = "Tap Floating Action Button";
}
@override
void dispose() {
this._stateController.dispose();
this._visionTextController.dispose();
super.dispose();
}
Future getImage() async {
var image = await ImagePicker.pickImage(source: ImageSource.camera);
setState(() {
this._image = image;
});
}
Future cropImage() async {
var croppedImage = await ImageCropper.cropImage(sourcePath: this._image.path,
aspectRatioPresets: [
CropAspectRatioPreset.square,
CropAspectRatioPreset.ratio3x2,
CropAspectRatioPreset.original,
CropAspectRatioPreset.ratio4x3,
CropAspectRatioPreset.ratio16x9
],
androidUiSettings: AndroidUiSettings(
toolbarTitle: 'Cropper',
toolbarColor: Colors.deepOrange,
toolbarWidgetColor: Colors.white,
initAspectRatio: CropAspectRatioPreset.original,
lockAspectRatio: false),
iosUiSettings: IOSUiSettings(
minimumAspectRatio: 1.0,
)
);
setState(() {
this._image = croppedImage;
});
}
void vision() async {
if (this._image != null) {
FirebaseVisionImage visionImage = FirebaseVisionImage.fromFile(this._image);
VisionText visionText = await textRecognizer.processImage(visionImage);
String text = visionText.text;
print(text);
var buf = new StringBuffer();
for (TextBlock block in visionText.blocks) {
final Rect boundingBox = block.boundingBox;
final List<Offset> cornerPoints = block.cornerPoints;
final String text = block.text;
final List<RecognizedLanguage> languages = block.recognizedLanguages;
print(languages);
buf.write("=====================\n");
for (TextLine line in block.lines) {
// Same getters as TextBlock
buf.write("${line.text}\n");
for (TextElement element in line.elements) {
// Same getters as TextBlock
}
}
}
setState(() {
this._visionTextController.text = buf.toString();
});
}
}
void showTime(){
setState(() {
this._time = DateTime.now().toString();
});
}
void loadOnPressed() {
Firestore.instance.document("sample/sandwichData")
.get().then((DocumentSnapshot ds){
setState(() {
this._stateController.text = ds["hotDogStatus"];
});
print("status=$this.status");
});
}
void saveOnPressed() {
Firestore.instance.document("sample/sandwichData")
.updateData({"hotDogStatus":_stateController.text})
.then((value) => print("success"))
.catchError((value) => print("error $value"));
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text('Flutter Firebase Sample'),
),
body: LayoutBuilder(
builder: (BuildContext context, BoxConstraints viewportConstraints) {
return SingleChildScrollView(
child: ConstrainedBox(
constraints: BoxConstraints(
minHeight: viewportConstraints.maxHeight,
),
child: IntrinsicHeight(
child: Column(
mainAxisAlignment: MainAxisAlignment.start,
mainAxisSize: MainAxisSize.max,
crossAxisAlignment: CrossAxisAlignment.start,
children: <Widget>[
Text(
this._time,
style: TextStyle(fontSize: 16.0),
),
Row(
mainAxisAlignment: MainAxisAlignment.start,
mainAxisSize: MainAxisSize.max,
crossAxisAlignment: CrossAxisAlignment.start,
children: <Widget>[
Flexible(
child: TextField(
controller: _stateController,
),
),
Padding(
padding: EdgeInsets.all(2.0),
child: RaisedButton(
onPressed: saveOnPressed,
child: Text("Save")),
),
Padding(
padding: EdgeInsets.all(2.0),
child: RaisedButton(
onPressed: loadOnPressed,
child: Text("Load"))
)
],
),
Column(
children: <Widget>[
Row(
children: <Widget>[
Padding(
padding: EdgeInsets.all(2.0),
child: RaisedButton(
onPressed: getImage,
child: Text("Pick Image"),
),
),
Padding(
padding: EdgeInsets.all(2.0),
child: RaisedButton(
onPressed: cropImage,
child: Text("Crop Image"),
),
),
Padding(
padding: EdgeInsets.all(2.0),
child: RaisedButton(
onPressed: vision,
child: Text("Vision Api"),
),
),
],
),
TextField(
controller: _visionTextController,
minLines: 6,
maxLines: 15,
decoration: InputDecoration(
border: OutlineInputBorder(),
),
),
Container(
//width: MediaQuery.of(context).size.width,
//height: 300,
child: FittedBox(
fit: BoxFit.fitHeight,
child: _image == null ? Text('No image selected.') : Image.file(_image),
),
),
],
),
],
),
),
),
);
},
),
floatingActionButton: FloatingActionButton(
onPressed: showTime,
child: Icon(Icons.timer),
),
);
}
}
class MyPage extends StatefulWidget {
final String message;
MyPage({this.message}):super() {}
@override
State<StatefulWidget> createState() => new MyPageState();
}
pubspec.yaml
dependencies:
flutter:
sdk: flutter
cupertino_icons: ^0.1.2
cloud_firestore: 0.13.4+2
firebase_ml_vision: 0.9.3+8
image_picker: 0.6.5
image_cropper: 1.2.
android/app/src/main/AndroidManifest.xml
<activity
android:name="com.yalantis.ucrop.UCropActivity"
android:screenOrientation="portrait"
android:theme="@style/Theme.AppCompat.Light.NoActionBar"/>
ios/Runner/Info.plist
以下を追記
<key>NSPhotoLibraryUsageDescription</key>
<string>What purpose to use</string>
<key>NSCameraUsageDescription</key>
<string>What purpose to use</string>
<key>NSMicrophoneUsageDescription</key>
<string>What purpose to use</string>
