如何获取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
相关产品推荐
相关产品推荐

