זיהוי טקסט בתמונות באמצעות Firebase ML ב-iOS

אפשר להשתמש ב-Firebase ML כדי לזהות טקסט בתמונות. ‫Firebase ML כולל גם API לשימוש כללי שמתאים לזיהוי טקסט בתמונות, כמו טקסט של תמרור רחוב, וגם API שעבר אופטימיזציה לזיהוי טקסט במסמכים.

לפני שמתחילים

    אם עדיין לא הוספתם את Firebase לאפליקציה, אתם צריכים לעשות זאת לפי השלבים שמפורטים במדריך לתחילת העבודה.

    משתמשים ב-Swift Package Manager כדי להתקין ולנהל יחסי תלות ב-Firebase.

    1. ב-Xcode, כשהפרויקט של האפליקציה פתוח, עוברים אל File > Add Packages (קובץ > הוספת חבילות).
    2. כשמוצגת בקשה, מוסיפים את מאגר Firebase Apple platforms SDK:
    3.   https://github.com/firebase/firebase-ios-sdk.git
    4. בוחרים את הספרייה Firebase ML.
    5. מוסיפים את הדגל -ObjC לקטע Other Linker Flags בהגדרות הבנייה של יעד הקישור.
    6. אחרי שתסיימו, פלטפורמת Xcode תתחיל באופן אוטומטי לטפל ביחסי התלות ולהוריד אותם ברקע.

    עכשיו מבצעים הגדרה באפליקציה:

    1. באפליקציה, מייבאים את Firebase:

      Swift

      import FirebaseMLModelDownloader

      Objective-C

      @import FirebaseMLModelDownloader;
  1. אם עדיין לא הפעלתם ממשקי API מבוססי-Cloud בפרויקט, עכשיו הזמן לעשות זאת:

    1. פותחים את Firebase ML הדף APIs במסוף Firebase.
    2. אם עדיין לא שדרגתם את הפרויקט לתוכנית התמחור Blaze עם תשלום לפי שימוש, לוחצים על שדרוג כדי לעשות זאת. (תתבקשו לשדרג רק אם הפרויקט שלכם לא נמצא בתוכנית התמחור Blaze).

      רק פרויקטים בתוכנית התמחור Blaze יכולים להשתמש בממשקי API מבוססי-Cloud.

    3. אם ממשקי API מבוססי-ענן לא מופעלים כבר, לוחצים על הפעלת ממשקי API מבוססי-ענן.

עכשיו אפשר להתחיל לזהות טקסט בתמונות.

הנחיות לגבי תמונות קלט

  • כדי ש-Firebase ML יוכל לזהות טקסט בצורה מדויקת, התמונות שמוזנות צריכות להכיל טקסט שמיוצג על ידי נתוני פיקסלים מספיקים. באופן אידיאלי, עבור טקסט לטיני, כל תו צריך להיות בגודל 16x16 פיקסלים לפחות. בטקסט בסינית, ביפנית או בקוריאנית, כל תו צריך להיות בגודל ‎24x24 פיקסלים. בכל השפות, בדרך כלל אין יתרון בדיוק אם התווים גדולים מ-24x24 פיקסלים.

    לדוגמה, תמונה בגודל ‎640x480 יכולה להתאים לסריקה של כרטיס ביקור שממלא את כל הרוחב של התמונה. כדי לסרוק מסמך שמודפס על נייר בגודל Letter, יכול להיות שתידרש תמונה בגודל 720x1280 פיקסלים.

  • פוקוס לא טוב של התמונה עלול לפגוע בדיוק של זיהוי הטקסט. אם התוצאות לא מספיק טובות, אפשר לבקש מהמשתמש לצלם מחדש את התמונה.


זיהוי טקסט בתמונות

כדי לזהות טקסט בתמונה, מפעילים את הכלי לזיהוי טקסט כמו שמתואר בהמשך.

1. הפעלת הכלי לזיהוי טקסט

מעבירים את התמונה כ-UIImage או כ-CMSampleBufferRef לשיטה process(_:completion:) של VisionTextRecognizer:

  1. מקבלים מופע של VisionTextRecognizer על ידי קריאה ל- cloudTextRecognizer:

    Swift

    let vision = Vision.vision()
    let textRecognizer = vision.cloudTextRecognizer()
    
    // Or, to provide language hints to assist with language detection:
    // See https://cloud.google.com/vision/docs/languages for supported languages
    let options = VisionCloudTextRecognizerOptions()
    options.languageHints = ["en", "hi"]
    let textRecognizer = vision.cloudTextRecognizer(options: options)

    Objective-C

    FIRVision *vision = [FIRVision vision];
    FIRVisionTextRecognizer *textRecognizer = [vision cloudTextRecognizer];
    
    // Or, to provide language hints to assist with language detection:
    // See https://cloud.google.com/vision/docs/languages for supported languages
    FIRVisionCloudTextRecognizerOptions *options =
            [[FIRVisionCloudTextRecognizerOptions alloc] init];
    options.languageHints = @[@"en", @"hi"];
    FIRVisionTextRecognizer *textRecognizer = [vision cloudTextRecognizerWithOptions:options];
  2. כדי להתקשר אל Cloud Vision, התמונה צריכה להיות בפורמט של מחרוזת בקידוד Base64. כדי לעבד UIImage:

    Swift

    guard let imageData = uiImage.jpegData(compressionQuality: 1.0) else { return }
    let base64encodedImage = imageData.base64EncodedString()

    Objective-C

    NSData *imageData = UIImageJPEGRepresentation(uiImage, 1.0f);
    NSString *base64encodedImage =
      [imageData base64EncodedStringWithOptions:NSDataBase64Encoding76CharacterLineLength];
  3. לאחר מכן, מעבירים את התמונה לשיטה process(_:completion:):

    Swift

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

    Objective-C

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

2. חילוץ טקסט מבלוקים של טקסט מזוהה

אם פעולת זיהוי הטקסט תצליח, יוחזר אובייקט VisionText. אובייקט VisionText מכיל את הטקסט המלא שזוהה בתמונה, ואפס אובייקטים מסוג VisionTextBlock או יותר.

כל רכיב VisionTextBlock מייצג בלוק טקסט מלבני, שמכיל אפס אובייקטים מסוג VisionTextLine או יותר. כל אובייקט VisionTextLine מכיל אפס אובייקטים מסוג VisionTextElement או יותר, שמייצגים מילים וישויות דמויות מילים (תאריכים, מספרים וכו').

לכל אובייקט VisionTextBlock, VisionTextLine ו-VisionTextElement, אפשר לקבל את הטקסט שזוהה באזור ואת קואורדינטות התיחום של האזור.

לדוגמה:

Swift

let resultText = result.text
for block in result.blocks {
    let blockText = block.text
    let blockConfidence = block.confidence
    let blockLanguages = block.recognizedLanguages
    let blockCornerPoints = block.cornerPoints
    let blockFrame = block.frame
    for line in block.lines {
        let lineText = line.text
        let lineConfidence = line.confidence
        let lineLanguages = line.recognizedLanguages
        let lineCornerPoints = line.cornerPoints
        let lineFrame = line.frame
        for element in line.elements {
            let elementText = element.text
            let elementConfidence = element.confidence
            let elementLanguages = element.recognizedLanguages
            let elementCornerPoints = element.cornerPoints
            let elementFrame = element.frame
        }
    }
}

Objective-C

NSString *resultText = result.text;
for (FIRVisionTextBlock *block in result.blocks) {
  NSString *blockText = block.text;
  NSNumber *blockConfidence = block.confidence;
  NSArray<FIRVisionTextRecognizedLanguage *> *blockLanguages = block.recognizedLanguages;
  NSArray<NSValue *> *blockCornerPoints = block.cornerPoints;
  CGRect blockFrame = block.frame;
  for (FIRVisionTextLine *line in block.lines) {
    NSString *lineText = line.text;
    NSNumber *lineConfidence = line.confidence;
    NSArray<FIRVisionTextRecognizedLanguage *> *lineLanguages = line.recognizedLanguages;
    NSArray<NSValue *> *lineCornerPoints = line.cornerPoints;
    CGRect lineFrame = line.frame;
    for (FIRVisionTextElement *element in line.elements) {
      NSString *elementText = element.text;
      NSNumber *elementConfidence = element.confidence;
      NSArray<FIRVisionTextRecognizedLanguage *> *elementLanguages = element.recognizedLanguages;
      NSArray<NSValue *> *elementCornerPoints = element.cornerPoints;
      CGRect elementFrame = element.frame;
    }
  }
}

השלבים הבאים


זיהוי טקסט בתמונות של מסמכים

כדי לזהות את הטקסט במסמך, מגדירים ומריצים את הכלי לזיהוי טקסט במסמך כמו שמתואר בהמשך.

ממשק ה-API לזיהוי טקסט במסמכים, שמתואר בהמשך, נועד להקל על העבודה עם תמונות של מסמכים. אבל אם אתם מעדיפים את הממשק שמספק ה-API של טקסט דליל, אתם יכולים להשתמש בו במקום זאת כדי לסרוק מסמכים. לשם כך, צריך להגדיר את הכלי לזיהוי טקסט בענן לשימוש במודל של טקסט צפוף.

כדי להשתמש ב-API לזיהוי טקסט במסמך:

1. הפעלת הכלי לזיהוי טקסט

מעבירים את התמונה כ-UIImage או כ-CMSampleBufferRef לשיטה process(_:completion:) של VisionDocumentTextRecognizer:

  1. מקבלים מופע של VisionDocumentTextRecognizer על ידי קריאה ל- cloudDocumentTextRecognizer:

    Swift

    let vision = Vision.vision()
    let textRecognizer = vision.cloudDocumentTextRecognizer()
    
    // Or, to provide language hints to assist with language detection:
    // See https://cloud.google.com/vision/docs/languages for supported languages
    let options = VisionCloudDocumentTextRecognizerOptions()
    options.languageHints = ["en", "hi"]
    let textRecognizer = vision.cloudDocumentTextRecognizer(options: options)

    Objective-C

    FIRVision *vision = [FIRVision vision];
    FIRVisionDocumentTextRecognizer *textRecognizer = [vision cloudDocumentTextRecognizer];
    
    // Or, to provide language hints to assist with language detection:
    // See https://cloud.google.com/vision/docs/languages for supported languages
    FIRVisionCloudDocumentTextRecognizerOptions *options =
            [[FIRVisionCloudDocumentTextRecognizerOptions alloc] init];
    options.languageHints = @[@"en", @"hi"];
    FIRVisionDocumentTextRecognizer *textRecognizer = [vision cloudDocumentTextRecognizerWithOptions:options];
  2. כדי להתקשר אל Cloud Vision, התמונה צריכה להיות בפורמט של מחרוזת בקידוד Base64. כדי לעבד UIImage:

    Swift

    guard let imageData = uiImage.jpegData(compressionQuality: 1.0) else { return }
    let base64encodedImage = imageData.base64EncodedString()

    Objective-C

    NSData *imageData = UIImageJPEGRepresentation(uiImage, 1.0f);
    NSString *base64encodedImage =
      [imageData base64EncodedStringWithOptions:NSDataBase64Encoding76CharacterLineLength];
  3. לאחר מכן, מעבירים את התמונה לשיטה process(_:completion:):

    Swift

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

    Objective-C

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

2. חילוץ טקסט מבלוקים של טקסט מזוהה

אם פעולת זיהוי הטקסט תצליח, יוחזר אובייקט VisionDocumentText. אובייקט VisionDocumentText מכיל את הטקסט המלא שזוהה בתמונה ואת ההיררכיה של האובייקטים שמשקפים את המבנה של המסמך שזוהה:

לכל אובייקט VisionDocumentTextBlock, VisionDocumentTextParagraph,‏ VisionDocumentTextWord ו-VisionDocumentTextSymbol, אפשר לקבל את הטקסט שזוהה באזור ואת קואורדינטות התיחום של האזור.

לדוגמה:

Swift

let resultText = result.text
for block in result.blocks {
    let blockText = block.text
    let blockConfidence = block.confidence
    let blockRecognizedLanguages = block.recognizedLanguages
    let blockBreak = block.recognizedBreak
    let blockCornerPoints = block.cornerPoints
    let blockFrame = block.frame
    for paragraph in block.paragraphs {
        let paragraphText = paragraph.text
        let paragraphConfidence = paragraph.confidence
        let paragraphRecognizedLanguages = paragraph.recognizedLanguages
        let paragraphBreak = paragraph.recognizedBreak
        let paragraphCornerPoints = paragraph.cornerPoints
        let paragraphFrame = paragraph.frame
        for word in paragraph.words {
            let wordText = word.text
            let wordConfidence = word.confidence
            let wordRecognizedLanguages = word.recognizedLanguages
            let wordBreak = word.recognizedBreak
            let wordCornerPoints = word.cornerPoints
            let wordFrame = word.frame
            for symbol in word.symbols {
                let symbolText = symbol.text
                let symbolConfidence = symbol.confidence
                let symbolRecognizedLanguages = symbol.recognizedLanguages
                let symbolBreak = symbol.recognizedBreak
                let symbolCornerPoints = symbol.cornerPoints
                let symbolFrame = symbol.frame
            }
        }
    }
}

Objective-C

NSString *resultText = result.text;
for (FIRVisionDocumentTextBlock *block in result.blocks) {
  NSString *blockText = block.text;
  NSNumber *blockConfidence = block.confidence;
  NSArray<FIRVisionTextRecognizedLanguage *> *blockRecognizedLanguages = block.recognizedLanguages;
  FIRVisionTextRecognizedBreak *blockBreak = block.recognizedBreak;
  CGRect blockFrame = block.frame;
  for (FIRVisionDocumentTextParagraph *paragraph in block.paragraphs) {
    NSString *paragraphText = paragraph.text;
    NSNumber *paragraphConfidence = paragraph.confidence;
    NSArray<FIRVisionTextRecognizedLanguage *> *paragraphRecognizedLanguages = paragraph.recognizedLanguages;
    FIRVisionTextRecognizedBreak *paragraphBreak = paragraph.recognizedBreak;
    CGRect paragraphFrame = paragraph.frame;
    for (FIRVisionDocumentTextWord *word in paragraph.words) {
      NSString *wordText = word.text;
      NSNumber *wordConfidence = word.confidence;
      NSArray<FIRVisionTextRecognizedLanguage *> *wordRecognizedLanguages = word.recognizedLanguages;
      FIRVisionTextRecognizedBreak *wordBreak = word.recognizedBreak;
      CGRect wordFrame = word.frame;
      for (FIRVisionDocumentTextSymbol *symbol in word.symbols) {
        NSString *symbolText = symbol.text;
        NSNumber *symbolConfidence = symbol.confidence;
        NSArray<FIRVisionTextRecognizedLanguage *> *symbolRecognizedLanguages = symbol.recognizedLanguages;
        FIRVisionTextRecognizedBreak *symbolBreak = symbol.recognizedBreak;
        CGRect symbolFrame = symbol.frame;
      }
    }
  }
}

השלבים הבאים