شناسایی کردن نوشتار در تصاویر با ML Kit در iOS

می‌توانید از ML Kit برای تشخیص نوشتار در تصاویر یا ویدیوها، مانند نوشتار روی تابلو خیابان، استفاده کنید. ویژگی‌های اصلی این قابلیت عبارت‌اند از:

Text Recognition v2 API
شرحتشخیص نوشتار در تصاویر یا ویدیوها، پشتیبانی از خط‌های لاتین، چینی، دواناگری، ژاپنی، و کره‌ای و طیف گسترده‌ای از زبان‌ها.
نام‌های کیت توسعه نرم‌افزارGoogleMLKit/TextRecognition
GoogleMLKit/TextRecognitionChinese
GoogleMLKit/TextRecognitionDevanagari
GoogleMLKit/TextRecognitionJapanese
GoogleMLKit/TextRecognitionKorean
پیاده‌سازیدارایی‌ها در زمان ساخت به‌طور ایستا به برنامه‌تان پیوند داده شده‌اند
تأثیر اندازه برنامهحدود ۳۸ مگابایت برای هر کیت توسعه نرم‌افزار اسکریپت
عملکرددر اکثر دستگاه‌ها برای کیت توسعه نرم‌افزار نویسه‌های لاتین هم‌زمان است، برای بقیه کندتر است.

امتحان کنید

  • با برنامه نمونه کار کنید تا نمونه‌ای از کاربرد این API را ببینید.
  • کد را خودتان با codelab امتحان کنید.

قبل‌از شروع

  1. پادهای ML Kit زیر را در 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. پس‌از نصب یا به‌روزرسانی Pods پروژه، پروژه Xcode را بااستفاده از .xcworkspace آن باز کنید. «کیت یادگیری ماشین» در Xcode نسخه ۱۲.۴ یا بالاتر پشتیبانی می‌شود.

۱. ایجاد نمونه‌ای از TextRecognizer

با فراخوانی +textRecognizer(options:)، نمونه‌ای از TextRecognizer ایجاد کنید و گزینه‌های مربوط به کیت توسعه نرم‌افزاری را که به‌عنوان وابستگی در بالا اعلام کرده‌اید ارسال کنید:

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)

آبجکتیو-سی

// 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];

۲. آماده کردن تصویر ورودی

تصویر را به‌عنوان UIImage یا CMSampleBufferRef به روش process(_:completion:) TextRecognizer ارسال کنید:

بااستفاده از UIImage یا CMSampleBuffer، شیء VisionImage ایجاد کنید.

اگر از UIImage استفاده می‌کنید، این مراحل را دنبال کنید:

  • یک شیء VisionImage با UIImage ایجاد کن. حتماً .orientation صحیح را مشخص کنید.

    Swift

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

    آبجکتیو-سی

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

اگر از CMSampleBuffer استفاده می‌کنید، این مراحل را دنبال کنید:

  • جهت داده‌های تصویر موجود در CMSampleBuffer را مشخص کنید.

    برای دریافت جهت تصویر:

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

    آبجکتیو-سی

    - (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;
      }
    }
          
  • ایجاد شیء VisionImage بااستفاده از شیء CMSampleBuffer و جهت:

    Swift

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

۳. پردازش تصویر

سپس تصویر را به روش process(_:completion:) ارسال کنید:

Swift

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

۴. استخراج نوشتار از بلوک‌های نوشتار تشخیص‌داده‌شده

اگر عملیات تشخیص نوشتار موفقیت‌آمیز باشد، شیء Text را برمی‌گرداند. شیء Text حاوی نوشتار کامل تشخیص‌داده‌شده در تصویر و صفر یا چند شیء TextBlock است.

هر TextBlock نشان‌دهنده یک بلوک مستطیلی از نوشتار است که حاوی صفر یا چند شیء TextLine است. هر شیء TextLine حاوی صفر یا چند شیء TextElement است، که نشان‌دهنده کلمات و نهادهای کلمه‌مانند مثل تاریخ و عدد است.

برای هر شیء TextBlock، TextLine، و TextElement، می‌توانید نوشتار تشخیص‌داده‌شده در منطقه و مختصات مرزی منطقه را دریافت کنید.

برای مثال:

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

آبجکتیو-سی

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

دستورالعمل‌های تصویر ورودی

  • برای اینکه ML Kit بتواند نوشتار را به‌درستی تشخیص دهد، تصاویر ورودی باید حاوی نوشتاری باشند که با داده‌های پیکسلی کافی نمایش داده شده است. در حالت ایده‌آل، هر نویسه باید حداقل ۱۶×۱۶ پیکسل باشد. به‌طور کلی، بزرگ‌تر بودن نویسه‌ها از ۲۴×۲۴ پیکسل تأثیری بر دقت ندارد.

    بنابراین، برای مثال، تصویری با ابعاد ۶۴۰ در ۴۸۰ ممکن است برای اسکن کارت کسب‌وکاری که کل عرض تصویر را اشغال می‌کند، مناسب باشد. برای اسکن کردن سندی که روی کاغذ اندازه نامه چاپ شده است، ممکن است به تصویری با ابعاد ۷۲۰×۱۲۸۰ پیکسل نیاز باشد.

  • فوکوس ضعیف تصویر می‌تواند بر دقت تشخیص نوشتار تأثیر بگذارد. اگر نتایج قابل‌قبولی دریافت نمی‌کنید، از کاربر بخواهید تصویر را دوباره بگیرد.

  • اگر درحال تشخیص نوشتار در برنامه‌ای هم‌زمان هستید، باید ابعاد کلی تصاویر ورودی را درنظر بگیرید. تصاویر کوچک‌تر سریع‌تر پردازش می‌شوند. برای کاهش تأخیر، مطمئن شوید که نوشتار تا حد امکان بخش بیشتری از تصویر را اشغال می‌کند و تصاویر را با وضوح پایین‌تر ثبت کنید (الزامات دقت ذکرشده در بالا را درنظر داشته باشید). برای اطلاعات بیشتر، نکته‌هایی برای بهبود عملکرد را ببینید.

نکته‌هایی برای بهبود عملکرد

  • برای پردازش فریم‌های ویدیو، از results(in:) API همگام آشکارساز استفاده کنید. این روش را از تابع captureOutput(_, didOutput:from:) مربوط به AVCaptureVideoDataOutputSampleBufferDelegate فراخوانی کنید تا نتایج را به‌صورت همگام از فریم ویدیو داده‌شده دریافت کنید. Keep AVCaptureVideoDataOutput's alwaysDiscardsLateVideoFrames as true to throttle calls to the detector. اگر درحین اجرای آشکارساز، فریم ویدیویی جدیدی دردسترس قرار گیرد، آن فریم حذف خواهد شد.
  • اگر از خروجی آشکارساز برای هم‌پوشانی گرافیک روی تصویر ورودی استفاده می‌کنید، ابتدا نتیجه را از ML Kit دریافت کنید، سپس تصویر و هم‌پوشانی را در یک مرحله رندر کنید. با انجام این کار، فقط یک بار برای هر فریم ورودی پردازش‌شده، به سطح نمایشگر رندر می‌کنید. برای نمونه، updatePreviewOverlayViewWithLastFrame را در نمونه شروع سریع ML Kit ببینید.
  • تصاویر را با وضوح پایین‌تری بگیرید. بااین‌حال، الزامات ابعاد تصویر این API را نیز به‌خاطر داشته باشید.
  • برای جلوگیری از افت احتمالی عملکرد، چند نمونه TextRecognizer را با گزینه‌های متن متفاوت به‌طور هم‌زمان اجرا نکنید.