يمكنك استخدام حزمة تعلّم الآلة للتعرّف على النص في الصور أو الفيديو، مثل نص لافتة شارع. في ما يلي الخصائص الرئيسية لهذه الميزة:
للتجربة:
- يمكنك تجربة التطبيق النموذجي للاطّلاع على مثال على استخدام واجهة برمجة التطبيقات هذه.
- يمكنك تجربة الرمز بنفسك من خلال الدرس التطبيقي حول الترميز.
قبل البدء
- أدرِج مجموعات حزمة تعلّم الآلة التالية في ملف 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. تتوفّر حزمة تعلّم الآلة في الإصدار 12.4 من Xcode أو الإصدارات الأحدث.
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 إلى
TextRecognizer في طريقة process(_:completion:):
يمكنك إنشاء عنصر 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;
}
}
}إرشادات الصور المُدخَلة
-
لكي تتعرّف حزمة تعلّم الآلة على النص بدقة، يجب أن تحتوي الصور المُدخَلة على نص ممثّل ببيانات بكسل كافية. من الأفضل أن يكون حجم كل حرف 16×16 بكسل على الأقل. لا تتحسّن الدقة بشكل عام إذا كان حجم الأحرف أكبر من 24×24 بكسل.
على سبيل المثال، قد تكون صورة بحجم 640×480 بكسل مناسبة لفحص بطاقة عمل تشغل العرض الكامل للصورة. لفحص مستند مطبوع على ورق بحجم الرسالة، قد تكون هناك حاجة إلى صورة بحجم 720×1280 بكسل.
-
يمكن أن يؤثر عدم وضوح الصورة في دقة التعرّف على النص. إذا لم تحصل على نتائج مقبولة، اطلب من المستخدم إعادة التقاط الصورة.
-
إذا كنت تتعرّف على النص في تطبيق في الوقت الفعلي، عليك مراعاة الأبعاد الإجمالية للصور المُدخَلة. يمكن معالجة الصور الأصغر حجمًا بشكل أسرع. للحدّ من وقت الاستجابة، تأكَّد من أنّ النص يشغل أكبر مساحة ممكنة من الصورة، والتقط الصور بدقة أقل (مع مراعاة متطلبات الدقة المذكورة أعلاه). لمزيد من المعلومات، يُرجى الاطّلاع على مقالة نصائح لتحسين الأداء.
نصائح لتحسين الأداء
- لمعالجة إطارات الفيديو، استخدِم واجهة برمجة التطبيقات المتزامنة
results(in:)الخاصة بأداة الكشف. استدعِ هذه الطريقة من الـAVCaptureVideoDataOutputSampleBufferDelegatecaptureOutput(_, didOutput:from:)للحصول على النتائج بشكل متزامن من إطار الفيديو المحدّد. احتفِظ بقيمةalwaysDiscardsLateVideoFramesفيAVCaptureVideoDataOutputعلىtrueللحدّ من عدد استدعاءات أداة الكشف. إذا أصبح إطار فيديو جديد متاحًا أثناء تشغيل أداة الكشف، سيتم إسقاطه. - إذا كنت تستخدم ناتج أداة الكشف لتراكب الرسومات على الصورة المُدخَلة، احصل أولاً على النتيجة من حزمة تعلّم الآلة، ثم اعرض الصورة والتراكب في خطوة واحدة. من خلال إجراء ذلك، يمكنك العرض على سطح العرض مرة واحدة فقط لكل إطار إدخال تتم معالجته. يمكنك الاطّلاع على updatePreviewOverlayViewWithLastFrame في نموذج التشغيل السريع في حزمة تعلّم الآلة للحصول على مثال.
- ننصحك بالتقاط الصور بدقة أقل. ومع ذلك، عليك أيضًا مراعاة متطلبات أبعاد الصور في واجهة برمجة التطبيقات هذه.
- لتجنُّب أي تدهور محتمل في الأداء، لا تشغِّل عدة
TextRecognizerمثيلات بخيارات نصوص مختلفة في الوقت نفسه.