میتوانید از ML Kit برای برچسبگذاری اشیای شناساییشده در تصویر استفاده کنید. مدل پیشفرض ارائهشده با ML Kit از بیشاز ۴۰۰ برچسب مختلف پشتیبانی میکند.
| ویژگی | تفکیکشده | موجود در بستهبندی |
|---|---|---|
| پیادهسازی | مدل بهصورت پویا ازطریق «خدمات Google Play» بارگیری میشود. | مدل بهصورت ایستا در زمان ساخت به شما پیوند داده میشود. |
| حجم برنامه | حدود ۲۰۰ کیلوبایت افزایش اندازه. | حدود ۵٫۷ مگابایت افزایش اندازه. |
| زمان مقداردهی اولیه | ممکن است لازم باشد قبلاز اولین استفاده، منتظر بمانید تا مدل بارگیری شود. | مدل بلافاصله دردسترس است |
امتحان کنید
- با برنامه نمونه بازی کنید تا نمونهای از استفاده از این API را ببینید.
قبلاز شروع
در فایل
build.gradleسطح پروژه، حتماً مخزن Maven مربوط به Google را در هر دو بخشbuildscriptوallprojectsاضافه کنید.وابستگیهای کتابخانههای ML Kit Android را به فایل gradle سطح برنامه واحدتان اضافه کنید، که معمولاً
app/build.gradleاست. یکی از وابستگیهای زیر را براساس نیازهایتان انتخاب کنید:برای بستهبندی مدل با برنامهتان:
dependencies { // ... // Use this dependency to bundle the model with your app implementation 'com.google.mlkit:image-labeling:17.0.9' }برای استفاده از مدل در «خدمات Google Play»:
dependencies { // ... // Use this dependency to use the dynamically downloaded model in Google Play Services implementation 'com.google.android.gms:play-services-mlkit-image-labeling:16.0.8' }اگر انتخاب کنید از مدل در «خدمات Google Play» استفاده کنید، میتوانید برنامهتان را پیکربندی کنید تا پساز نصب برنامه از «فروشگاه Play»، مدل را بهطور خودکار در دستگاه بارگیری کند. برای انجام این کار، اظهارنامه زیر را به فایل
AndroidManifest.xmlبرنامهتان اضافه کنید:<application ...> ... <meta-data android:name="com.google.mlkit.vision.DEPENDENCIES" android:value="ica" > <!-- To use multiple models: android:value="ica,model2,model3" --> </application>همچنین میتوانید دردسترس بودن مدل را بهطور صریح بررسی کنید و ازطریق خدمات Google Play ModuleInstallClient API درخواست بارگیری کنید.
اگر بارگیری مدل در زمان نصب را فعال نکنید یا درخواست بارگیری صریح نکنید، مدل اولینبار که برچسبزن را اجرا میکنید بارگیری میشود. درخواستهایی که قبلاز تکمیل بارگیری انجام میدهید، نتیجهای نخواهد داشت.
اکنون آماده برچسبگذاری تصاویر هستید.
۱. آماده کردن تصویر ورودی
شیءInputImage از تصویرتان ایجاد کنید.
برچسبزن تصویر زمانی سریعترین عملکرد را دارد که از Bitmap یا، درصورت استفاده از
camera2 API، از YUV_420_888 media.Image استفاده کنید که درصورت امکان
توصیه میشود.
میتوانید InputImage
شیء را از منابع مختلف ایجاد کنید که هرکدام در زیر توضیح داده شده است.
استفاده از media.Image
برای ایجاد شیء InputImage
از شیء media.Image، مثلاً وقتی تصویری را از
دوربین دستگاه ضبط میکنید، شیء media.Image و چرخش تصویر را به
InputImage.fromMediaImage() ارسال کنید.
اگر از کتابخانه
CameraX استفاده میکنید، کلاسهای OnImageCapturedListener و
ImageAnalysis.Analyzer مقدار چرخش را برای شما
محاسبه میکنند.
Kotlin
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 // ... } } }
اگر از کتابخانه دوربینی استفاده نمیکنید که درجه چرخش تصویر را به شما ارائه دهد، میتوانید آن را از درجه چرخش دستگاه و جهت حسگر دوربین در دستگاه محاسبه کنید:
Kotlin
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() ارسال کنید:
Kotlin
val image = InputImage.fromMediaImage(mediaImage, rotation)
Java
InputImage image = InputImage.fromMediaImage(mediaImage, rotation);
استفاده از نشانی وب فایل
برای ایجاد یک شیء InputImage
از نشانی وب فایل، بافت برنامه و نشانی وب فایل را به
InputImage.fromFilePath() ارسال کنید. این کار زمانی مفید است که
از هدف ACTION_GET_CONTENT برای درخواست از کاربر برای انتخاب
تصویری از برنامه گالری خود استفاده میکنید.
Kotlin
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 را با بافر یا آرایه، همراه با ارتفاع، عرض، قالب کدبندی رنگ، و درجه چرخش تصویر ایجاد کنید:
Kotlin
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، اعلان زیر را انجام دهید:
Kotlin
val image = InputImage.fromBitmap(bitmap, 0)
Java
InputImage image = InputImage.fromBitmap(bitmap, rotationDegree);
تصویر با شیء Bitmap بههمراه درجه چرخش نشان داده میشود.
۲. پیکربندی و اجرای برچسبزن تصویر
برای برچسبگذاری اشیا در تصویر، شیءInputImage را به
متد ImageLabeler در process ارسال کنید.
ابتدا نمونهای از
ImageLabelerرا دریافت کنید.اگر میخواهید از برچسبزن تصویر دروندستگاهی استفاده کنید، اظهارنامه زیر را ارائه دهید:
Kotlin
// To use default options: val labeler = ImageLabeling.getClient(ImageLabelerOptions.DEFAULT_OPTIONS) // Or, to set the minimum confidence required: // val options = ImageLabelerOptions.Builder() // .setConfidenceThreshold(0.7f) // .build() // val labeler = ImageLabeling.getClient(options)
جاوا
// To use default options: ImageLabeler labeler = ImageLabeling.getClient(ImageLabelerOptions.DEFAULT_OPTIONS); // Or, to set the minimum confidence required: // ImageLabelerOptions options = // new ImageLabelerOptions.Builder() // .setConfidenceThreshold(0.7f) // .build(); // ImageLabeler labeler = ImageLabeling.getClient(options);
- سپس تصویر را به روش
process()ارسال کنید:
Kotlin
labeler.process(image) .addOnSuccessListener { labels -> // Task completed successfully // ... } .addOnFailureListener { e -> // Task failed with an exception // ... }
جاوا
labeler.process(image) .addOnSuccessListener(new OnSuccessListener<List<ImageLabel>>() { @Override public void onSuccess(List<ImageLabel> labels) { // Task completed successfully // ... } }) .addOnFailureListener(new OnFailureListener() { @Override public void onFailure(@NonNull Exception e) { // Task failed with an exception // ... } });
۳. دریافت اطلاعات درباره اشیای برچسبگذاریشده
اگر عملیات برچسبگذاری تصویر موفقیتآمیز باشد، فهرستی ازImageLabel شیء به شنونده موفقیت ارسال میشود. هر
ImageLabel شیء نشاندهنده چیزی است که در تصویر برچسبگذاری شده است. مدل پایه از بیشاز ۴۰۰ برچسب مختلف پشتیبانی میکند.
میتوانید شرح نوشتاری هر برچسب، نمایه در میان همه برچسبهای پشتیبانیشده توسط
مدل، و امتیاز اطمینان مطابقت را دریافت کنید. برای مثال:
Kotlin
for (label in labels) { val text = label.text val confidence = label.confidence val index = label.index }
جاوا
for (ImageLabel label : labels) { String text = label.getText(); float confidence = label.getConfidence(); int index = label.getIndex(); }
نکتههایی برای بهبود عملکرد همزمان
اگر میخواهید تصاویر را در یک برنامه همزمان برچسبگذاری کنید، این دستورالعملها را دنبال کنید تا به بهترین نرخ فریم دست یابید:
- اگر از
Cameraیاcamera2API استفاده میکنید، فراخوانیها به برچسبزن تصویر را محدود کنید. اگر قاب ویدیو جدیدی درحین اجرای برچسبزن تصویر دردسترس قرار گرفت، قاب را رها کنید. برای نمونه، کلاسVisionProcessorBaseرا در برنامه نمونه شروع سریع ببینید. - اگر از
CameraXAPI استفاده میکنید، مطمئن شوید که استراتژی فشار برگشتی روی مقدار پیشفرض آنImageAnalysis.STRATEGY_KEEP_ONLY_LATESTتنظیم شده باشد. این کار تضمین میکند که در هر زمان فقط یک تصویر برای تجزیهوتحلیل ارسال شود. اگر وقتی تحلیلگر مشغول است تصاویر بیشتری تولید شود، بهطور خودکار حذف میشوند و برای تحویل در صف قرار نمیگیرند. وقتی تصویر درحال تجزیهوتحلیل با فراخوانی ImageProxy.close() بسته شود، جدیدترین تصویر بعدی ارائه خواهد شد. - اگر از برونداد برچسبزن تصویر برای رونهادن گرافیک روی تصویر ورودی استفاده میکنید، ابتدا نتیجه را از ML Kit دریافت کنید، سپس تصویر و رونهاد را در یک مرحله پردازش کنید. این کار فقط یکبار برای هر قاب ورودی در سطح نمایش انجام میشود. برای نمونه، کلاسهای
CameraSourcePreviewوGraphicOverlayرا در برنامه نمونه راهاندازی سریع ببینید. - اگر از Camera2 API استفاده میکنید، تصاویر را در قالب
ImageFormat.YUV_420_888ضبط کنید. اگر از Camera API قدیمیتر استفاده میکنید، تصاویر را در قالبImageFormat.NV21ضبط کنید.