אפשר להשתמש ב-ML Kit כדי לזהות טקסט בתמונות או בסרטונים, כמו הטקסט של שלט רחוב. המאפיינים העיקריים של התכונה הזו הם:
Text Recognition v2 API | |
---|---|
תיאור | זיהוי טקסט בתמונות או בסרטונים, תמיכה בכתבים לטינית, סינית, דבנאגרי, יפנית וקוריאנית ובמגוון רחב של שפות. |
שמות של SDK | GoogleMLKit/TextRecognition |
הטמעה | הנכסים מקושרים באופן סטטי לאפליקציה בזמן ה-build |
ההשפעה של גודל האפליקציה | כ-38MB לכל SDK של סקריפט |
ביצועים | בזמן אמת ברוב המכשירים עם ערכת SDK לכתב לטינית, איטי יותר במכשירים אחרים. |
רוצה לנסות?
- כדאי לנסות את האפליקציה לדוגמה כדי לראות דוגמה לשימוש ב-API הזה.
- אתם יכולים לנסות את הקוד בעצמכם באמצעות codelab.
לפני שמתחילים
- מוסיפים את ה-pods הבאים של ML Kit ל-Podfile:
# To recognize Latin script pod 'GoogleMLKit/TextRecognition', '7.0.0' # To recognize Chinese script pod 'GoogleMLKit/TextRecognitionChinese', '7.0.0' # To recognize Devanagari script pod 'GoogleMLKit/TextRecognitionDevanagari', '7.0.0' # To recognize Japanese script pod 'GoogleMLKit/TextRecognitionJapanese', '7.0.0' # To recognize Korean script pod 'GoogleMLKit/TextRecognitionKorean', '7.0.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
ל-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. עיבוד התמונה
לאחר מכן, מעבירים את התמונה לשיטה 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 יכולה להתאים לסריקה של כרטיס ביקור שממלא את כל רוחב התמונה. כדי לסרוק מסמך שמודפס על נייר בגודל Letter, יכול להיות שתצטרכו תמונה בגודל 720x1280 פיקסלים.
-
מיקוד לקוי של התמונה עלול להשפיע על רמת הדיוק של זיהוי הטקסט. אם התוצאות לא מתקבלות, נסו לבקש מהמשתמש לצלם מחדש את התמונה.
-
אם אתם מזהים טקסט באפליקציה בזמן אמת, כדאי להביא בחשבון את המימדים הכוללים של תמונות הקלט. עיבוד של תמונות קטנות יותר מתבצע מהר יותר. כדי לצמצם את זמן האחזור, חשוב לוודא שהטקסט תופס כמה שיותר משטח התמונה ולצלם תמונות ברזולוציות נמוכות יותר (תוך התחשבות בדרישות הדיוק שצוינו למעלה). מידע נוסף זמין במאמר טיפים לשיפור הביצועים.
טיפים לשיפור הביצועים
- כדי לעבד פריימים של סרטונים, משתמשים ב-API הסינכרוני
results(in:)
של הגלאי. צריך לקרוא לשיטה הזו מהפונקציהcaptureOutput(_, didOutput:from:)
שלAVCaptureVideoDataOutputSampleBufferDelegate
כדי לקבל תוצאות מסונכרנות מהפריים הנתון של הסרטון. כדי להגביל את השיחות לגלאי, משאירים אתalwaysDiscardsLateVideoFrames
שלAVCaptureVideoDataOutput
כ-true
. אם פריים חדש של וידאו יהפוך לזמין בזמן שהגלאי פועל, הוא יידחה. - אם משתמשים בפלט של הגלאי כדי להוסיף שכבת-על של גרפיקה לתמונה הקלט, קודם מקבלים את התוצאה מ-ML Kit, ואז מבצעים עיבוד תמונה של התמונה ומוסיפים את שכבת-העל בשלב אחד. כך מבצעים רינדור למשטח התצוגה רק פעם אחת לכל מסגרת קלט שעברה עיבוד. דוגמה לכך מופיעה ב-updatePreviewOverlayViewWithLastFrame בדוגמה למתחילים של ML Kit.
- כדאי לצלם תמונות ברזולוציה נמוכה יותר. עם זאת, חשוב לזכור גם את הדרישות לגבי מידות התמונות ב-API הזה.
- כדי למנוע פגיעה פוטנציאלית בביצועים, אין להפעיל בו-זמנית כמה מכונות
TextRecognizer
עם אפשרויות שונות של סקריפטים.