1. शुरू करने से पहले
कोड टाइप करने से, आपको कोड याद रखने में मदद मिलती है. साथ ही, इससे आपको कॉन्टेंट को बेहतर तरीके से समझने में मदद मिलती है. कॉपी-पेस्ट करने से समय बच सकता है. हालांकि, इस तरीके का इस्तेमाल करने से, लंबे समय में कोडिंग की बेहतर क्षमताएं हासिल की जा सकती हैं और कोडिंग को ज़्यादा बेहतर तरीके से किया जा सकता है.
इस कोडलैब में, आपको एक Android ऐप्लिकेशन बनाने का तरीका बताया जाएगा. यह ऐप्लिकेशन, लाइव कैमरे से मिलने वाले फ़ीड पर रीयल-टाइम में इमेज सेगमेंटेशन करता है. इसके लिए, TensorFlow Lite के नए रनटाइम, LiteRT का इस्तेमाल किया जाता है. आपको एक स्टार्टर Android ऐप्लिकेशन लेना होगा और उसमें इमेज सेगमेंटेशन की सुविधाएँ जोड़नी होंगी. हम प्रीप्रोसेसिंग, अनुमान, और पोस्टप्रोसेसिंग के चरणों के बारे में भी जानेंगे. आपको:
- ऐसा Android ऐप्लिकेशन बनाएं जो इमेज को रीयल-टाइम में सेगमेंट करता हो.
- पहले से ट्रेन किए गए LiteRT इमेज सेगमेंटेशन मॉडल को इंटिग्रेट करें.
- मॉडल के लिए, इनपुट इमेज को पहले से प्रोसेस करता है.
- सीपीयू और जीपीयू ऐक्सेलरेटर के लिए, LiteRT रनटाइम का इस्तेमाल करें.
- सेगमेंटेशन मास्क दिखाने के लिए, मॉडल के आउटपुट को प्रोसेस करने का तरीका जानें.
- सामने वाले कैमरे के लिए, सेटिंग में बदलाव करने का तरीका जानें.
आखिर में, आपको नीचे दी गई इमेज जैसा कुछ दिखेगा:

ज़रूरी शर्तें
यह कोडलैब, अनुभवी मोबाइल डेवलपर के लिए बनाया गया है. यह उन डेवलपर के लिए है जो मशीन लर्निंग के बारे में जानना चाहते हैं. आपको इनके बारे में जानकारी होनी चाहिए:
- Kotlin और Android Studio का इस्तेमाल करके Android डेवलपमेंट
- इमेज प्रोसेसिंग के बुनियादी सिद्धांत
आपको क्या सीखने को मिलेगा
- Android ऐप्लिकेशन में LiteRT रनटाइम को इंटिग्रेट और इस्तेमाल करने का तरीका.
- पहले से ट्रेन किए गए LiteRT मॉडल का इस्तेमाल करके, इमेज सेगमेंटेशन कैसे किया जाता है.
- मॉडल के लिए, इनपुट इमेज को पहले से प्रोसेस करने का तरीका.
- मॉडल के लिए अनुमान लगाने की प्रोसेस को कैसे चलाया जाए.
- नतीजे देखने के लिए, सेगमेंटेशन मॉडल के आउटपुट को प्रोसेस करने का तरीका.
- रीयल-टाइम में कैमरा फ़ीड प्रोसेस करने के लिए, CameraX का इस्तेमाल करने का तरीका.
आपको किन चीज़ों की ज़रूरत होगी
- Android Studio का नया वर्शन (v2025.1.1 पर टेस्ट किया गया).
- कोई फ़िज़िकल Android डिवाइस. इसे Galaxy और Pixel डिवाइसों पर सबसे अच्छी तरह से टेस्ट किया गया है.
- GitHub से लिया गया सैंपल कोड.
- Kotlin में Android डेवलपमेंट की बुनियादी जानकारी.
2. इमेज सेगमेंटेशन
इमेज सेगमेंटेशन, कंप्यूटर विज़न का एक टास्क है. इसमें किसी इमेज को कई सेगमेंट या क्षेत्रों में बांटा जाता है. ऑब्जेक्ट का पता लगाने की सुविधा, किसी ऑब्जेक्ट के चारों ओर बाउंडिंग बॉक्स बनाती है. वहीं, इमेज सेगमेंटेशन की सुविधा, इमेज में मौजूद हर पिक्सल को कोई क्लास या लेबल असाइन करती है. इससे इमेज के कॉन्टेंट के बारे में ज़्यादा जानकारी मिलती है. साथ ही, आपको हर ऑब्जेक्ट के सटीक आकार और सीमा के बारे में पता चलता है.
उदाहरण के लिए, सिर्फ़ यह जानने के बजाय कि बॉक्स में एक ‘व्यक्ति' है, यह पता लगाया जा सकता है कि उस व्यक्ति से कौनसे पिक्सल जुड़े हैं. इस ट्यूटोरियल में, पहले से ट्रेन किए गए मशीन लर्निंग मॉडल का इस्तेमाल करके, Android डिवाइस पर रीयल-टाइम इमेज सेगमेंटेशन करने का तरीका बताया गया है.

LiteRT: Pushing the Edge of On-Device ML
मोबाइल डिवाइसों पर रीयल-टाइम में सटीक सेगमेंटेशन करने वाली मुख्य टेक्नोलॉजी LiteRT है. LiteRT, TensorFlow Lite के लिए Google का अगली पीढ़ी का हाई-परफ़ॉर्मेंस रनटाइम है. इसे इस तरह से डिज़ाइन किया गया है कि यह हार्डवेयर से सबसे अच्छी परफ़ॉर्मेंस हासिल कर सके.
यह सुविधा, जीपीयू (ग्राफ़िक्स प्रोसेसिंग यूनिट) और एनपीयू (न्यूरल प्रोसेसिंग यूनिट) जैसे हार्डवेयर एक्सेलरेटर का बेहतर तरीके से इस्तेमाल करके ऐसा करती है. सेगमेंटेशन मॉडल के कंप्यूटेशनल वर्कलोड को सामान्य सीपीयू से इन खास प्रोसेसर पर ट्रांसफ़र करके, LiteRT अनुमान लगाने में लगने वाले समय को काफ़ी कम कर देता है. इसकी मदद से, लाइव कैमरा फ़ीड पर जटिल मॉडल को आसानी से चलाया जा सकता है. साथ ही, मशीन लर्निंग की मदद से सीधे तौर पर आपके फ़ोन पर किए जा सकने वाले कामों को बढ़ाया जा सकता है. इस लेवल की परफ़ॉर्मेंस के बिना, रीयल-टाइम सेगमेंटेशन बहुत धीमा और खराब होगा. इससे उपयोगकर्ताओं को अच्छा अनुभव नहीं मिलेगा.
3. सेट अप करें
रिपॉज़िटरी का क्लोन बनाना
सबसे पहले, LiteRT के लिए रिपॉज़िटरी क्लोन करें:
git clone https://github.com/google-ai-edge/litert-samples.git
litert-samples/compiled_model_api/image_segmentation एक डायरेक्ट्री है. इसमें आपको ज़रूरी सभी संसाधन मिलेंगे. इस कोडलैब के लिए, आपको सिर्फ़ kotlin_cpu_gpu/android_starter प्रोजेक्ट की ज़रूरत होगी. अगर आपको कोई समस्या आ रही है, तो पूरा हो चुका प्रोजेक्ट देखें: kotlin_cpu_gpu/android
फ़ाइल पाथ के बारे में जानकारी
इस ट्यूटोरियल में, Linux/macOS फ़ॉर्मैट में फ़ाइल पाथ दिए गए हैं. अगर Windows का इस्तेमाल किया जा रहा है, तो आपको पाथ में बदलाव करना होगा.
Android Studio के प्रोजेक्ट व्यू और स्टैंडर्ड फ़ाइल सिस्टम व्यू के बीच के अंतर को समझना भी ज़रूरी है. Android Studio का प्रोजेक्ट व्यू, आपके प्रोजेक्ट की फ़ाइलों को व्यवस्थित तरीके से दिखाता है. इन्हें Android डेवलपमेंट के लिए व्यवस्थित किया जाता है. इस ट्यूटोरियल में दिए गए फ़ाइल पाथ, फ़ाइल सिस्टम के पाथ के बारे में बताते हैं. ये Android Studio के प्रोजेक्ट व्यू में मौजूद पाथ के बारे में नहीं बताते.
स्टार्टर ऐप्लिकेशन इंपोर्ट करना
चलिए, Android Studio में स्टार्टर ऐप्लिकेशन इंपोर्ट करके शुरू करते हैं.
- Android Studio खोलें और Open को चुनें.

kotlin_cpu_gpu/android_starterडायरेक्ट्री पर जाएं और उसे खोलें.

यह पक्का करने के लिए कि आपके ऐप्लिकेशन के लिए सभी डिपेंडेंसी उपलब्ध हैं, इंपोर्ट करने की प्रोसेस पूरी होने के बाद आपको अपने प्रोजेक्ट को Gradle फ़ाइलों के साथ सिंक करना चाहिए.
- Android Studio टूलबार से, Sync Project with Gradle Files को चुनें.

- कृपया इस चरण को न छोड़ें. अगर यह काम नहीं करता है, तो ट्यूटोरियल के बाकी हिस्से का कोई मतलब नहीं रहेगा.
स्टार्टर ऐप्लिकेशन चलाना
प्रोजेक्ट को Android Studio में इंपोर्ट करने के बाद, अब ऐप्लिकेशन को पहली बार चलाने के लिए तैयार हैं.
अपने Android डिवाइस को यूएसबी के ज़रिए कंप्यूटर से कनेक्ट करें. इसके बाद, Android Studio टूलबार में मौजूद चलाएं पर क्लिक करें.

ऐप्लिकेशन आपके डिवाइस पर लॉन्च हो जाना चाहिए. आपको कैमरे का लाइव फ़ीड दिखेगा, लेकिन अभी सेगमेंटेशन नहीं होगा. इस ट्यूटोरियल में, फ़ाइल में किए गए सभी बदलाव litert-samples/compiled_model_api/image_segmentation/kotlin_cpu_gpu/android_starter/app/src/main/java/com/google/ai/edge/examples/image_segmentation डायरेक्ट्री में सेव होंगे. अब आपको पता चल गया होगा कि Android Studio, इस डायरेक्ट्री को फिर से क्यों व्यवस्थित करता है 😃.

आपको ImageSegmentationHelper.kt, MainViewModel.kt, और view/SegmentationOverlay.kt फ़ाइलों में भी TODO टिप्पणियां दिखेंगी. यहां दिए गए तरीके में, आपको इन TODO को भरकर इमेज सेगमेंटेशन की सुविधा लागू करनी होगी.
4. स्टार्टर ऐप्लिकेशन के बारे में जानकारी
स्टार्टर ऐप्लिकेशन में पहले से ही बुनियादी यूज़र इंटरफ़ेस (यूआई) और कैमरे को मैनेज करने का लॉजिक मौजूद होता है. यहां मुख्य फ़ाइलों के बारे में खास जानकारी दी गई है:
app/src/main/java/com/google/ai/edge/examples/image_segmentation/MainActivity.kt: यह ऐप्लिकेशन का मुख्य एंट्री पॉइंट है. यह Jetpack Compose का इस्तेमाल करके यूज़र इंटरफ़ेस (यूआई) सेट अप करता है और कैमरे की अनुमतियों को मैनेज करता है.app/src/main/java/com/google/ai/edge/examples/image_segmentation/MainViewModel.kt: यह ViewModel, यूज़र इंटरफ़ेस (यूआई) की स्थिति को मैनेज करता है. साथ ही, इमेज सेगमेंटेशन की प्रोसेस को व्यवस्थित करता है.app/src/main/java/com/google/ai/edge/examples/image_segmentation/ImageSegmentationHelper.kt: यहां हम इमेज सेगमेंटेशन के लिए मुख्य लॉजिक जोड़ेंगे. यह मॉडल को लोड करने, कैमरा फ़्रेम को प्रोसेस करने, और अनुमान लगाने का काम करेगा.app/src/main/java/com/google/ai/edge/examples/image_segmentation/view/CameraScreen.kt: यह कंपोज़ेबल फ़ंक्शन, कैमरे की झलक और सेगमेंटेशन ओवरले दिखाता है.app/download_model.gradle: यह स्क्रिप्टselfie_multiclass.tfliteको डाउनलोड करती है. यह पहले से ट्रेन किया गया TensorFlow Lite इमेज सेगमेंटेशन मॉडल है. हम इसका इस्तेमाल करेंगे.
5. LiteRT के बारे में जानकारी और डिपेंडेंसी जोड़ना
अब, स्टार्टर ऐप्लिकेशन में इमेज सेगमेंटेशन की सुविधा जोड़ते हैं.
1. LiteRT डिपेंडेंसी जोड़ना
सबसे पहले, आपको अपने प्रोजेक्ट में LiteRT लाइब्रेरी जोड़नी होगी. यह Google के ऑप्टिमाइज़ किए गए रनटाइम के साथ, डिवाइस पर मशीन लर्निंग की सुविधा चालू करने का पहला और ज़रूरी चरण है.
app/build.gradle.kts फ़ाइल खोलें और dependencies ब्लॉक में यह लाइन जोड़ें:
// LiteRT for on-device ML
implementation(libs.litert)
डिपेंडेंसी जोड़ने के बाद, अपने प्रोजेक्ट को Gradle फ़ाइलों के साथ सिंक करें. इसके लिए, Android Studio के सबसे ऊपर दाएं कोने में मौजूद, अभी सिंक करें बटन पर क्लिक करें.

2. Key LiteRT API के बारे में जानकारी
खोलें ImageSegmentationHelper.kt
लागू करने का कोड लिखने से पहले, LiteRT API के उन मुख्य कॉम्पोनेंट को समझना ज़रूरी है जिनका इस्तेमाल किया जाएगा. पक्का करें कि आपने com.google.ai.edge.litert पैकेज से इंपोर्ट किया हो. साथ ही, ImageSegmentationHelper.kt के सबसे ऊपर ये इंपोर्ट जोड़ें:
import com.google.ai.edge.litert.Accelerator
import com.google.ai.edge.litert.CompiledModel
CompiledModel: यह आपके TFLite मॉडल के साथ इंटरैक्ट करने के लिए सेंट्रल क्लास है. यह एक ऐसा मॉडल होता है जिसे पहले से कंपाइल किया गया होता है. साथ ही, इसे सीपीयू या जीपीयू जैसे किसी खास हार्डवेयर ऐक्सेलरेटर के लिए ऑप्टिमाइज़ किया गया होता है. प्री-कंपाइलेशन, LiteRT की एक मुख्य सुविधा है. इससे अनुमान लगाने की प्रोसेस तेज़ और ज़्यादा असरदार हो जाती है.CompiledModel.Options: इस बिल्डर क्लास का इस्तेमाल,CompiledModelको कॉन्फ़िगर करने के लिए किया जाता है. सबसे अहम सेटिंग यह तय करना है कि आपको अपने मॉडल को चलाने के लिए, किस हार्डवेयर ऐक्सलरेटर का इस्तेमाल करना है.Accelerator: इस enum की मदद से, अनुमान लगाने के लिए हार्डवेयर चुना जा सकता है. स्टार्टर प्रोजेक्ट में, इन विकल्पों को मैनेज करने के लिए पहले से ही कॉन्फ़िगरेशन मौजूद है:Accelerator.CPU: डिवाइस के सीपीयू पर मॉडल चलाने के लिए. यह सबसे ज़्यादा डिवाइसों के साथ काम करने वाला विकल्प है.Accelerator.GPU: डिवाइस के जीपीयू पर मॉडल चलाने के लिए. इमेज पर आधारित मॉडल के लिए, यह सीपीयू की तुलना में ज़्यादा तेज़ होता है.
- इनपुट और आउटपुट बफ़र (
TensorBuffer): LiteRT, मॉडल के इनपुट और आउटपुट के लिएTensorBufferका इस्तेमाल करता है. इससे आपको मेमोरी पर बेहतर कंट्रोल मिलता है और डेटा की गैर-ज़रूरी कॉपी नहीं बनती हैं. आपको ये बफ़र,model.createInputBuffers()औरmodel.createOutputBuffers()का इस्तेमाल करके सीधे अपनेCompiledModelइंस्टेंस से मिलेंगे. इसके बाद, इनमें अपना इनपुट डेटा लिखें और इनसे नतीजे पढ़ें. model.run(): यह फ़ंक्शन, अनुमान लगाने की प्रोसेस को पूरा करता है. इसमें इनपुट और आउटपुट बफ़र पास किए जाते हैं. इसके बाद, LiteRT चुने गए हार्डवेयर ऐक्सलरेटर पर मॉडल चलाने का मुश्किल काम करता है.
6. ImageSegmentationHelper को लागू करने की शुरुआती प्रोसेस पूरी करना
अब कुछ कोड लिखने का समय है. आपको ImageSegmentationHelper.kt को लागू करने की शुरुआती प्रोसेस पूरी करनी होगी. इसमें LiteRT मॉडल को होल्ड करने के लिए, Segmenter प्राइवेट क्लास सेट अप करना और इसे सही तरीके से रिलीज़ करने के लिए, cleanup() फ़ंक्शन लागू करना शामिल है.
Segmenterक्लास औरcleanup()फ़ंक्शन को पूरा करें:ImageSegmentationHelper.ktफ़ाइल में, आपकोSegmenterनाम की एक प्राइवेट क्लास औरcleanup()नाम का एक फ़ंक्शन दिखेगा. सबसे पहले, मॉडल को होल्ड करने के लिए कंस्ट्रक्टर को तय करके, इनपुट/आउटपुट बफ़र के लिए प्रॉपर्टी बनाकर, और मॉडल को रिलीज़ करने के लिएclose()तरीके को जोड़कर,Segmenterक्लास को पूरा करें. इसके बाद, इस नएclose()तरीके को कॉल करने के लिए,cleanup()फ़ंक्शन लागू करें.मौजूदाSegmenterक्लास औरcleanup()फ़ंक्शन को इससे बदलें: (~लाइन 83)private class Segmenter( // Add this argument private val model: CompiledModel, private val coloredLabels: List<ColoredLabel>, ) { // Add these private vals private val inputBuffers = model.createInputBuffers() private val outputBuffers = model.createOutputBuffers() fun cleanup() { // cleanup buffers inputBuffers.forEach { it.close() } outputBuffers.forEach { it.close() } // cleanup model model.close() } }- toAccelerator तरीके को तय करें: यह तरीका, ऐक्सेलरेटर मेन्यू से तय किए गए ऐक्सेलरेटर एनम को, इंपोर्ट किए गए LiteRT मॉड्यूल (~लाइन 225) के लिए खास तौर पर बनाए गए ऐक्सेलरेटर एनम पर मैप करता है:
fun toAccelerator(acceleratorEnum: AcceleratorEnum): Accelerator { return when (acceleratorEnum) { AcceleratorEnum.CPU -> Accelerator.CPU AcceleratorEnum.GPU -> Accelerator.GPU } } CompiledModelको शुरू करें: अबinitSegmenterफ़ंक्शन ढूंढें. यहां आपकोCompiledModelइंस्टेंस बनाना होगा. साथ ही, इसका इस्तेमाल करके, अब तय की गईSegmenterक्लास को इंस्टैंशिएट करना होगा. यह कोड, मॉडल को तय किए गए ऐक्सेलरेटर (सीपीयू या जीपीयू) के साथ सेट अप करता है. साथ ही, इसे अनुमान लगाने के लिए तैयार करता है.TODOमें मौजूदTODOको इस कोड से बदलें (Cmd/Ctrl+f ‘initSegmenter` या ~लाइन 62):initSegmentercleanup() try { withContext(singleThreadDispatcher) { val model = CompiledModel.create( context.assets, "selfie_multiclass.tflite", CompiledModel.Options(toAccelerator(acceleratorEnum)), null, ) segmenter = Segmenter(model, coloredLabels) Log.d(TAG, "Created an image segmenter") } } catch (e: Exception) { Log.i(TAG, "Create LiteRT from selfie_multiclass is failed: ${e.message}") _error.emit(e) }
7. सेगमेंटेशन और प्रीप्रोसेसिंग शुरू करना
अब हमारे पास मॉडल है. इसलिए, हमें सेगमेंटेशन की प्रोसेस शुरू करनी होगी और मॉडल के लिए इनपुट डेटा तैयार करना होगा.
ट्रिगर सेगमेंटेशन
सेगमेंटेशन की प्रोसेस MainViewModel.kt में शुरू होती है. इसे कैमरे से फ़्रेम मिलते हैं.
खोलें MainViewModel.kt
- कैमरा फ़्रेम से सेगमेंटेशन ट्रिगर करना:
MainViewModelमें मौजूदsegmentफ़ंक्शन, सेगमेंटेशन टास्क के लिए एंट्री पॉइंट होते हैं. जब भी कैमरे से कोई नई इमेज उपलब्ध होती है या गैलरी से कोई इमेज चुनी जाती है, तब इन्हें कॉल किया जाता है. इसके बाद, ये फ़ंक्शन हमारेImageSegmentationHelperमेंsegmentतरीके को कॉल करते हैं. दोनोंsegmentफ़ंक्शन में मौजूदTODOs की जगह, यहां दिया गया कोड डालें (लाइन ~107):// For ImageProxy (from CameraX) fun segment(imageProxy: ImageProxy) { segmentJob = viewModelScope.launch { imageSegmentationHelper.segment(imageProxy.toBitmap(), imageProxy.imageInfo.rotationDegrees) imageProxy.close() } } // For Bitmaps (from gallery) fun segment(bitmap: Bitmap, rotationDegrees: Int) { segmentJob = viewModelScope.launch { val argbBitmap = bitmap.copy(Bitmap.Config.ARGB_8888, true) imageSegmentationHelper.segment(argbBitmap, rotationDegrees) } }
इमेज को प्रीप्रोसेस करना
अब इमेज की प्रीप्रोसेसिंग करने के लिए, ImageSegmentationHelper.kt पर वापस जाएं.
खोलें ImageSegmentationHelper.kt
- Public
segmentफ़ंक्शन लागू करें: यह फ़ंक्शन, रैपर के तौर पर काम करता है. यहSegmenterक्लास में मौजूद privatesegmentफ़ंक्शन को कॉल करता है.TODOको (~लाइन 95) से बदलें:try { withContext(singleThreadDispatcher) { segmenter?.segment(bitmap, rotationDegrees)?.let { if (isActive) _segmentation.emit(it) } } } catch (e: Exception) { Log.i(TAG, "Image segment error occurred: ${e.message}") _error.emit(e) } - प्री-प्रोसेसिंग लागू करना:
Segmenterक्लास के अंदर मौजूद प्राइवेटsegmentफ़ंक्शन में, हम इनपुट इमेज में ज़रूरी बदलाव करेंगे, ताकि उसे मॉडल के लिए तैयार किया जा सके. इसमें इमेज को बड़ा या छोटा करना, घुमाना, और सामान्य करना शामिल है. इसके बाद, यह फ़ंक्शन अनुमान लगाने के लिए, किसी दूसरे निजीsegmentफ़ंक्शन को कॉल करेगा.segment(bitmap: Bitmap, ...)फ़ंक्शन में मौजूदTODOको (~line 121) से बदलें:val totalStartTime = SystemClock.uptimeMillis() val rotation = -rotationDegrees / 90 val (h, w) = Pair(256, 256) // Preprocessing val preprocessStartTime = SystemClock.uptimeMillis() var image = bitmap.scale(w, h, true) image = rot90Clockwise(image, rotation) val inputFloatArray = normalize(image, 127.5f, 127.5f) Log.d(TAG, "Preprocessing time: ${SystemClock.uptimeMillis() - preprocessStartTime} ms") // Inference val inferenceStartTime = SystemClock.uptimeMillis() val segmentResult = segment(inputFloatArray) Log.d(TAG, "Inference time: ${SystemClock.uptimeMillis() - inferenceStartTime} ms") Log.d(TAG, "Total segmentation time: ${SystemClock.uptimeMillis() - totalStartTime} ms") return SegmentationResult(segmentResult, SystemClock.uptimeMillis() - inferenceStartTime)
8. LiteRT की मदद से प्राइमरी इन्फ़रेंस
इनपुट डेटा को पहले से प्रोसेस करने के बाद, अब हम LiteRT का इस्तेमाल करके मुख्य अनुमान लगा सकते हैं.
खोलें ImageSegmentationHelper.kt
- मॉडल को लागू करना: प्राइवेट
segment(inputFloatArray: FloatArray)फ़ंक्शन में, हम सीधे तौर पर LiteRTrun()तरीके से इंटरैक्ट करते हैं. हम पहले से प्रोसेस किए गए डेटा को इनपुट बफ़र में लिखते हैं, मॉडल को चलाते हैं, और आउटपुट बफ़र से नतीजे पढ़ते हैं. इस फ़ंक्शन में मौजूदTODOको (~लाइन 188) से बदलें:val (h, w, c) = Triple(256, 256, 6) // MODEL EXECUTION PHASE val modelExecStartTime = SystemClock.uptimeMillis() // Write input data - measure time val bufferWriteStartTime = SystemClock.uptimeMillis() inputBuffers[0].writeFloat(inputFloatArray) val bufferWriteTime = SystemClock.uptimeMillis() - bufferWriteStartTime Log.d(TAG, "Buffer write time: $bufferWriteTime ms") // Optional tensor inspection logTensorStats("Input tensor", inputFloatArray) // Run model inference - measure time val modelRunStartTime = SystemClock.uptimeMillis() model.run(inputBuffers, outputBuffers) val modelRunTime = SystemClock.uptimeMillis() - modelRunStartTime Log.d(TAG, "Model.run() time: $modelRunTime ms") // Read output data - measure time val bufferReadStartTime = SystemClock.uptimeMillis() val outputFloatArray = outputBuffers[0].readFloat() val outputBuffer = FloatBuffer.wrap(outputFloatArray) val bufferReadTime = SystemClock.uptimeMillis() - bufferReadStartTime Log.d(TAG, "Buffer read time: $bufferReadTime ms") val modelExecTime = SystemClock.uptimeMillis() - modelExecStartTime Log.d(TAG, "Total model execution time: $modelExecTime ms") // Optional tensor inspection logTensorStats("Output tensor", outputFloatArray) // POSTPROCESSING PHASE val postprocessStartTime = SystemClock.uptimeMillis() // Process mask from model output val inferenceData = InferenceData(width = w, height = h, channels = c, buffer = outputBuffer) val mask = processImage(inferenceData) val postprocessTime = SystemClock.uptimeMillis() - postprocessStartTime Log.d(TAG, "Postprocessing time (mask creation): $postprocessTime ms") return Segmentation( listOf(Mask(mask, inferenceData.width, inferenceData.height)), coloredLabels, )
9. प्रोसेस होने के बाद और ओवरले दिखाना
इन्फ़्रेंस चलाने के बाद, हमें मॉडल से रॉ आउटपुट मिलता है. हमें इस आउटपुट को प्रोसेस करके, विज़ुअल सेगमेंटेशन मास्क बनाना होगा. इसके बाद, इसे स्क्रीन पर दिखाना होगा.
खोलें ImageSegmentationHelper.kt
- आउटपुट प्रोसेसिंग लागू करना:
processImageफ़ंक्शन, मॉडल से मिले रॉ फ़्लोटिंग-पॉइंट आउटपुट कोByteBufferमें बदलता है. यहByteBuffer, सेगमेंटेशन मास्क को दिखाता है. यह हर पिक्सल के लिए, सबसे ज़्यादा संभावना वाली क्लास का पता लगाकर ऐसा करता है. इसकेTODOको (~line 238) से बदलें:val mask = ByteBuffer.allocateDirect(inferenceData.width * inferenceData.height) for (i in 0 until inferenceData.height) { for (j in 0 until inferenceData.width) { val offset = inferenceData.channels * (i * inferenceData.width + j) var maxIndex = 0 var maxValue = inferenceData.buffer.get(offset) for (index in 1 until inferenceData.channels) { if (inferenceData.buffer.get(offset + index) > maxValue) { maxValue = inferenceData.buffer.get(offset + index) maxIndex = index } } mask.put(i * inferenceData.width + j, maxIndex.toByte()) } } return mask
खोलें MainViewModel.kt
- सेगमेंटेशन के नतीजों को इकट्ठा और प्रोसेस करना: अब हम
ImageSegmentationHelperसे मिले सेगमेंटेशन के नतीजों को प्रोसेस करने के लिए,MainViewModelपर वापस जाते हैं.segmentationUiShareFlow,SegmentationResultको इकट्ठा करता है. इसके बाद, मास्क को रंगीनBitmapमें बदलता है और उसे यूज़र इंटरफ़ेस (यूआई) को उपलब्ध कराता है.segmentationUiShareFlowप्रॉपर्टी में मौजूदTODOको (~लाइन 63) से बदलें. पहले से मौजूद कोड को न बदलें, सिर्फ़ मुख्य हिस्सा भरें:viewModelScope.launch { imageSegmentationHelper.segmentation .filter { it.segmentation.masks.isNotEmpty() } .map { val segmentation = it.segmentation val mask = segmentation.masks[0] val maskArray = mask.data val width = mask.width val height = mask.height val pixelSize = width * height val pixels = IntArray(pixelSize) val colorLabels = segmentation.coloredLabels.mapIndexed { index, coloredLabel -> ColorLabel(index, coloredLabel.label, coloredLabel.argb) } // Set color for pixels for (i in 0 until pixelSize) { val colorLabel = colorLabels[maskArray[i].toInt()] val color = colorLabel.getColor() pixels[i] = color } // Get image info val overlayInfo = OverlayInfo(pixels = pixels, width = width, height = height) val inferenceTime = it.inferenceTime Pair(overlayInfo, inferenceTime) } .collect { flow.emit(it) } }
खोलें view/SegmentationOverlay.kt
आखिरी चरण में, उपयोगकर्ता के सामने वाले कैमरे पर फ़्लिप करने पर, सेगमेंटेशन ओवरले को सही तरीके से ओरिएंट करना होता है. सामने वाले कैमरे के लिए, कैमरे का फ़ीड अपने-आप मिरर हो जाता है. इसलिए, हमें अपने ओवरले Bitmap पर भी हॉरिज़ॉन्टल फ़्लिप लागू करना होगा, ताकि यह कैमरे की झलक के साथ सही तरीके से अलाइन हो सके.
- ओवरले के ओरिएंटेशन को मैनेज करना:
SegmentationOverlay.ktफ़ाइल मेंTODOढूंढें और उसे इस कोड से बदलें. यह कोड यह जांच करता है कि सामने की ओर मौजूद कैमरा चालू है या नहीं. अगर कैमरा चालू है, तो यहCanvasपर ड्रॉ होने से पहले, ओवरलेBitmapपर हॉरिज़ॉन्टल फ़्लिप लागू करता है. (~लाइन 42):val orientedBitmap = if (lensFacing == CameraSelector.LENS_FACING_FRONT) { // Create a matrix for horizontal flipping val matrix = Matrix().apply { preScale(-1f, 1f) } Bitmap.createBitmap(image, 0, 0, image.width, image.height, matrix, false).also { image.recycle() } } else { image }
10. फ़ाइनल ऐप्लिकेशन को चलाना और उसका इस्तेमाल करना
अब आपने कोड में सभी ज़रूरी बदलाव कर लिए हैं. अब ऐप्लिकेशन को चलाने और अपने काम को ऐक्शन में देखने का समय है!
- ऐप्लिकेशन चलाना: अपने Android डिवाइस को कनेक्ट करें. इसके बाद, Android Studio टूलबार में मौजूद चलाएं पर क्लिक करें.

- सुविधाओं को आज़माएँ: ऐप्लिकेशन लॉन्च होने के बाद, आपको लाइव कैमरा फ़ीड दिखेगा. इसमें रंगीन सेगमेंटेशन ओवरले होगा.
- कैमरे स्विच करें: सामने और पीछे वाले कैमरे के बीच स्विच करने के लिए, सबसे ऊपर मौजूद कैमरा फ़्लिप करने वाले आइकॉन पर टैप करें. ध्यान दें कि ओवरले सही तरीके से कैसे दिखता है.
- ऐक्सेलरेटर बदलें: हार्डवेयर ऐक्सेलरेटर बदलने के लिए, सबसे नीचे मौजूद "सीपीयू" या "जीपीयू" बटन पर टैप करें. स्क्रीन पर सबसे नीचे दिख रहे अनुमान लगाने में लगने वाले समय में हुए बदलाव को देखें. जीपीयू की स्पीड काफ़ी ज़्यादा होनी चाहिए.
- गैलरी में मौजूद इमेज का इस्तेमाल करना: अपने डिवाइस की फ़ोटो गैलरी से कोई इमेज चुनने के लिए, सबसे ऊपर मौजूद "गैलरी" टैब पर टैप करें. ऐप्लिकेशन, चुनी गई स्टैटिक इमेज पर सेगमेंटेशन करेगा.

अब आपके पास LiteRT की मदद से बनाया गया, पूरी तरह से काम करने वाला और रीयल-टाइम इमेज सेगमेंटेशन ऐप्लिकेशन है!
11. ऐडवांस (ज़रूरी नहीं): एनपीयू का इस्तेमाल करना
इस रिपॉज़िटरी में, ऐप्लिकेशन का ऐसा वर्शन भी शामिल है जिसे न्यूरल प्रोसेसिंग यूनिट (एनपीयू) के लिए ऑप्टिमाइज़ किया गया है. एनपीयू वर्शन, उन डिवाइसों पर परफ़ॉर्मेंस को बेहतर बना सकता है जिनमें एनपीयू की सुविधा काम करती है.
एनपीयू वर्शन को आज़माने के लिए, Android Studio में kotlin_npu/android प्रोजेक्ट खोलें. यह कोड, सीपीयू/जीपीयू वर्शन से काफ़ी मिलता-जुलता है. इसे NPU डेलिगेट का इस्तेमाल करने के लिए कॉन्फ़िगर किया गया है.
एनपीयू डेलिगेट का इस्तेमाल करने के लिए, आपको अर्ली ऐक्सेस प्रोग्राम में रजिस्टर करना होगा.
12. बधाई हो!
आपने LiteRT का इस्तेमाल करके, रीयल-टाइम में इमेज सेगमेंटेशन करने वाला Android ऐप्लिकेशन बना लिया है. आपने इनके बारे में जानकारी पा ली है:
- Android ऐप्लिकेशन में LiteRT रनटाइम को इंटिग्रेट करें.
- TFLite इमेज सेगमेंटेशन मॉडल को लोड और रन करें.
- मॉडल के इनपुट को पहले से प्रोसेस करें.
- सेगमेंटेशन मास्क बनाने के लिए, मॉडल के आउटपुट को प्रोसेस करें.
- रीयल-टाइम कैमरा ऐप्लिकेशन के लिए, CameraX का इस्तेमाल करें.
अगले चरण
- इमेज सेगमेंटेशन के लिए कोई दूसरा मॉडल आज़माएं.
- अलग-अलग LiteRT डेलिगेट (सीपीयू, जीपीयू, एनपीयू) के साथ एक्सपेरिमेंट करें.