ژست‌ها را با ML Kit در اندروید شناسایی کنید

کیت ML دو SDK بهینه شده برای تشخیص ژست ارائه می‌دهد.

نام SDK تشخیص ژست تشخیص ژست دقیق
پیاده‌سازی کد و دارایی‌ها در زمان ساخت به صورت ایستا به برنامه شما متصل می‌شوند. کد و دارایی‌ها در زمان ساخت به صورت ایستا به برنامه شما متصل می‌شوند.
تأثیر اندازه برنامه (شامل کد و دارایی‌ها) حدود ۱۰.۱ مگابایت حدود ۱۳.۳ مگابایت
عملکرد پیکسل ۳ ایکس ال: حدود ۳۰ فریم بر ثانیه پیکسل ۳ ایکس ال: حدود ۲۳ فریم بر ثانیه با پردازنده، حدود ۳۰ فریم بر ثانیه با پردازنده گرافیکی

امتحانش کن.

قبل از اینکه شروع کنی

  1. در فایل build.gradle سطح پروژه خود، مطمئن شوید که مخزن Maven گوگل را هم در بخش‌های buildscript و هم allprojects خود وارد کرده‌اید.
  2. وابستگی‌های کتابخانه‌های اندروید ML Kit را به فایل gradle سطح app ماژول خود که معمولاً app/build.gradle است، اضافه کنید:

    dependencies {
      // If you want to use the base sdk
      implementation 'com.google.mlkit:pose-detection:18.0.0-beta5'
      // If you want to use the accurate sdk
      implementation 'com.google.mlkit:pose-detection-accurate:18.0.0-beta5'
    }
    

۱. یک نمونه از PoseDetector ایجاد کنید

گزینه‌های PoseDetector

برای تشخیص حالت چهره در یک تصویر، ابتدا یک نمونه از PoseDetector ایجاد کنید و به صورت اختیاری تنظیمات آشکارساز را مشخص کنید.

حالت تشخیص

PoseDetector در دو حالت تشخیص عمل می‌کند. مطمئن شوید که حالتی را انتخاب می‌کنید که با مورد استفاده شما مطابقت دارد.

STREAM_MODE (پیش‌فرض)
آشکارساز حالت ابتدا برجسته‌ترین فرد در تصویر را تشخیص می‌دهد و سپس تشخیص حالت را اجرا می‌کند. در فریم‌های بعدی، مرحله تشخیص فرد انجام نخواهد شد مگر اینکه فرد مبهم شود یا دیگر با اطمینان بالا تشخیص داده نشود. آشکارساز حالت تلاش می‌کند تا برجسته‌ترین فرد را ردیابی کند و حالت او را در هر استنتاج برگرداند. این کار تأخیر را کاهش می‌دهد و تشخیص را روان‌تر می‌کند. از این حالت زمانی استفاده کنید که می‌خواهید حالت را در یک جریان ویدیویی تشخیص دهید.
SINGLE_IMAGE_MODE
آشکارساز حالت، یک شخص را شناسایی کرده و سپس تشخیص حالت را اجرا می‌کند. مرحله تشخیص شخص برای هر تصویر اجرا می‌شود، بنابراین تأخیر بیشتر خواهد بود و ردیابی شخص وجود ندارد. هنگام استفاده از تشخیص حالت روی تصاویر ثابت یا جایی که ردیابی مطلوب نیست، از این حالت استفاده کنید.

پیکربندی سخت‌افزار

PoseDetector از پیکربندی‌های سخت‌افزاری متعددی برای بهینه‌سازی عملکرد پشتیبانی می‌کند:

  • CPU : آشکارساز را فقط با استفاده از CPU اجرا کنید
  • CPU_GPU : آشکارساز را با استفاده از CPU و GPU اجرا کنید

هنگام ساخت گزینه‌های آشکارساز، می‌توانید از API setPreferredHardwareConfigs برای کنترل انتخاب سخت‌افزار استفاده کنید. به طور پیش‌فرض، تمام پیکربندی‌های سخت‌افزاری به صورت ترجیحی تنظیم می‌شوند.

کیت ML، در دسترس بودن، پایداری، صحت و تأخیر هر پیکربندی را در نظر می‌گیرد و بهترین پیکربندی را از بین پیکربندی‌های ترجیحی انتخاب می‌کند. اگر هیچ یک از پیکربندی‌های ترجیحی قابل اجرا نباشد، پیکربندی CPU به طور خودکار به عنوان جایگزین استفاده می‌شود. کیت ML این بررسی‌ها و آماده‌سازی‌های مرتبط را به روشی غیر مسدودکننده قبل از فعال کردن هرگونه شتاب انجام می‌دهد، بنابراین به احتمال زیاد اولین باری که کاربر شما آشکارساز را اجرا می‌کند، CPU استفاده خواهد کرد. پس از اتمام تمام آماده‌سازی‌ها، بهترین پیکربندی در اجراهای بعدی استفاده خواهد شد.

مثال‌هایی از کاربردهای setPreferredHardwareConfigs :

  • برای اینکه ML Kit بهترین پیکربندی را انتخاب کند، این API را فراخوانی نکنید.
  • اگر نمی‌خواهید هیچ شتابی را فعال کنید، فقط CPU را وارد کنید.
  • اگر می‌خواهید از GPU برای کاهش بار CPU استفاده کنید، حتی اگر GPU کندتر باشد، فقط CPU_GPU وارد کنید.

گزینه‌های آشکارساز حالت را مشخص کنید:

کاتلین

// Base pose detector with streaming frames, when depending on the pose-detection sdk
val options = PoseDetectorOptions.Builder()
    .setDetectorMode(PoseDetectorOptions.STREAM_MODE)
    .build()

// Accurate pose detector on static images, when depending on the pose-detection-accurate sdk
val options = AccuratePoseDetectorOptions.Builder()
    .setDetectorMode(AccuratePoseDetectorOptions.SINGLE_IMAGE_MODE)
    .build()

جاوا

// Base pose detector with streaming frames, when depending on the pose-detection sdk
PoseDetectorOptions options =
   new PoseDetectorOptions.Builder()
       .setDetectorMode(PoseDetectorOptions.STREAM_MODE)
       .build();

// Accurate pose detector on static images, when depending on the pose-detection-accurate sdk
AccuratePoseDetectorOptions options =
   new AccuratePoseDetectorOptions.Builder()
       .setDetectorMode(AccuratePoseDetectorOptions.SINGLE_IMAGE_MODE)
       .build();

در نهایت، یک نمونه از PoseDetector ایجاد کنید. گزینه‌هایی را که مشخص کرده‌اید، به آن بدهید:

کاتلین

val poseDetector = PoseDetection.getClient(options)

جاوا

PoseDetector poseDetector = PoseDetection.getClient(options);

۲. تصویر ورودی را آماده کنید

برای تشخیص حالت‌های مختلف در یک تصویر، یک شیء InputImage از Bitmap ، media.Image ، ByteBuffer ، آرایه بایت یا یک فایل روی دستگاه ایجاد کنید. سپس، شیء InputImage را به PoseDetector ارسال کنید.

برای تشخیص حالت بدن، باید از تصویری با ابعاد حداقل ۴۸۰x۳۶۰ پیکسل استفاده کنید. اگر حالت بدن را به صورت بلادرنگ تشخیص می‌دهید، ثبت فریم‌ها با این حداقل وضوح می‌تواند به کاهش تأخیر کمک کند.

شما می‌توانید یک شیء InputImage را از منابع مختلفی ایجاد کنید که هر کدام در زیر توضیح داده شده‌اند.

استفاده از یک media.Image

برای ایجاد یک شیء InputImage از یک شیء media.Image ، مانند زمانی که از دوربین یک دستگاه تصویر می‌گیرید، شیء media.Image و چرخش تصویر را به InputImage.fromMediaImage() ارسال کنید.

اگر از کتابخانه CameraX استفاده می‌کنید، کلاس‌های OnImageCapturedListener و ImageAnalysis.Analyzer مقدار چرخش را برای شما محاسبه می‌کنند.

کاتلین

private class YourImageAnalyzer : ImageAnalysis.Analyzer {

    override fun analyze(imageProxy: ImageProxy) {
        val mediaImage = imageProxy.image
        if (mediaImage != null) {
            val image = InputImage.fromMediaImage(mediaImage, imageProxy.imageInfo.rotationDegrees)
            // Pass image to an ML Kit Vision API
            // ...
        }
    }
}

جاوا

private class YourAnalyzer implements ImageAnalysis.Analyzer {

    @Override
    public void analyze(ImageProxy imageProxy) {
        Image mediaImage = imageProxy.getImage();
        if (mediaImage != null) {
          InputImage image =
                InputImage.fromMediaImage(mediaImage, imageProxy.getImageInfo().getRotationDegrees());
          // Pass image to an ML Kit Vision API
          // ...
        }
    }
}

اگر از کتابخانه دوربینی که درجه چرخش تصویر را به شما بدهد استفاده نمی‌کنید، می‌توانید آن را از درجه چرخش دستگاه و جهت سنسور دوربین در دستگاه محاسبه کنید:

کاتلین

private val ORIENTATIONS = SparseIntArray()

init {
    ORIENTATIONS.append(Surface.ROTATION_0, 0)
    ORIENTATIONS.append(Surface.ROTATION_90, 90)
    ORIENTATIONS.append(Surface.ROTATION_180, 180)
    ORIENTATIONS.append(Surface.ROTATION_270, 270)
}

/**
 * Get the angle by which an image must be rotated given the device's current
 * orientation.
 */
@RequiresApi(api = Build.VERSION_CODES.LOLLIPOP)
@Throws(CameraAccessException::class)
private fun getRotationCompensation(cameraId: String, activity: Activity, isFrontFacing: Boolean): Int {
    // Get the device's current rotation relative to its "native" orientation.
    // Then, from the ORIENTATIONS table, look up the angle the image must be
    // rotated to compensate for the device's rotation.
    val deviceRotation = activity.windowManager.defaultDisplay.rotation
    var rotationCompensation = ORIENTATIONS.get(deviceRotation)

    // Get the device's sensor orientation.
    val cameraManager = activity.getSystemService(CAMERA_SERVICE) as CameraManager
    val sensorOrientation = cameraManager
            .getCameraCharacteristics(cameraId)
            .get(CameraCharacteristics.SENSOR_ORIENTATION)!!

    if (isFrontFacing) {
        rotationCompensation = (sensorOrientation + rotationCompensation) % 360
    } else { // back-facing
        rotationCompensation = (sensorOrientation - rotationCompensation + 360) % 360
    }
    return rotationCompensation
}

جاوا

private static final SparseIntArray ORIENTATIONS = new SparseIntArray();
static {
    ORIENTATIONS.append(Surface.ROTATION_0, 0);
    ORIENTATIONS.append(Surface.ROTATION_90, 90);
    ORIENTATIONS.append(Surface.ROTATION_180, 180);
    ORIENTATIONS.append(Surface.ROTATION_270, 270);
}

/**
 * Get the angle by which an image must be rotated given the device's current
 * orientation.
 */
@RequiresApi(api = Build.VERSION_CODES.LOLLIPOP)
private int getRotationCompensation(String cameraId, Activity activity, boolean isFrontFacing)
        throws CameraAccessException {
    // Get the device's current rotation relative to its "native" orientation.
    // Then, from the ORIENTATIONS table, look up the angle the image must be
    // rotated to compensate for the device's rotation.
    int deviceRotation = activity.getWindowManager().getDefaultDisplay().getRotation();
    int rotationCompensation = ORIENTATIONS.get(deviceRotation);

    // Get the device's sensor orientation.
    CameraManager cameraManager = (CameraManager) activity.getSystemService(CAMERA_SERVICE);
    int sensorOrientation = cameraManager
            .getCameraCharacteristics(cameraId)
            .get(CameraCharacteristics.SENSOR_ORIENTATION);

    if (isFrontFacing) {
        rotationCompensation = (sensorOrientation + rotationCompensation) % 360;
    } else { // back-facing
        rotationCompensation = (sensorOrientation - rotationCompensation + 360) % 360;
    }
    return rotationCompensation;
}

سپس، شیء media.Image و مقدار درجه چرخش را به InputImage.fromMediaImage() ارسال کنید:

کاتلین

val image = InputImage.fromMediaImage(mediaImage, rotation)

Java

InputImage image = InputImage.fromMediaImage(mediaImage, rotation);

استفاده از یک URI فایل

برای ایجاد یک شیء InputImage از یک URI فایل، متن برنامه و URI فایل را به InputImage.fromFilePath() ارسال کنید. این زمانی مفید است که از یک ACTION_GET_CONTENT برای وادار کردن کاربر به انتخاب یک تصویر از برنامه گالری خود استفاده می‌کنید.

کاتلین

val image: InputImage
try {
    image = InputImage.fromFilePath(context, uri)
} catch (e: IOException) {
    e.printStackTrace()
}

Java

InputImage image;
try {
    image = InputImage.fromFilePath(context, uri);
} catch (IOException e) {
    e.printStackTrace();
}

استفاده از ByteBuffer یا ByteArray

برای ایجاد یک شیء InputImage از یک ByteBuffer یا یک ByteArray ، ابتدا درجه چرخش تصویر را همانطور که قبلاً برای ورودی media.Image توضیح داده شد، محاسبه کنید. سپس، شیء InputImage را با بافر یا آرایه، به همراه ارتفاع، عرض، فرمت کدگذاری رنگ و درجه چرخش تصویر ایجاد کنید:

کاتلین

val image = InputImage.fromByteBuffer(
        byteBuffer,
        /* image width */ 480,
        /* image height */ 360,
        rotationDegrees,
        InputImage.IMAGE_FORMAT_NV21 // or IMAGE_FORMAT_YV12
)
// Or:
val image = InputImage.fromByteArray(
        byteArray,
        /* image width */ 480,
        /* image height */ 360,
        rotationDegrees,
        InputImage.IMAGE_FORMAT_NV21 // or IMAGE_FORMAT_YV12
)

جاوا

InputImage image = InputImage.fromByteBuffer(byteBuffer,
        /* image width */ 480,
        /* image height */ 360,
        rotationDegrees,
        InputImage.IMAGE_FORMAT_NV21 // or IMAGE_FORMAT_YV12
);
// Or:
InputImage image = InputImage.fromByteArray(
        byteArray,
        /* image width */480,
        /* image height */360,
        rotation,
        InputImage.IMAGE_FORMAT_NV21 // or IMAGE_FORMAT_YV12
);

استفاده از Bitmap

برای ایجاد یک شیء InputImage از یک شیء Bitmap ، تعریف زیر را انجام دهید:

کاتلین

val image = InputImage.fromBitmap(bitmap, 0)

Java

InputImage image = InputImage.fromBitmap(bitmap, rotationDegree);

تصویر توسط یک شیء Bitmap به همراه درجه چرخش نمایش داده می‌شود.

۳. تصویر را پردازش کنید

شیء InputImage آماده‌شده را به متد process از PoseDetector ارسال کنید.

کاتلین

Task<Pose> result = poseDetector.process(image)
       .addOnSuccessListener { results ->
           // Task completed successfully
           // ...
       }
       .addOnFailureListener { e ->
           // Task failed with an exception
           // ...
       }

جاوا

Task<Pose> result =
        poseDetector.process(image)
                .addOnSuccessListener(
                        new OnSuccessListener<Pose>() {
                            @Override
                            public void onSuccess(Pose pose) {
                                // Task completed successfully
                                // ...
                            }
                        })
                .addOnFailureListener(
                        new OnFailureListener() {
                            @Override
                            public void onFailure(@NonNull Exception e) {
                                // Task failed with an exception
                                // ...
                            }
                        });

۴. اطلاعات مربوط به ژست شناسایی شده را دریافت کنید

اگر شخصی در تصویر تشخیص داده شود، API تشخیص حالت، یک شیء Pose با ۳۳ PoseLandmark برمی‌گرداند.

اگر فرد کاملاً درون تصویر نبود، مدل مختصات نقاط دیدنی گمشده را خارج از قاب اختصاص می‌دهد و به آنها مقادیر InFrameConfidence پایینی می‌دهد.

اگر هیچ شخصی در فریم شناسایی نشده باشد، شیء Pose حاوی هیچ PoseLandmark نیست.

کاتلین

// Get all PoseLandmarks. If no person was detected, the list will be empty
val allPoseLandmarks = pose.getAllPoseLandmarks()

// Or get specific PoseLandmarks individually. These will all be null if no person
// was detected
val leftShoulder = pose.getPoseLandmark(PoseLandmark.LEFT_SHOULDER)
val rightShoulder = pose.getPoseLandmark(PoseLandmark.RIGHT_SHOULDER)
val leftElbow = pose.getPoseLandmark(PoseLandmark.LEFT_ELBOW)
val rightElbow = pose.getPoseLandmark(PoseLandmark.RIGHT_ELBOW)
val leftWrist = pose.getPoseLandmark(PoseLandmark.LEFT_WRIST)
val rightWrist = pose.getPoseLandmark(PoseLandmark.RIGHT_WRIST)
val leftHip = pose.getPoseLandmark(PoseLandmark.LEFT_HIP)
val rightHip = pose.getPoseLandmark(PoseLandmark.RIGHT_HIP)
val leftKnee = pose.getPoseLandmark(PoseLandmark.LEFT_KNEE)
val rightKnee = pose.getPoseLandmark(PoseLandmark.RIGHT_KNEE)
val leftAnkle = pose.getPoseLandmark(PoseLandmark.LEFT_ANKLE)
val rightAnkle = pose.getPoseLandmark(PoseLandmark.RIGHT_ANKLE)
val leftPinky = pose.getPoseLandmark(PoseLandmark.LEFT_PINKY)
val rightPinky = pose.getPoseLandmark(PoseLandmark.RIGHT_PINKY)
val leftIndex = pose.getPoseLandmark(PoseLandmark.LEFT_INDEX)
val rightIndex = pose.getPoseLandmark(PoseLandmark.RIGHT_INDEX)
val leftThumb = pose.getPoseLandmark(PoseLandmark.LEFT_THUMB)
val rightThumb = pose.getPoseLandmark(PoseLandmark.RIGHT_THUMB)
val leftHeel = pose.getPoseLandmark(PoseLandmark.LEFT_HEEL)
val rightHeel = pose.getPoseLandmark(PoseLandmark.RIGHT_HEEL)
val leftFootIndex = pose.getPoseLandmark(PoseLandmark.LEFT_FOOT_INDEX)
val rightFootIndex = pose.getPoseLandmark(PoseLandmark.RIGHT_FOOT_INDEX)
val nose = pose.getPoseLandmark(PoseLandmark.NOSE)
val leftEyeInner = pose.getPoseLandmark(PoseLandmark.LEFT_EYE_INNER)
val leftEye = pose.getPoseLandmark(PoseLandmark.LEFT_EYE)
val leftEyeOuter = pose.getPoseLandmark(PoseLandmark.LEFT_EYE_OUTER)
val rightEyeInner = pose.getPoseLandmark(PoseLandmark.RIGHT_EYE_INNER)
val rightEye = pose.getPoseLandmark(PoseLandmark.RIGHT_EYE)
val rightEyeOuter = pose.getPoseLandmark(PoseLandmark.RIGHT_EYE_OUTER)
val leftEar = pose.getPoseLandmark(PoseLandmark.LEFT_EAR)
val rightEar = pose.getPoseLandmark(PoseLandmark.RIGHT_EAR)
val leftMouth = pose.getPoseLandmark(PoseLandmark.LEFT_MOUTH)
val rightMouth = pose.getPoseLandmark(PoseLandmark.RIGHT_MOUTH)

جاوا

// Get all PoseLandmarks. If no person was detected, the list will be empty
List<PoseLandmark> allPoseLandmarks = pose.getAllPoseLandmarks();

// Or get specific PoseLandmarks individually. These will all be null if no person
// was detected
PoseLandmark leftShoulder = pose.getPoseLandmark(PoseLandmark.LEFT_SHOULDER);
PoseLandmark rightShoulder = pose.getPoseLandmark(PoseLandmark.RIGHT_SHOULDER);
PoseLandmark leftElbow = pose.getPoseLandmark(PoseLandmark.LEFT_ELBOW);
PoseLandmark rightElbow = pose.getPoseLandmark(PoseLandmark.RIGHT_ELBOW);
PoseLandmark leftWrist = pose.getPoseLandmark(PoseLandmark.LEFT_WRIST);
PoseLandmark rightWrist = pose.getPoseLandmark(PoseLandmark.RIGHT_WRIST);
PoseLandmark leftHip = pose.getPoseLandmark(PoseLandmark.LEFT_HIP);
PoseLandmark rightHip = pose.getPoseLandmark(PoseLandmark.RIGHT_HIP);
PoseLandmark leftKnee = pose.getPoseLandmark(PoseLandmark.LEFT_KNEE);
PoseLandmark rightKnee = pose.getPoseLandmark(PoseLandmark.RIGHT_KNEE);
PoseLandmark leftAnkle = pose.getPoseLandmark(PoseLandmark.LEFT_ANKLE);
PoseLandmark rightAnkle = pose.getPoseLandmark(PoseLandmark.RIGHT_ANKLE);
PoseLandmark leftPinky = pose.getPoseLandmark(PoseLandmark.LEFT_PINKY);
PoseLandmark rightPinky = pose.getPoseLandmark(PoseLandmark.RIGHT_PINKY);
PoseLandmark leftIndex = pose.getPoseLandmark(PoseLandmark.LEFT_INDEX);
PoseLandmark rightIndex = pose.getPoseLandmark(PoseLandmark.RIGHT_INDEX);
PoseLandmark leftThumb = pose.getPoseLandmark(PoseLandmark.LEFT_THUMB);
PoseLandmark rightThumb = pose.getPoseLandmark(PoseLandmark.RIGHT_THUMB);
PoseLandmark leftHeel = pose.getPoseLandmark(PoseLandmark.LEFT_HEEL);
PoseLandmark rightHeel = pose.getPoseLandmark(PoseLandmark.RIGHT_HEEL);
PoseLandmark leftFootIndex = pose.getPoseLandmark(PoseLandmark.LEFT_FOOT_INDEX);
PoseLandmark rightFootIndex = pose.getPoseLandmark(PoseLandmark.RIGHT_FOOT_INDEX);
PoseLandmark nose = pose.getPoseLandmark(PoseLandmark.NOSE);
PoseLandmark leftEyeInner = pose.getPoseLandmark(PoseLandmark.LEFT_EYE_INNER);
PoseLandmark leftEye = pose.getPoseLandmark(PoseLandmark.LEFT_EYE);
PoseLandmark leftEyeOuter = pose.getPoseLandmark(PoseLandmark.LEFT_EYE_OUTER);
PoseLandmark rightEyeInner = pose.getPoseLandmark(PoseLandmark.RIGHT_EYE_INNER);
PoseLandmark rightEye = pose.getPoseLandmark(PoseLandmark.RIGHT_EYE);
PoseLandmark rightEyeOuter = pose.getPoseLandmark(PoseLandmark.RIGHT_EYE_OUTER);
PoseLandmark leftEar = pose.getPoseLandmark(PoseLandmark.LEFT_EAR);
PoseLandmark rightEar = pose.getPoseLandmark(PoseLandmark.RIGHT_EAR);
PoseLandmark leftMouth = pose.getPoseLandmark(PoseLandmark.LEFT_MOUTH);
PoseLandmark rightMouth = pose.getPoseLandmark(PoseLandmark.RIGHT_MOUTH);

نکاتی برای بهبود عملکرد

کیفیت نتایج شما به کیفیت تصویر ورودی بستگی دارد:

  • برای اینکه کیت ML بتواند ژست را به طور دقیق تشخیص دهد، فرد موجود در تصویر باید با داده‌های پیکسلی کافی نمایش داده شود؛ برای بهترین عملکرد، سوژه باید حداقل ۲۵۶x۲۵۶ پیکسل باشد.
  • اگر در یک برنامه بلادرنگ ژست را تشخیص می‌دهید، ممکن است بخواهید ابعاد کلی تصاویر ورودی را نیز در نظر بگیرید. تصاویر کوچکتر می‌توانند سریع‌تر پردازش شوند، بنابراین برای کاهش تأخیر، تصاویر را با وضوح پایین‌تر ضبط کنید، اما الزامات وضوح بالا را در نظر داشته باشید و مطمئن شوید که سوژه تا حد امکان فضای بیشتری از تصویر را اشغال کند.
  • فوکوس ضعیف تصویر نیز می‌تواند بر دقت تأثیر بگذارد. اگر نتایج قابل قبولی به دست نیاوردید، از کاربر بخواهید که دوباره تصویر را ثبت کند.

اگر می‌خواهید از تشخیص ژست در یک برنامه‌ی بلادرنگ استفاده کنید، برای دستیابی به بهترین نرخ فریم، این دستورالعمل‌ها را دنبال کنید:

  • از sdk پایه pose-detection و STREAM_MODE استفاده کنید.
  • ضبط تصاویر با وضوح پایین‌تر را در نظر بگیرید. با این حال، الزامات ابعاد تصویر این API را نیز در نظر داشته باشید.
  • اگر از API Camera یا camera2 استفاده می‌کنید، فراخوانی‌های throttle به آشکارساز انجام می‌شود. اگر در حین اجرای آشکارساز، یک فریم ویدیویی جدید در دسترس قرار گرفت، فریم را حذف کنید. برای مثال، به کلاس VisionProcessorBase در برنامه نمونه شروع سریع مراجعه کنید.
  • اگر از API CameraX استفاده می‌کنید، مطمئن شوید که استراتژی فشار معکوس (backpressure strategy) روی مقدار پیش‌فرض خود ImageAnalysis.STRATEGY_KEEP_ONLY_LATEST تنظیم شده است. این تضمین می‌کند که فقط یک تصویر در هر زمان برای تجزیه و تحلیل تحویل داده می‌شود. اگر تصاویر بیشتری هنگام مشغول بودن تحلیلگر تولید شوند، به طور خودکار حذف می‌شوند و برای تحویل در صف قرار نمی‌گیرند. پس از بسته شدن تصویر در حال تجزیه و تحلیل با فراخوانی ImageProxy.close()، آخرین تصویر بعدی تحویل داده می‌شود.
  • اگر از خروجی آشکارساز برای همپوشانی گرافیک روی تصویر ورودی استفاده می‌کنید، ابتدا نتیجه را از کیت ML دریافت کنید، سپس تصویر و همپوشانی را در یک مرحله رندر کنید. این کار فقط یک بار برای هر فریم ورودی روی سطح نمایشگر رندر می‌شود. برای مثال به کلاس‌های CameraSourcePreview و GraphicOverlay در برنامه نمونه شروع سریع مراجعه کنید.
  • اگر از API دوربین ۲ استفاده می‌کنید، تصاویر را با فرمت ImageFormat.YUV_420_888 ضبط کنید. اگر از API دوربین قدیمی‌تر استفاده می‌کنید، تصاویر را با فرمت ImageFormat.NV21 ضبط کنید.

مراحل بعدی

  • برای یادگیری نحوه استفاده از نشانه‌های ژست برای طبقه‌بندی ژست‌ها، به نکات طبقه‌بندی ژست مراجعه کنید.