Read documents using the Vision framework
Machine Learning & AI 进阶 1m

用 Vision 框架读取文档:结构化识别与镜头污渍检测

Read documents using the Vision framework

2025年6月9日

在 Apple 官方观看视频

一句话判断

RecognizeDocumentsRequest 是 RecognizeTextRequest 的结构化升级版——它不只识别文字,还能解析表格行列、列表层级、段落分组,并自动检测邮箱/电话/URL 等关键数据。如果你之前用 RecognizeTextRequest 然后自己用坐标计算表格结构,现在可以大幅简化代码了。

这场 Session 讲了什么

Megan Williams 介绍了 Vision 框架的三个新特性:

RecognizeDocumentsRequest:支持 26 种语言的文字识别。返回 DocumentObservation,具有层级结构——Document → Text / Tables / Lists / Barcodes。Table 由 Cell 组成的二维数组构成,支持行列访问,Cell 可跨多行多列(用 Range 表示)。Cell 内容是 Container,可包含 Text、嵌套 Table、List 或 Barcode。

文字的多种访问方式:transcript(完整文本字符串)、lines(行数组)、paragraphs(自然阅读分组)、words(单词数组,中日韩泰语不支持)。DataDetection 自动识别文本中的关键数据:邮箱、电话、地址、URL、日期(转日历事件)、度量单位、金额、追踪号、付款标识、航班号。

DetectLensSmudgeRequest:检测图片是否由污渍镜头拍摄。返回 SmudgeObservation,confidence 在 0-1 之间,越高越可能有污渍。需要注意高置信度也可能是运动模糊、长曝光、云雾场景导致的假阳性。可与 DetectFaceCaptureQualityRequest(人脸质量)和 CalculateImageAestheticScoresRequest(整体美学评分 + 实用图片识别)组合使用筛选高质量图片。

Hand Pose 检测模型更新:用更小的现代化模型替换旧模型,21 个关节不变,精度提升、内存减少、延迟降低。但关节位置与旧模型不同,已训练的手势分类器需要重新训练。

值得深挖的点

DocumentObservation 的层级设计很实用。以前用 RecognizeTextRequest 提取表格,你需要用每个文字框的坐标信息自己计算行列归属——代码复杂且容易出错。现在 RecognizeDocumentsRequest 直接返回 Table 对象,Cell 已经按行列组织好,你只需要遍历 rows 就能提取数据。这减少的代码量和提升的可靠性是实打实的。

DataDetection 是一个独立的新框架。Vision 调用它来检测文本中的关键数据。检测能力覆盖了文档处理中最常见的结构化信息——联系信息(邮箱/电话/地址)、时间(日期/时间转日历事件)、金额(美元 + 货币单位)、物流(追踪号/航班号)。这些数据的自动检测让”扫描名片创建联系人”或”扫描发票提取金额”这类需求的实现变得非常直接。

镜头污渍检测的 confidence 阈值选择是一个业务决策。高阈值(比如 0.9):更多图片通过但可能有低质量图片。低阈值(比如 0.5):更严格的过滤但可能误杀好图片(比如运动模糊的照片)。你的 app 应该根据使用场景选择阈值——文档扫描 app 应该用较低阈值(宁可误杀),照片管理 app 可以用较高阈值(宁可放过)。

手部姿态模型更换的影响比表面看起来大。不只是模型文件更换——关节位置变了意味着所有基于关节坐标训练的分类器都需要重新训练。如果你的 app 有自定义手势识别(比如”OK 手势触发拍照”),必须用新模型重新训练,否则识别准确率会显著下降。

代码片段

// 1. 用 RecognizeDocumentsRequest 解析表格
import Vision

func extractTable(from image: CGImage) async throws -> DocumentObservation.Table? {
    let request = RecognizeDocumentsRequest()
    let results = try await request.perform(on: image)
    return results.first?.tables.first
}

// 2. 遍历表格行提取联系人
struct Contact {
    let name: String
    let email: String?
    let phone: String?
}

func parseContacts(from table: DocumentObservation.Table) -> [Contact] {
    table.rows.map { row in
        let nameCell = row.first!
        let name = nameCell.content.transcript

        var email: String?
        var phone: String?

        for cell in row.dropFirst() {
            for data in cell.content.detectedData {
                switch data.details {
                case .email(let e): email = e
                case .phone(let p): phone = p
                default: break
                }
            }
        }
        return Contact(name: name, email: email, phone: phone)
    }
}

// 3. 镜头污渍检测
func filterSmudgedImages(_ images: [CGImage]) async throws -> [CGImage] {
    let request = DetectLensSmudgeRequest()
    var cleanImages: [CGImage] = []

    for image in images {
        let result = try await request.perform(on: image)
        if result.confidence < 0.7 {
            cleanImages.append(image)
        }
    }
    return cleanImages
}

// 4. 组合使用:质量检查流水线
func processImage(_ image: CGImage) async throws -> Bool {
    // 先检查镜头污渍
    let smudgeResult = try await DetectLensSmudgeRequest().perform(on: image)
    guard smudgeResult.confidence < 0.7 else { return false }

    // 再检查整体美学分数
    let aestheticResult = try await CalculateImageAestheticScoresRequest().perform(on: image)
    guard !aestheticResult.isUtility else { return false }

    // 通过所有检查
    return true
}

最佳实践

  1. 表格解析直接用 RecognizeDocumentsRequest。不要再用 RecognizeTextRequest + 坐标计算来做表格识别——新 API 的行列解析准确率和代码简洁度都远超手动方案。

  2. 用 DataDetection 自动提取关键数据。不要自己写正则表达式匹配邮箱/电话——Vision 集成的 DataDetection 框架覆盖了更多的格式变体,而且会持续更新。

  3. 污渍检测阈值根据场景选择。文档扫描用 0.5-0.7(严格),照片筛选用 0.8-0.9(宽松)。先在你的测试数据集上评估不同阈值的 precision/recall。

  4. 组合多个 Vision API 做质量检查。污渍检测 → 美学评分 → 实用图片过滤,形成多级质量筛选流水线。每个 API 负责一个维度,组合后效果更好。

  5. 手部姿态模型升级后必须重新训练分类器。如果你的 app 使用了 ML 手势分类器,检查是否有新模型可用,用新模型的关节数据重新训练。

还有什么值得关注

  • 所有 Vision API 完全在设备端运行,支持 iOS / macOS / iPadOS / tvOS / visionOS
  • 文字识别支持 26 种语言,但 word 级别不支持中日韩泰语
  • DocumentObservation 目前每个图片返回一个
  • Container 的 boundingRegion 提供了每个元素在图片中的位置信息
  • 表格导出为 tab-separated string 可直接粘贴到 Notes 和 Numbers
  • Apple 提供了完整的示例 app 可以从开发者网站下载
机器学习