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
相关产品推荐
相关产品推荐

