Swift 中使用.accurate精度的文本识别出现倒置读取(0606识别为9090)问题
Vision文本识别出现倒置结果的修复方案
问题根因
0606被识别为9090的异常,核心原因是送入Vision框架的图片未做方向校正:
Vision框架默认以「原点在左上角、无旋转」的图片为识别基准,但UIImage自带的方向元数据经常和实际像素方向不一致——你直接取image.cgImage传给识别器时,框架拿到的是带180度旋转的像素数据,就会把倒立的文本做正向识别。这种方向错位刚好匹配你遇到的识别结果:正向的0606整体倒置180度后,数字6会变为9,同时阅读顺序完全反转,最终被识别为9090。.accurate模式下框架对这类方向偏差的容错能力反而比.fast模式更差,不会自动帮你修正方向错位的问题。
具体修改步骤
- 第一步:给UIImage增加方向校正能力,把所有方向的图片统一转为
up方向的标准像素图
加入扩展方法实现方向归一化:extension UIImage { func normalizedCGImage() -> CGImage? { guard imageOrientation != .up else { return cgImage } var transform = CGAffineTransform.identity switch imageOrientation { case .down, .downMirrored: transform = transform.translatedBy(x: size.width, y: size.height).rotated(by: .pi) case .left, .leftMirrored: transform = transform.translatedBy(x: size.width, y: 0).rotated(by: .pi/2) case .right, .rightMirrored: transform = transform.translatedBy(x: 0, y: size.height).rotated(by: -.pi/2) default: break } guard let sourceCGImage = cgImage, let colorSpace = sourceCGImage.colorSpace else { return nil } let context = CGContext( data: nil, width: Int(size.width), height: Int(size.height), bitsPerComponent: sourceCGImage.bitsPerComponent, bytesPerRow: 0, space: colorSpace, bitmapInfo: sourceCGImage.bitmapInfo.rawValue ) context?.concatenate(transform) let drawRect: CGRect switch imageOrientation { case .left, .leftMirrored, .right, .rightMirrored: drawRect = CGRect(x: 0, y: 0, width: size.height, height: size.width) default: drawRect = CGRect(x: 0, y: 0, width: size.width, height: size.height) } context?.draw(sourceCGImage, in: drawRect) return context?.makeImage() } } - 第二步:替换原代码里直接取cgImage的逻辑
原代码中直接传入image.cgImage的部分,换成调用校正方法得到的标准化图片:DispatchQueue.global(qos: .userInitiated).async { // 替换原来的 guard let img = image.cgImage ... guard let normalizedImage = image.normalizedCGImage() else { fatalError("Missing valid image to scan") } let handler = VNImageRequestHandler(cgImage: normalizedImage, options: [:]) try? handler.perform([request]) } - 第三步:补充识别请求的必要配置,减少识别偏差
在设置识别精度的位置追加配置,避免框架做不必要的结果篡改:request.recognitionLevel = .accurate request.usesLanguageCorrection = false // 识别编码/数字场景下关闭语言校正,避免框架自动修改数字结果
额外代码优化点
- 你原代码中在识别闭包外定义
textString变量的逻辑存在问题:识别闭包是异步回调,多个识别结果会覆盖同一个外部变量,要把textString的初始化移到识别回调内部,按观察结果的实际坐标顺序拼接,不要靠循环顺序直接覆盖赋值 - 如果是从相机采集的识别场景,要同步确认相机输出帧的方向和当前设备方向匹配,不要把横置、倒置的帧直接送入识别流程
内容的提问来源于stack exchange,提问作者Omar Rayyan
相关产品推荐
相关产品推荐

