Android पर, पसंद के मुताबिक बनाए गए क्लासिफ़िकेशन मॉडल की मदद से, चीज़ों का पता लगाएं, उन्हें ट्रैक करें, और उनकी कैटगरी तय करें

वीडियो के लगातार फ़्रेम में मौजूद ऑब्जेक्ट का पता लगाने और उन्हें ट्रैक करने के लिए, ML Kit का इस्तेमाल किया जा सकता है.

जब ML Kit को कोई इमेज पास की जाती है, तो वह इमेज में मौजूद पांच ऑब्जेक्ट तक की पहचान करता है. साथ ही, इमेज में हर ऑब्जेक्ट की पोज़िशन भी बताता है. वीडियो स्ट्रीम में मौजूद ऑब्जेक्ट की पहचान करते समय, हर ऑब्जेक्ट का एक यूनीक आईडी होता है. इसका इस्तेमाल, ऑब्जेक्ट को एक फ़्रेम से दूसरे फ़्रेम तक ट्रैक करने के लिए किया जा सकता है.

पहचान किए गए ऑब्जेक्ट को कैटगरी में बांटने के लिए, कस्टम इमेज क्लासिफ़िकेशन मॉडल का इस्तेमाल किया जा सकता है. मॉडल की कंपैटिबिलिटी से जुड़ी ज़रूरी शर्तों, पहले से ट्रेन किए गए मॉडल ढूंढने की जगह, और अपने मॉडल को ट्रेन करने के तरीके के बारे में जानने के लिए, ML Kit के साथ कस्टम मॉडल इस्तेमाल करने का तरीका लेख पढ़ें.

कस्टम मॉडल को इंटिग्रेट करने के दो तरीके हैं. मॉडल को अपने ऐप्लिकेशन के एसेट फ़ोल्डर में रखकर बंडल किया जा सकता है. इसके अलावा, इसे Cloud Storage से डाइनैमिक तरीके से डाउनलोड किया जा सकता है. यहां दी गई टेबल में, इन दोनों विकल्पों की तुलना की गई है.

बंडल किया गया मॉडल होस्ट किया गया मॉडल
मॉडल, आपके ऐप्लिकेशन के APK का हिस्सा होता है. इससे इसका साइज़ बढ़ जाता है. मॉडल, आपके APK का हिस्सा नहीं होता. इसे Cloud Storage पर अपलोड करके होस्ट किया जाता है. हमारा सुझाव है कि आप Firebase के लिए Cloud Storage का इस्तेमाल करें.
मॉडल तुरंत उपलब्ध हो जाता है. भले ही, Android डिवाइस ऑफ़लाइन हो आपके ऐप्लिकेशन में, मांग पर मॉडल डाउनलोड करने के लिए कोड शामिल होना चाहिए
Firebase प्रोजेक्ट की ज़रूरत नहीं होती Firebase प्रोजेक्ट की ज़रूरत होती है (अगर Firebase के लिए Cloud Storage का इस्तेमाल किया जा रहा है).
मॉडल को अपडेट करने के लिए, आपको अपना ऐप्लिकेशन फिर से पब्लिश करना होगा ऐप्लिकेशन को फिर से पब्लिश किए बिना, मॉडल के अपडेट पुश करें
कोई इन-बिल्ट A/B टेस्टिंग नहीं Firebase रिमोट कॉन्फ़िगरेशन के साथ A/B टेस्टिंग

इसे आज़माएं

शुरू करने से पहले

1. अपने प्रोजेक्ट-लेवल की build.gradle.kts फ़ाइल में, पक्का करें कि आपने Google की Maven रिपॉज़िटरी को अपने buildscript और allprojects सेक्शन, दोनों में शामिल किया हो.

  1. अपने मॉड्यूल की ऐप्लिकेशन-लेवल की Gradle फ़ाइल में, ML Kit की Android लाइब्रेरी के लिए डिपेंडेंसी जोड़ें. आम तौर पर, यह फ़ाइल app/build.gradle.kts होती है:

    अपने ऐप्लिकेशन के साथ मॉडल बंडल करने के लिए:

    dependencies {
      // ...
      // Object detection & tracking feature with custom bundled model
      implementation("com.google.mlkit:object-detection-custom:17.0.2")
    }
    
  2. अगर आपको Firebase के लिए Cloud Storage से कोई मॉडल डाउनलोड करना है, तो पक्का करें कि आपने अपने Android प्रोजेक्ट में Firebase जोड़ा हो. अगर आपने ऐसा नहीं किया है, तो Firebase जोड़ें. मॉडल बंडल करने पर, इसकी ज़रूरत नहीं होती.

1. मॉडल लोड करना

मॉडल को स्थानीय तौर पर बंडल किए गए सोर्स या रिमोट तौर पर होस्ट किए गए सोर्स से लोड किया जा सकता है.

स्थानीय मॉडल सोर्स कॉन्फ़िगर करना

मॉडल को अपने ऐप्लिकेशन के साथ बंडल करने के लिए:

  1. मॉडल फ़ाइल (आम तौर पर, इसका नाम .tflite या .lite से खत्म होता है) को अपने ऐप्लिकेशन के assets/ फ़ोल्डर में कॉपी करें. (आपको पहले फ़ोल्डर बनाना पड़ सकता है. इसके लिए, app/ फ़ोल्डर पर राइट-क्लिक करें. इसके बाद, New > Folder > Assets Folder पर क्लिक करें.)

  2. LocalModel ऑब्जेक्ट बनाएं. इसमें मॉडल फ़ाइल का पाथ तय करें:

    Kotlin

    val localModel = LocalModel.Builder()
            .setAssetFilePath("model.tflite")
            // or .setAbsoluteFilePath(absolute path to model file)
            // or .setUri(URI to model file)
            .build()

    Java

    LocalModel localModel =
        new LocalModel.Builder()
            .setAssetFilePath("model.tflite")
            // or .setAbsoluteFilePath(absolute path to model file)
            // or .setUri(URI to model file)
            .build();

रिमोट तौर पर होस्ट किए गए मॉडल सोर्स को कॉन्फ़िगर करना

रिमोट तौर पर होस्ट किए गए मॉडल का इस्तेमाल करने के लिए, आपको अपने ऐप्लिकेशन के लॉजिक का इस्तेमाल करके, मॉडल फ़ाइल को डिवाइस के लोकल स्टोरेज में डाउनलोड करना होगा. इसके बाद, इसे लोकल मॉडल के तौर पर लोड करना होगा. हमारा सुझाव है कि मॉडल को होस्ट करने के लिए, Firebase के लिए Cloud Storage का इस्तेमाल करें. लागू करने के बारे में ज़्यादा जानने के लिए, देखें Firebase ML से Cloud Storage पर माइग्रेट करने की गाइड.

2. ऑब्जेक्ट डिटेक्टर को कॉन्फ़िगर करना

मॉडल सोर्स कॉन्फ़िगर करने के बाद, अपने इस्तेमाल के उदाहरण के लिए, CustomObjectDetectorOptions ऑब्जेक्ट की मदद से ऑब्जेक्ट डिटेक्टर को कॉन्फ़िगर करें. आपके पास ये सेटिंग बदलने का विकल्प है:

ऑब्जेक्ट डिटेक्टर की सेटिंग
डिटेक्शन मोड STREAM_MODE (डिफ़ॉल्ट) | SINGLE_IMAGE_MODE

STREAM_MODE (डिफ़ॉल्ट) में, ऑब्जेक्ट डिटेक्टर कम समय में काम करता है. हालांकि, डिटेक्टर के शुरुआती कुछ इस्तेमाल में, नतीजे अधूरे हो सकते हैं. जैसे, बाउंडिंग बॉक्स या कैटगरी के लेबल की जानकारी न होना. इसके अलावा, STREAM_MODE, डिटेक्टर ऑब्जेक्ट को ट्रैकिंग आईडी असाइन करता है. इनका इस्तेमाल, ऑब्जेक्ट को अलग-अलग फ़्रेम में ट्रैक करने के लिए किया जा सकता है. इस मोड का इस्तेमाल तब करें, जब आपको ऑब्जेक्ट ट्रैक करने हों या जब कम समय में नतीजे पाना ज़रूरी हो. जैसे, वीडियो स्ट्रीम को रीयल टाइम में प्रोसेस करते समय.

SINGLE_IMAGE_MODE में, ऑब्जेक्ट डिटेक्टर, ऑब्जेक्ट का बाउंडिंग बॉक्स तय होने के बाद नतीजा दिखाता है. अगर आपने क्लासिफ़िकेशन की सुविधा भी चालू की है, तो बाउंडिंग बॉक्स और कैटगरी का लेबल, दोनों उपलब्ध होने के बाद नतीजा दिखेगा. इसलिए, डिटेक्शन में ज़्यादा समय लग सकता है. इसके अलावा, SINGLE_IMAGE_MODE में, ट्रैकिंग आईडी असाइन नहीं किए जाते. इस मोड का इस्तेमाल तब करें, जब कम समय में नतीजे पाना ज़रूरी न हो और आपको आंशिक नतीजों से कोई समस्या न हो.

एक से ज़्यादा ऑब्जेक्ट का पता लगाना और उन्हें ट्रैक करना false (डिफ़ॉल्ट) | true

पांच ऑब्जेक्ट तक का पता लगाना और उन्हें ट्रैक करना है या सिर्फ़ सबसे अहम ऑब्जेक्ट (डिफ़ॉल्ट).

ऑब्जेक्ट को कैटगरी में बांटना false (डिफ़ॉल्ट) | true

दिए गए कस्टम क्लासिफ़ायर मॉडल का इस्तेमाल करके, पहचान किए गए ऑब्जेक्ट को कैटगरी में बांटना है या नहीं. अपने कस्टम क्लासिफ़िकेशन मॉडल का इस्तेमाल करने के लिए, आपको इसे true पर सेट करना होगा.

क्लासिफ़िकेशन कॉन्फ़िडेंस थ्रेशोल्ड

पहचान किए गए लेबल का कम से कम कॉन्फ़िडेंस स्कोर. अगर इसे सेट नहीं किया जाता है, तो मॉडल के मेटाडेटा में तय किया गया कोई भी क्लासिफ़ायर थ्रेशोल्ड इस्तेमाल किया जाएगा. अगर मॉडल में कोई मेटाडेटा नहीं है या मेटाडेटा में कोई क्लासिफ़ायर थ्रेशोल्ड तय नहीं किया गया है, तो 0.0 का डिफ़ॉल्ट थ्रेशोल्ड इस्तेमाल किया जाएगा.

हर ऑब्जेक्ट के लिए ज़्यादा से ज़्यादा लेबल

हर ऑब्जेक्ट के लिए ज़्यादा से ज़्यादा लेबल की संख्या. डिटेक्टर इतने लेबल की जानकारी देगा. अगर इसे सेट नहीं किया जाता है, तो 10 की डिफ़ॉल्ट वैल्यू इस्तेमाल की जाएगी.

ऑब्जेक्ट डिटेक्शन और ट्रैकिंग एपीआई को इन दो मुख्य इस्तेमाल के उदाहरणों के लिए ऑप्टिमाइज़ किया गया है:

  • कैमरा व्यूफ़ाइंडर में मौजूद सबसे अहम ऑब्जेक्ट का लाइव डिटेक्शन और ट्रैकिंग.
  • स्टैटिक इमेज में मौजूद एक से ज़्यादा ऑब्जेक्ट का पता लगाना.

इन इस्तेमाल के उदाहरणों के लिए, स्थानीय तौर पर बंडल किए गए मॉडल की मदद से एपीआई को कॉन्फ़िगर करने के लिए:

Kotlin

// Live detection and tracking
val customObjectDetectorOptions =
        CustomObjectDetectorOptions.Builder(localModel)
        .setDetectorMode(CustomObjectDetectorOptions.STREAM_MODE)
        .enableClassification()
        .setClassificationConfidenceThreshold(0.5f)
        .setMaxPerObjectLabelCount(3)
        .build()

// Multiple object detection in static images
val customObjectDetectorOptions =
        CustomObjectDetectorOptions.Builder(localModel)
        .setDetectorMode(CustomObjectDetectorOptions.SINGLE_IMAGE_MODE)
        .enableMultipleObjects()
        .enableClassification()
        .setClassificationConfidenceThreshold(0.5f)
        .setMaxPerObjectLabelCount(3)
        .build()

val objectDetector =
        ObjectDetection.getClient(customObjectDetectorOptions)

Java

// Live detection and tracking
CustomObjectDetectorOptions customObjectDetectorOptions =
        new CustomObjectDetectorOptions.Builder(localModel)
                .setDetectorMode(CustomObjectDetectorOptions.STREAM_MODE)
                .enableClassification()
                .setClassificationConfidenceThreshold(0.5f)
                .setMaxPerObjectLabelCount(3)
                .build();

// Multiple object detection in static images
CustomObjectDetectorOptions customObjectDetectorOptions =
        new CustomObjectDetectorOptions.Builder(localModel)
                .setDetectorMode(CustomObjectDetectorOptions.SINGLE_IMAGE_MODE)
                .enableMultipleObjects()
                .enableClassification()
                .setClassificationConfidenceThreshold(0.5f)
                .setMaxPerObjectLabelCount(3)
                .build();

ObjectDetector objectDetector =
    ObjectDetection.getClient(customObjectDetectorOptions);

अगर आपके पास रिमोट तौर पर होस्ट किया गया मॉडल है, तो आपको इसे रन करने से पहले यह देखना होगा कि यह डाउनलोड हो गया है या नहीं.

हालांकि, आपको डिटेक्टर चलाने से पहले ही इसकी पुष्टि करनी होती है. अगर आपके पास रिमोट तौर पर होस्ट किया गया मॉडल और स्थानीय तौर पर बंडल किया गया मॉडल, दोनों हैं, तो इमेज डिटेक्टर को इंस्टैंशिएट करते समय, यह जांच करना सही हो सकता है: अगर रिमोट मॉडल डाउनलोड हो गया है, तो उससे डिटेक्टर बनाएं. अगर ऐसा नहीं है, तो स्थानीय मॉडल से डिटेक्टर बनाएं.

Kotlin

val modelFile = File(context.cacheDir, "my_remote_model.tflite")

val model = if (modelFile.exists()) {
    // Use the downloaded model if available
    LocalModel.Builder().setAbsoluteFilePath(modelFile.absolutePath).build()
} else {
    // Fall back to the bundled model
    LocalModel.Builder().setAssetFilePath("model.tflite").build()
}

val customObjectDetectorOptions =
        CustomObjectDetectorOptions.Builder(model)
        .setDetectorMode(CustomObjectDetectorOptions.SINGLE_IMAGE_MODE)
        .enableClassification()
        .setClassificationConfidenceThreshold(0.5f)
        .setMaxPerObjectLabelCount(3)
        .build()

val objectDetector =
        ObjectDetection.getClient(customObjectDetectorOptions)

Java

File modelFile = new File(context.getCacheDir(), "my_remote_model.tflite");

LocalModel model;
if (modelFile.exists()) {
    // Use the downloaded model if available
    model = new LocalModel.Builder().setAbsoluteFilePath(modelFile.getAbsolutePath()).build();
} else {
    // Fall back to the bundled model
    model = new LocalModel.Builder().setAssetFilePath("model.tflite").build();
}

CustomObjectDetectorOptions customObjectDetectorOptions =
        new CustomObjectDetectorOptions.Builder(model)
                .setDetectorMode(CustomObjectDetectorOptions.SINGLE_IMAGE_MODE)
                .enableClassification()
                .setClassificationConfidenceThreshold(0.5f)
                .setMaxPerObjectLabelCount(3)
                .build();

ObjectDetector objectDetector =
        ObjectDetection.getClient(customObjectDetectorOptions);

अगर आपके पास सिर्फ़ रिमोट तौर पर होस्ट किया गया मॉडल है, तो आपको मॉडल से जुड़ी सुविधाओं को बंद कर देना चाहिए. जैसे, अपने यूज़र इंटरफ़ेस (यूआई) के किसी हिस्से को धुंधला करना या छिपाना. ऐसा तब तक करें, जब तक आपको यह पुष्टि न हो जाए कि मॉडल डाउनलोड हो गया है.

Kotlin

val localFile = File(context.cacheDir, "my_remote_model.tflite")
if (localFile.exists()) {
    // Model is already cached, initialize immediately
    initializeDetector(localFile)
} else {
    // Model is not yet available, show loading UI and start download
    showLoadingUI()
    val storage = Firebase.storage
    val modelRef = storage.getReferenceFromUrl("gs://YOUR_BUCKET/path/to/model.tflite")
    modelRef.getFile(localFile)
        .addOnSuccessListener {
            // Download complete, initialize the detector
            hideLoadingUI()
            initializeDetector(localFile)
        }
        .addOnFailureListener {
            // Handle download error
            showErrorUI()
        }
}

private fun initializeDetector(modelFile: File) {
    val localModel = LocalModel.Builder().setAbsoluteFilePath(modelFile.absolutePath).build()
    val customObjectDetectorOptions = CustomObjectDetectorOptions.Builder(localModel)
            .setDetectorMode(CustomObjectDetectorOptions.SINGLE_IMAGE_MODE)
            .enableClassification()
            .build()
    val objectDetector = ObjectDetection.getClient(customObjectDetectorOptions)
    // Enable ML-related UI features here
    enableMLFeatures(objectDetector)
}

Java

File localFile = new File(context.getCacheDir(), "my_remote_model.tflite");
if (localFile.exists()) {
    // Model is already cached, initialize immediately
    initializeDetector(localFile);
} else {
    // Model is not yet available, show loading UI and start download
    showLoadingUI();
    FirebaseStorage storage = FirebaseStorage.getInstance();
    StorageReference modelRef = storage.getReferenceFromUrl("gs://YOUR_BUCKET/path/to/model.tflite");
    modelRef.getFile(localFile)
        .addOnSuccessListener(new OnSuccessListener<FileDownloadTask.TaskSnapshot>() {
            @Override
            public void onSuccess(FileDownloadTask.TaskSnapshot taskSnapshot) {
                // Download complete, initialize the detector
                hideLoadingUI();
                initializeDetector(localFile);
            }
        })
        .addOnFailureListener(new OnFailureListener() {
            @Override
            public void onFailure(@NonNull Exception exception) {
                // Handle download error
                showErrorUI();
            }
        });
}

private void initializeDetector(File modelFile) {
    LocalModel localModel = new LocalModel.Builder().setAbsoluteFilePath(modelFile.getAbsolutePath()).build();
    CustomObjectDetectorOptions customObjectDetectorOptions =
            new CustomObjectDetectorOptions.Builder(localModel)
                    .setDetectorMode(CustomObjectDetectorOptions.SINGLE_IMAGE_MODE)
                    .enableClassification()
                    .build();
    ObjectDetector objectDetector = ObjectDetection.getClient(customObjectDetectorOptions);
    // Enable ML-related UI features here
    enableMLFeatures(objectDetector);
}

3. इनपुट इमेज तैयार करना

अपनी इमेज से InputImage ऑब्जेक्ट बनाएं. ऑब्जेक्ट डिटेक्टर, सीधे तौर पर Bitmap, NV21 ByteBuffer या YUV_420_888 media.Image से काम करता है. अगर आपके पास इनमें से किसी एक का डायरेक्ट ऐक्सेस है, तो हमारा सुझाव है कि आप इन सोर्स से InputImage बनाएं. अगर आपने InputImage को किसी दूसरे सोर्स से बनाया है, तो हम आपके लिए इंटरनल तौर पर कन्वर्ज़न को मैनेज करेंगे. हालांकि, यह कम असरदार हो सकता है.

InputImage ऑब्जेक्ट को अलग-अलग सोर्स से बनाया जा सकता है. हर सोर्स के बारे में यहां बताया गया है.

media.Image का इस्तेमाल करना

media.Image ऑब्जेक्ट से InputImage ऑब्जेक्ट बनाने के लिए, media.Image ऑब्जेक्ट और इमेज का रोटेशन, InputImage.fromMediaImage() को पास करें. जैसे, डिवाइस के कैमरे से इमेज कैप्चर करते समय.

अगर CameraX लाइब्रेरी का इस्तेमाल किया जाता है, तो OnImageCapturedListener और ImageAnalysis.Analyzer क्लास, आपके लिए रोटेशन वैल्यू का हिसाब लगाती हैं.

Kotlin

private class YourImageAnalyzer : ImageAnalysis.Analyzer {

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

Java

private class YourAnalyzer implements ImageAnalysis.Analyzer {

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

अगर आपने ऐसी कैमरा लाइब्रेरी का इस्तेमाल नहीं किया है जिससे आपको इमेज के रोटेशन डिग्री की जानकारी मिलती है, तो डिवाइस के रोटेशन डिग्री और डिवाइस में मौजूद कैमरा सेंसर के ओरिएंटेशन से इसका हिसाब लगाया जा सकता है:

Kotlin

private val ORIENTATIONS = SparseIntArray()

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

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

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

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

Java

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

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

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

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

इसके बाद, media.Image ऑब्जेक्ट और रोटेशन डिग्री की वैल्यू को InputImage.fromMediaImage() को पास करें:

Kotlin

val image = InputImage.fromMediaImage(mediaImage, rotation)

Java

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

फ़ाइल यूआरआई का इस्तेमाल करना

फ़ाइल यूआरआई से InputImage ऑब्जेक्ट बनाने के लिए, ऐप्लिकेशन का कॉन्टेक्स्ट और फ़ाइल यूआरआई InputImage.fromFilePath() को पास करें. यह तब काम आता है, जब ACTION_GET_CONTENT इंटेंट का इस्तेमाल करके, उपयोगकर्ता को उसकी गैलरी ऐप्लिकेशन से इमेज चुनने के लिए कहा जाता है.

Kotlin

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

Java

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

ByteBuffer या ByteArray का इस्तेमाल करना

ByteBuffer या ByteArray से InputImage ऑब्जेक्ट बनाने के लिए, पहले इमेज के रोटेशन डिग्री का हिसाब लगाएं. जैसा कि media.Image इनपुट के लिए पहले बताया गया है. इसके बाद, बफ़र या ऐरे के साथ InputImage ऑब्जेक्ट बनाएं. इसमें इमेज की ऊंचाई, चौड़ाई, कलर एन्कोडिंग फ़ॉर्मैट, और रोटेशन डिग्री शामिल करें:

Kotlin

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

Java

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 का इस्तेमाल करना

Bitmap ऑब्जेक्ट से InputImage ऑब्जेक्ट बनाने के लिए, यह एलान करें:

Kotlin

val image = InputImage.fromBitmap(bitmap, 0)

Java

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

इमेज को रोटेशन डिग्री के साथ Bitmap ऑब्जेक्ट के तौर पर दिखाया जाता है.

4. ऑब्जेक्ट डिटेक्टर चलाना

Kotlin

objectDetector
    .process(image)
    .addOnFailureListener(e -> {...})
    .addOnSuccessListener(results -> {
        for (detectedObject in results) {
          // ...
        }
    });

Java

objectDetector
    .process(image)
    .addOnFailureListener(e -> {...})
    .addOnSuccessListener(results -> {
        for (DetectedObject detectedObject : results) {
          // ...
        }
    });

5. लेबल किए गए ऑब्जेक्ट के बारे में जानकारी पाना

अगर process() को कॉल करने पर, यह प्रोसेस पूरी हो जाती है, तो सफलता के लिसनर को DetectedObject की सूची पास की जाती है.

हर DetectedObject में ये प्रॉपर्टी शामिल होती हैं:

बाउंडिंग बॉक्स एक Rect जो इमेज में ऑब्जेक्ट की पोज़िशन दिखाता है.
ट्रैकिंग आईडी एक पूर्णांक जो अलग-अलग इमेज में ऑब्जेक्ट की पहचान करता है. SINGLE_IMAGE_MODE में, इसकी वैल्यू नल होती है.
लेबल
लेबल वर्णन लेबल का टेक्स्ट ब्यौरा. यह सिर्फ़ तब दिखता है, जब LiteRT मॉडल के मेटाडेटा में लेबल के ब्यौरे शामिल हों.
लेबल इंडेक्स क्लासिफ़ायर के साथ काम करने वाले सभी लेबल में, लेबल का इंडेक्स.
लेबल कॉन्फ़िडेंस ऑब्जेक्ट क्लासिफ़िकेशन कितना सटीक है.

Kotlin

// The list of detected objects contains one item if multiple
// object detection wasn't enabled.
for (detectedObject in results) {
    val boundingBox = detectedObject.boundingBox
    val trackingId = detectedObject.trackingId
    for (label in detectedObject.labels) {
      val text = label.text
      val index = label.index
      val confidence = label.confidence
    }
}

Java

// The list of detected objects contains one item if multiple
// object detection wasn't enabled.
for (DetectedObject detectedObject : results) {
  Rect boundingBox = detectedObject.getBoundingBox();
  Integer trackingId = detectedObject.getTrackingId();
  for (Label label : detectedObject.getLabels()) {
    String text = label.getText();
    int index = label.getIndex();
    float confidence = label.getConfidence();
  }
}

बेहतर उपयोगकर्ता अनुभव देना

बेहतर उपयोगकर्ता अनुभव देने के लिए, अपने ऐप्लिकेशन में इन दिशा-निर्देशों का पालन करें:

  • ऑब्जेक्ट का पता लगाने की सुविधा, ऑब्जेक्ट की विज़ुअल जटिलता पर निर्भर करती है. विज़ुअल सुविधाओं की कम संख्या वाले ऑब्जेक्ट का पता लगाने के लिए, उन्हें इमेज के बड़े हिस्से में दिखाना पड़ सकता है. आपको उपयोगकर्ताओं को इनपुट कैप्चर करने के बारे में निर्देश देने चाहिए. इससे, उन ऑब्जेक्ट का पता लगाने में मदद मिलेगी जिन्हें आपको पहचानना है.
  • क्लासिफ़िकेशन का इस्तेमाल करते समय, अगर आपको ऐसे ऑब्जेक्ट का पता लगाना है जो काम करने वाली कैटगरी में शामिल नहीं हैं, तो अज्ञात ऑब्जेक्ट के लिए खास हैंडलिंग लागू करें.

इसके अलावा, ML Kit मटीरियल डिज़ाइन शोकेस ऐप्लिकेशन और मशीन लर्निंग की सुविधाओं के कलेक्शन के लिए, मटीरियल डिज़ाइन पैटर्न देखें.

प्रदर्शन सुधारना

अगर आपको रीयल-टाइम ऐप्लिकेशन में ऑब्जेक्ट का पता लगाने की सुविधा का इस्तेमाल करना है, तो बेहतर फ़्रेमरेट पाने के लिए, इन दिशा-निर्देशों का पालन करें:

  • रीयल-टाइम ऐप्लिकेशन में स्ट्रीमिंग मोड का इस्तेमाल करते समय, एक से ज़्यादा ऑब्जेक्ट का पता लगाने की सुविधा का इस्तेमाल न करें. ऐसा इसलिए, क्योंकि ज़्यादातर डिवाइस, सही फ़्रेमरेट नहीं दे पाएंगे.

  • अगर Camera या camera2 API का इस्तेमाल किया जाता है, तो डिटेक्टर को कॉल करने की संख्या सीमित करें. अगर डिटेक्टर के चालू होने के दौरान, वीडियो का कोई नया फ़्रेम उपलब्ध होता है, तो उस फ़्रेम को छोड़ दें. उदाहरण के लिए, क्विकस्टार्ट सैंपल ऐप्लिकेशन में VisionProcessorBase क्लास देखें.
  • अगर CameraX API का इस्तेमाल किया जाता है, तो पक्का करें कि बैकप्रेशर रणनीति, अपनी डिफ़ॉल्ट वैल्यू ImageAnalysis.STRATEGY_KEEP_ONLY_LATEST पर सेट हो. इससे यह पक्का होता है कि एक बार में सिर्फ़ एक इमेज, विश्लेषण के लिए डिलीवर की जाएगी. अगर एनालाइज़र के व्यस्त होने पर ज़्यादा इमेज जनरेट होती हैं, तो उन्हें अपने-आप छोड़ दिया जाएगा. साथ ही, उन्हें डिलीवरी के लिए क्यू में नहीं रखा जाएगा. विश्लेषण की जा रही इमेज को ImageProxy.close() को कॉल करके बंद करने के बाद, अगली सबसे नई इमेज डिलीवर की जाएगी.
  • अगर इनपुट इमेज पर ग्राफ़िक्स ओवरले करने के लिए, डिटेक्टर के आउटपुट का इस्तेमाल किया जाता है, तो पहले ML Kit से नतीजा पाएं. इसके बाद, इमेज रेंडर करें और एक ही चरण में ओवरले करें. इससे, हर इनपुट फ़्रेम के लिए, डिसप्ले सर्फ़ेस पर सिर्फ़ एक बार रेंडर किया जाता है. उदाहरण के लिए, क्विकस्टार्ट सैंपल ऐप्लिकेशन में CameraSourcePreview और GraphicOverlay क्लास देखें.
  • अगर Camera2 API का इस्तेमाल किया जाता है, तो ImageFormat.YUV_420_888 फ़ॉर्मैट में इमेज कैप्चर करें. अगर पुराने Camera API का इस्तेमाल किया जाता है, तो ImageFormat.NV21 फ़ॉर्मैट में इमेज कैप्चर करें.