شما میتوانید از کیت ML برای تشخیص متن در تصاویر یا ویدیو، مانند متن یک تابلوی خیابان، استفاده کنید. ویژگیهای اصلی این ویژگی عبارتند از:
| ویژگی | بدون دسته بندی | بستهبندیشده | 
|---|---|---|
| نام کتابخانه | com.google.android.gms:play-services-mlkit-text-recognition com.google.android.gms:play-services-mlkit-text-recognition-chinese com.google.android.gms:play-services-mlkit-text-recognition-devanagari com.google.android.gms:play-services-mlkit-text-recognition-japanese com.google.android.gms:play-services-mlkit-text-recognition-korean | com.google.mlkit: تشخیص متن com.google.mlkit: تشخیص متن-چینی com.google.mlkit:text-recognition-devanagari com.google.mlkit: تشخیص متن-ژاپنی com.google.mlkit: تشخیص متن-کرهای | 
| پیادهسازی | مدل به صورت پویا از طریق سرویسهای گوگل پلی دانلود میشود. | مدل در زمان ساخت به صورت ایستا به برنامه شما متصل است. | 
| اندازه برنامه | حدود ۲۶۰ کیلوبایت افزایش حجم به ازای هر معماری اسکریپت. | حدود ۴ مگابایت افزایش حجم به ازای هر اسکریپت در هر معماری. | 
| زمان اولیه سازی | ممکن است لازم باشد قبل از اولین استفاده، منتظر دانلود مدل باشید. | مدل فوراً موجود است. | 
| عملکرد | در اکثر دستگاهها برای کتابخانه خط لاتین، به صورت آنی و برای سایر دستگاهها کندتر است. | در اکثر دستگاهها برای کتابخانه خط لاتین، به صورت آنی و برای سایر دستگاهها کندتر است. | 
امتحانش کن.
- برای مشاهدهی نحوهی استفاده از این API، با برنامهی نمونه کار کنید.
- خودتان کد را با codelab امتحان کنید.
قبل از اینکه شروع کنی
-  در فایل build.gradleسطح پروژه خود، مطمئن شوید که مخزن Maven گوگل را هم در بخشهایbuildscriptو همallprojectsخود وارد کردهاید.
- وابستگیهای کتابخانههای اندروید ML Kit را به فایل gradle سطح app ماژول خود که معمولاً - app/build.gradleاست، اضافه کنید:- برای باندل کردن مدل با اپلیکیشن خود: - dependencies { // To recognize Latin script implementation 'com.google.mlkit:text-recognition:16.0.1' // To recognize Chinese script implementation 'com.google.mlkit:text-recognition-chinese:16.0.1' // To recognize Devanagari script implementation 'com.google.mlkit:text-recognition-devanagari:16.0.1' // To recognize Japanese script implementation 'com.google.mlkit:text-recognition-japanese:16.0.1' // To recognize Korean script implementation 'com.google.mlkit:text-recognition-korean:16.0.1' }- برای استفاده از مدل در سرویسهای گوگل پلی: - dependencies { // To recognize Latin script implementation 'com.google.android.gms:play-services-mlkit-text-recognition:19.0.1' // To recognize Chinese script implementation 'com.google.android.gms:play-services-mlkit-text-recognition-chinese:16.0.1' // To recognize Devanagari script implementation 'com.google.android.gms:play-services-mlkit-text-recognition-devanagari:16.0.1' // To recognize Japanese script implementation 'com.google.android.gms:play-services-mlkit-text-recognition-japanese:16.0.1' // To recognize Korean script implementation 'com.google.android.gms:play-services-mlkit-text-recognition-korean:16.0.1' }
- اگر تصمیم دارید از مدل در سرویسهای گوگل پلی استفاده کنید ، میتوانید برنامه خود را طوری پیکربندی کنید که پس از نصب برنامه از فروشگاه پلی استور، مدل را به طور خودکار روی دستگاه دانلود کند. برای انجام این کار، اعلان زیر را به فایل - AndroidManifest.xmlبرنامه خود اضافه کنید:- <application ...> ... <meta-data android:name="com.google.mlkit.vision.DEPENDENCIES" android:value="ocr" > <!-- To use multiple models: android:value="ocr,ocr_chinese,ocr_devanagari,ocr_japanese,ocr_korean,..." --> </application>- همچنین میتوانید به طور صریح در دسترس بودن مدل را بررسی کرده و از طریق API ModuleInstallClient سرویسهای Google Play درخواست دانلود دهید. اگر دانلودهای مدل زمان نصب را فعال نکنید یا درخواست دانلود صریح ندهید، مدل در اولین باری که اسکنر را اجرا میکنید دانلود میشود. درخواستهایی که قبل از اتمام دانلود ارسال میکنید، نتیجهای ندارند. 
 ۱. یک نمونه از TextRecognizer ایجاد کنید
 یک نمونه از TextRecognizer ایجاد کنید و گزینههای مربوط به کتابخانهای که در بالا به عنوان وابستگی اعلام کردهاید را به آن ارسال کنید: کاتلین
// When using Latin script library val recognizer = TextRecognition.getClient(TextRecognizerOptions.DEFAULT_OPTIONS) // When using Chinese script library val recognizer = TextRecognition.getClient(ChineseTextRecognizerOptions.Builder().build()) // When using Devanagari script library val recognizer = TextRecognition.getClient(DevanagariTextRecognizerOptions.Builder().build()) // When using Japanese script library val recognizer = TextRecognition.getClient(JapaneseTextRecognizerOptions.Builder().build()) // When using Korean script library val recognizer = TextRecognition.getClient(KoreanTextRecognizerOptions.Builder().build())
جاوا
// When using Latin script library TextRecognizer recognizer = TextRecognition.getClient(TextRecognizerOptions.DEFAULT_OPTIONS); // When using Chinese script library TextRecognizer recognizer = TextRecognition.getClient(new ChineseTextRecognizerOptions.Builder().build()); // When using Devanagari script library TextRecognizer recognizer = TextRecognition.getClient(new DevanagariTextRecognizerOptions.Builder().build()); // When using Japanese script library TextRecognizer recognizer = TextRecognition.getClient(new JapaneseTextRecognizerOptions.Builder().build()); // When using Korean script library TextRecognizer recognizer = TextRecognition.getClient(new KoreanTextRecognizerOptions.Builder().build());
۲. تصویر ورودی را آماده کنید
 برای تشخیص متن در یک تصویر، یک شیء InputImage از Bitmap ، media.Image ، ByteBuffer ، آرایه بایت یا یک فایل روی دستگاه ایجاد کنید. سپس، شیء InputImage را به متد processImage از TextRecognizer ارسال کنید.
 شما میتوانید یک شیء InputImage را از منابع مختلفی ایجاد کنید که هر کدام در زیر توضیح داده شدهاند.
 استفاده از یک media.Image
 برای ایجاد یک شیء InputImage از یک شیء media.Image ، مانند زمانی که از دوربین یک دستگاه تصویر میگیرید، شیء media.Image و چرخش تصویر را به InputImage.fromMediaImage() ارسال کنید.
 اگر از کتابخانه CameraX استفاده میکنید، کلاسهای OnImageCapturedListener و ImageAnalysis.Analyzer مقدار چرخش را برای شما محاسبه میکنند. 
کاتلین
private class YourImageAnalyzer : ImageAnalysis.Analyzer { override fun analyze(imageProxy: ImageProxy) { val mediaImage = imageProxy.image if (mediaImage != null) { val image = InputImage.fromMediaImage(mediaImage, imageProxy.imageInfo.rotationDegrees) // Pass image to an ML Kit Vision API // ... } } }
جاوا
private class YourAnalyzer implements ImageAnalysis.Analyzer { @Override public void analyze(ImageProxy imageProxy) { Image mediaImage = imageProxy.getImage(); if (mediaImage != null) { InputImage image = InputImage.fromMediaImage(mediaImage, imageProxy.getImageInfo().getRotationDegrees()); // Pass image to an ML Kit Vision API // ... } } }
اگر از کتابخانه دوربینی که درجه چرخش تصویر را به شما بدهد استفاده نمیکنید، میتوانید آن را از درجه چرخش دستگاه و جهت سنسور دوربین در دستگاه محاسبه کنید:
کاتلین
private val ORIENTATIONS = SparseIntArray() init { ORIENTATIONS.append(Surface.ROTATION_0, 0) ORIENTATIONS.append(Surface.ROTATION_90, 90) ORIENTATIONS.append(Surface.ROTATION_180, 180) ORIENTATIONS.append(Surface.ROTATION_270, 270) } /** * Get the angle by which an image must be rotated given the device's current * orientation. */ @RequiresApi(api = Build.VERSION_CODES.LOLLIPOP) @Throws(CameraAccessException::class) private fun getRotationCompensation(cameraId: String, activity: Activity, isFrontFacing: Boolean): Int { // Get the device's current rotation relative to its "native" orientation. // Then, from the ORIENTATIONS table, look up the angle the image must be // rotated to compensate for the device's rotation. val deviceRotation = activity.windowManager.defaultDisplay.rotation var rotationCompensation = ORIENTATIONS.get(deviceRotation) // Get the device's sensor orientation. val cameraManager = activity.getSystemService(CAMERA_SERVICE) as CameraManager val sensorOrientation = cameraManager .getCameraCharacteristics(cameraId) .get(CameraCharacteristics.SENSOR_ORIENTATION)!! if (isFrontFacing) { rotationCompensation = (sensorOrientation + rotationCompensation) % 360 } else { // back-facing rotationCompensation = (sensorOrientation - rotationCompensation + 360) % 360 } return rotationCompensation }
جاوا
private static final SparseIntArray ORIENTATIONS = new SparseIntArray(); static { ORIENTATIONS.append(Surface.ROTATION_0, 0); ORIENTATIONS.append(Surface.ROTATION_90, 90); ORIENTATIONS.append(Surface.ROTATION_180, 180); ORIENTATIONS.append(Surface.ROTATION_270, 270); } /** * Get the angle by which an image must be rotated given the device's current * orientation. */ @RequiresApi(api = Build.VERSION_CODES.LOLLIPOP) private int getRotationCompensation(String cameraId, Activity activity, boolean isFrontFacing) throws CameraAccessException { // Get the device's current rotation relative to its "native" orientation. // Then, from the ORIENTATIONS table, look up the angle the image must be // rotated to compensate for the device's rotation. int deviceRotation = activity.getWindowManager().getDefaultDisplay().getRotation(); int rotationCompensation = ORIENTATIONS.get(deviceRotation); // Get the device's sensor orientation. CameraManager cameraManager = (CameraManager) activity.getSystemService(CAMERA_SERVICE); int sensorOrientation = cameraManager .getCameraCharacteristics(cameraId) .get(CameraCharacteristics.SENSOR_ORIENTATION); if (isFrontFacing) { rotationCompensation = (sensorOrientation + rotationCompensation) % 360; } else { // back-facing rotationCompensation = (sensorOrientation - rotationCompensation + 360) % 360; } return rotationCompensation; }
 سپس، شیء media.Image و مقدار درجه چرخش را به InputImage.fromMediaImage() ارسال کنید: 
کاتلین
val image = InputImage.fromMediaImage(mediaImage, rotation)
Java
InputImage image = InputImage.fromMediaImage(mediaImage, rotation);
استفاده از یک URI فایل
 برای ایجاد یک شیء InputImage از یک URI فایل، متن برنامه و URI فایل را به InputImage.fromFilePath() ارسال کنید. این زمانی مفید است که از یک ACTION_GET_CONTENT برای وادار کردن کاربر به انتخاب یک تصویر از برنامه گالری خود استفاده میکنید. 
کاتلین
val image: InputImage try { image = InputImage.fromFilePath(context, uri) } catch (e: IOException) { e.printStackTrace() }
Java
InputImage image; try { image = InputImage.fromFilePath(context, uri); } catch (IOException e) { e.printStackTrace(); }
استفاده از ByteBuffer یا ByteArray
 برای ایجاد یک شیء InputImage از یک ByteBuffer یا یک ByteArray ، ابتدا درجه چرخش تصویر را همانطور که قبلاً برای ورودی media.Image توضیح داده شد، محاسبه کنید. سپس، شیء InputImage را با بافر یا آرایه، به همراه ارتفاع، عرض، فرمت کدگذاری رنگ و درجه چرخش تصویر ایجاد کنید: 
کاتلین
val image = InputImage.fromByteBuffer( byteBuffer, /* image width */ 480, /* image height */ 360, rotationDegrees, InputImage.IMAGE_FORMAT_NV21 // or IMAGE_FORMAT_YV12 ) // Or: val image = InputImage.fromByteArray( byteArray, /* image width */ 480, /* image height */ 360, rotationDegrees, InputImage.IMAGE_FORMAT_NV21 // or IMAGE_FORMAT_YV12 )
جاوا
InputImage image = InputImage.fromByteBuffer(byteBuffer, /* image width */ 480, /* image height */ 360, rotationDegrees, InputImage.IMAGE_FORMAT_NV21 // or IMAGE_FORMAT_YV12 ); // Or: InputImage image = InputImage.fromByteArray( byteArray, /* image width */480, /* image height */360, rotation, InputImage.IMAGE_FORMAT_NV21 // or IMAGE_FORMAT_YV12 );
 استفاده از Bitmap
 برای ایجاد یک شیء InputImage از یک شیء Bitmap ، تعریف زیر را انجام دهید: 
کاتلین
val image = InputImage.fromBitmap(bitmap, 0)
Java
InputImage image = InputImage.fromBitmap(bitmap, rotationDegree);
 تصویر توسط یک شیء Bitmap به همراه درجه چرخش نمایش داده میشود.
۳. تصویر را پردازش کنید
 تصویر را به متد process ارسال کنید: 
کاتلین
val result = recognizer.process(image) .addOnSuccessListener { visionText -> // Task completed successfully // ... } .addOnFailureListener { e -> // Task failed with an exception // ... }
جاوا
Task<Text> result = recognizer.process(image) .addOnSuccessListener(new OnSuccessListener<Text>() { @Override public void onSuccess(Text visionText) { // Task completed successfully // ... } }) .addOnFailureListener( new OnFailureListener() { @Override public void onFailure(@NonNull Exception e) { // Task failed with an exception // ... } });
۴. استخراج متن از بلوکهای متن شناختهشده
 اگر عملیات تشخیص متن با موفقیت انجام شود، یک شیء Text به شنوندهی success ارسال میشود. یک شیء Text شامل متن کامل تشخیص داده شده در تصویر و صفر یا چند شیء TextBlock است.
 هر TextBlock نشان دهنده یک بلوک مستطیلی از متن است که شامل صفر یا چند شیء Line است. هر شیء Line نشان دهنده یک خط از متن است که شامل صفر یا چند شیء Element است. هر شیء Element نشان دهنده یک کلمه یا یک موجودیت کلمه مانند است که شامل صفر یا چند شیء Symbol است. هر شیء Symbol نشان دهنده یک کاراکتر، یک رقم یا یک موجودیت کلمه مانند است.
 برای هر شیء TextBlock ، Line ، Element و Symbol ، میتوانید متن تشخیص داده شده در ناحیه، مختصات مرزی ناحیه و بسیاری از ویژگیهای دیگر مانند اطلاعات چرخش، امتیاز اطمینان و غیره را دریافت کنید.
برای مثال:
کاتلین
val resultText = result.text for (block in result.textBlocks) { val blockText = block.text val blockCornerPoints = block.cornerPoints val blockFrame = block.boundingBox for (line in block.lines) { val lineText = line.text val lineCornerPoints = line.cornerPoints val lineFrame = line.boundingBox for (element in line.elements) { val elementText = element.text val elementCornerPoints = element.cornerPoints val elementFrame = element.boundingBox } } }
جاوا
String resultText = result.getText(); for (Text.TextBlock block : result.getTextBlocks()) { String blockText = block.getText(); Point[] blockCornerPoints = block.getCornerPoints(); Rect blockFrame = block.getBoundingBox(); for (Text.Line line : block.getLines()) { String lineText = line.getText(); Point[] lineCornerPoints = line.getCornerPoints(); Rect lineFrame = line.getBoundingBox(); for (Text.Element element : line.getElements()) { String elementText = element.getText(); Point[] elementCornerPoints = element.getCornerPoints(); Rect elementFrame = element.getBoundingBox(); for (Text.Symbol symbol : element.getSymbols()) { String symbolText = symbol.getText(); Point[] symbolCornerPoints = symbol.getCornerPoints(); Rect symbolFrame = symbol.getBoundingBox(); } } } }
دستورالعملهای تصویر ورودی
- برای اینکه کیت ML متن را به طور دقیق تشخیص دهد، تصاویر ورودی باید حاوی متنی باشند که با دادههای پیکسلی کافی نمایش داده میشود. در حالت ایدهآل، هر کاراکتر باید حداقل 16x16 پیکسل باشد. به طور کلی هیچ مزیتی برای دقت کاراکترهایی که بزرگتر از 24x24 پیکسل هستند، وجود ندارد. - بنابراین، برای مثال، یک تصویر با ابعاد ۶۴۰x۴۸۰ پیکسل ممکن است برای اسکن یک کارت ویزیت که تمام عرض تصویر را اشغال میکند، مناسب باشد. برای اسکن یک سند چاپ شده روی کاغذ با اندازه Letter، ممکن است به یک تصویر با ابعاد ۷۲۰x۱۲۸۰ پیکسل نیاز باشد. 
- فوکوس ضعیف تصویر میتواند بر دقت تشخیص متن تأثیر بگذارد. اگر نتایج قابل قبولی دریافت نمیکنید، سعی کنید از کاربر بخواهید که تصویر را دوباره ثبت کند. 
- اگر متن را در یک برنامه بلادرنگ تشخیص میدهید، باید ابعاد کلی تصاویر ورودی را در نظر بگیرید. تصاویر کوچکتر میتوانند سریعتر پردازش شوند. برای کاهش تأخیر، مطمئن شوید که متن تا حد امکان فضای بیشتری از تصویر را اشغال میکند و تصاویر را با وضوح پایینتر ضبط کنید (با در نظر گرفتن الزامات دقت ذکر شده در بالا). برای اطلاعات بیشتر، به نکاتی برای بهبود عملکرد مراجعه کنید. 
نکاتی برای بهبود عملکرد
-  اگر از API Cameraیاcamera2استفاده میکنید، فراخوانیهای throttle به آشکارساز انجام میشود. اگر در حین اجرای آشکارساز، یک فریم ویدیویی جدید در دسترس قرار گرفت، فریم را حذف کنید. برای مثال، به کلاسVisionProcessorBaseدر برنامه نمونه شروع سریع مراجعه کنید.
-  اگر از API CameraXاستفاده میکنید، مطمئن شوید که استراتژی فشار معکوس (backpressure strategy) روی مقدار پیشفرض خودImageAnalysis.STRATEGY_KEEP_ONLY_LATESTتنظیم شده است. این تضمین میکند که فقط یک تصویر در هر زمان برای تجزیه و تحلیل تحویل داده میشود. اگر تصاویر بیشتری هنگام مشغول بودن تحلیلگر تولید شوند، به طور خودکار حذف میشوند و برای تحویل در صف قرار نمیگیرند. پس از بسته شدن تصویر در حال تجزیه و تحلیل با فراخوانی ImageProxy.close()، آخرین تصویر بعدی تحویل داده میشود.
-  اگر از خروجی آشکارساز برای همپوشانی گرافیک روی تصویر ورودی استفاده میکنید، ابتدا نتیجه را از کیت ML دریافت کنید، سپس تصویر و همپوشانی را در یک مرحله رندر کنید. این کار فقط یک بار برای هر فریم ورودی روی سطح نمایشگر رندر میشود. برای مثال به کلاسهای CameraSourcePreviewوGraphicOverlayدر برنامه نمونه شروع سریع مراجعه کنید.
-  اگر از API دوربین ۲ استفاده میکنید، تصاویر را با فرمت ImageFormat.YUV_420_888ضبط کنید. اگر از API دوربین قدیمیتر استفاده میکنید، تصاویر را با فرمتImageFormat.NV21ضبط کنید.
- ضبط تصاویر با وضوح پایینتر را در نظر بگیرید. با این حال، الزامات ابعاد تصویر این API را نیز در نظر داشته باشید.
