视觉,VNDetectTextRectanglesRequest-无法将单个数字识别为区域

And*_*ejZ 5 ocr mobile ios swift apple-vision

我想VNDetectTextRectanglesRequest从Vision框架中使用它来检测仅包含一个字符(数字为“ 9”)且带有白色背景的图像中的区域。我正在使用以下代码来做到这一点:

 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")
}
Run Code Online (Sandbox Code Playgroud)

我得到的观察结果数为0,但是,如果我在黑色背景上提供带有文本“ 123”的图像,则会将“ 123”检测为文本区域。所描述的问题也出现在2位数字上,白色背景上的'22'也没有被检测到。

在我的情况下,为什么Vision API在白色背景上只能检测到3位以上的数字?

Ret*_*unk 2

在 XCode 12.5 和 Swift 5 中,长字符仍然是 VNRecognizeTextRequest 和 VNDetectTextRectanglesRequest 的问题。

我见过 VNDetectTextRectanglesRequest 几乎可以找到一张纸上的所有单个单词,但无法检测到单独的字符(处理整个图像时)。将属性 VNDetectTextRectanglesRequest.regionOfInterest 设置为较小的区域可能会有所帮助。

对我有用的是让单个字符占据 VNRecognizeTextRequest 的更多感兴趣区域(ROI)。我在各种高度上测试了单个字符,很明显,一旦单个字符在 ROI 内达到一定大小,它们就会开始阅读。

对于某些单个字符,当 ROI 大约为字符本身宽度的三倍和高度的三倍时,似乎会发生检测。这是一个相当严格的兴趣区域。正确放置是另一个问题,但也是可以解决的。

如果处理时间对您的应用程序来说不是问题,您可以创建一个跨越怀疑包含单独字符的区域的数组 [CGRect]。

我怀疑,当 VNRecognizeTextRequest 对边缘内容、边缘密度和/或类似于笔划的图像特征执行初始检查时,如果没有找到足够的候选者,它会提前退出。该初始检查可能只是嵌入的 VNDetectTextRectanglesRequest。无论初始检查是什么,它运行得很快,所以我不认为它有那么复杂。

有关笔画检测以查找字符的更多信息,请搜索有关笔画宽度变换的 SO 帖子和文章。还有这个: https: //www.microsoft.com/en-us/research/publication/detecting-text-in-natural-scenes-with-rinkle-width-transform/。SWT 旨在处理“自然”图像,例如户外看到的文本。

有一些技巧可以解决这个问题。其中一些黑客行为令人不快,但对于特定的应用程序来说,它们可能是值得的。

  • 创建小感兴趣区域 (ROI) 的网格。在一个又一个 ROI 上运行文本请求。
  • 作为 VNDetectTextRectanglesRequest 的廉价替代品,查找具有表明可能存在单个字符的边缘内容的图像区域。如果不出意外,这可能有助于忽略没有边缘内容的区域。
  • 在处理图像之前尝试使用缩放滤镜来放大图像。这可以确保单个字符足够大以便阅读。(对于 CIFilters,一个非常方便的资源是https://cifilter.io/
  • 对图像运行多次传递。首先,对完整图像运行 OCR。然后获取已读单词的边界框。寻找盒子之间的可疑间隙。在可疑的空白区域上运行小 ROI 网格。
  • 使用 Tesseract 作为备份。(https://www.seemuapps.com/swift-optical-character-recognition-tutorial
  • 如果图像中存在单个字符的多个实例,但您只想读取一个字符,请处理整个图像以获取所有字符,然后(在代码中)选择所需的字符。

2024 年更新:在没有更改我的代码的情况下,VNRecognizeTextRequest似乎在识别单个字符方面做得更好。我猜底层模型已经随着 iOS 新版本的更新而更新,但我不知道。