تصاویر را با یک مدل آموزش دیده با AutoML در Android برچسب بزنید

بعد از اینکه مدل خود را با استفاده از AutoML Vision Edge آموزش دادید ، می‌توانید از آن در برنامه خود برای برچسب‌گذاری تصاویر استفاده کنید. دو راه برای ادغام مدل‌های آموزش‌دیده شده از AutoML Vision Edge وجود دارد: می‌توانید مدل را با قرار دادن آن در پوشه دارایی برنامه خود دسته‌بندی کنید، یا می‌توانید به صورت پویا آن را از Firebase دانلود کنید.
گزینه های بسته بندی مدل
همراه با برنامه شما
  • مدل بخشی از APK برنامه شما است
  • این مدل بلافاصله در دسترس است، حتی زمانی که دستگاه اندروید آفلاین است
  • بدون نیاز به پروژه Firebase
میزبانی شده با Firebase
  • مدل را با آپلود آن در Firebase Machine Learning میزبانی کنید
  • اندازه APK را کاهش می دهد
  • مدل در صورت تقاضا دانلود می شود
  • به روز رسانی مدل را بدون انتشار مجدد برنامه خود فشار دهید
  • تست آسان A/B با Firebase Remote Config
  • به پروژه Firebase نیاز دارد

آن را امتحان کنید

قبل از شروع

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 دانلود کنید.
گزینه های بسته بندی مدل
همراه با برنامه شما
  • مدل بخشی از APK برنامه شما است
  • این مدل بلافاصله در دسترس است، حتی زمانی که دستگاه اندروید آفلاین است
  • بدون نیاز به پروژه Firebase
میزبانی شده با Firebase
  • مدل را با آپلود آن در Firebase Machine Learning میزبانی کنید
  • اندازه APK را کاهش می دهد
  • مدل در صورت تقاضا دانلود می شود
  • به روز رسانی مدل را بدون انتشار مجدد برنامه خود فشار دهید
  • تست آسان A/B با Firebase Remote Config
  • به پروژه Firebase نیاز دارد

آن را امتحان کنید

قبل از شروع

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 دانلود کنید.
گزینه های بسته بندی مدل
همراه با برنامه شما
  • مدل بخشی از APK برنامه شما است
  • این مدل بلافاصله در دسترس است، حتی زمانی که دستگاه اندروید آفلاین است
  • بدون نیاز به پروژه Firebase
میزبانی شده با Firebase
  • مدل را با آپلود آن در Firebase Machine Learning میزبانی کنید
  • اندازه APK را کاهش می دهد
  • مدل در صورت تقاضا دانلود می شود
  • به روز رسانی مدل را بدون انتشار مجدد برنامه خود فشار دهید
  • تست آسان A/B با Firebase Remote Config
  • به پروژه Firebase نیاز دارد

آن را امتحان کنید

قبل از شروع

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 دانلود کنید.
گزینه های بسته بندی مدل
همراه با برنامه شما
  • مدل بخشی از APK برنامه شما است
  • این مدل بلافاصله در دسترس است، حتی زمانی که دستگاه اندروید آفلاین است
  • بدون نیاز به پروژه Firebase
میزبانی شده با Firebase
  • مدل را با آپلود آن در Firebase Machine Learning میزبانی کنید
  • اندازه APK را کاهش می دهد
  • مدل در صورت تقاضا دانلود می شود
  • به روز رسانی مدل را بدون انتشار مجدد برنامه خود فشار دهید
  • تست آسان A/B با Firebase Remote Config
  • به پروژه Firebase نیاز دارد

آن را امتحان کنید

قبل از شروع

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 ضبط کنید.