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

如何获取Apple VNRecognizeTextRequest检测结果的文本方向

如何获取Apple VNRecognizeTextRequest检测结果的文本方向

嘿,我来帮你搞定这个问题!很多人用VNRecognizeTextRequest识别文本时都会疑惑怎么拿到文本的方向,其实只要结合识别结果里的观测对象,再配合你设置的图像方向,就能轻松判断出来~

首先,先把你没写完的识别代码补全,关键是要在请求的回调里处理识别结果,拿到每个文本的观测数据:

func detectText(from ciImage: CIImage) {
    // 你这里设置了图像orientation为.down,因为输入的CIImage是倒的,这个参数一定要和实际图像方向匹配!
    let requestHandler = VNImageRequestHandler(ciImage: ciImage, orientation: .down, options: [:])
    
    let request = VNRecognizeTextRequest { request, error in
        // 先把识别结果转成VNRecognizedTextObservation数组,这是核心的观测对象
        guard let observations = request.results as? [VNRecognizedTextObservation], error == nil else {
            print("识别出错:\(error?.localizedDescription ?? "未知错误")")
            return
        }
        
        // 遍历每一个识别到的文本块
        for observation in observations {
            // 取置信度最高的文本结果
            guard let topText = observation.topCandidates(1).first else { continue }
            print("识别到的文本:\(topText.string)")
            
            // 调用方法判断这个文本块的方向
            self.judgeTextOrientation(observation: observation, imageOrientation: .down)
        }
    }
    
    // 可以根据需求设置识别精度,.accurate是高精度,.fast是快速识别
    request.recognitionLevel = .accurate
    
    do {
        try requestHandler.perform([request])
    } catch {
        print("执行识别请求失败:\(error.localizedDescription)")
    }
}

接下来就是核心的方向判断方法,这里有两种思路,都给你列出来:

方法一:通过文本边界框的宽高比判断

Vision框架返回的boundingBox是基于图像坐标系的(原点在图像左下角),我们可以通过边界框的宽高比例,再结合你传入的图像原始方向,就能大致判断文本是水平还是垂直:

func judgeTextOrientation(observation: VNRecognizedTextObservation, imageOrientation: CGImagePropertyOrientation) {
    let textBox = observation.boundingBox
    // 宽大于高,说明文本是横向排列;反之是纵向
    let isHorizontal = textBox.size.width > textBox.size.height
    
    // 结合图像的原始方向,推导文本的实际显示方向
    switch imageOrientation {
    case .up:
        let direction = isHorizontal ? "水平方向(从左到右)" : "垂直方向(从上到下)"
        print("文本方向:\(direction)")
    case .down:
        // 图像是倒着的,所以水平文本实际是从右到左,垂直文本是从下到上
        let direction = isHorizontal ? "水平方向(从右到左)" : "垂直方向(从下到上)"
        print("文本方向:\(direction)")
    case .left:
        // 图像左转90度,此时宽高比的判断要反过来,宽大于高其实是垂直文本
        let direction = isHorizontal ? "垂直方向(从下到上)" : "水平方向(从右到左)"
        print("文本方向:\(direction)")
    case .right:
        // 图像右转90度,同理宽大于高是垂直文本
        let direction = isHorizontal ? "垂直方向(从上到下)" : "水平方向(从左到右)"
        print("文本方向:\(direction)")
    default:
        print("暂时无法确定该图像方向下的文本走向")
    }
}

方法二:用字符边界框精准判断(iOS 16+可用)

如果你用的是iOS 16及以上系统,VNRecognizedTextObservation还提供了characterBoxes属性,能拿到每个字符的边界框,通过字符的排列顺序可以更精准判断方向,比如看第一个字符和最后一个字符的X坐标:

func judgeTextOrientationPrecisely(observation: VNRecognizedTextObservation) {
    guard let charBoxes = observation.characterBoxes, !charBoxes.isEmpty else {
        print("无法获取字符边界框,无法精准判断方向")
        return
    }
    
    let firstChar = charBoxes.first!
    let lastChar = charBoxes.last!
    // 第一个字符的X坐标小于最后一个,说明是从左到右排列
    let isLeftToRight = firstChar.boundingBox.minX < lastChar.boundingBox.minX
    // 再结合字符框的宽高比,判断是水平还是垂直
    let isHorizontal = firstChar.boundingBox.size.width > firstChar.boundingBox.size.height
    
    if isHorizontal {
        print("精准判断:\(isLeftToRight ? "水平从左到右" : "水平从右到左")")
    } else {
        print("精准判断:\(isLeftToRight ? "垂直从上到下" : "垂直从下到上")")
    }
}

最后要提醒你:创建VNImageRequestHandler时设置的orientation参数一定要和你的输入图像实际方向完全匹配,否则Vision框架识别出来的文本边界框和方向都会出错,这是很多人踩坑的点哦!

内容来源于stack exchange

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.04.08 13:03:05