您可以使用机器学习套件识别图片或视频中的文字,例如路牌的文字。此功能的主要特点包括:
文本识别 API | |
---|---|
说明 | 识别图片或视频中的拉丁字母文本。 |
SDK 名称 | Google |
实现 | 资源在构建时以静态方式关联到您的应用。 |
应用大小影响 | 约 20 MB |
性能 | 在大多数设备上都是实时的。 |
试试看
准备工作
- 在 Podfile 中添加以下机器学习套件 pod:
pod 'GoogleMLKit/TextRecognition','2.2.0'
- 安装或更新项目的 Pod 之后,请使用 Xcode 项目的
.xcworkspace
打开该项目。Xcode 12.4 版或更高版本支持机器学习套件。
1. 创建 TextRecognizer
实例
通过调用 TextRecognizer
实例+textRecognizer
创建 TextRecognizer
的实例:let textRecognizer = TextRecognizer.textRecognizer()
MLKTextRecognizer *textRecognizer = [MLKTextRecognizer textRecognizer];
2. 准备输入图片
将图片作为 UIImage
或 CMSampleBufferRef
传递给 TextRecognizer
的 process(_:completion:)
方法:
使用 UIImage
或 CMSampleBuffer
创建 VisionImage
对象。
如果您使用的是 UIImage
,请按以下步骤操作:
- 使用
UIImage
创建一个VisionImage
对象。请务必指定正确的.orientation
。let image = VisionImage(image: UIImage)
visionImage.orientation = image.imageOrientationMLKVisionImage *visionImage = [[MLKVisionImage alloc] initWithImage:image];
visionImage.orientation = image.imageOrientation;
如果您使用的是 CMSampleBuffer
,请按以下步骤操作:
-
指定
CMSampleBuffer
中包含的图片数据的方向。如需获取图片方向,请按以下步骤操作:
func imageOrientation(
deviceOrientation: UIDeviceOrientation,
cameraPosition: AVCaptureDevice.Position
) -> UIImage.Orientation {
switch deviceOrientation {
case .portrait:
return cameraPosition == .front ? .leftMirrored : .right
case .landscapeLeft:
return cameraPosition == .front ? .downMirrored : .up
case .portraitUpsideDown:
return cameraPosition == .front ? .rightMirrored : .left
case .landscapeRight:
return cameraPosition == .front ? .upMirrored : .down
case .faceDown, .faceUp, .unknown:
return .up
}
}
- (UIImageOrientation)
imageOrientationFromDeviceOrientation:(UIDeviceOrientation)deviceOrientation
cameraPosition:(AVCaptureDevicePosition)cameraPosition {
switch (deviceOrientation) {
case UIDeviceOrientationPortrait:
return cameraPosition == AVCaptureDevicePositionFront ? UIImageOrientationLeftMirrored
: UIImageOrientationRight;
case UIDeviceOrientationLandscapeLeft:
return cameraPosition == AVCaptureDevicePositionFront ? UIImageOrientationDownMirrored
: UIImageOrientationUp;
case UIDeviceOrientationPortraitUpsideDown:
return cameraPosition == AVCaptureDevicePositionFront ? UIImageOrientationRightMirrored
: UIImageOrientationLeft;
case UIDeviceOrientationLandscapeRight:
return cameraPosition == AVCaptureDevicePositionFront ? UIImageOrientationUpMirrored
: UIImageOrientationDown;
case UIDeviceOrientationUnknown:
case UIDeviceOrientationFaceUp:
case UIDeviceOrientationFaceDown:
return UIImageOrientationUp;
}
}
- 使用
CMSampleBuffer
对象和屏幕方向创建一个VisionImage
对象:let image = VisionImage(buffer: sampleBuffer)
image.orientation = imageOrientation(
deviceOrientation: UIDevice.current.orientation,
cameraPosition: cameraPosition)MLKVisionImage *image = [[MLKVisionImage alloc] initWithBuffer:sampleBuffer];
image.orientation =
[self imageOrientationFromDeviceOrientation:UIDevice.currentDevice.orientation
cameraPosition:cameraPosition];
3. 处理图片
然后,将图片传递给 process(_:completion:)
方法:
textRecognizer.process(visionImage) { result, error in
guard error == nil, let result = result else {
// Error handling
return
}
// Recognized text
}
[textRecognizer processImage:image
completion:^(MLKText *_Nullable result,
NSError *_Nullable error) {
if (error != nil || result == nil) {
// Error handling
return;
}
// Recognized text
}];
4. 从识别出的文本块中提取文本
如果文本识别操作成功,它将返回一个 Text
对象。Text
对象包含图片中识别到的完整文本以及零个或零个以上的 TextBlock
对象。
每个 TextBlock
表示一个矩形文本块,其中包含零个或零个以上的 TextLine
对象。每个 TextLine
对象包含零个或多个 TextElement
对象,这些对象表示字词和类似字词的实体,例如日期和数字。
对于每个 TextBlock
、TextLine
和 TextElement
对象,您可以获取区域中识别出的文本以及该区域的边界坐标。
例如:
let resultText = result.text
for block in result.blocks {
let blockText = block.text
let blockLanguages = block.recognizedLanguages
let blockCornerPoints = block.cornerPoints
let blockFrame = block.frame
for line in block.lines {
let lineText = line.text
let lineLanguages = line.recognizedLanguages
let lineCornerPoints = line.cornerPoints
let lineFrame = line.frame
for element in line.elements {
let elementText = element.text
let elementCornerPoints = element.cornerPoints
let elementFrame = element.frame
}
}
}
NSString *resultText = result.text;
for (MLKTextBlock *block in result.blocks) {
NSString *blockText = block.text;
NSArray<MLKTextRecognizedLanguage *> *blockLanguages = block.recognizedLanguages;
NSArray<NSValue *> *blockCornerPoints = block.cornerPoints;
CGRect blockFrame = block.frame;
for (MLKTextLine *line in block.lines) {
NSString *lineText = line.text;
NSArray<MLKTextRecognizedLanguage *> *lineLanguages = line.recognizedLanguages;
NSArray<NSValue *> *lineCornerPoints = line.cornerPoints;
CGRect lineFrame = line.frame;
for (MLKTextElement *element in line.elements) {
NSString *elementText = element.text;
NSArray<NSValue *> *elementCornerPoints = element.cornerPoints;
CGRect elementFrame = element.frame;
}
}
}
输入图片准则
-
为了使机器学习套件准确识别文本,输入图片必须包含由足够像素数据表示的文本。理想情况下,每个字符至少应为 16x16 像素。通常情况下,大于 24x24 像素的字符在准确性上没有任何益处。
例如,640x480 像素的图片可能非常适合用于扫描占据图片整个宽度的名片。如需扫描打印在信纸大小纸张上的文档,可能需要 720x1280 像素的图片。
-
图片聚焦不良会影响文本识别的准确性。如果您无法获得可接受的结果,请尝试让用户重新捕获图片。
-
如果您是在实时应用中识别文本,则应考虑输入图片的整体尺寸。较小图片的处理速度会更快。为了缩短延迟时间,请确保文本在图像中占据尽可能多的空间,并以较低的分辨率捕获图片(请注意上述准确性要求)。如需了解详情,请参阅性能提升技巧。
效果提升技巧
- 如需处理视频帧,请使用检测器的
results(in:)
同步 API。从AVCaptureVideoDataOutputSampleBufferDelegate
的captureOutput(_, didOutput:from:)
函数调用此方法,以从指定视频帧同步获取结果。将AVCaptureVideoDataOutput
的alwaysDiscardsLateVideoFrames
保留为true
,以限制对检测器的调用。如果在检测器运行时有新视频帧可用,该帧将被丢弃。 - 如果要将检测器的输出作为图形叠加在输入图片上,请先从机器学习套件获取结果,然后在一个步骤中完成图片的呈现和叠加。采用这一方法,每个已处理的输入帧只需在显示表面呈现一次。如需查看示例,请参阅机器学习套件快速入门示例中的 updatePreviewOverlayViewWithLastFrame。
- 建议以较低分辨率捕获图片,不过,您也要牢记此 API 的图片尺寸要求。