תוכלו להשתמש בלמידת מכונה כדי לזהות טקסט בתמונות או בסרטונים, כמו הטקסט של שלט רחוב. המאפיינים העיקריים של התכונה הזו הם:
ממשק API לזיהוי טקסט גרסה 2 | |
---|---|
תיאור | קל לזהות טקסט בתמונות או בסרטונים, תמיכה בסקריפטים לטיניים, סיניים, דוונאגרי, יפנית וקוריאנית, ומגוון רחב של שפות. |
שמות SDK | GoogleMLKit/TextRecognition |
יישום | הנכסים מקושרים באופן סטטי לאפליקציה שלך בזמן היצירה |
ההשפעה על גודל האפליקציה | כ-38MB לכל סקריפט של סקריפט |
ביצועים | זמן אמת ברוב המכשירים ל-SDK לסקריפט לטיני, איטי יותר לאחרים. |
אני רוצה לנסות
- כדאי לשחק עם האפליקציה לדוגמה כדי לראות שימוש לדוגמה ב-API הזה.
- עליכם לנסות את הקוד בעצמכם באמצעות Codelab.
לפני שמתחילים
- מוסיפים את רכיבי ה-ML Kit ל-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 Kit בגרסה 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
אל שיטת 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. עיבוד התמונה
לאחר מכן, צריך להעביר את התמונה למתודה 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 ואז לעבד את התמונה ואת שכבת-העל בפעולה אחת. לאחר מכן, תוכלו לעבד את שטח התצוגה פעם אחת בלבד בכל מסגרת קלט שעובדה. תוכלו לעיין ב-updatePreviewLayerViewWithLastFrame שמופיע בדוגמה למתחילים של ML Kit.
- כדאי לצלם תמונות ברזולוציה נמוכה יותר. עם זאת, חשוב גם לזכור את הדרישות לגבי מידות התמונה ב-API הזה.
- כדי למנוע פגיעה אפשרית בביצועים, אין להריץ כמה
מופעים של
TextRecognizer
בו-זמנית עם אפשרויות שונות של סקריפטים.