تصاویر را با یک مدل آموزش دیده با AutoML در Android برچسب بزنید
بعد از اینکه مدل خود را با استفاده از AutoML Vision Edge آموزش دادید ، میتوانید از آن در برنامه خود برای برچسبگذاری تصاویر استفاده کنید. دو راه برای ادغام مدلهای آموزشدیده شده از AutoML Vision Edge وجود دارد: میتوانید مدل را با قرار دادن آن در پوشه دارایی برنامه خود دستهبندی کنید، یا میتوانید به صورت پویا آن را از Firebase دانلود کنید.گزینه های بسته بندی مدل | |
---|---|
همراه با برنامه شما |
|
میزبانی شده با Firebase |
|
آن را امتحان کنید
- با برنامه نمونه بازی کنید تا نمونه استفاده از این API را ببینید.
قبل از شروع
1. در فایلbuild.gradle
در سطح پروژه خود، مطمئن شوید که مخزن Maven Google را در هر دو بخش buildscript
و allprojects
خود قرار دهید.2. وابستگیهای کتابخانههای اندروید ML Kit را به فایل gradle سطح برنامه ماژول خود اضافه کنید، که معمولاً
app/build.gradle
است: برای بستهبندی یک مدل با برنامه خود: dependencies { // ... // Image labeling feature with bundled automl model implementation 'com.google.mlkit:image-labeling-automl:16.2.1' }برای دانلود پویا یک مدل از Firebase، وابستگی
linkFirebase
را اضافه کنید: dependencies { // ... // Image labeling feature with automl model downloaded // from firebase implementation 'com.google.mlkit:image-labeling-automl:16.2.1' implementation 'com.google.mlkit:linkfirebase:16.0.1' }3. اگر می خواهید مدلی را دانلود کنید ، مطمئن شوید که Firebase را به پروژه اندروید خود اضافه کرده اید، اگر قبلاً این کار را نکرده اید. هنگامی که مدل را بسته بندی می کنید، این مورد نیاز نیست.
1. مدل را بارگذاری کنید
یک منبع مدل محلی را پیکربندی کنید
برای بستهبندی مدل با برنامهتان:1. مدل و ابرداده آن را از آرشیو فشرده ای که از کنسول Firebase دانلود کرده اید استخراج کنید. توصیه میکنیم از فایلها در حین دانلود، بدون تغییر (از جمله نام فایل) استفاده کنید.
2. مدل خود و فایل های فراداده آن را در بسته برنامه خود قرار دهید:
الف اگر در پروژه خود پوشه دارایی ندارید، با کلیک راست روی پوشه
app/
، سپس روی New > Folder > Assets Folder کلیک کنید.ب یک پوشه فرعی در زیر پوشه assets ایجاد کنید تا حاوی فایل های مدل باشد.
ج فایلهای
model.tflite
، dict.txt
و manifest.json
را در پوشه فرعی کپی کنید (هر سه فایل باید در یک پوشه باشند).3. موارد زیر را به فایل
build.gradle
برنامه خود اضافه کنید تا مطمئن شوید که Gradle فایل مدل را هنگام ساخت برنامه فشرده نمی کند: android { // ... aaptOptions { noCompress "tflite" } }فایل مدل در بسته برنامه گنجانده شده و به عنوان دارایی خام در اختیار ML Kit قرار خواهد گرفت.
توجه: با شروع نسخه 4.1 پلاگین Android Gradle، tflite. به طور پیش فرض به لیست noCompress اضافه می شود و دیگر نیازی به موارد فوق نیست.
4. شی
LocalModel
ایجاد کنید، مسیر فایل مانیفست مدل را مشخص کنید: کاتلین
val localModel = AutoMLImageLabelerLocalModel.Builder() .setAssetFilePath("manifest.json") // or .setAbsoluteFilePath(absolute file path to manifest file) .build()
جاوا
AutoMLImageLabelerLocalModel localModel = new AutoMLImageLabelerLocalModel.Builder() .setAssetFilePath("manifest.json") // or .setAbsoluteFilePath(absolute file path to manifest file) .build();
یک منبع مدل میزبانی شده توسط Firebase را پیکربندی کنید
برای استفاده از مدل میزبانی از راه دور، یک شی RemoteModel
ایجاد کنید و نامی را که به مدل اختصاص داده اید هنگام انتشار آن مشخص کنید:
کاتلین
// Specify the name you assigned in the Firebase console. val remoteModel = AutoMLImageLabelerRemoteModel.Builder("your_model_name").build()
جاوا
// Specify the name you assigned in the Firebase console. AutoMLImageLabelerRemoteModel remoteModel = new AutoMLImageLabelerRemoteModel.Builder("your_model_name").build();
سپس، با مشخص کردن شرایطی که میخواهید اجازه دانلود را بدهید، کار دانلود مدل را شروع کنید. اگر مدل در دستگاه نباشد، یا اگر نسخه جدیدتری از مدل موجود باشد، این کار به صورت ناهمزمان مدل را از Firebase دانلود میکند:
کاتلین
val downloadConditions = DownloadConditions.Builder() .requireWifi() .build() RemoteModelManager.getInstance().download(remoteModel, downloadConditions) .addOnSuccessListener { // Success. }
جاوا
DownloadConditions downloadConditions = new DownloadConditions.Builder() .requireWifi() .build(); RemoteModelManager.getInstance().download(remoteModel, downloadConditions) .addOnSuccessListener(new OnSuccessListener() { @Override public void onSuccess(@NonNull Task task) { // Success. } });
بسیاری از برنامهها وظیفه دانلود را در کد اولیه خود شروع میکنند، اما شما میتوانید این کار را در هر زمانی قبل از نیاز به استفاده از مدل انجام دهید.
یک برچسب تصویر از مدل خود ایجاد کنید
پس از پیکربندی منابع مدل خود، یک شی ImageLabeler
از یکی از آنها ایجاد کنید.
اگر فقط یک مدل به صورت محلی دارید، فقط یک برچسب از شی AutoMLImageLabelerLocalModel
خود ایجاد کنید و آستانه امتیاز اطمینان مورد نیاز خود را پیکربندی کنید ( به ارزیابی مدل خود مراجعه کنید):
کاتلین
val autoMLImageLabelerOptions = AutoMLImageLabelerOptions.Builder(localModel) .setConfidenceThreshold(0) // Evaluate your model in the Firebase console // to determine an appropriate value. .build() val labeler = ImageLabeling.getClient(autoMLImageLabelerOptions)
جاوا
AutoMLImageLabelerOptions autoMLImageLabelerOptions = new AutoMLImageLabelerOptions.Builder(localModel) .setConfidenceThreshold(0.0f) // Evaluate your model in the Firebase console // to determine an appropriate value. .build(); ImageLabeler labeler = ImageLabeling.getClient(autoMLImageLabelerOptions)
اگر یک مدل با میزبانی از راه دور دارید، قبل از اجرای آن باید بررسی کنید که دانلود شده است. با استفاده از متد isModelDownloaded()
مدیر مدل می توانید وضعیت وظیفه دانلود مدل را بررسی کنید.
اگرچه شما فقط باید قبل از اجرای برچسبگذار این موضوع را تأیید کنید، اگر هم یک مدل با میزبانی از راه دور و هم یک مدل بستهبندی محلی دارید، ممکن است این بررسی را هنگام نمونهسازی برچسبکننده تصویر انجام دهید: یک برچسبگذار از مدل راه دور ایجاد کنید اگر دانلود شده است، و در غیر این صورت از مدل محلی.
کاتلین
RemoteModelManager.getInstance().isModelDownloaded(remoteModel) .addOnSuccessListener { isDownloaded -> val optionsBuilder = if (isDownloaded) { AutoMLImageLabelerOptions.Builder(remoteModel) } else { AutoMLImageLabelerOptions.Builder(localModel) } // Evaluate your model in the Firebase console to determine an appropriate threshold. val options = optionsBuilder.setConfidenceThreshold(0.0f).build() val labeler = ImageLabeling.getClient(options) }
جاوا
RemoteModelManager.getInstance().isModelDownloaded(remoteModel) .addOnSuccessListener(new OnSuccessListener() { @Override public void onSuccess(Boolean isDownloaded) { AutoMLImageLabelerOptions.Builder optionsBuilder; if (isDownloaded) { optionsBuilder = new AutoMLImageLabelerOptions.Builder(remoteModel); } else { optionsBuilder = new AutoMLImageLabelerOptions.Builder(localModel); } AutoMLImageLabelerOptions options = optionsBuilder .setConfidenceThreshold(0.0f) // Evaluate your model in the Firebase console // to determine an appropriate threshold. .build(); ImageLabeler labeler = ImageLabeling.getClient(options); } });
اگر فقط یک مدل با میزبانی از راه دور دارید، باید عملکردهای مربوط به مدل را غیرفعال کنید - به عنوان مثال، خاکستری کردن یا پنهان کردن بخشی از رابط کاربری خود - تا زمانی که تأیید کنید مدل دانلود شده است. می توانید این کار را با پیوست کردن شنونده به متد download()
مدیر مدل انجام دهید:
کاتلین
RemoteModelManager.getInstance().download(remoteModel, conditions) .addOnSuccessListener { // Download complete. Depending on your app, you could enable the ML // feature, or switch from the local model to the remote model, etc. }
جاوا
RemoteModelManager.getInstance().download(remoteModel, conditions) .addOnSuccessListener(new OnSuccessListener() { @Override public void onSuccess(Void v) { // Download complete. Depending on your app, you could enable // the ML feature, or switch from the local model to the remote // model, etc. } });
2. تصویر ورودی را آماده کنید
سپس، برای هر تصویری که می خواهید برچسب گذاری کنید، یک شی InputImage
از تصویر خود ایجاد کنید. وقتی از Bitmap
استفاده میکنید، برچسبگذار تصویر سریعترین کار را انجام میدهد، یا اگر از camera2 API استفاده میکنید، یک media.Image
YUV_420_888. Image، که در صورت امکان توصیه میشوند.
می توانید یک شی InputImage
از منابع مختلف ایجاد کنید که هر کدام در زیر توضیح داده شده است.
استفاده از یک media.Image
برای ایجاد یک شیء InputImage
از یک شیء media.Image
، مانند زمانی که تصویری را از دوربین دستگاه میگیرید، شیء media.Image
.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
همراه با درجه چرخش نمایش داده می شود.
3. برچسب تصویر را اجرا کنید
برای برچسب گذاری اشیاء در یک تصویر، شیimage
را به متد process()
ImageLabeler
ارسال کنید. کاتلین
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 // ... } });
4. اطلاعاتی در مورد اشیاء برچسب دار دریافت کنید
اگر عملیات برچسب گذاری تصویر با موفقیت انجام شود، لیستی از اشیاء ImageLabel
به شنونده موفقیت ارسال می شود. هر شی ImageLabel
چیزی را نشان می دهد که در تصویر برچسب گذاری شده است. میتوانید توضیحات متنی هر برچسب، امتیاز اطمینان مسابقه و شاخص مسابقه را دریافت کنید. به عنوان مثال:
کاتلین
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
یاcamera2
API استفاده میکنید، دریچه گاز با برچسب تصویر تماس میگیرد. اگر در حالی که برچسبدهنده تصویر در حال اجرا است، فریم ویدیویی جدیدی در دسترس است، قاب را رها کنید. برای مثال، کلاسVisionProcessorBase
را در برنامه نمونه سریع شروع کنید. - اگر از
CameraX
API استفاده میکنید، مطمئن شوید که استراتژی فشار برگشتی روی مقدار پیشفرضImageAnalysis.STRATEGY_KEEP_ONLY_LATEST
تنظیم شده است.STRATEGY_KEEP_ONLY_LATEST. این تضمین می کند که هر بار فقط یک تصویر برای تجزیه و تحلیل تحویل داده می شود. اگر در زمانی که آنالایزر مشغول است، تصاویر بیشتری تولید شود، به طور خودکار حذف می شوند و برای تحویل در صف قرار نمی گیرند. هنگامی که تصویر مورد تجزیه و تحلیل با فراخوانی ImageProxy.close بسته شد، آخرین تصویر بعدی تحویل داده می شود. - اگر از خروجی برچسب تصویر برای همپوشانی گرافیک روی تصویر ورودی استفاده می کنید، ابتدا نتیجه را از کیت ML دریافت کنید، سپس تصویر را رندر کنید و در یک مرحله همپوشانی کنید. این تنها یک بار برای هر فریم ورودی به سطح نمایشگر نمایش داده می شود. برای مثال، کلاسهای
CameraSourcePreview
وGraphicOverlay
را در برنامه نمونه شروع سریع ببینید. - اگر از Camera2 API استفاده می کنید، تصاویر را با فرمت
ImageFormat.YUV_420_888
بگیرید. اگر از دوربین قدیمیتر API استفاده میکنید، تصاویر را با فرمتImageFormat.NV21
بگیرید.
تصاویر را با یک مدل آموزش دیده با AutoML در Android برچسب بزنید
بعد از اینکه مدل خود را با استفاده از AutoML Vision Edge آموزش دادید ، میتوانید از آن در برنامه خود برای برچسبگذاری تصاویر استفاده کنید. دو راه برای ادغام مدلهای آموزشدیده شده از AutoML Vision Edge وجود دارد: میتوانید مدل را با قرار دادن آن در پوشه دارایی برنامه خود دستهبندی کنید، یا میتوانید به صورت پویا آن را از Firebase دانلود کنید.گزینه های بسته بندی مدل | |
---|---|
همراه با برنامه شما |
|
میزبانی شده با Firebase |
|
آن را امتحان کنید
- با برنامه نمونه بازی کنید تا نمونه استفاده از این API را ببینید.
قبل از شروع
1. در فایلbuild.gradle
در سطح پروژه خود، مطمئن شوید که مخزن Maven Google را در هر دو بخش buildscript
و allprojects
خود قرار دهید.2. وابستگیهای کتابخانههای اندروید ML Kit را به فایل gradle سطح برنامه ماژول خود اضافه کنید، که معمولاً
app/build.gradle
است: برای بستهبندی یک مدل با برنامه خود: dependencies { // ... // Image labeling feature with bundled automl model implementation 'com.google.mlkit:image-labeling-automl:16.2.1' }برای دانلود پویا یک مدل از Firebase، وابستگی
linkFirebase
را اضافه کنید: dependencies { // ... // Image labeling feature with automl model downloaded // from firebase implementation 'com.google.mlkit:image-labeling-automl:16.2.1' implementation 'com.google.mlkit:linkfirebase:16.0.1' }3. اگر می خواهید مدلی را دانلود کنید ، مطمئن شوید که Firebase را به پروژه اندروید خود اضافه کرده اید، اگر قبلاً این کار را نکرده اید. هنگامی که مدل را بسته بندی می کنید، این مورد نیاز نیست.
1. مدل را بارگذاری کنید
یک منبع مدل محلی را پیکربندی کنید
برای بستهبندی مدل با برنامهتان:1. مدل و ابرداده آن را از آرشیو فشرده ای که از کنسول Firebase دانلود کرده اید استخراج کنید. توصیه میکنیم از فایلها در حین دانلود، بدون تغییر (از جمله نام فایل) استفاده کنید.
2. مدل خود و فایل های فراداده آن را در بسته برنامه خود قرار دهید:
الف اگر در پروژه خود پوشه دارایی ندارید، با کلیک راست روی پوشه
app/
، سپس روی New > Folder > Assets Folder کلیک کنید.ب یک پوشه فرعی در زیر پوشه assets ایجاد کنید تا حاوی فایل های مدل باشد.
ج فایلهای
model.tflite
، dict.txt
و manifest.json
را در پوشه فرعی کپی کنید (هر سه فایل باید در یک پوشه باشند).3. موارد زیر را به فایل
build.gradle
برنامه خود اضافه کنید تا مطمئن شوید که Gradle فایل مدل را هنگام ساخت برنامه فشرده نمی کند: android { // ... aaptOptions { noCompress "tflite" } }فایل مدل در بسته برنامه گنجانده شده و به عنوان دارایی خام در اختیار ML Kit قرار خواهد گرفت.
توجه: با شروع نسخه 4.1 پلاگین Android Gradle، tflite. به طور پیش فرض به لیست noCompress اضافه می شود و دیگر نیازی به موارد فوق نیست.
4. شی
LocalModel
ایجاد کنید، مسیر فایل مانیفست مدل را مشخص کنید: کاتلین
val localModel = AutoMLImageLabelerLocalModel.Builder() .setAssetFilePath("manifest.json") // or .setAbsoluteFilePath(absolute file path to manifest file) .build()
جاوا
AutoMLImageLabelerLocalModel localModel = new AutoMLImageLabelerLocalModel.Builder() .setAssetFilePath("manifest.json") // or .setAbsoluteFilePath(absolute file path to manifest file) .build();
یک منبع مدل میزبانی شده توسط Firebase را پیکربندی کنید
برای استفاده از مدل میزبانی از راه دور، یک شی RemoteModel
ایجاد کنید و نامی را که به مدل اختصاص داده اید هنگام انتشار آن مشخص کنید:
کاتلین
// Specify the name you assigned in the Firebase console. val remoteModel = AutoMLImageLabelerRemoteModel.Builder("your_model_name").build()
جاوا
// Specify the name you assigned in the Firebase console. AutoMLImageLabelerRemoteModel remoteModel = new AutoMLImageLabelerRemoteModel.Builder("your_model_name").build();
سپس، با مشخص کردن شرایطی که میخواهید اجازه دانلود را بدهید، کار دانلود مدل را شروع کنید. اگر مدل در دستگاه نباشد، یا اگر نسخه جدیدتری از مدل موجود باشد، این کار به صورت ناهمزمان مدل را از Firebase دانلود میکند:
کاتلین
val downloadConditions = DownloadConditions.Builder() .requireWifi() .build() RemoteModelManager.getInstance().download(remoteModel, downloadConditions) .addOnSuccessListener { // Success. }
جاوا
DownloadConditions downloadConditions = new DownloadConditions.Builder() .requireWifi() .build(); RemoteModelManager.getInstance().download(remoteModel, downloadConditions) .addOnSuccessListener(new OnSuccessListener() { @Override public void onSuccess(@NonNull Task task) { // Success. } });
بسیاری از برنامهها وظیفه دانلود را در کد اولیه خود شروع میکنند، اما شما میتوانید این کار را در هر زمانی قبل از نیاز به استفاده از مدل انجام دهید.
یک برچسب تصویر از مدل خود ایجاد کنید
پس از پیکربندی منابع مدل خود، یک شی ImageLabeler
از یکی از آنها ایجاد کنید.
اگر فقط یک مدل به صورت محلی دارید، فقط یک برچسب از شی AutoMLImageLabelerLocalModel
خود ایجاد کنید و آستانه امتیاز اطمینان مورد نیاز خود را پیکربندی کنید ( به ارزیابی مدل خود مراجعه کنید):
کاتلین
val autoMLImageLabelerOptions = AutoMLImageLabelerOptions.Builder(localModel) .setConfidenceThreshold(0) // Evaluate your model in the Firebase console // to determine an appropriate value. .build() val labeler = ImageLabeling.getClient(autoMLImageLabelerOptions)
جاوا
AutoMLImageLabelerOptions autoMLImageLabelerOptions = new AutoMLImageLabelerOptions.Builder(localModel) .setConfidenceThreshold(0.0f) // Evaluate your model in the Firebase console // to determine an appropriate value. .build(); ImageLabeler labeler = ImageLabeling.getClient(autoMLImageLabelerOptions)
اگر یک مدل با میزبانی از راه دور دارید، قبل از اجرای آن باید بررسی کنید که دانلود شده است. با استفاده از متد isModelDownloaded()
مدیر مدل می توانید وضعیت وظیفه دانلود مدل را بررسی کنید.
اگرچه شما فقط باید قبل از اجرای برچسبگذار این موضوع را تأیید کنید، اگر هم یک مدل با میزبانی از راه دور و هم یک مدل بستهبندی محلی دارید، ممکن است این بررسی را هنگام نمونهسازی برچسبکننده تصویر انجام دهید: یک برچسبگذار از مدل راه دور ایجاد کنید اگر دانلود شده است، و در غیر این صورت از مدل محلی.
کاتلین
RemoteModelManager.getInstance().isModelDownloaded(remoteModel) .addOnSuccessListener { isDownloaded -> val optionsBuilder = if (isDownloaded) { AutoMLImageLabelerOptions.Builder(remoteModel) } else { AutoMLImageLabelerOptions.Builder(localModel) } // Evaluate your model in the Firebase console to determine an appropriate threshold. val options = optionsBuilder.setConfidenceThreshold(0.0f).build() val labeler = ImageLabeling.getClient(options) }
جاوا
RemoteModelManager.getInstance().isModelDownloaded(remoteModel) .addOnSuccessListener(new OnSuccessListener() { @Override public void onSuccess(Boolean isDownloaded) { AutoMLImageLabelerOptions.Builder optionsBuilder; if (isDownloaded) { optionsBuilder = new AutoMLImageLabelerOptions.Builder(remoteModel); } else { optionsBuilder = new AutoMLImageLabelerOptions.Builder(localModel); } AutoMLImageLabelerOptions options = optionsBuilder .setConfidenceThreshold(0.0f) // Evaluate your model in the Firebase console // to determine an appropriate threshold. .build(); ImageLabeler labeler = ImageLabeling.getClient(options); } });
اگر فقط یک مدل با میزبانی از راه دور دارید، باید عملکردهای مربوط به مدل را غیرفعال کنید - به عنوان مثال، خاکستری کردن یا پنهان کردن بخشی از رابط کاربری خود - تا زمانی که تأیید کنید مدل دانلود شده است. می توانید این کار را با پیوست کردن شنونده به متد download()
مدیر مدل انجام دهید:
کاتلین
RemoteModelManager.getInstance().download(remoteModel, conditions) .addOnSuccessListener { // Download complete. Depending on your app, you could enable the ML // feature, or switch from the local model to the remote model, etc. }
جاوا
RemoteModelManager.getInstance().download(remoteModel, conditions) .addOnSuccessListener(new OnSuccessListener() { @Override public void onSuccess(Void v) { // Download complete. Depending on your app, you could enable // the ML feature, or switch from the local model to the remote // model, etc. } });
2. تصویر ورودی را آماده کنید
سپس، برای هر تصویری که می خواهید برچسب گذاری کنید، یک شی InputImage
از تصویر خود ایجاد کنید. وقتی از Bitmap
استفاده میکنید، برچسبگذار تصویر سریعترین کار را انجام میدهد، یا اگر از camera2 API استفاده میکنید، یک media.Image
YUV_420_888. Image، که در صورت امکان توصیه میشوند.
می توانید یک شی InputImage
از منابع مختلف ایجاد کنید که هر کدام در زیر توضیح داده شده است.
استفاده از یک media.Image
برای ایجاد یک شیء InputImage
از یک شیء media.Image
، مانند زمانی که تصویری را از دوربین دستگاه میگیرید، شیء media.Image
.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
همراه با درجه چرخش نمایش داده می شود.
3. برچسب تصویر را اجرا کنید
برای برچسب گذاری اشیاء در یک تصویر، شیimage
را به متد process()
ImageLabeler
ارسال کنید. کاتلین
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 // ... } });
4. اطلاعاتی در مورد اشیاء برچسب دار دریافت کنید
اگر عملیات برچسب گذاری تصویر با موفقیت انجام شود، لیستی از اشیاء ImageLabel
به شنونده موفقیت ارسال می شود. هر شی ImageLabel
چیزی را نشان می دهد که در تصویر برچسب گذاری شده است. میتوانید توضیحات متنی هر برچسب، امتیاز اطمینان مسابقه و شاخص مسابقه را دریافت کنید. به عنوان مثال:
کاتلین
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
یاcamera2
API استفاده میکنید، دریچه گاز با برچسب تصویر تماس میگیرد. اگر در حالی که برچسبدهنده تصویر در حال اجرا است، فریم ویدیویی جدیدی در دسترس است، قاب را رها کنید. برای مثال، کلاسVisionProcessorBase
را در برنامه نمونه سریع شروع کنید. - اگر از
CameraX
API استفاده میکنید، مطمئن شوید که استراتژی فشار برگشتی روی مقدار پیشفرضImageAnalysis.STRATEGY_KEEP_ONLY_LATEST
تنظیم شده است.STRATEGY_KEEP_ONLY_LATEST. این تضمین می کند که هر بار فقط یک تصویر برای تجزیه و تحلیل تحویل داده می شود. اگر در زمانی که آنالایزر مشغول است، تصاویر بیشتری تولید شود، به طور خودکار حذف می شوند و برای تحویل در صف قرار نمی گیرند. هنگامی که تصویر مورد تجزیه و تحلیل با فراخوانی ImageProxy.close بسته شد، آخرین تصویر بعدی تحویل داده می شود. - اگر از خروجی برچسب تصویر برای همپوشانی گرافیک روی تصویر ورودی استفاده می کنید، ابتدا نتیجه را از کیت ML دریافت کنید، سپس تصویر را رندر کنید و در یک مرحله همپوشانی کنید. این تنها یک بار برای هر فریم ورودی به سطح نمایشگر نمایش داده می شود. برای مثال، کلاسهای
CameraSourcePreview
وGraphicOverlay
را در برنامه نمونه شروع سریع ببینید. - اگر از Camera2 API استفاده می کنید، تصاویر را با فرمت
ImageFormat.YUV_420_888
بگیرید. اگر از دوربین قدیمیتر API استفاده میکنید، تصاویر را با فرمتImageFormat.NV21
بگیرید.
تصاویر را با یک مدل آموزش دیده با AutoML در Android برچسب بزنید
بعد از اینکه مدل خود را با استفاده از AutoML Vision Edge آموزش دادید ، میتوانید از آن در برنامه خود برای برچسبگذاری تصاویر استفاده کنید. دو راه برای ادغام مدلهای آموزشدیده شده از AutoML Vision Edge وجود دارد: میتوانید مدل را با قرار دادن آن در پوشه دارایی برنامه خود دستهبندی کنید، یا میتوانید به صورت پویا آن را از Firebase دانلود کنید.گزینه های بسته بندی مدل | |
---|---|
همراه با برنامه شما |
|
میزبانی شده با Firebase |
|
آن را امتحان کنید
- با برنامه نمونه بازی کنید تا نمونه استفاده از این API را ببینید.
قبل از شروع
1. در فایلbuild.gradle
در سطح پروژه خود، مطمئن شوید که مخزن Maven Google را در هر دو بخش buildscript
و allprojects
خود قرار دهید.2. وابستگیهای کتابخانههای اندروید ML Kit را به فایل gradle سطح برنامه ماژول خود اضافه کنید، که معمولاً
app/build.gradle
است: برای بستهبندی یک مدل با برنامه خود: dependencies { // ... // Image labeling feature with bundled automl model implementation 'com.google.mlkit:image-labeling-automl:16.2.1' }برای دانلود پویا یک مدل از Firebase، وابستگی
linkFirebase
را اضافه کنید: dependencies { // ... // Image labeling feature with automl model downloaded // from firebase implementation 'com.google.mlkit:image-labeling-automl:16.2.1' implementation 'com.google.mlkit:linkfirebase:16.0.1' }3. اگر می خواهید مدلی را دانلود کنید ، مطمئن شوید که Firebase را به پروژه اندروید خود اضافه کرده اید، اگر قبلاً این کار را نکرده اید. هنگامی که مدل را بسته بندی می کنید، این مورد نیاز نیست.
1. مدل را بارگذاری کنید
یک منبع مدل محلی را پیکربندی کنید
برای بستهبندی مدل با برنامهتان:1. مدل و ابرداده آن را از آرشیو فشرده ای که از کنسول Firebase دانلود کرده اید استخراج کنید. توصیه میکنیم از فایلها در حین دانلود، بدون تغییر (از جمله نام فایل) استفاده کنید.
2. مدل خود و فایل های فراداده آن را در بسته برنامه خود قرار دهید:
الف اگر در پروژه خود پوشه دارایی ندارید، با کلیک راست روی پوشه
app/
، سپس روی New > Folder > Assets Folder کلیک کنید.ب یک پوشه فرعی در زیر پوشه assets ایجاد کنید تا حاوی فایل های مدل باشد.
ج فایلهای
model.tflite
، dict.txt
و manifest.json
را در پوشه فرعی کپی کنید (هر سه فایل باید در یک پوشه باشند).3. موارد زیر را به فایل
build.gradle
برنامه خود اضافه کنید تا مطمئن شوید که Gradle فایل مدل را هنگام ساخت برنامه فشرده نمی کند: android { // ... aaptOptions { noCompress "tflite" } }فایل مدل در بسته برنامه گنجانده شده و به عنوان دارایی خام در اختیار ML Kit قرار خواهد گرفت.
توجه: با شروع نسخه 4.1 پلاگین Android Gradle، tflite. به طور پیش فرض به لیست noCompress اضافه می شود و دیگر نیازی به موارد فوق نیست.
4. شی
LocalModel
ایجاد کنید، مسیر فایل مانیفست مدل را مشخص کنید: کاتلین
val localModel = AutoMLImageLabelerLocalModel.Builder() .setAssetFilePath("manifest.json") // or .setAbsoluteFilePath(absolute file path to manifest file) .build()
جاوا
AutoMLImageLabelerLocalModel localModel = new AutoMLImageLabelerLocalModel.Builder() .setAssetFilePath("manifest.json") // or .setAbsoluteFilePath(absolute file path to manifest file) .build();
یک منبع مدل میزبانی شده توسط Firebase را پیکربندی کنید
برای استفاده از مدل میزبانی از راه دور، یک شی RemoteModel
ایجاد کنید و نامی را که به مدل اختصاص داده اید هنگام انتشار آن مشخص کنید:
کاتلین
// Specify the name you assigned in the Firebase console. val remoteModel = AutoMLImageLabelerRemoteModel.Builder("your_model_name").build()
جاوا
// Specify the name you assigned in the Firebase console. AutoMLImageLabelerRemoteModel remoteModel = new AutoMLImageLabelerRemoteModel.Builder("your_model_name").build();
سپس، با مشخص کردن شرایطی که میخواهید اجازه دانلود را بدهید، کار دانلود مدل را شروع کنید. اگر مدل در دستگاه نباشد، یا اگر نسخه جدیدتری از مدل موجود باشد، این کار به صورت ناهمزمان مدل را از Firebase دانلود میکند:
کاتلین
val downloadConditions = DownloadConditions.Builder() .requireWifi() .build() RemoteModelManager.getInstance().download(remoteModel, downloadConditions) .addOnSuccessListener { // Success. }
جاوا
DownloadConditions downloadConditions = new DownloadConditions.Builder() .requireWifi() .build(); RemoteModelManager.getInstance().download(remoteModel, downloadConditions) .addOnSuccessListener(new OnSuccessListener() { @Override public void onSuccess(@NonNull Task task) { // Success. } });
بسیاری از برنامهها وظیفه دانلود را در کد اولیه خود شروع میکنند، اما شما میتوانید این کار را در هر زمانی قبل از نیاز به استفاده از مدل انجام دهید.
یک برچسب تصویر از مدل خود ایجاد کنید
پس از پیکربندی منابع مدل خود، یک شی ImageLabeler
از یکی از آنها ایجاد کنید.
اگر فقط یک مدل به صورت محلی دارید، فقط یک برچسب از شی AutoMLImageLabelerLocalModel
خود ایجاد کنید و آستانه امتیاز اطمینان مورد نیاز خود را پیکربندی کنید ( به ارزیابی مدل خود مراجعه کنید):
کاتلین
val autoMLImageLabelerOptions = AutoMLImageLabelerOptions.Builder(localModel) .setConfidenceThreshold(0) // Evaluate your model in the Firebase console // to determine an appropriate value. .build() val labeler = ImageLabeling.getClient(autoMLImageLabelerOptions)
جاوا
AutoMLImageLabelerOptions autoMLImageLabelerOptions = new AutoMLImageLabelerOptions.Builder(localModel) .setConfidenceThreshold(0.0f) // Evaluate your model in the Firebase console // to determine an appropriate value. .build(); ImageLabeler labeler = ImageLabeling.getClient(autoMLImageLabelerOptions)
اگر یک مدل با میزبانی از راه دور دارید، قبل از اجرای آن باید بررسی کنید که دانلود شده است. با استفاده از متد isModelDownloaded()
مدیر مدل می توانید وضعیت وظیفه دانلود مدل را بررسی کنید.
اگرچه شما فقط باید قبل از اجرای برچسبگذار این موضوع را تأیید کنید، اگر هم یک مدل با میزبانی از راه دور و هم یک مدل بستهبندی محلی دارید، ممکن است این بررسی را هنگام نمونهسازی برچسبکننده تصویر انجام دهید: یک برچسبگذار از مدل راه دور ایجاد کنید اگر دانلود شده است، و در غیر این صورت از مدل محلی.
کاتلین
RemoteModelManager.getInstance().isModelDownloaded(remoteModel) .addOnSuccessListener { isDownloaded -> val optionsBuilder = if (isDownloaded) { AutoMLImageLabelerOptions.Builder(remoteModel) } else { AutoMLImageLabelerOptions.Builder(localModel) } // Evaluate your model in the Firebase console to determine an appropriate threshold. val options = optionsBuilder.setConfidenceThreshold(0.0f).build() val labeler = ImageLabeling.getClient(options) }
جاوا
RemoteModelManager.getInstance().isModelDownloaded(remoteModel) .addOnSuccessListener(new OnSuccessListener() { @Override public void onSuccess(Boolean isDownloaded) { AutoMLImageLabelerOptions.Builder optionsBuilder; if (isDownloaded) { optionsBuilder = new AutoMLImageLabelerOptions.Builder(remoteModel); } else { optionsBuilder = new AutoMLImageLabelerOptions.Builder(localModel); } AutoMLImageLabelerOptions options = optionsBuilder .setConfidenceThreshold(0.0f) // Evaluate your model in the Firebase console // to determine an appropriate threshold. .build(); ImageLabeler labeler = ImageLabeling.getClient(options); } });
اگر فقط یک مدل با میزبانی از راه دور دارید، باید عملکردهای مربوط به مدل را غیرفعال کنید - به عنوان مثال، خاکستری کردن یا پنهان کردن بخشی از رابط کاربری خود - تا زمانی که تأیید کنید مدل دانلود شده است. می توانید این کار را با پیوست کردن شنونده به متد download()
مدیر مدل انجام دهید:
کاتلین
RemoteModelManager.getInstance().download(remoteModel, conditions) .addOnSuccessListener { // Download complete. Depending on your app, you could enable the ML // feature, or switch from the local model to the remote model, etc. }
جاوا
RemoteModelManager.getInstance().download(remoteModel, conditions) .addOnSuccessListener(new OnSuccessListener() { @Override public void onSuccess(Void v) { // Download complete. Depending on your app, you could enable // the ML feature, or switch from the local model to the remote // model, etc. } });
2. تصویر ورودی را آماده کنید
سپس، برای هر تصویری که می خواهید برچسب گذاری کنید، یک شی InputImage
از تصویر خود ایجاد کنید. وقتی از Bitmap
استفاده میکنید، برچسبگذار تصویر سریعترین کار را انجام میدهد، یا اگر از camera2 API استفاده میکنید، یک media.Image
YUV_420_888. Image، که در صورت امکان توصیه میشوند.
می توانید یک شی InputImage
از منابع مختلف ایجاد کنید که هر کدام در زیر توضیح داده شده است.
استفاده از یک media.Image
برای ایجاد یک شیء InputImage
از یک شیء media.Image
، مانند زمانی که تصویری را از دوربین دستگاه میگیرید، شیء media.Image
.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
همراه با درجه چرخش نمایش داده می شود.
3. برچسب تصویر را اجرا کنید
برای برچسب گذاری اشیاء در یک تصویر، شیimage
را به متد process()
ImageLabeler
ارسال کنید. کاتلین
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 // ... } });
4. اطلاعاتی در مورد اشیاء برچسب دار دریافت کنید
اگر عملیات برچسب گذاری تصویر با موفقیت انجام شود، لیستی از اشیاء ImageLabel
به شنونده موفقیت ارسال می شود. هر شی ImageLabel
چیزی را نشان می دهد که در تصویر برچسب گذاری شده است. میتوانید توضیحات متنی هر برچسب، امتیاز اطمینان مسابقه و شاخص مسابقه را دریافت کنید. به عنوان مثال:
کاتلین
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
یاcamera2
API استفاده میکنید، دریچه گاز با برچسب تصویر تماس میگیرد. اگر در حالی که برچسبدهنده تصویر در حال اجرا است، فریم ویدیویی جدیدی در دسترس است، قاب را رها کنید. برای مثال، کلاسVisionProcessorBase
را در برنامه نمونه سریع شروع کنید. - اگر از
CameraX
API استفاده میکنید، مطمئن شوید که استراتژی فشار برگشتی روی مقدار پیشفرضImageAnalysis.STRATEGY_KEEP_ONLY_LATEST
تنظیم شده است.STRATEGY_KEEP_ONLY_LATEST. این تضمین می کند که هر بار فقط یک تصویر برای تجزیه و تحلیل تحویل داده می شود. اگر در زمانی که آنالایزر مشغول است، تصاویر بیشتری تولید شود، به طور خودکار حذف می شوند و برای تحویل در صف قرار نمی گیرند. هنگامی که تصویر مورد تجزیه و تحلیل با فراخوانی ImageProxy.close بسته شد، آخرین تصویر بعدی تحویل داده می شود. - اگر از خروجی برچسب تصویر برای همپوشانی گرافیک روی تصویر ورودی استفاده می کنید، ابتدا نتیجه را از کیت ML دریافت کنید، سپس تصویر را رندر کنید و در یک مرحله همپوشانی کنید. این تنها یک بار برای هر فریم ورودی به سطح نمایشگر نمایش داده می شود. برای مثال، کلاسهای
CameraSourcePreview
وGraphicOverlay
را در برنامه نمونه شروع سریع ببینید. - اگر از Camera2 API استفاده می کنید، تصاویر را با فرمت
ImageFormat.YUV_420_888
بگیرید. اگر از دوربین قدیمیتر API استفاده میکنید، تصاویر را با فرمتImageFormat.NV21
بگیرید.
تصاویر را با یک مدل آموزش دیده با AutoML در Android برچسب بزنید
بعد از اینکه مدل خود را با استفاده از AutoML Vision Edge آموزش دادید ، میتوانید از آن در برنامه خود برای برچسبگذاری تصاویر استفاده کنید. دو راه برای ادغام مدلهای آموزشدیده شده از AutoML Vision Edge وجود دارد: میتوانید مدل را با قرار دادن آن در پوشه دارایی برنامه خود دستهبندی کنید، یا میتوانید به صورت پویا آن را از Firebase دانلود کنید.گزینه های بسته بندی مدل | |
---|---|
همراه با برنامه شما |
|
میزبانی شده با Firebase |
|
آن را امتحان کنید
- با برنامه نمونه بازی کنید تا نمونه استفاده از این API را ببینید.
قبل از شروع
1. در فایلbuild.gradle
در سطح پروژه خود، مطمئن شوید که مخزن Maven Google را در هر دو بخش buildscript
و allprojects
خود قرار دهید.2. وابستگیهای کتابخانههای اندروید ML Kit را به فایل gradle سطح برنامه ماژول خود اضافه کنید، که معمولاً
app/build.gradle
است: برای بستهبندی یک مدل با برنامه خود: dependencies { // ... // Image labeling feature with bundled automl model implementation 'com.google.mlkit:image-labeling-automl:16.2.1' }برای دانلود پویا یک مدل از Firebase، وابستگی
linkFirebase
را اضافه کنید: dependencies { // ... // Image labeling feature with automl model downloaded // from firebase implementation 'com.google.mlkit:image-labeling-automl:16.2.1' implementation 'com.google.mlkit:linkfirebase:16.0.1' }3. اگر می خواهید مدلی را دانلود کنید ، مطمئن شوید که Firebase را به پروژه اندروید خود اضافه کرده اید، اگر قبلاً این کار را نکرده اید. هنگامی که مدل را بسته بندی می کنید، این مورد نیاز نیست.
1. مدل را بارگذاری کنید
یک منبع مدل محلی را پیکربندی کنید
برای بستهبندی مدل با برنامهتان:1. مدل و ابرداده آن را از آرشیو فشرده ای که از کنسول Firebase دانلود کرده اید استخراج کنید. توصیه میکنیم از فایلها در حین دانلود، بدون تغییر (از جمله نام فایل) استفاده کنید.
2. مدل خود و فایل های فراداده آن را در بسته برنامه خود قرار دهید:
الف اگر در پروژه خود پوشه دارایی ندارید، با کلیک راست روی پوشه
app/
، سپس روی New > Folder > Assets Folder کلیک کنید.ب یک پوشه فرعی در زیر پوشه assets ایجاد کنید تا حاوی فایل های مدل باشد.
ج فایلهای
model.tflite
، dict.txt
و manifest.json
را در پوشه فرعی کپی کنید (هر سه فایل باید در یک پوشه باشند).3. موارد زیر را به فایل
build.gradle
برنامه خود اضافه کنید تا مطمئن شوید که Gradle فایل مدل را هنگام ساخت برنامه فشرده نمی کند: android { // ... aaptOptions { noCompress "tflite" } }فایل مدل در بسته برنامه گنجانده شده و به عنوان دارایی خام در اختیار ML Kit قرار خواهد گرفت.
توجه: با شروع نسخه 4.1 پلاگین Android Gradle، tflite. به طور پیش فرض به لیست noCompress اضافه می شود و دیگر نیازی به موارد فوق نیست.
4. شی
LocalModel
ایجاد کنید، مسیر فایل مانیفست مدل را مشخص کنید: کاتلین
val localModel = AutoMLImageLabelerLocalModel.Builder() .setAssetFilePath("manifest.json") // or .setAbsoluteFilePath(absolute file path to manifest file) .build()
جاوا
AutoMLImageLabelerLocalModel localModel = new AutoMLImageLabelerLocalModel.Builder() .setAssetFilePath("manifest.json") // or .setAbsoluteFilePath(absolute file path to manifest file) .build();
یک منبع مدل میزبانی شده توسط Firebase را پیکربندی کنید
برای استفاده از مدل میزبانی از راه دور، یک شی RemoteModel
ایجاد کنید و نامی را که به مدل اختصاص داده اید هنگام انتشار آن مشخص کنید:
کاتلین
// Specify the name you assigned in the Firebase console. val remoteModel = AutoMLImageLabelerRemoteModel.Builder("your_model_name").build()
جاوا
// Specify the name you assigned in the Firebase console. AutoMLImageLabelerRemoteModel remoteModel = new AutoMLImageLabelerRemoteModel.Builder("your_model_name").build();
سپس، با مشخص کردن شرایطی که میخواهید اجازه دانلود را بدهید، کار دانلود مدل را شروع کنید. اگر مدل در دستگاه نباشد، یا اگر نسخه جدیدتری از مدل موجود باشد، این کار به صورت ناهمزمان مدل را از Firebase دانلود میکند:
کاتلین
val downloadConditions = DownloadConditions.Builder() .requireWifi() .build() RemoteModelManager.getInstance().download(remoteModel, downloadConditions) .addOnSuccessListener { // Success. }
جاوا
DownloadConditions downloadConditions = new DownloadConditions.Builder() .requireWifi() .build(); RemoteModelManager.getInstance().download(remoteModel, downloadConditions) .addOnSuccessListener(new OnSuccessListener() { @Override public void onSuccess(@NonNull Task task) { // Success. } });
بسیاری از برنامهها وظیفه دانلود را در کد اولیه خود شروع میکنند، اما شما میتوانید این کار را در هر زمانی قبل از نیاز به استفاده از مدل انجام دهید.
یک برچسب تصویر از مدل خود ایجاد کنید
پس از پیکربندی منابع مدل خود، یک شی ImageLabeler
از یکی از آنها ایجاد کنید.
اگر فقط یک مدل به صورت محلی دارید، فقط یک برچسب از شی AutoMLImageLabelerLocalModel
خود ایجاد کنید و آستانه امتیاز اطمینان مورد نیاز خود را پیکربندی کنید ( به ارزیابی مدل خود مراجعه کنید):
کاتلین
val autoMLImageLabelerOptions = AutoMLImageLabelerOptions.Builder(localModel) .setConfidenceThreshold(0) // Evaluate your model in the Firebase console // to determine an appropriate value. .build() val labeler = ImageLabeling.getClient(autoMLImageLabelerOptions)
جاوا
AutoMLImageLabelerOptions autoMLImageLabelerOptions = new AutoMLImageLabelerOptions.Builder(localModel) .setConfidenceThreshold(0.0f) // Evaluate your model in the Firebase console // to determine an appropriate value. .build(); ImageLabeler labeler = ImageLabeling.getClient(autoMLImageLabelerOptions)
اگر یک مدل با میزبانی از راه دور دارید، قبل از اجرای آن باید بررسی کنید که دانلود شده است. با استفاده از متد isModelDownloaded()
مدیر مدل می توانید وضعیت وظیفه دانلود مدل را بررسی کنید.
اگرچه شما فقط باید قبل از اجرای برچسبگذار این موضوع را تأیید کنید، اگر هم یک مدل با میزبانی از راه دور و هم یک مدل بستهبندی محلی دارید، ممکن است این بررسی را هنگام نمونهسازی برچسبکننده تصویر انجام دهید: یک برچسبگذار از مدل راه دور ایجاد کنید اگر دانلود شده است، و در غیر این صورت از مدل محلی.
کاتلین
RemoteModelManager.getInstance().isModelDownloaded(remoteModel) .addOnSuccessListener { isDownloaded -> val optionsBuilder = if (isDownloaded) { AutoMLImageLabelerOptions.Builder(remoteModel) } else { AutoMLImageLabelerOptions.Builder(localModel) } // Evaluate your model in the Firebase console to determine an appropriate threshold. val options = optionsBuilder.setConfidenceThreshold(0.0f).build() val labeler = ImageLabeling.getClient(options) }
جاوا
RemoteModelManager.getInstance().isModelDownloaded(remoteModel) .addOnSuccessListener(new OnSuccessListener() { @Override public void onSuccess(Boolean isDownloaded) { AutoMLImageLabelerOptions.Builder optionsBuilder; if (isDownloaded) { optionsBuilder = new AutoMLImageLabelerOptions.Builder(remoteModel); } else { optionsBuilder = new AutoMLImageLabelerOptions.Builder(localModel); } AutoMLImageLabelerOptions options = optionsBuilder .setConfidenceThreshold(0.0f) // Evaluate your model in the Firebase console // to determine an appropriate threshold. .build(); ImageLabeler labeler = ImageLabeling.getClient(options); } });
اگر فقط یک مدل با میزبانی از راه دور دارید، باید عملکردهای مربوط به مدل را غیرفعال کنید - به عنوان مثال، خاکستری کردن یا پنهان کردن بخشی از رابط کاربری خود - تا زمانی که تأیید کنید مدل دانلود شده است. می توانید این کار را با پیوست کردن شنونده به متد download()
مدیر مدل انجام دهید:
کاتلین
RemoteModelManager.getInstance().download(remoteModel, conditions) .addOnSuccessListener { // Download complete. Depending on your app, you could enable the ML // feature, or switch from the local model to the remote model, etc. }
جاوا
RemoteModelManager.getInstance().download(remoteModel, conditions) .addOnSuccessListener(new OnSuccessListener() { @Override public void onSuccess(Void v) { // Download complete. Depending on your app, you could enable // the ML feature, or switch from the local model to the remote // model, etc. } });
2. تصویر ورودی را آماده کنید
سپس، برای هر تصویری که می خواهید برچسب گذاری کنید، یک شی InputImage
از تصویر خود ایجاد کنید. وقتی از Bitmap
استفاده میکنید، برچسبگذار تصویر سریعترین کار را انجام میدهد، یا اگر از camera2 API استفاده میکنید، یک media.Image
YUV_420_888. Image، که در صورت امکان توصیه میشوند.
می توانید یک شی InputImage
از منابع مختلف ایجاد کنید که هر کدام در زیر توضیح داده شده است.
استفاده از یک media.Image
برای ایجاد یک شیء InputImage
از یک شیء media.Image
، مانند زمانی که تصویری را از دوربین دستگاه میگیرید، شیء media.Image
.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
همراه با درجه چرخش نمایش داده می شود.
3. برچسب تصویر را اجرا کنید
برای برچسب گذاری اشیاء در یک تصویر، شیimage
را به متد process()
ImageLabeler
ارسال کنید. کاتلین
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 // ... } });
4. اطلاعات مربوط به اشیاء دارای برچسب را دریافت کنید
اگر عملکرد برچسب زدن تصویر موفق شود ، لیستی از اشیاء ImageLabel
به شنونده موفقیت منتقل می شود. هر شیء ImageLabel
چیزی را نشان می دهد که در تصویر برچسب گذاری شده است. می توانید توضیحات متن هر برچسب ، نمره اعتماد به نفس مسابقه و شاخص مسابقه را دریافت کنید. به عنوان مثال:
کاتلین
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
یاcamera2
API استفاده می کنید ، گاز دریچه گاز به برچسب تصویر تماس می گیرد. اگر یک قاب ویدیویی جدید در حالی که برچسب تصویر در حال اجرا است در دسترس قرار می گیرد ، قاب را رها کنید. برای مثال به کلاسVisionProcessorBase
در برنامه نمونه QuickStart مراجعه کنید. - اگر از API
CameraX
استفاده می کنید ، مطمئن باشید که استراتژی Backpressure روی مقدار پیش فرضImageAnalysis.STRATEGY_KEEP_ONLY_LATEST
تنظیم شده است. این تضمین می کند که فقط یک تصویر برای تجزیه و تحلیل در یک زمان تحویل داده می شود. اگر تصاویر بیشتری در هنگام شلوغ شدن آنالایزر تولید شود ، آنها به طور خودکار از بین می روند و برای تحویل صف نمی شوند. هنگامی که تصویر مورد تجزیه و تحلیل قرار می گیرد با فراخوانی ImageProxy.Close () ، آخرین تصویر بعدی تحویل داده می شود. - اگر از خروجی برچسب تصویر برای پوشش گرافیک روی تصویر ورودی استفاده می کنید ، ابتدا نتیجه را از کیت ML دریافت کنید ، سپس تصویر را در یک مرحله ارائه دهید. این فقط یک بار برای هر قاب ورودی به سطح نمایشگر منتقل می شود. برای مثال به کلاسهای
CameraSourcePreview
وGraphicOverlay
در برنامه نمونه QuickStart مراجعه کنید. - اگر از API Camera2 استفاده می کنید ، تصاویر را با فرمت
ImageFormat.YUV_420_888
ضبط کنید. اگر از API دوربین قدیمی تر استفاده می کنید ، تصاویر را در قالبImageFormat.NV21
ضبط کنید.