תוכלו להשתמש בערכת למידת מכונה כדי לזהות טקסט בתמונות או בסרטונים, כמו טקסט של שלט. המאפיינים העיקריים של תכונה זו הם:
ממשק API לזיהוי טקסט | |
---|---|
תיאור | זיהוי טקסט לטיני בתמונות או בסרטונים. |
שם ה-SDK | GoogleMLKit/TextRecognition (version 2.2.0) |
יישום | הנכסים מקושרים באופן סטטי לאפליקציה שלך בשלב הבנייה. |
ההשפעה על גודל האפליקציה | כ-20MB |
ביצועים | זמן אמת ברוב המכשירים. |
רוצה לנסות?
- כדאי לשחק עם האפליקציה לדוגמה כדי לראות שימוש לדוגמה ב-API הזה.
- אפשר לנסות את הקוד בעצמך באמצעות ה-Codelab.
לפני שמתחילים
- יש לכלול את ה-pods הבאים ב-ML Kit ב-Podfile:
pod 'GoogleMLKit/TextRecognition','2.2.0'
- אחרי ההתקנה או העדכון של ה-Pods של הפרויקט, פותחים את פרויקט Xcode באמצעות
.xcworkspace
שלו. ערכת ה-ML נתמכת ב-Xcode מגרסה 12.4 ואילך.
1. יצירת מופע של TextRecognizer
יצירת מכונה של TextRecognizer
על ידי התקשרות ל-+textRecognizer
:
Swift
let textRecognizer = TextRecognizer.textRecognizer()
Objective-C
MLKTextRecognizer *textRecognizer = [MLKTextRecognizer textRecognizer];
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 פיקסלים.
-
התמקדות גרועה בתמונה יכולה להשפיע על הדיוק של זיהוי הטקסט. אם לא מתקבלות תוצאות קבילות, אפשר לנסות לבקש מהמשתמש לצלם שוב את התמונה.
-
אם מזהים טקסט בזמן אמת, צריך להביא בחשבון את המידות הכלליות של תמונות הקלט. אפשר לעבד תמונות קטנות יותר מהר יותר. כדי לצמצם את זמן האחזור, צריך לתפוס את גודל הטקסט כמה שיותר גדול ולצלם תמונות ברזולוציות נמוכות יותר (חשוב לזכור את דרישות הדיוק שצוינו למעלה). מידע נוסף זמין במאמר טיפים לשיפור הביצועים.
טיפים לשיפור הביצועים
- לעיבוד מסגרות וידאו, יש להשתמש ב-
results(in:)
ב-API הסינכרוני של המזהה. ניתן לקרוא לשיטה הזו באמצעות הפונקציהAVCaptureVideoDataOutputSampleBufferDelegate
captureOutput(_, didOutput:from:)
כדי לקבל תוצאות סינכרוניות מהפריים של הווידאו. צריך להשאיר את ה-alwaysDiscardsLateVideoFrames
שלAVCaptureVideoDataOutput
בתורtrue
כדי לווסת את השיחות. אם יהפוך לפריים חדש של סרטון בזמן שהמזהה פועל, הוא יוסר. - אם משתמשים בפלט של המזהה כשכבת-על של גרפיקה בתמונת הקלט, קודם צריך לקבל את התוצאה מ-ML Kit, ואז לעבד את התמונה ואת שכבת-העל בפעולה אחת. אם עושים זאת, מתבצע רינדור של התצוגה למשטח התצוגה רק פעם אחת בכל מסגרת קלט שעברה עיבוד. כדי לקבל דוגמה, אפשר לעיין בupdatePreviewLayerViewWithLastFrame שבדוגמה למתחילים של ML.
- כדאי לצלם תמונות ברזולוציה נמוכה יותר. עם זאת, חשוב לזכור גם את הדרישות בנוגע למידות התמונה ב-API הזה.