我在 OCR 服务器中使用
VNRecognizeTextRequest
,该服务器通过 TCP 接受图像、执行 OCR 并返回提取的文本。目标是支持所有语言,但中文有问题。
总体工作完美,但有一些图像返回零观察结果,即OCR失败。
但是,如果我在预览中打开这些图像,我可以选择文本并将其复制到剪贴板。我假设 MacOs 预览应用程序使用相同的
VNRecognize
OCR 框架,因此令人困惑的是为什么 OCR 在预览中成功,但在 Swift 程序中使用 VNRecognizeTextRequest
时失败。
这里有两张图像,显示我可以从 Preview.app 中的图像中选择和复制文本:
环境是MacOS 15.0.1(这是一个MacOS应用程序,而不是iOS)
这是代码。 我尝试过
VNRecognizeTextRequest.usesLanguageCorrection
和 VNRecognizeTextRequest.recognitionLanguages
的各种组合,但在上面的两张图片上会失败。
关于如何更改以使程序与 Preview.app 的行为相匹配,有什么建议吗? 我会将原始图像放在这篇文章的底部。
public func doOcr(image: CGImage, outStrings: inout [String]) async -> Bool
{
var ret = true
let ocrRequest = VNRecognizeTextRequest(completionHandler: ocrCompleteCb)
ocrRequest.recognitionLevel = .accurate
ocrRequest.automaticallyDetectsLanguage = true
ocrRequest.customWords = ["…", "᠁", "..."]
ocrRequest.usesLanguageCorrection = false
print("usesLanguageCorrection: \(ocrRequest.usesLanguageCorrection)")
//ocrRequest.recognitionLanguages = ["zh-Hant"];
let imageRequestHandler = VNImageRequestHandler(cgImage: image)
do
{
try imageRequestHandler.perform([ocrRequest])
outStrings = mOcrResults
}
catch
{
outStrings.append("\(error)")
ret = false
print("OCR Error: \(error)")
}
return ret
}
private func ocrCompleteCb(request: VNRequest, error: Error?)
{
mOcrResults.removeAll()
// Handle the recognition results
guard let observations = request.results as? [VNRecognizedTextObservation] else
{
print("Unexpected observation type.")
return
}
// <<< Zero observations found on OCR failure >>>
mLogger.consoleLogMsg("ocrCompleteCb \(observations.count) observations")
for observation in observations
{
let topCandidate = observation.topCandidates(1).first
if let recognizedText = topCandidate?.string
{
mLogger.consoleLogMsg("Found: \(recognizedText)")
mOcrResults.append(recognizedText)
}
}
}
[
幸运的是,我发现在图像周围添加白边
VNRecognizeTextRequest
会起作用!
文本周围边距的大小似乎很重要。如果太小或太大,则无法识别文本。 我还没有找到边框尺寸的最佳位置。对于此特定图像,40 像素即可。
另外,我为
VNRecognizeTextRequest
设置了以下选项:
ocrRequest.recognitionLanguages = ["zh-Hans", "zh-Hant"] // ["en-US", "zh-Hans", "zh-Hant"];
ocrRequest.recognitionLevel = .accurate
ocrRequest.automaticallyDetectsLanguage = false
ocrRequest.usesLanguageCorrection = false