WWDC Quick Look 💓 By SwiftGGTeam
Extract document data using Vision

Extract document data using Vision

元の動画を見る

ハイライト

Vision のバーコード検出は、Codabar、GS1Databar、MicroQR などの新しいバーコードをサポートするためにリビジョン 2 にアップグレードされました。ドキュメントのセグメント化を検出するために、新しい VNDocumentSegmentationRequest が追加されました。 OCR は、中国語と日本語の正確な認識モードを含む多言語サポートを拡張します。

主な内容

バーコード検出の新機能

バーコード検出がリビジョン 2 (02:07) にアップグレードされ、次の 4 つの新しいバーコード タイプが追加されました。

  • Codabar: 図書館、血液銀行などで使用されます。
  • GS1Databar: スーパーマーケットのクーポン、レシート
  • MicroPDF: 小さなタグ
  • MicroQR: 小さなスペースの QR コードで、通常の QR コードよりもスペースを大幅に節約できます。

リビジョン 2 では、動作の不一致 (02:40) も修正されました。以前に対象領域 (ROI) を指定した場合、返される境界ボックスは依然として完全な画像を基準にしていました。他の Vision リクエストと一致するように、境界ボックスの座標は ROI を基準にしています。

Vision の利点の 1 つは、スキャンを繰り返す必要がなく、複数のバーコードと複数のバーコード タイプを同時に検出できることです (04:07)。ただし、指定するシンボルの数が増えるほど、検出が遅くなることに注意してください。必要なタイプのみを指定してください。

テキスト認識の言語サポート

Vision のテキスト認識には 2 つのモードがあります (07:29):

  • 高速: ラテン文字認識エンジン、さまざまなラテン文字セット (ドイツ語の小文字記号など) をサポート
  • 正確: 機械学習に基づく認識装置、単語と行による処理、中国語や日本語などの非ラテン語をサポート

言語の選択は、認識段階と言語修正段階 (08:02) に影響します。高速モードでは、言語の選択によってサポートされるラテン文字セットが決まります。 Accurate モードでは、言語の選択によってどの認識モデルを使用するかが決まります (中国語にはまったく異なるモデルが使用されます)。

リビジョン 2 では、言語サポートが大幅に拡張されています (09:25)。使用するのに最適supportedRecognitionLanguages()固定リストを想定するのではなく、サポートされている言語をクエリします。複数の言語を使用する場合は順序が重要であり、曖昧なケースは順番に解決されます。

ドキュメントのセグメント化: インテリジェントなドキュメント検出

今年の新作VNDocumentSegmentationRequest(10:34) は、紙、看板、メモ、領収書、ラベルなど、複数の種類の文書でトレーニングされた機械学習主導の文書検出器です。

低解像度のセグメンテーション マスク (各ピクセルは、そのピクセルがドキュメントに属しているかどうかの信頼度を表します) と 4 つのコーナー ポイントを返します。Neural Engine を搭載したデバイス上でリアルタイムに実行できます。ビジョンキットVNDocumentCameraViewControllerこのリクエストは、従来の長方形検出器の代わりに使用されるようになりました。

そしてVNDetectRectanglesRequest違い (12:25):

特性資料請求長方形のリクエスト
アルゴリズムの種類機械学習従来のコンピュータビジョン
走行場所ニューラル エンジン/GPU/CPUCPU
文書の形状任意の形状長方形である必要があります
ぼやけたコーナー写真 ぼやけたコーナー対応できる挑戦的
書類を折りたたむ対応できる挑戦的
結果を返すマスク + コーナーポイントコーナーポイントのみ
検出量1 つだけが返されます複数返品可能

##詳細

バーコードスキャンの基本コード

06:18

import Foundation
import Vision

let url = URL(fileReferenceLiteralResourceName: "codeall_4.png") as CFURL

guard let imageSource = CGImageSourceCreateWithURL(url, nil),
      let barcodeImage = CGImageSourceCreateImageAtIndex(imageSource, 0, nil) else {
    fatalError("Unable to create barcode image.")
}

let imageRequestHandler = VNImageRequestHandler(cgImage: barcodeImage)

let detectBarcodesRequest = VNDetectBarcodesRequest()
detectBarcodesRequest.revision = VNDetectBarcodesRequestRevision2
detectBarcodesRequest.symbologies = [.codabar]

try imageRequestHandler.perform([detectBarcodesRequest])

if let detectedBarcodes = detectBarcodesRequest.results {
    drawBarcodes(detectedBarcodes, sourceImage: barcodeImage)

    detectedBarcodes.forEach {
        print($0.payloadStringValue ?? "")
    }
}

キーポイント:

  • revision明示的に設定する必要があります。そうでない場合、新しい SDK は最新リビジョンで自動的にコンパイルされます。
  • symbologies1 つ以上を指定できます。空の配列は、すべてのタイプをスキャンすることを意味します。
  • 1D バーコード (Codabar など) は複数の検出を返すため、ペイロードを使用して重複を排除する必要があります。
  • payloadStringValueバーコードによってエンコードされた実際のデータです

バーコード境界ボックスを描画する

public func createCGPathForTopLeftCCWQuadrilateral(
    _ topLeft: CGPoint,
    _ bottomLeft: CGPoint,
    _ bottomRight: CGPoint,
    _ topRight: CGPoint,
    _ transform: CGAffineTransform
) -> CGPath {
    let path = CGMutablePath()
    path.move(to: topLeft, transform: transform)
    path.addLine(to: bottomLeft, transform: transform)
    path.addLine(to: bottomRight, transform: transform)
    path.addLine(to: topRight, transform: transform)
    path.addLine(to: topLeft, transform: transform)
    path.closeSubpath()
    return path
}

public func drawBarcodes(_ observations: [VNBarcodeObservation], sourceImage: CGImage) -> CGImage? {
    let size = CGSize(width: sourceImage.width, height: sourceImage.height)
    let imageSpaceTransform = CGAffineTransform(scaleX: size.width, y: size.height)
    let colorSpace = CGColorSpace(name: CGColorSpace.sRGB)
    let cgContext = CGContext(
        data: nil,
        width: Int(size.width),
        height: Int(size.height),
        bitsPerComponent: 8,
        bytesPerRow: 8 * 4 * Int(size.width),
        space: colorSpace!,
        bitmapInfo: CGImageAlphaInfo.premultipliedLast.rawValue
    )!

    cgContext.setStrokeColor(CGColor(srgbRed: 1.0, green: 0.0, blue: 0.0, alpha: 0.7))
    cgContext.setLineWidth(25.0)
    cgContext.draw(sourceImage, in: CGRect(x: 0.0, y: 0.0, width: size.width, height: size.height))

    for currentObservation in observations {
        let path = createCGPathForTopLeftCCWQuadrilateral(
            currentObservation.topLeft,
            currentObservation.bottomLeft,
            currentObservation.bottomRight,
            currentObservation.topRight,
            imageSpaceTransform
        )
        cgContext.addPath(path)
        cgContext.strokePath()
    }
    return cgContext.makeImage()
}

キーポイント:

  • バーコードの四隅を使用します。topLeftbottomLeftbottomRighttopRight急行
  • 正規化された座標 (0 ~ 1) は、画像サイズを乗算してピクセル座標に変換されます。
  • CGAffineTransform(scaleX:y:)スケーリング変換を構築する

ドキュメントの分割と視点の修正

14:02

import Foundation
import CoreImage
import Vision
import CoreML

guard var inputImage = CIImage(contentsOf: #fileLiteral(resourceName: "IMG_0001.HEIC"))
else { fatalError("image not found") }

let requestHandler = VNImageRequestHandler(ciImage: inputImage)
let documentDetectionRequest = VNDetectDocumentSegmentationRequest()
try requestHandler.perform([documentDetectionRequest])

guard let document = documentDetectionRequest.results?.first,
      let documentImage = perspectiveCorrectedImage(
        from: inputImage,
        rectangleObservation: document
      ) else {
    fatalError("Unable to get document image.")
}

documentImage

キーポイント:

  • VNDetectDocumentSegmentationRequestセグメンテーション マスクと 4 つのコーナー ポイントを返します
  • 遠近補正は自分で行う必要があります。Core Imageを使用してください。CIPerspectiveCorrectionフィルター
  • 補正された画像は、OCR、四角形検出、バーコードスキャンに直接使用できます。

遠近補正補助機能

public func perspectiveCorrectedImage(
    from inputImage: CIImage,
    rectangleObservation: VNRectangleObservation
) -> CIImage? {
    let imageSize = inputImage.extent.size

    // 验证检测到的矩形有效
    let boundingBox = rectangleObservation.boundingBox.scaled(to: imageSize)
    guard inputImage.extent.contains(boundingBox)
    else { print("invalid detected rectangle"); return nil }

    // 获取四个角点的像素坐标
    let topLeft = rectangleObservation.topLeft.scaled(to: imageSize)
    let topRight = rectangleObservation.topRight.scaled(to: imageSize)
    let bottomLeft = rectangleObservation.bottomLeft.scaled(to: imageSize)
    let bottomRight = rectangleObservation.bottomRight.scaled(to: imageSize)

    // 应用透视矫正滤镜
    let correctedImage = inputImage
        .cropped(to: boundingBox)
        .applyingFilter("CIPerspectiveCorrection", parameters: [
            "inputTopLeft": CIVector(cgPoint: topLeft),
            "inputTopRight": CIVector(cgPoint: topRight),
            "inputBottomLeft": CIVector(cgPoint: bottomLeft),
            "inputBottomRight": CIVector(cgPoint: bottomRight)
        ])
    return correctedImage
}

extension CGPoint {
    func scaled(to size: CGSize) -> CGPoint {
        return CGPoint(x: self.x * size.width, y: self.y * size.height)
    }
}

extension CGRect {
    func scaled(to size: CGSize) -> CGRect {
        return CGRect(
            x: self.origin.x * size.width,
            y: self.origin.y * size.height,
            width: self.size.width * size.width,
            height: self.size.height * size.height
        )
    }
}

キーポイント:

  • 正規化された座標は画像サイズで乗算されます
  • CIPerspectiveCorrection遠近感の歪みを補正するフィルター
  • 最初に境界ボックスをトリミングすると、後続の処理のデータ量を減らすことができます。

複雑なドキュメントのスキャン: アンケート分析の例

講演者は、完全なアンケート スキャン プロセスをデモンストレーションしました (14:02):

  1. 文書分割検出 + 遠近補正
  2. バーコード検出(QRコードにアンケートタイトルを格納)
  3. 長方形の検出 (チェックボックスを見つけます)
  4. OCR(質問テキストの認識)
  5. コア ML 分類 (チェックボックスがチェックされているかどうかを決定します)

主要な構成:

// 矩形检测配置
rectanglesDetection.minimumSize = 0.1  // 默认 0.2,太小检测不到
rectanglesDetection.maximumObservations = 0  // 0 表示无限制

// OCR 请求
let ocrRequest = VNRecognizeTextRequest { request, error in
    textBlocks = request.results as! [VNRecognizedTextObservation]
}

// Core ML 分类器(复选框是否勾选)
let classificationRequest = createclassificationRequest()

各チェックボックス領域に対して遠近補正を行った後、Create MLで学習させた画像分類器を入力し、「Yes」か「No」を判定します。信頼度 > 0.9 の場合、対応する質問テキストを検索します (テキスト行を長方形の位置と一致させます)。

重要ポイント

1.医療シナリオ向けの複数のバーコード スキャン アプリ

  • やるべきこと: 病院で iPhone を使用して、患者のリストバンド、薬瓶、処方箋にある複数のバーコードを一度にスキャンし、情報を自動的に要約します。
  • 価値がある理由: Vision は複数のバーコードとタイプを同時に検出できるため、専用のハンドヘルド スキャナーよりも柔軟性が高くなります。
  • 開始方法: を使用しますVNDetectBarcodesRequestリビジョン 2 の設定symbologies医療シナリオで一般的に使用される Codabar と QR

2.多言語紙幣認識システム

  • 何をすべきか: 中国、日本、韓国の請求書の重要な情報 (金額、日付、販売者) を自動的に識別します。
  • 実行する価値がある理由: Accurate モードの中国語認識が WWDC2021 で改善され、複雑なチケット レイアウトを処理できるようになりました
  • 開始方法: を使用しますVNRecognizeTextRequest正確モード、recognitionLanguagesターゲット言語として設定し、VNDocumentSegmentationRequest最初にドキュメント領域を検出します

3.スマートフォーム入力アシスタント

  • 何をすべきか: ユーザーが紙のフォームを受け取ると、アプリがフィールドの内容を自動的に抽出し、入力可能な電子バージョンを生成します。
  • 実行する価値がある理由: 文書セグメンテーション検出はさまざまな文書形状を処理でき、長方形検出は表セルを検出でき、OCR はテキストを抽出します。
  • 開始方法: 最初に使用しますVNDocumentSegmentationRequest使用前に文書を検出して修正するVNDetectRectanglesRequestテーブル入力領域を見つけて、最後に使用しますVNRecognizeTextRequestコンテンツの抽出

4.カスタムチェックボックス/チェックボックス認識

  • 何をすべきか: ユーザーが記入したアンケートと試験の解答用紙のチェック ステータスを特定します。
  • 実行する価値がある理由: Vision の四角形検出はチェックボックスの位置を特定し、Core ML 画像分類器はチェックされているかどうかを判断できます。
  • 開始方法: チェックされたチェックボックス画像とチェックされていないチェックボックス画像を収集し、Create ML を使用して 2 番目の分類子をトレーニングし、アプリ内で Vision の四角形検出結果を結合します。

関連セッション

コメント

GitHub Issues · utterances