8

我想使用VNDetectTextRectanglesRequestVision 框架来检测图像中的区域,该图像仅包含一个字符,数字“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")
}

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

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

4

1 回答 1

1

在 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-stroke-width-transform/ 。SWT 旨在处理“自然”图像,例如在户外看到的文本。

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

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