パスポートMRZのためのフラッターOCR認識


先週、私はsimple Android application ダイナマイトでcamera SDK and OCR SDK パスポートMRZを認識する.フラッタ開発を容易にするために、私は今週、Dynamsoft OCR SDKを包装するためにフラッタプラグインを作ると決めました.以来、公式フラッターカメラのプラグインは、パブでダウンロード可能です.私はカメラの部分に努力をする必要はありません.

のためのフラッタプラグイン


いつものように、最初の手順は次のコマンドを実行してプラグインプロジェクトを作成することです.
flutter create --org com.dynamsoft --template=plugin --platforms=android -a java flutter_ocr_sdk
その後、DynamsoftのMavenリポジトリを追加し、android/build.gradle :
rootProject.allprojects {
    repositories {
        maven {
            url "http://download2.dynamsoft.com/maven/dlr/aar"
        }
        google()
        jcenter()
    }
}

dependencies {
    implementation "com.dynamsoft:dynamsoftlabelrecognition:1.2.1@aar"
}
その後、我々はandroid/src/main/java/com/dynamsoft/flutter_ocr_sdk/FlutterOcrSdkPlugin.java エントリポイントonMethodCall() . 5つのメソッドコールを処理しますsetOrganizationID , recognizeByFile , recognizeByBuffer , loadModelFiles , and loadTemplate :
  • setOrganizationID() : 登録するDynamsoft account Dynamsoftサーバから認可を得るために組織IDを取得します.
    public void setOrganizationID(String id) {
        DMLTSConnectionParameters ltspar = new DMLTSConnectionParameters();
        ltspar.organizationID = id;
        mLabelRecognition.initLicenseFromLTS(ltspar, new DLRLTSLicenseVerificationListener() {
            @Override
            public void LTSLicenseVerificationCallback(boolean b, Exception e) {
                if (e != null) {
                    Log.e("lts error: ", e.getMessage());
                }
            }
        });
    }
    
  • recognizeByFile() : 画像ファイルによるMRZ OCR認識
    public String recognizeByFile(String fileName, String templateName) {
        JSONObject ret = new JSONObject();
        DLRResult[] results = null;
        try {
            results = mLabelRecognition.recognizeByFile(fileName, templateName);
            ret = wrapResults(results);
        } catch (LabelRecognitionException e) {
            Log.e(TAG, e.toString());
        }
        return ret.toString();
    }
    
  • recognizeByBuffer() : 画像データのバイト列によるMRZ OCR認識
    public String recognizeByBuffer(byte[] bytes, int width, int height, int stride, int format, String templateName) {
        JSONObject ret = new JSONObject();
        DLRResult[] results = null;
        DLRImageData data = new DLRImageData();
        data.bytes = bytes;
        data.width = width;
        data.height = height;
        data.stride = stride;
        data.format = format;
        try {
            results = mLabelRecognition.recognizeByBuffer(data, templateName);
            ret = wrapResults(results);
        } catch (LabelRecognitionException e) {
            Log.e(TAG, e.toString());
        }
        return ret.toString();
    }
    
  • loadModelFiles() : 深い学習に基づいて訓練された文字モデルファイルを読み込みます.
    public void loadModelFiles(String name, byte[] prototxtBuffer, byte[] txtBuffer, byte[] characterModelBuffer) {
        try {
            mLabelRecognition.appendCharacterModelBuffer(name, prototxtBuffer, txtBuffer, characterModelBuffer);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
    
  • loadTemplate() : MRZ認識のために特定のパラメタを含むテンプレートファイルをロードしてください.
    public void loadTemplate(String content) {
        try {
            mLabelRecognition.appendSettingsFromString(content);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
    
  • 最後のステップは、対応するフラッタ方法をlib/flutter_ocr_sdk.dart .
    Future<void> setOrganizationID(String id) async {
        await _channel.invokeMethod('setOrganizationID', {'id': id});
    }
    
    Future<String> recognizeByFile(String filename, String template) async {
        return await _channel.invokeMethod('recognizeByFile', {
          'filename': filename,
          'template': template,
        });
    }
    
    Future<String> recognizeByBuffer(Uint8List bytes, int width, int height,
          int stride, int format, String template) async {
        return await _channel.invokeMethod('recognizeByBuffer', {
          'bytes': bytes,
          'width': width,
          'height': height,
          'stride': stride,
          'format': format,
          'template': template,
        });
    }
    
    Future<void> loadModelFiles(String name, Uint8List prototxtBuffer,
          Uint8List txtBuffer, Uint8List characterModelBuffer) async {
        return await _channel.invokeMethod('loadModelFiles', {
          'name': name,
          'prototxtBuffer': prototxtBuffer,
          'txtBuffer': txtBuffer,
          'characterModelBuffer': characterModelBuffer,
        });
    }
    
    Future<void> loadTemplate(String template) async {
        return await _channel.invokeMethod('loadTemplate', {
          'template': template,
        });
    }
    
    パスポートMRZ標準によると、MRZ文字列からパスポート情報を抽出するパーサーを作成します.
    static String parse(String line1, String line2) {
        // https://en.wikipedia.org/wiki/Machine-readable_passport
        String result = "";
        // Type
        String tmp = "Type: ";
        tmp += line1[0];
        result += tmp + '\n\n';
    
        // Issuing country
        tmp = "Issuing country: ";
        tmp += line1.substring(2, 5);
        result += tmp + '\n\n';
    
        // Surname
        int index = 5;
        tmp = "Surname: ";
        for (; index < 44; index++) {
          if (line1[index] != '<') {
            tmp += line1[index];
          } else {
            break;
          }
        }
        result += tmp + '\n\n';
    
        // Given names
        tmp = "Given Names: ";
        index += 2;
        for (; index < 44; index++) {
          if (line1[index] != '<') {
            tmp += line1[index];
          } else {
            tmp += ' ';
          }
        }
        result += tmp + '\n\n';
    
        // Passport number
        tmp = "Passport number: ";
        index = 0;
        for (; index < 9; index++) {
          if (line2[index] != '<') {
            tmp += line2[index];
          } else {
            break;
          }
        }
        result += tmp + '\n\n';
    
        // Nationality
        tmp = "Nationality: ";
        tmp += line2.substring(10, 13);
        result += tmp + '\n\n';
    
        // Date of birth
        tmp = line2.substring(13, 19);
        tmp = tmp.substring(0, 2) +
            '/' +
            tmp.substring(2, 4) +
            '/' +
            tmp.substring(4, 6);
        tmp = "Date of birth (YYMMDD): " + tmp;
        result += tmp + '\n\n';
    
        // Sex
        tmp = "Sex: ";
        tmp += line2[20];
        result += tmp + '\n\n';
    
        // Expiration date of passport
        tmp = line2.substring(21, 27);
        tmp = tmp.substring(0, 2) +
            '/' +
            tmp.substring(2, 4) +
            '/' +
            tmp.substring(4, 6);
        tmp = "Expiration date of passport (YYMMDD): " + tmp;
        result += tmp + '\n\n';
    
        // Personal number
        if (line2[28] != '<') {
          tmp = "Personal number: ";
          for (index = 28; index < 42; index++) {
            if (line2[index] != '<') {
              tmp += line2[index];
            } else {
              break;
            }
          }
          result += tmp + '\n\n';
        }
    
        return result;
    }
    

    どのようにフラッターの資産をロードするには?


    Flutterプロジェクトでモデルとテンプレートファイルを読み込むにはAssetBundle :
    Future<String> loadAssetString(String path) async {
        return await rootBundle.loadString(path);
    }
    
    Future<ByteData> loadAssetBytes(String path) async {
    return await rootBundle.load(path);
    }
    
    また、ファイルを宣言する必要がありますpubspec.yaml .

    パスポートMRZを認識するフラッターアプリを構築する


    まず、ダウンロードmodel package モデルフォルダにファイルを展開します.
    インexample/pubspec.yaml , カメラプラグインを追加し、モデルファイルをアクセスできます.
    dependencies:
        camera:
    
    flutter:
      assets:
        - model/
        - model/CharacterModel/
    
    では、パスポートMRZ認識を実装するためにいくつかの手順を踏みましょうexample/main.dart :

  • カメラプラグインとOCRプラグインを初期化します
    final cameras = await availableCameras();
    final firstCamera = cameras.first;
    
    class MobileState extends State<Mobile> {
      CameraController _controller;
      Future<void> _initializeControllerFuture;
      FlutterOcrSdk _textRecognizer;
      final picker = ImagePicker();
    
      @override
      void initState() {
        super.initState();
    
        _controller = CameraController(
          widget.camera,
          ResolutionPreset.ultraHigh,
        );
    
        _initializeControllerFuture = _controller.initialize();
        _initializeControllerFuture.then((_) {
          setState(() {});
        });
    
        initBarcodeSDK();
      }
    
      Future<void> initBarcodeSDK() async {
        _textRecognizer = FlutterOcrSdk();
        _textRecognizer.loadModel('model/');
      }
    }
    

  • カメラビューとフローティングアクションボタンを使用してUIレイアウトを構築します
    @override
    Widget build(BuildContext context) {
        double width = MediaQuery.of(context).size.width;
        double height = MediaQuery.of(context).size.height;
        double left = 5;
        double mrzHeight = 50;
        double mrzWidth = width - left * 2;
        return Scaffold(
            body: Stack(children: [
                getCameraWidget(),
                Positioned(
                left: left,
                top: height - mrzHeight * 4,
                child: Container(
                    width: mrzWidth,
                    height: mrzHeight,
                    decoration: BoxDecoration(
                    border: Border.all(
                        width: 2,
                        color: Colors.blue,
                    ),
                    ),
                ),
                )
            ]),
            floatingActionButton: FloatingActionButton(
                child: Icon(Icons.camera),
                onPressed: () async {
                showDialog(
                    context: context,
                    builder: (BuildContext context) {
                        return Center(
                        child: CircularProgressIndicator(),
                        );
                    });
                pictureScan();
                },
            ),
        );
    }
    

  • 新しいページにMRZとショー結果を認識するために写真を撮ってください.
    void pictureScan() async {
        final image = await _controller.takePicture();
        if (image == null) {
          Navigator.pop(context);
          return;
        }
        String ret = await _textRecognizer.recognizeByFile(image?.path, 'locr');
        String results = getTextResults(ret);
        Navigator.pop(context);
        Navigator.push(
          context,
          MaterialPageRoute(
            builder: (context) => DisplayPictureScreen(
                imagePath: image?.path, barcodeResults: results),
          ),
        );
    }
    
    class DisplayPictureScreen extends StatelessWidget {
      final String imagePath;
      final String barcodeResults;
    
      const DisplayPictureScreen({Key key, this.imagePath, this.barcodeResults})
          : super(key: key);
    
      @override
      Widget build(BuildContext context) {
        return Scaffold(
          appBar: AppBar(title: Text('OCR')),
          body: Stack(
            alignment: const Alignment(0.0, 0.0),
            children: [
              Image.file(
                File(imagePath),
                fit: BoxFit.cover,
                height: double.infinity,
                width: double.infinity,
                alignment: Alignment.center,
              ),
              Container(
                decoration: BoxDecoration(
                  color: Colors.black45,
                ),
                child: Text(
                  barcodeResults,
                  style: TextStyle(
                    fontSize: 14,
                    color: Colors.white,
                  ),
                ),
              ),
            ],
          ),
        );
      }
    }
    

  • パスポートMRZ認識アプリケーションを実行します
    cd example
    flutter run
    

  • ソースコード


    https://github.com/yushulx/flutter_ocr_sdk