Flutter文档检测插件document_detector的使用

发布于 1周前 作者 wuwangju 来自 Flutter

Flutter文档检测插件document_detector的使用

插件用于调用Android和iOS的原生SDK。如果您有任何疑问,请发送电子邮件至我们的移动负责人邮箱:daniel.seitenfus@combateafraude.com。

目前支持的文件包括身份证(RG)、驾驶证(CNH)、外国人身份证(RNE)、车辆登记证(CRLV)、工作证(CTPS)和护照。如果您有其他文件建议,请联系我们!

隐私政策和使用条款

使用我们的插件时,请确保您已同意我们的隐私政策和使用条款。

前提条件

最低配置要求

配置 版本
Flutter 1.12+
Dart 2.12+
Android API 21+
Compile SDK Version 30+
iOS 11.0+

如果您的Dart版本低于2.12,请检查此兼容版本

设置

Android

ROOT_PROJECT/android/app/build.gradle文件中添加以下内容:

android {

    ...

    dataBinding.enabled = true

    compileOptions {
        sourceCompatibility = JavaVersion.VERSION_1_8
        targetCompatibility = JavaVersion.VERSION_1_8
    }

    aaptOptions {
        noCompress "tflite"
    }
}

iOS

ROOT_PROJECT/ios/Podfile文件末尾添加以下内容:

source 'https://github.com/combateafraude/iOS.git'
source 'https://cdn.cocoapods.org/' # 或者 'https://github.com/CocoaPods/Specs' 如果CDN不可用

最后,在ROOT_PROJECT/ios/Runner/Info.plist文件中添加权限:

<key>NSCameraUsageDescription</key>
<string>为了读取文档</string>

<!-- 仅在文档上传流程中需要 -->
<key>NSPhotoLibraryUsageDescription</key>
<string>为了选择图像</string>

为了启用葡萄牙语的文字和语音功能,在项目目录ROOT_PROJECT/ios中,打开.xcworkspace文件,并在Xcode中通过Project > Info > Localizations添加葡萄牙语(巴西)。

Flutter

ROOT_PROJECT/pubspec.yaml文件中添加插件:

dependencies:  
  document_detector:
    git:
      url: https://github.com/combateafraude/Flutter.git
      ref: document-detector-v5.23.0

禁用安全验证以进行测试

我们不断采取措施使产品更加安全,减少身份欺诈的可能性。SDK包含一些可能会阻止在某些上下文中运行的限制。为了禁用它们,您可以使用如下示例中的方法:

DocumentDetectorAndroidSettings androidSettings =
        DocumentDetectorAndroidSettings(
          emulatorSettings: true,
          rootSettings: true,
          useDeveloperMode: true,
          useAdb: true,
          useDebug: true,
        );

documentDetector.setAndroidSettings(androidSettings);

注意! 仅在测试环境中建议禁用安全验证。对于生产环境的应用发布,请使用默认设置。

使用示例

DocumentDetector documentDetector = new DocumentDetector(mobileToken: mobileToken);
documentDetector.setDocumentFlow(List<DocumentDetectorStep> documentSteps);

// 其他自定义参数

DocumentDetectorResult documentDetectorResult = await documentDetector.start();

if (documentDetectorResult is DocumentDetectorSuccess) {
  // SDK成功结束并捕获了文档照片
} else if (documentDetectorResult is DocumentDetectorFailure) {
  // SDK因某种失败而结束,文档照片未被捕捉
} else {
  // 用户只是简单地关闭了SDK,没有任何结果
}

通用自定义设置

.documentDetector.setPeopleId(String peopleId)
.documentDetector.setAnalyticsSettings(bool useAnalytics)
.documentDetector.setDocumentFlow(List<DocumentDetectorStep> documentSteps)
.documentDetector.setPopupSettings(bool show)
.documentDetector.enableSound(bool enable)
.documentDetector.setNetworkSettings(int requestTimeout)
.documentDetector.setShowPreview(ShowPreview showPreview)
.documentDetector.setAutoDetection(bool enable)
.documentDetector.setCurrentStepDoneDelay(bool showDelay, int delay)
.documentDetector.setMessageSettings(MessageSettings messageSettings)
.documentDetector.setGetImageUrlExpireTime(String expireTime)
.documentDetector.setAndroidSettings(DocumentDetectorAndroidSettings androidSettings)
.documentDetector.setIosSettings(DocumentDetectorIosSettings iosSettings)
.documentDetector.setUploadSettings(UploadSettings uploadSettings)

示例

ShowPreview showPreview = new ShowPreview(
        show: true,
        title: "照片看起来如何?",
        subtitle: "看看照片是否清晰",
        confirmLabel: "是的,看起来很好!",
        retryLabel: "重新拍摄");

documentDetector.setShowPreview(showPreview);
MessageSettings messageSettings = new MessageSettings(
      fitTheDocumentMessageResIdName: "示例消息",
      holdItMessageResIdName:"示例消息",
      verifyingQualityMessageResIdName: "示例消息"
      lowQualityDocumentMessageResIdName:"示例消息" ,
      uploadingImageMessageResIdName:"示例消息",
      openDocumentWrongMessage: "示例消息",
      showOpenDocumentMessage: true);
documentDetector.setMessageSettings(messageSettings);

Android 自定义设置

DocumentDetectorStepCustomizationAndroid customizationAndroid = new DocumentDetectorStepCustomizationAndroid(
    stepLabelStringResName: "my_custom_string",
    illustrationDrawableResName: "my_custom_illustration",
    audioRawResName: "my_custom_audio"
);
DocumentDetectorAndroidSettings androidSettings = new DocumentDetectorAndroidSettings(
    enableSwitchCameraButton: false,
    compressQuality: 50,
    resolution: Resolution.QUAD_HD
);

iOS 自定义设置

DocumentDetectorIosSettings iosSettings = new DocumentDetectorIosSettings(
    enableManualCapture: true,
    timeEnableManualCapture: 15000,
    compressQuality: 1,
    resolution: IosResolution.HD1280x720
);

收集结果

DocumentDetector的结果对象是一个抽象类型DocumentDetectorResult。它可能是DocumentDetectorSuccessDocumentDetectorFailureDocumentDetectorClosed的一个实例。

DocumentDetectorSuccess

字段 备注
List<Capture> captures 文档捕获列表
String type SDK检测到的文档类型
String trackingId 在服务器上的执行标识符

Capture

字段 备注
String imagePath 图像在设备上的完整路径
String imageUrl 图像存储在临时服务器上的URL
String label 捕获的检测标签
double quality 图像的质量,范围为1.0到5.0

DocumentDetectorFailure

字段 备注
String message 友好的错误信息
String type 结束SDK的错误类型

iOS视图定制

要定制iOS视图,需要将Flutter插件本地添加到项目中。使用ViewCode原生方法实现定制。

点击这里查看一个示例,其中包含该功能的使用指南。

示例代码

import 'package:document_detector/android/android_settings.dart';
import 'package:document_detector/android/capture_stage/capture_mode.dart';
import 'package:document_detector/android/capture_stage/capture_stage.dart';
import 'package:document_detector/android/customization.dart';
import 'package:document_detector/android/maskType.dart';
import 'package:document_detector/android/resolution.dart';
import 'package:document_detector/ios/ios_resolution.dart';
import 'package:document_detector/message_settings.dart';
import 'package:document_detector/show_preview.dart';
import 'package:document_detector/document_detector_step.dart';
import 'package:document_detector/document_type.dart';
import 'package:document_detector/ios/ios_settings.dart';
import 'package:document_detector/result/capture.dart';
import 'package:document_detector/result/document_detector_failure.dart';
import 'package:document_detector/result/document_detector_result.dart';
import 'package:document_detector/result/document_detector_success.dart';
import 'package:document_detector/upload_settings.dart';
import 'package:flutter/material.dart';

import 'package:document_detector/document_detector.dart';
import 'package:flutter/services.dart';
import 'package:permission_handler/permission_handler.dart';

void main() {
  runApp(MyApp());
}

class MyApp extends StatefulWidget {
  [@override](/user/override)
  _MyAppState createState() => _MyAppState();
}

class _MyAppState extends State<MyApp> {
  String _result = "";
  String _description = "";

  String mobileToken = "";

  [@override](/user/override)
  void initState() {
    super.initState();
    requestPermissions();
  }

  void requestPermissions() async {
    await [
      Permission.camera,
    ].request();
  }

  void startDocumentDetector(List<DocumentDetectorStep> documentSteps) async {
    String result = "";
    String description = "";

    DocumentDetector documentDetector =
        new DocumentDetector(mobileToken: mobileToken);

    DocumentDetectorIosSettings documentDetectorIosSettings =
        new DocumentDetectorIosSettings(
            enableManualCapture: true, timeEnableManualCapture: 15000);

    DocumentDetectorAndroidSettings detectorAndroidSettings =
        new DocumentDetectorAndroidSettings(
            enableSwitchCameraButton: false,
            compressQuality: 50,
            resolution: Resolution.QUAD_HD);

    DocumentDetectorCustomizationAndroid documentDetectorCustomizationAndroid =
        new DocumentDetectorCustomizationAndroid(maskType: MaskType.DETAILED);

    MessageSettings messageSettings = new MessageSettings(
        openDocumentWrongMessage: "关闭文档",
        showOpenDocumentMessage: true,
        unsupportedDocumentMessage: "对不起,此文档不受支持");

    DocumentDetectorIosSettings iosSettings = new DocumentDetectorIosSettings(
        resolution: IosResolution.HD1280x720, compressQuality: 1);

    List<String> formats = ["PDF", "PNG"];

    documentDetector.setIosSettings(iosSettings);

    documentDetector.setMessageSettings(messageSettings);

    documentDetector.setDocumentFlow(documentSteps);

    documentDetector.setAndroidSettings(detectorAndroidSettings);

    // 将其他参数放在这里

    try {
      DocumentDetectorResult documentDetectorResult =
          await documentDetector.start();

      if (documentDetectorResult is DocumentDetectorSuccess) {
        result = "成功!";
        description = "类型: " +
            (documentDetectorResult.type != null
                ? documentDetectorResult.type
                : "null");
        for (Capture capture in documentDetectorResult.captures) {
          description += "\n\n\t捕获:\n\timagePath: " +
              capture.imagePath +
              "\n\timageUrl: " +
              (capture.imageUrl != null
                  ? capture.imageUrl.split("?")[0] + "..."
                  : "null") +
              "\n\tlabel: " +
              (capture.label != null ? capture.label : "null") +
              "\n\t质量: " +
              (capture.quality != null ? capture.quality.toString() : "null");
        }
      } else if (documentDetectorResult is DocumentDetectorFailure) {
        result = "失败!";
        description = "\t类型: " +
            documentDetectorResult.type +
            "\n\t消息: " +
            documentDetectorResult.message;
      } else {
        result = "已关闭!";
      }
    } on PlatformException catch (err) {
      result = "异常!";
      description = err.message;
    }

    if (!mounted) return;

    setState(() {
      _result = result;
      _description = description;
    });
  }

  [@override](/user/override)
  Widget build(BuildContext context) {
    return MaterialApp(
        home: Scaffold(
            appBar: AppBar(
              title: const Text('DocumentDetector插件示例'),
            ),
            body: Container(
                margin: const EdgeInsets.all(20.0),
                child: Column(
                  children: [
                    Row(
                      children: [
                        ElevatedButton(
                          child: Text('启动CNH文档检测器'),
                          onPressed: () async {
                            startDocumentDetector([
                              new DocumentDetectorStep(
                                  document: DocumentType.CNH_FRONT),
                              new DocumentDetectorStep(
                                  document: DocumentType.CNH_BACK)
                            ]);
                          },
                        )
                      ],
                    ),
                    Row(
                      children: [
                        ElevatedButton(
                          child: Text('启动RG文档检测器'),
                          onPressed: () async {
                            startDocumentDetector([
                              new DocumentDetectorStep(
                                  document: DocumentType.RG_FRONT),
                              new DocumentDetectorStep(
                                  document: DocumentType.RG_BACK)
                            ]);
                          },
                        )
                      ],
                    ),
                    Row(
                      children: [
                        ElevatedButton(
                          child: Text('启动RNE文档检测器'),
                          onPressed: () async {
                            startDocumentDetector([
                              new DocumentDetectorStep(
                                  document: DocumentType.RNE_FRONT),
                              new DocumentDetectorStep(
                                  document: DocumentType.RNE_BACK)
                            ]);
                          },
                        )
                      ],
                    ),
                    Row(
                      children: [
                        Container(
                            margin: EdgeInsets.only(top: 10.0),
                            child: Text("结果: $_result"))
                      ],
                    ),
                    Row(
                      mainAxisAlignment: MainAxisAlignment.spaceBetween,
                      children: [
                        Expanded(
                          child: Text("描述:\n$_description",
                              overflow: TextOverflow.clip),
                        )
                      ],
                    ),
                  ],
                ))));
  }
}

更多关于Flutter文档检测插件document_detector的使用的实战系列教程也可以访问 https://www.itying.com/category-92-b0.html

1 回复

更多关于Flutter文档检测插件document_detector的使用的实战系列教程也可以访问 https://www.itying.com/category-92-b0.html


document_detector 是一个用于在 Flutter 应用程序中检测文档的插件。它可以帮助你从图像中检测并提取文档的边缘。这个插件通常用于扫描文档、自动裁剪图像边缘等场景。

安装插件

首先,你需要在 pubspec.yaml 文件中添加 document_detector 插件的依赖:

dependencies:
  flutter:
    sdk: flutter
  document_detector: ^1.0.0  # 请检查最新版本

然后运行 flutter pub get 来安装插件。

使用插件

1. 导入插件

在你的 Dart 文件中导入 document_detector 插件:

import 'package:document_detector/document_detector.dart';

2. 初始化插件

在使用插件之前,通常需要先初始化它:

DocumentDetector documentDetector = DocumentDetector();

3. 检测文档边缘

你可以使用 detectDocument 方法来检测图像中的文档边缘。这个方法通常需要传入一个图像文件的路径或图像数据。

String imagePath = 'path_to_your_image.jpg';

try {
  List<Offset> documentCorners = await documentDetector.detectDocument(imagePath);
  
  // documentCorners 是一个包含四个 Offset 的列表,表示检测到的文档的四个角
  if (documentCorners != null && documentCorners.length == 4) {
    print('Document detected with corners: $documentCorners');
  } else {
    print('No document detected.');
  }
} catch (e) {
  print('Error detecting document: $e');
}

4. 处理检测结果

detectDocument 方法返回一个包含四个 Offset 的列表,这些 Offset 表示检测到的文档的四个角的坐标。你可以使用这些坐标来裁剪图像、绘制文档边界等。

5. 绘制文档边界(可选)

如果你想在 Flutter 中绘制检测到的文档边界,可以使用 CustomPaintCanvas

class DocumentPainter extends CustomPainter {
  final List<Offset> corners;

  DocumentPainter(this.corners);

  @override
  void paint(Canvas canvas, Size size) {
    if (corners.length == 4) {
      final paint = Paint()
        ..color = Colors.red
        ..strokeWidth = 2.0
        ..style = PaintingStyle.stroke;

      final path = Path()
        ..moveTo(corners[0].dx, corners[0].dy)
        ..lineTo(corners[1].dx, corners[1].dy)
        ..lineTo(corners[2].dx, corners[2].dy)
        ..lineTo(corners[3].dx, corners[3].dy)
        ..close();

      canvas.drawPath(path, paint);
    }
  }

  @override
  bool shouldRepaint(covariant CustomPainter oldDelegate) {
    return true;
  }
}

然后在你的 Widget 中使用这个 CustomPainter

CustomPaint(
  painter: DocumentPainter(documentCorners),
  child: Image.file(File(imagePath)),
)
回到顶部
AI 助手
你好,我是IT营的 AI 助手
您可以尝试点击下方的快捷入口开启体验!