You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Swift中VNRecognizeTextRequest中文OCR失败,预览APP可正常识别

针对VNRecognizeTextRequest中文OCR匹配预览APP行为的修改方案

核心问题分析

预览APP的OCR表现更稳定,大概率是因为它对输入图像做了预处理,同时优化了VNRecognizeTextRequest的参数组合,以及正确处理了图像的方向信息。以下是具体的修改步骤:

1. 图像预处理优化

部分图片可能因为色彩空间、对比度或格式问题导致识别失败,先对CGImage做预处理:

  • 转换为8位灰度图像,增强文本与背景的对比度
  • 确保图像的色彩空间符合Vision框架的最优要求

添加预处理函数:

private func preprocessImage(_ cgImage: CGImage) -> CGImage? {
    let context = CIContext(options: [.useSoftwareRenderer: false])
    guard let ciImage = CIImage(cgImage: cgImage) else { return nil }
    
    // 转换为灰度并增强对比度
    let grayscaleFilter = CIFilter(name: "CIColorControls")!
    grayscaleFilter.setValue(ciImage, forKey: kCIInputImageKey)
    grayscaleFilter.setValue(0.0, forKey: kCIInputSaturationKey)
    grayscaleFilter.setValue(1.2, forKey: kCIInputContrastKey)
    grayscaleFilter.setValue(0.1, forKey: kCIInputBrightnessKey)
    
    guard let filteredImage = grayscaleFilter.outputImage else { return nil }
    return context.createCGImage(filteredImage, from: filteredImage.extent)
}

2. 调整VNRecognizeTextRequest参数组合

修改请求参数,匹配预览APP的可能配置:

  • 启用语言修正(预览APP大概率依赖此功能优化中文识别)
  • 明确设置多语言优先级,将中文(简体/繁体)放在首位,同时保留自动检测
  • 添加更多中文相关的自定义词汇,辅助识别特殊字符
  • 启用字符框检测(预览APP的文本选择依赖此功能,可能同时提升识别率)

修改后的doOcr函数:

public func doOcr(image: CGImage, outStrings: inout [String]) async -> Bool {
    var ret = true
    // 先预处理图像
    guard let processedImage = preprocessImage(image) else {
        outStrings.append("图像预处理失败")
        return false
    }
    
    let ocrRequest = VNRecognizeTextRequest(completionHandler: ocrCompleteCb)
    ocrRequest.recognitionLevel = .accurate
    ocrRequest.automaticallyDetectsLanguage = true
    // 设置语言优先级:优先识别中文,再自动检测其他语言
    ocrRequest.recognitionLanguages = ["zh-Hans", "zh-Hant", "en-US"]
    ocrRequest.usesLanguageCorrection = true
    ocrRequest.usesCharacterBoxes = true
    // 补充中文常见特殊字符
    ocrRequest.customWords = ["…", "᠁", "...", "——", "「", "」", "【", "】"]
    
    // 处理图像方向:读取EXIF信息设置正确的orientation
    let orientation = CGImagePropertyOrientation(rawValue: UInt32(image.properties[kCGImagePropertyOrientation] as? Int ?? 1)) ?? .up
    let imageRequestHandler = VNImageRequestHandler(cgImage: processedImage, orientation: orientation)
    
    do {
        try imageRequestHandler.perform([ocrRequest])
        outStrings = mOcrResults
    } catch {
        outStrings.append("\(error)")
        ret = false
        print("OCR Error: \(error)")
    }

    return ret
}

3. 优化回调处理逻辑

确保回调中正确处理所有候选结果,避免遗漏:

private func ocrCompleteCb(request: VNRequest, error: Error?) {
    mOcrResults.removeAll()
    
    guard let observations = request.results as? [VNRecognizedTextObservation] else {
        print("Unexpected observation type.")
        return
    }
    
    mLogger.consoleLogMsg("ocrCompleteCb \(observations.count) observations")
    
    for observation in observations {
        // 获取所有候选结果(不止top1),提升识别成功率
        for candidate in observation.topCandidates(3) {
            let recognizedText = candidate.string.trimmingCharacters(in: .whitespacesAndNewlines)
            if !recognizedText.isEmpty {
                mLogger.consoleLogMsg("Found: \(recognizedText)")
                mOcrResults.append(recognizedText)
                break // 取第一个有效结果即可
            }
        }
    }
}

4. 额外排查点

  • 检查TCP传输过程中是否损坏了图像数据,导致CGImage的属性丢失或格式异常
  • 测试将图片保存到本地后再识别,排除传输环节的问题

内容的提问来源于stack exchange,提问作者Danny

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.16 19:31:02