אפשר להשתמש ב-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'
- אחרי שמתקינים או מעדכנים את קבוצות ה-Pod של הפרויקט, פותחים את פרויקט 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
ל-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:)
של הגלאי. מפעילים את ה-method הזה מהפונקציהcaptureOutput(_, didOutput:from:)
שלAVCaptureVideoDataOutputSampleBufferDelegate
כדי לקבל באופן סינכרוני תוצאות מהפריים הנתון של הווידאו. צריך להשאיר אתalwaysDiscardsLateVideoFrames
שלAVCaptureVideoDataOutput
בתורtrue
כדי לווסת את הקריאות לגלאי. אם פריים חדש של וידאו יהיה זמין בזמן שהגלאי פועל, היא תוסר. - אם משתמשים בפלט של הגלאי כדי ליצור שכבת-על של גרפיקה בתמונת הקלט, מקבלים קודם את התוצאה מ-ML Kit ואז מעבדים את התמונה ושכבת-העל בפעולה אחת. כך אפשר לעבד את משטח המסך פעם אחת בלבד לכל מסגרת קלט שעברה עיבוד. כדוגמה, אפשר לעיין ב-updatePreviewOverlayViewWithLastFrame בדוגמה של המדריך למתחילים ל-ML Kit.
- כדאי לצלם תמונות ברזולוציה נמוכה יותר. עם זאת, חשוב גם לזכור את הדרישות לגבי מידות התמונה של ה-API.
- כדי למנוע פגיעה פוטנציאלית בביצועים, אין להריץ כמה מכונות
TextRecognizer
עם אפשרויות שונות של סקריפטים בו-זמנית.