تشخیص متن در تصاویر با ML Kit در iOS

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

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

امتحانش کن.

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

قبل از اینکه شروع کنی

  1. پادهای کیت ML زیر را در پادفایل خود قرار دهید:
    # 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 ‎ آن باز کنید. ML Kit در Xcode نسخه ۱۲.۴ یا بالاتر پشتیبانی می‌شود.

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

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

سویفت

// 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 صحیح را مشخص می‌کنید.

    سویفت

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

    هدف-سی

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

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

سپس، تصویر را به متد 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
}];

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

اگر عملیات تشخیص متن با موفقیت انجام شود، یک شیء 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;
    }
  }
}

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

  • برای اینکه کیت ML متن را به طور دقیق تشخیص دهد، تصاویر ورودی باید حاوی متنی باشند که با داده‌های پیکسلی کافی نمایش داده می‌شود. در حالت ایده‌آل، هر کاراکتر باید حداقل 16x16 پیکسل باشد. به طور کلی هیچ مزیتی برای دقت کاراکترهایی که بزرگتر از 24x24 پیکسل هستند، وجود ندارد.

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

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

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

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

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