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>

Follow me!

コメントを残す

メールアドレスが公開されることはありません。 * が付いている欄は必須項目です