You need to enable JavaScript to run this app.
最新活动
大模型
产品
解决方案
定价
生态与合作
支持与服务
开发者
了解我们

使用Vision框架VNDetectTextRectanglesRequest无法识别单双数字问题

为什么VNDetectTextRectanglesRequest无法识别白背景下的单个/两位数字?

我尝试使用Vision框架的VNDetectTextRectanglesRequest识别白背景下仅含单个数字“9”的图像文本区域,但实际运行后observations结果数量为0。奇怪的是,黑背景下的数字“123”可以被正常识别,而且白背景下的两位数字“22”也无法被识别,只有3位及以上的数字才能在白背景下被检测到。

我的检测代码如下:

private func performTextDetection() { 
    let textRequest = VNDetectTextRectanglesRequest(completionHandler: self.detectTextHandler) 
    textRequest.reportCharacterBoxes = true 
    textRequest.preferBackgroundProcessing = false 
    let handler = VNImageRequestHandler(cgImage: loadedImage.cgImage!, options: [:]) 
    DispatchQueue.global(qos: .userInteractive).async { 
        do { 
            try handler.perform([textRequest]) 
        } catch { 
            print ("Error") 
        } 
    } 
} 

func detectTextHandler(request: VNRequest, error: Error?) { 
    guard let observations = request.results, !observations.isEmpty else { 
        fatalError("no results") 
    } 
    print("there is result") 
}

请问这是什么原因导致的,该如何解决?


这个问题其实和VNDetectTextRectanglesRequest的默认检测阈值以及文本特征有关,我来拆解一下原因和解决方法:

核心原因

  1. 默认最小文本高度阈值过高VNDetectTextRectanglesRequest默认的minimumTextHeight参数值(通常是0.05,即文本高度占图像高度的5%)可能过滤掉了单个/两位数字这类较小的文本块。白背景下的单个数字本身视觉占比小,加上对比度的影响(黑底白字的对比度在视觉上更容易被检测模型捕捉),就会出现检测不到的情况。
  2. 文本块的特征匹配逻辑:Vision的文本检测模型更倾向于识别有连续字符的文本区域,单个或两个字符的文本块在白背景下的特征不够明显,容易被模型判定为非文本区域。

解决方法

1. 调整最小文本高度阈值

显式设置minimumTextHeight为更小的值,比如0.01(根据你的图像实际尺寸调整,确保数字高度占比至少达到这个值):

private func performTextDetection() { 
    let textRequest = VNDetectTextRectanglesRequest(completionHandler: self.detectTextHandler) 
    textRequest.reportCharacterBoxes = true 
    textRequest.preferBackgroundProcessing = false 
    // 调整最小文本高度阈值,适配小尺寸数字
    textRequest.minimumTextHeight = 0.01 
    let handler = VNImageRequestHandler(cgImage: loadedImage.cgImage!, options: [:]) 
    DispatchQueue.global(qos: .userInteractive).async { 
        do { 
            try handler.perform([textRequest]) 
        } catch { 
            print ("Error") 
        } 
    } 
}

2. 增强图像对比度(可选)

如果调整阈值后还是检测不到,可以尝试反转图像(将白底黑字转为黑底白字),因为Vision对黑底白字的文本检测兼容性更好:

// 反转图像的示例代码
func invertedImage(from image: UIImage) -> UIImage? {
    guard let cgImage = image.cgImage else { return nil }
    let ciImage = CIImage(cgImage: cgImage)
    guard let filter = CIFilter(name: "CIColorInvert") else { return nil }
    filter.setValue(ciImage, forKey: kCIInputImageKey)
    guard let outputImage = filter.outputImage else { return nil }
    return UIImage(ciImage: outputImage)
}

// 在performTextDetection中使用反转后的图像
let invertedImg = invertedImage(from: loadedImage)!
let handler = VNImageRequestHandler(cgImage: invertedImg.cgImage!, options: [:])

3. 检查图像分辨率

确保你的输入图像分辨率足够,数字的实际像素高度不要太小(比如至少20像素以上)。如果图像分辨率太低,可以先对图像进行放大处理后再检测。

额外提示

如果你不仅需要检测文本区域,还需要识别数字内容,可以考虑使用VNRecognizeTextRequest,它的文本检测逻辑对小字符的兼容性也更好,同时能直接返回识别出的文本内容。


内容的提问来源于stack exchange,提问作者AndrzejZ

火山引擎 最新活动