Nhận dạng văn bản trong hình ảnh bằng Bộ công cụ học máy trên iOS

Bạn có thể dùng Bộ công cụ học máy để nhận dạng văn bản trong hình ảnh hoặc video, chẳng hạn như văn bản trên biển báo đường phố. Các đặc điểm chính của tính năng này là:

API Nhận dạng văn bản phiên bản 2
Mô tảNhận dạng văn bản trong hình ảnh hoặc video, hỗ trợ các hệ chữ Latinh, Trung Quốc, Devanagari, Nhật Bản và Hàn Quốc cũng như nhiều ngôn ngữ.
Tên SDKGoogleMLKit/TextRecognition
GoogleMLKit/TextRecognitionChinese
GoogleMLKit/TextRecognitionDevanagari
GoogleMLKit/TextRecognitionJapanese
GoogleMLKit/TextRecognitionKorean
Triển khaiCác thành phần được liên kết tĩnh với ứng dụng của bạn trong thời gian xây dựng
Tác động đến kích thước ứng dụngKhoảng 38 MB cho mỗi SDK tập lệnh
Hiệu suấtTheo thời gian thực trên hầu hết các thiết bị đối với SDK hệ chữ Latinh, chậm hơn đối với các hệ chữ khác.

Dùng thử

Trước khi bắt đầu

  1. Đưa các nhóm Bộ công cụ học máy sau đây vào Podfile:
    # To recognize Latin script
    pod 'GoogleMLKit/TextRecognition', '8.0.0'
    # To recognize Chinese script
    pod 'GoogleMLKit/TextRecognitionChinese', '8.0.0'
    # To recognize Devanagari script
    pod 'GoogleMLKit/TextRecognitionDevanagari', '8.0.0'
    # To recognize Japanese script
    pod 'GoogleMLKit/TextRecognitionJapanese', '8.0.0'
    # To recognize Korean script
    pod 'GoogleMLKit/TextRecognitionKorean', '8.0.0'
    
  2. Sau khi cài đặt hoặc cập nhật các nhóm của dự án, hãy mở dự án Xcode bằng .xcworkspace. Bộ công cụ học máy được hỗ trợ trong Xcode phiên bản 12.4 trở lên.

1. Tạo một thực thể của TextRecognizer

Tạo một thực thể của TextRecognizer bằng cách gọi +textRecognizer(options:), truyền các tuỳ chọn liên quan đến SDK mà bạn đã khai báo là phần phụ thuộc ở trên:

Swift

// When using Latin script recognition SDK
let latinOptions = TextRecognizerOptions()
let latinTextRecognizer = TextRecognizer.textRecognizer(options:options)

// When using Chinese script recognition SDK
let chineseOptions = ChineseTextRecognizerOptions()
let chineseTextRecognizer = TextRecognizer.textRecognizer(options:options)

// When using Devanagari script recognition SDK
let devanagariOptions = DevanagariTextRecognizerOptions()
let devanagariTextRecognizer = TextRecognizer.textRecognizer(options:options)

// When using Japanese script recognition SDK
let japaneseOptions = JapaneseTextRecognizerOptions()
let japaneseTextRecognizer = TextRecognizer.textRecognizer(options:options)

// When using Korean script recognition SDK
let koreanOptions = KoreanTextRecognizerOptions()
let koreanTextRecognizer = TextRecognizer.textRecognizer(options:options)

Objective-C

// When using Latin script recognition SDK
MLKTextRecognizerOptions *latinOptions = [[MLKTextRecognizerOptions alloc] init];
MLKTextRecognizer *latinTextRecognizer = [MLKTextRecognizer textRecognizerWithOptions:options];

// When using Chinese script recognition SDK
MLKChineseTextRecognizerOptions *chineseOptions = [[MLKChineseTextRecognizerOptions alloc] init];
MLKTextRecognizer *chineseTextRecognizer = [MLKTextRecognizer textRecognizerWithOptions:options];

// When using Devanagari script recognition SDK
MLKDevanagariTextRecognizerOptions *devanagariOptions = [[MLKDevanagariTextRecognizerOptions alloc] init];
MLKTextRecognizer *devanagariTextRecognizer = [MLKTextRecognizer textRecognizerWithOptions:options];

// When using Japanese script recognition SDK
MLKJapaneseTextRecognizerOptions *japaneseOptions = [[MLKJapaneseTextRecognizerOptions alloc] init];
MLKTextRecognizer *japaneseTextRecognizer = [MLKTextRecognizer textRecognizerWithOptions:options];

// When using Korean script recognition SDK
MLKKoreanTextRecognizerOptions *koreanOptions = [[MLKKoreanTextRecognizerOptions alloc] init];
MLKTextRecognizer *koreanTextRecognizer = [MLKTextRecognizer textRecognizerWithOptions:options];

2. Chuẩn bị hình ảnh đầu vào

Truyền hình ảnh dưới dạng UIImage hoặc CMSampleBufferRef đến phương thức process(_:completion:) của TextRecognizer:

Tạo đối tượng VisionImage bằng UIImage hoặc CMSampleBuffer.

Nếu bạn sử dụng UIImage, hãy làm theo các bước sau:

  • Tạo đối tượng VisionImage bằng UIImage. Đảm bảo bạn chỉ định .orientation chính xác.

    Swift

    let image = VisionImage(image: UIImage)
    visionImage.orientation = image.imageOrientation

    Objective-C

    MLKVisionImage *visionImage = [[MLKVisionImage alloc] initWithImage:image];
    visionImage.orientation = image.imageOrientation;

Nếu bạn sử dụng CMSampleBuffer, hãy làm theo các bước sau:

  • Chỉ định hướng của dữ liệu hình ảnh có trong the CMSampleBuffer.

    Cách lấy hướng hình ảnh:

    Swift

    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
      }
    }
          

    Objective-C

    - (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;
      }
    }
          
  • Tạo đối tượng VisionImage bằng đối tượng CMSampleBuffer và hướng:

    Swift

    let image = VisionImage(buffer: sampleBuffer)
    image.orientation = imageOrientation(
      deviceOrientation: UIDevice.current.orientation,
      cameraPosition: cameraPosition)

    Objective-C

     MLKVisionImage *image = [[MLKVisionImage alloc] initWithBuffer:sampleBuffer];
     image.orientation =
       [self imageOrientationFromDeviceOrientation:UIDevice.currentDevice.orientation
                                    cameraPosition:cameraPosition];

3. Xử lý hình ảnh

Sau đó, hãy truyền hình ảnh đến phương thức process(_:completion:):

Swift

textRecognizer.process(visionImage) { result, error in
  guard error == nil, let result = result else {
    // Error handling
    return
  }
  // Recognized text
}

Objective-C

[textRecognizer processImage:image
                  completion:^(MLKText *_Nullable result,
                               NSError *_Nullable error) {
  if (error != nil || result == nil) {
    // Error handling
    return;
  }
  // Recognized text
}];

4. Trích xuất văn bản từ các khối văn bản được nhận dạng

Nếu thao tác nhận dạng văn bản thành công, thao tác này sẽ trả về đối tượng Text. Đối tượng Text chứa toàn bộ văn bản được nhận dạng trong hình ảnh và không hoặc nhiều đối tượng TextBlock.

Mỗi TextBlock đại diện cho một khối văn bản hình chữ nhật, chứa không hoặc nhiều đối tượng TextLine. Mỗi TextLine đối tượng chứa không hoặc nhiều TextElement đối tượng, đại diện cho các từ và thực thể giống như từ, chẳng hạn như ngày và số.

Đối với mỗi đối tượng TextBlock, TextLineTextElement, bạn có thể lấy văn bản được nhận dạng trong khu vực và toạ độ giới hạn của khu vực đó.

Ví dụ:

Swift

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
        }
    }
}

Objective-C

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;
    }
  }
}

Nguyên tắc về hình ảnh đầu vào

  • Để Bộ công cụ học máy nhận dạng văn bản một cách chính xác, hình ảnh đầu vào phải chứa văn bản được biểu thị bằng đủ dữ liệu pixel. Tốt nhất là mỗi ký tự phải có kích thước tối thiểu là 16x16 pixel. Thông thường, không có lợi ích nào về độ chính xác khi các ký tự lớn hơn 24x24 pixel.

    Vì vậy, ví dụ: hình ảnh 640x480 có thể hoạt động tốt để quét danh thiếp chiếm toàn bộ chiều rộng của hình ảnh. Để quét tài liệu được in trên giấy cỡ thư, có thể bạn cần hình ảnh 720x1280 pixel.

  • Tiêu điểm hình ảnh kém có thể ảnh hưởng đến độ chính xác của việc nhận dạng văn bản. Nếu bạn không nhận được kết quả chấp nhận được, hãy yêu cầu người dùng chụp lại hình ảnh.

  • Nếu đang nhận dạng văn bản trong ứng dụng theo thời gian thực, bạn nên cân nhắc kích thước tổng thể của hình ảnh đầu vào. Hình ảnh nhỏ hơn có thể được xử lý nhanh hơn. Để giảm độ trễ, hãy đảm bảo văn bản chiếm càng nhiều hình ảnh càng tốt và chụp ảnh ở độ phân giải thấp hơn (lưu ý đến các yêu cầu về độ chính xác đã đề cập ở trên). Để biết thêm thông tin, hãy xem Mẹo cải thiện hiệu suất.

Mẹo cải thiện hiệu suất

  • Để xử lý khung video, hãy sử dụng API đồng bộ results(in:) của trình phát hiện. Gọi phương thức này từ AVCaptureVideoDataOutputSampleBufferDelegate's captureOutput(_, didOutput:from:) hàm để đồng bộ nhận kết quả từ khung video đã cho. Giữ AVCaptureVideoDataOutput của alwaysDiscardsLateVideoFrames ở trạng thái true để điều tiết các lệnh gọi đến trình phát hiện. Nếu có một khung video mới trong khi trình phát hiện đang chạy, khung đó sẽ bị loại bỏ.
  • Nếu bạn dùng kết quả của trình phát hiện để phủ đồ hoạ lên hình ảnh đầu vào, trước tiên, hãy lấy kết quả từ Bộ công cụ học máy, sau đó hiển thị hình ảnh và lớp phủ trong một bước. Bằng cách đó, bạn chỉ hiển thị lên bề mặt hiển thị một lần cho mỗi khung đầu vào đã xử lý. Hãy xem updatePreviewOverlayViewWithLastFrame trong mẫu bắt đầu nhanh của Bộ công cụ học máy để biết ví dụ.
  • Cân nhắc chụp ảnh ở độ phân giải thấp hơn. Tuy nhiên, bạn cũng cần lưu ý đến các yêu cầu về kích thước hình ảnh của API này.
  • Để tránh làm giảm hiệu suất tiềm ẩn, đừng chạy đồng thời nhiều TextRecognizer thực thể có các tuỳ chọn tập lệnh khác nhau.