VNRecognizeTextRequest的minimumTextHeight参数无效果问题咨询
为什么VNRecognizeTextRequest的minimumTextHeight参数不生效?
我用VNRecognizeTextRequest处理来自DocumentCameraViewController的图片文本识别,传入minimumTextHeight参数后,不管设0.9还是0.1,识别到的文本(包含大小字号)数量完全一致。我只想识别标题这类大字号文本,请问这个参数为啥不起作用?
我的代码如下:
fileprivate func recognizeText(from images: [CGImage], minimumTextHeight:Float) -> String { var entireRecognizedText = "" let recognizeTextRequest = VNRecognizeTextRequest { (request, error) in guard error == nil else { return } guard let observations = request.results as? [VNRecognizedTextObservation] else { return } let maximumRecognitionCandidates = 1 for observation in observations { guard let candidate = observation.topCandidates(maximumRecognitionCandidates).first else { continue } entireRecognizedText += "\(candidate.string)\n" // show location of text in frame let stringRange = candidate.string.startIndex..<candidate.string.endIndex let boxObservation = try? candidate.boundingBox(for: stringRange) let boundingBox = boxObservation?.boundingBox ?? .zero print(candidate.string, boundingBox.origin.x, boundingBox.origin.y) } } recognizeTextRequest.revision = VNRecognizeTextRequestRevision3 recognizeTextRequest.recognitionLevel = .accurate recognizeTextRequest.minimumTextHeight = minimumTextHeight recognizeTextRequest.recognitionLanguages = ["en-US", "en-GB", "de-DE"] for image in images { let requestHandler = VNImageRequestHandler(cgImage: image, options: [:]) try? requestHandler.perform([recognizeTextRequest]) } return entireRecognizedText }
原因分析
- 参数是相对比例而非绝对像素:
minimumTextHeight的取值是文本高度相对于整个图像高度的归一化比例,不是实际像素值。比如如果你的图像分辨率是3000x2000,0.1对应的实际高度是200像素,如果小字号文本高度刚好超过200像素,就会被识别出来,导致参数看起来没效果。 - 针对单个字符而非整行文本:在VNRecognizeTextRequestRevision3中,这个参数过滤的是单个字符的高度,不是整行文本的高度。如果小字号的单个字符高度达标,整行都会被保留。
- 图像自动缩放干扰计算:
VNImageRequestHandler默认会对图像做预处理缩放,可能改变文本的相对高度比例,导致参数判断失效。
解决方案
- 正确计算归一化比例:先确定你要识别的最小文本高度(像素值),再除以图像的总高度得到比例。比如想要识别至少150像素高的文本,图像高度是2000,就设置
minimumTextHeight = 150/2000 = 0.075。 - 手动过滤观测结果:如果参数自带的过滤逻辑不满足需求,在遍历
VNRecognizedTextObservation时,手动计算文本的实际像素高度并过滤:for observation in observations { guard let candidate = observation.topCandidates(maximumRecognitionCandidates).first else { continue } // 计算文本实际高度 let imageHeight = CGFloat(image.height) let textBoundingBox = try? candidate.boundingBox(for: candidate.string.startIndex..<candidate.string.endIndex)?.boundingBox ?? .zero let actualTextHeight = textBoundingBox.size.height * imageHeight // 过滤低于阈值的文本 if actualTextHeight < 150 { // 这里150是你需要的最小像素高度 continue } entireRecognizedText += "\(candidate.string)\n" print(candidate.string, textBoundingBox.origin.x, textBoundingBox.origin.y) } - 关闭自动缩放:初始化
VNImageRequestHandler时指定缩放因子为1.0,避免框架自动缩放影响高度计算:let options: [VNImageOption: Any] = [.scaleFactor: 1.0] let requestHandler = VNImageRequestHandler(cgImage: image, options: options) - 调整识别模式:把
recognitionLevel从.accurate改成.fast,后者会更倾向于合并文本块,更容易通过高度过滤整行大字号文本。
内容的提问来源于stack exchange,提问作者CraigH
相关产品推荐
相关产品推荐

