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