ניתן להשתמש ב-ML Kit כדי לזהות טקסט בתמונות או בסרטונים, למשל טקסט של שלט רחוב. המאפיינים העיקריים של התכונה הזו הם:
ממשק API לזיהוי טקסט בגרסה 2 | |
---|---|
תיאור | זיהוי טקסט בתמונות או בסרטונים, תמיכה בכתבים לטיניים, סינית, דוואנגרי, יפנית וקוריאנית, ומגוון רחב של שפות. |
שמות SDK | GoogleMLKit/TextRecognition |
הטמעה | הנכסים מקושרים באופן סטטי לאפליקציה בזמן ה-build |
ההשפעה של גודל האפליקציה | כ-38MB לכל סקריפט SDK |
ביצועים | זמן אמת ברוב המכשירים ל-SDK בסקריפט לטיני, לאט יותר אצל אחרים. |
אני רוצה לנסות
- אפשר לנסות את האפליקציה לדוגמה כדי לראות דוגמה לשימוש ב-API הזה.
- אפשר לנסות את הקוד בעצמכם באמצעות codelab.
לפני שמתחילים
- יש לכלול את רצפי ערכת ה-ML הבאים בקובץ ה-Podfile:
# To recognize Latin script pod 'GoogleMLKit/TextRecognition', '3.2.0' # To recognize Chinese script pod 'GoogleMLKit/TextRecognitionChinese', '3.2.0' # To recognize Devanagari script pod 'GoogleMLKit/TextRecognitionDevanagari', '3.2.0' # To recognize Japanese script pod 'GoogleMLKit/TextRecognitionJapanese', '3.2.0' # To recognize Korean script pod 'GoogleMLKit/TextRecognitionKorean', '3.2.0'
- אחרי שמתקינים או מעדכנים את ה-Pods של הפרויקט, פותחים את פרויקט Xcode באמצעות ה-
.xcworkspace
שלו. ערכת ML נתמכת ב-Xcode בגרסה 12.4 ומעלה.
1. יצירת מופע של TextRecognizer
יוצרים מכונה של TextRecognizer
על ידי קריאה ל-+textRecognizer(options:)
, ומעבירים את האפשרויות שקשורות ל-SDK שעליו הצהרת כתלויות למעלה:
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. הכנת תמונת הקלט
מעבירים את התמונה כ-UIImage
או CMSampleBufferRef
ל-method process(_:completion:)
של TextRecognizer
:
יוצרים אובייקט VisionImage
באמצעות UIImage
או CMSampleBuffer
.
אם אתם משתמשים ב-UIImage
, עליכם לפעול לפי השלבים הבאים:
- יוצרים אובייקט
VisionImage
עםUIImage
. חשוב לציין את הערכים הנכונים של.orientation
.Swift
let image = VisionImage(image: UIImage) visionImage.orientation = image.imageOrientation
Objective-C
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 } }
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; } }
- יוצרים אובייקט
VisionImage
באמצעות האובייקטCMSampleBuffer
והכיוון שלו: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. עיבוד התמונה
לאחר מכן, מעבירים את התמונה ל-method 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. חילוץ טקסט מבלוקים של טקסט מזוהה
אם פעולת זיהוי הטקסט מצליחה, היא מחזירה אובייקט 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 } } }
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; } } }
הנחיות לבחירת תמונה לקלט
-
כדי ש-ML Kit יוכל לזהות טקסט באופן מדויק, תמונות הקלט צריכות להכיל טקסט שמיוצג על ידי כמות מספיקה של נתוני פיקסלים. רצוי שכל תו יהיה בגודל של לפחות 16x16 פיקסלים. בדרך כלל אין יתרון דיוק לגבי תווים שגדולים מ-24x24 פיקסלים.
לדוגמה, תמונה בגודל 640x480 יכולה להתאים מאוד לסריקת כרטיס ביקור שתופס את כל רוחב התמונה. כדי לסרוק מסמך שמודפס על נייר בגודל מכתב, ייתכן שתידרש תמונה בגודל 720x1280 פיקסלים.
-
מיקוד באיכות נמוכה יכול להשפיע על הדיוק של זיהוי הטקסט. אם התוצאות לא מקובלות עליך, כדאי לבקש מהמשתמש לצלם מחדש את התמונה.
-
אם אתם מזהים טקסט באפליקציה בזמן אמת, כדאי שתביאו בחשבון את הממדים הכוללים של תמונות הקלט. אפשר לעבד תמונות קטנות יותר מהר יותר. כדי לקצר את זמן האחזור, יש לוודא שהטקסט תופס חלק גדול ככל האפשר מהתמונה ולצלם תמונות ברזולוציות נמוכות יותר (שימו לב לדרישות הדיוק שצוינו למעלה). מידע נוסף זמין במאמר טיפים לשיפור הביצועים.
טיפים לשיפור הביצועים
- לעיבוד פריימים של סרטונים, צריך להשתמש ב-API הסינכרוני
results(in:)
של המזהה. צריך לקרוא לשיטה הזו מהפונקציהcaptureOutput(_, didOutput:from:)
שלAVCaptureVideoDataOutputSampleBufferDelegate
כדי לקבל באופן סינכרוני תוצאות מהפריים הנתון של הסרטון. יש לשמור אתalwaysDiscardsLateVideoFrames
שלAVCaptureVideoDataOutput
בתורtrue
כדי לווסת שיחות לגלאי. אם מתאפשרת פריים וידאו חדש בזמן שהמזהה פועל, היא תוסר. - אם משתמשים בפלט של הגלאי כדי להציג שכבות גרפיקה על תמונת הקלט, קודם מקבלים את התוצאה מ-ML Kit ואז מבצעים רינדור של התמונה ושכבת-העל בשלב אחד. כך, עיבוד הנתונים מתבצע על פני תצוגת המסך פעם אחת בלבד לכל מסגרת קלט מעובדת. כדי לראות דוגמה, אפשר לעיין בupdatePreviewOverlayViewWithLastFrame שבדוגמה למתחילים של ערכת ML.
- כדאי לצלם תמונות ברזולוציה נמוכה יותר. עם זאת, חשוב לזכור גם את הדרישות לגבי מידות התמונה של ה-API הזה.
- כדי למנוע ירידה פוטנציאלית בביצועים, כדאי לא להריץ בו-זמנית כמה מכונות של
TextRecognizer
עם אפשרויות שונות של סקריפטים.