মিডিয়াপাইপের সাথে অ্যান্ড্রয়েডে ডিভাইসে ইমেজ জেনারেশন

১. ভূমিকা

মিডিয়াপাইপ কী?

মিডিয়াপাইপ সলিউশনস আপনাকে আপনার অ্যাপে মেশিন-লার্নিং (এমএল) সলিউশন প্রয়োগ করার সুযোগ দেয়। এটি আগে থেকে তৈরি প্রসেসিং পাইপলাইন কনফিগার করার জন্য একটি ফ্রেমওয়ার্ক প্রদান করে, যা ব্যবহারকারীদের কাছে তাৎক্ষণিক, আকর্ষণীয় এবং দরকারি আউটপুট পৌঁছে দেয়। এমনকি আপনি মিডিয়াপাইপ মডেল মেকার ব্যবহার করে ডিফল্ট মডেলগুলো আপডেট করার জন্য এই সলিউশনগুলোর অনেকগুলো কাস্টমাইজও করতে পারেন।

টেক্সট থেকে ছবিতে রূপান্তর হলো মিডিয়াপাইপ সলিউশনস-এর দেওয়া বিভিন্ন মেশিন লার্নিং (এমএল) টাস্কগুলোর মধ্যে একটি।

এই কোডল্যাবে, আপনি একটি প্রায়-প্রাথমিক অ্যান্ড্রয়েড অ্যাপ দিয়ে শুরু করবেন এবং ধাপে ধাপে অগ্রসর হয়ে সরাসরি আপনার অ্যান্ড্রয়েড ডিভাইসে নতুন ছবি তৈরি করতে সক্ষম হবেন।

আপনি যা শিখবেন

  • মিডিয়াপাইপ টাস্ক ব্যবহার করে কীভাবে একটি অ্যান্ড্রয়েড অ্যাপে স্থানীয়ভাবে টেক্সট থেকে ছবি তৈরির ব্যবস্থা বাস্তবায়ন করা যায়।

আপনার যা যা লাগবে

  • অ্যান্ড্রয়েড স্টুডিও -র একটি ইনস্টল করা সংস্করণ (এই কোডল্যাবটি অ্যান্ড্রয়েড স্টুডিও জিরাফ দিয়ে লেখা ও পরীক্ষা করা হয়েছে)।
  • কমপক্ষে ৮ জিবি র‍্যাম সহ একটি অ্যান্ড্রয়েড ডিভাইস।
  • অ্যান্ড্রয়েড ডেভেলপমেন্টের প্রাথমিক জ্ঞান এবং আগে থেকে লেখা পাইথন স্ক্রিপ্ট চালানোর ক্ষমতা।

২. অ্যান্ড্রয়েড অ্যাপে মিডিয়াপাইপ টাস্ক যোগ করুন

অ্যান্ড্রয়েড স্টার্টার অ্যাপটি ডাউনলোড করুন

এই কোডল্যাবটি একটি পূর্ব-নির্মিত নমুনা দিয়ে শুরু হবে, যেখানে ছবি তৈরির একটি প্রাথমিক সংস্করণের জন্য ব্যবহৃত UI (ইউজার ইন্টারফেস) রয়েছে। আপনি সেই শুরুর অ্যাপটি অফিসিয়াল MediaPipe স্যাম্পলস রিপো-তে এখানে খুঁজে পাবেন। রিপোটি ক্লোন করুন অথবা Code > Download ZIP-এ ক্লিক করে জিপফাইলটি ডাউনলোড করুন।

অ্যান্ড্রয়েড স্টুডিওতে অ্যাপটি ইম্পোর্ট করুন

  1. অ্যান্ড্রয়েড স্টুডিও খুলুন।
  2. "Welcome to Android Studio" স্ক্রিন থেকে, উপরের ডান কোণায় থাকা "Open" নির্বাচন করুন।

a0b5b070b802e4ea.png

  1. আপনি যেখানে রিপোজিটরিটি ক্লোন বা ডাউনলোড করেছেন সেখানে যান এবং codelabs/image_generation_basic/android/start ডিরেক্টরিটি খুলুন।
  2. এই পর্যায়ে অ্যাপটি কম্পাইল হওয়া উচিত নয়, কারণ আপনি এখনও MediaPipe Tasks ডিপেন্ডেন্সিটি অন্তর্ভুক্ত করেননি।

অ্যাপটি ঠিক করে চালু করার জন্য, build.gradle ফাইলে গিয়ে // Step 1 - Add dependency পর্যন্ত স্ক্রল করুন। সেখান থেকে, নিম্নলিখিত লাইনটি অন্তর্ভুক্ত করুন এবং তারপরে Android Studio-এর শীর্ষে থাকা ব্যানারে প্রদর্শিত Sync Now বোতামটি চাপুন।

// Step 1 - Add dependency
implementation 'com.google.mediapipe:tasks-vision-image-generator:latest.release'

সিঙ্কিং সম্পন্ন হয়ে গেলে, সবুজ রান অ্যারোতে (run arrow) ক্লিক করে যাচাই করুন যে সবকিছু সঠিকভাবে খুলেছে এবং ইনস্টল হয়েছে কিনা। 7e15a9c9e1620fe7.png অ্যান্ড্রয়েড স্টুডিওর উপরের ডানদিকে থাকা আইকনে ক্লিক করুন। আপনি দেখবেন অ্যাপটি এমন একটি স্ক্রিনে খুলবে যেখানে দুটি রেডিও বাটন এবং INITIALIZE লেখা একটি বাটন থাকবে। আপনি যদি সেই বাটনটিতে ক্লিক করেন, তাহলে আপনাকে সাথে সাথে একটি আলাদা UI-তে নিয়ে যাওয়া হবে, যেখানে একটি টেক্সট প্রম্পট ও অন্যান্য অপশনের পাশাপাশি GENERATE লেখা একটি বাটন থাকবে।

83c31de8e8a320ee.png78b8765e832024e3.png

দুর্ভাগ্যবশত, স্টার্টার অ্যাপটি এই পর্যন্তই সীমাবদ্ধ, তাই এখন আপনার শেখার পালা কীভাবে আপনি এই অ্যাপটি সম্পূর্ণ করবেন এবং আপনার ডিভাইসে নতুন ছবি তৈরি করা শুরু করবেন!

৩. ইমেজ জেনারেটর সেট আপ করা

এই উদাহরণের জন্য, ছবি তৈরির বেশিরভাগ কাজ ImageGenerationHelper.kt ফাইলে সম্পন্ন হবে। আপনি যখন এই ফাইলটি খুলবেন, তখন ক্লাসের উপরের দিকে imageGenerator নামে একটি ভেরিয়েবল দেখতে পাবেন। এটিই সেই Task অবজেক্ট যা আপনার ছবি তৈরির অ্যাপে মূল কাজগুলো করবে।

ওই অবজেক্টটির ঠিক নিচে আপনি initializeImageGenerator() নামের একটি ফাংশন দেখতে পাবেন, যার সাথে নিম্নলিখিত কমেন্টটি রয়েছে: // ধাপ ২ - ইমেজ জেনারেটর ইনিশিয়ালাইজ করুন। আপনি হয়তো অনুমান করতে পারছেন, এখানেই আপনি ImageGenerator অবজেক্টটি ইনিশিয়ালাইজ করবেন। ইমেজ জেনারেশন মডেল পাথ সেট করতে এবং ImageGenerator অবজেক্টটি ইনিশিয়ালাইজ করতে, ওই ফাংশন বডিটি নিচের কোড দিয়ে প্রতিস্থাপন করুন:

// Step 2 - initialize the image generator
val options = ImageGeneratorOptions.builder()
    .setImageGeneratorModelDirectory(modelPath)
    .build()

imageGenerator = ImageGenerator.createFromOptions(context, options)

এর নিচে আপনি setInput() নামের আরেকটি ফাংশন দেখতে পাবেন। এটি তিনটি প্যারামিটার গ্রহণ করে: একটি প্রম্পট স্ট্রিং যা তৈরি হওয়া ছবিটি নির্ধারণ করতে ব্যবহৃত হবে, নতুন ছবিটি তৈরি করার সময় টাস্কটি কতবার পুনরাবৃত্তি করবে তার সংখ্যা, এবং একটি সিড ভ্যালু যা একই সিড ব্যবহার করে একই প্রম্পটের উপর ভিত্তি করে ছবিটির নতুন সংস্করণ তৈরি করতে ব্যবহার করা যেতে পারে। যখন আপনি এমন একটি ছবি তৈরি করার চেষ্টা করেন যা মধ্যবর্তী ধাপগুলো প্রদর্শন করে , তখন ইমেজ জেনারেটরের জন্য এই প্রাথমিক প্যারামিটারগুলো সেট করাই এই ফাংশনের উদ্দেশ্য।

setInput() ফাংশনের বডিতে (যেখানে আপনি // Step 3 - accept inputs কমেন্টটি দেখতে পাবেন) এই লাইনটি দিয়ে প্রতিস্থাপন করুন:

// Step 3 - accept inputs
imageGenerator.setInputs(prompt, iteration, seed)

পরবর্তী দুটি ধাপেই জেনারেশন বা তৈরির কাজটি সম্পন্ন হয়। `generate()` ফাংশনটি `setInput`-এর মতোই ইনপুট গ্রহণ করে, কিন্তু এটি একবারে একটি ইমেজ তৈরি করে এবং কোনো মধ্যবর্তী ধাপের ইমেজ রিটার্ন করে না। আপনি এই ফাংশনের বডিটি (যেখানে `// Step 4 - generate without showing iterations` কমেন্টটি রয়েছে) নিম্নলিখিত কোড দিয়ে প্রতিস্থাপন করতে পারেন:

// Step 4 - generate without showing iterations
val result = imageGenerator.generate(prompt, iteration, seed)
val bitmap = BitmapExtractor.extract(result?.generatedImage())
return bitmap

এটা জানা জরুরি যে এই কাজটি সিনক্রোনাসভাবে সম্পন্ন হয়, তাই আপনাকে একটি ব্যাকগ্রাউন্ড থ্রেড থেকে ফাংশনটি কল করতে হবে। এই কোডল্যাবে একটু পরেই আপনি এ সম্পর্কে আরও জানতে পারবেন।

এই ফাইলে আপনার শেষ ধাপটি হবে execute() ফাংশনটি পূরণ করা (ধাপ ৫ হিসাবে চিহ্নিত)। এটি একটি প্যারামিটার গ্রহণ করবে যা এটিকে বলে দেবে যে ImageGenerator execute() ফাংশন দ্বারা সম্পাদিত জেনারেশনের একক ধাপের জন্য এটি একটি অন্তর্বর্তী ইমেজ রিটার্ন করবে কি না। ফাংশন বডিটি এই কোড দিয়ে প্রতিস্থাপন করুন:

// Step 5 - generate with iterations
val result = imageGenerator.execute(showResult)

if (result == null || result.generatedImage() == null) {
    return Bitmap.createBitmap(512, 512, Bitmap.Config.ARGB_8888)
        .apply {
            val canvas = Canvas(this)
            val paint = Paint()
            paint.color = Color.WHITE
            canvas.drawPaint(paint)
        }
}

val bitmap =
    BitmapExtractor.extract(result.generatedImage())

return bitmap

এবং হেল্পার ফাইলের জন্য এটুকুই। পরবর্তী অংশে আপনি ViewModel ফাইলটি পূরণ করবেন, যা এই উদাহরণটির লজিক পরিচালনা করবে।

৪. অ্যাপটিকে একত্রিত করা

MainViewModel ফাইলটি এই উদাহরণ অ্যাপটির UI স্টেট এবং অন্যান্য লজিক পরিচালনা করবে। এখনই এটি খুলুন।

ফাইলের উপরের দিকে আপনি // Step 6 - set model path এই কমেন্টটি দেখতে পাবেন। এখানেই আপনি আপনার অ্যাপকে বলে দেবেন যে ইমেজ তৈরির জন্য প্রয়োজনীয় মডেল ফাইলগুলো কোথায় পাওয়া যাবে। এই উদাহরণের জন্য আপনি ভ্যালুটি /data/local/tmp/image_generator/bins/ সেট করবেন।

// Step 6 - set model path
private val MODEL_PATH = "/data/local/tmp/image_generator/bins/"

সেখান থেকে, generateImage() ফাংশন পর্যন্ত স্ক্রল করুন। এই ফাংশনের শেষের দিকে আপনি ধাপ ৭ এবং ধাপ ৮ দেখতে পাবেন, যা যথাক্রমে রিটার্ন করা ইটারেশন সহ অথবা কোনো ইটারেশন ছাড়াই ইমেজ তৈরি করতে ব্যবহৃত হবে। যেহেতু এই দুটি অপারেশনই সিনক্রোনাসভাবে ঘটে, আপনি লক্ষ্য করবেন যে এগুলো একটি কো-রুটিনের মধ্যে মোড়ানো আছে। আপনি // ধাপ ৭ - ইটারেশন না দেখিয়ে জেনারেট করুন-এর জায়গায় এই কোড ব্লকটি প্রতিস্থাপন করে ImageGenerationHelper ফাইল থেকে generate() কল করতে এবং তারপর UI স্টেট আপডেট করতে পারেন।

// Step 7 - Generate without showing iterations
val result = helper?.generate(prompt, iteration, seed)
_uiState.update {
    it.copy(outputBitmap = result)
}

ধাপ ৮ একটু বেশি জটিল। যেহেতু execute() ফাংশনটি ইমেজ তৈরির সমস্ত ধাপের পরিবর্তে শুধুমাত্র একটি ধাপ সম্পাদন করে, তাই আপনাকে একটি লুপের মাধ্যমে প্রতিটি ধাপ আলাদাভাবে কল করতে হবে। বর্তমান ধাপটি ব্যবহারকারীর জন্য প্রদর্শিত হবে কিনা, তাও আপনাকে নির্ধারণ করতে হবে। সবশেষে, বর্তমান ইটারেশনটি প্রদর্শিত হওয়ার প্রয়োজন হলে আপনাকে UI স্টেট আপডেট করতে হবে। আপনি এই সবকিছু এখনই করতে পারেন।

// Step 8 - Generate with showing iterations
helper?.setInput(prompt, iteration, seed)
for (step in 0 until iteration) {
    isDisplayStep =
        (displayIteration > 0 && ((step + 1) % displayIteration == 0))
    val result = helper?.execute(isDisplayStep)

    if (isDisplayStep) {
        _uiState.update {
            it.copy(
                outputBitmap = result,
                generatingMessage = "Generating... (${step + 1}/$iteration)",
            )
        }
    }
}

এই পর্যায়ে আপনি আপনার অ্যাপটি ইনস্টল করতে, ইমেজ জেনারেটরটি চালু করতে এবং তারপরে একটি টেক্সট প্রম্পটের উপর ভিত্তি করে একটি নতুন ছবি তৈরি করতে সক্ষম হবেন

...কিন্তু এখন ইমেজ জেনারেটর চালু করার চেষ্টা করলে অ্যাপটি ক্র্যাশ করছে। এর কারণ হলো, আপনাকে আপনার মডেল ফাইলগুলো ডিভাইসে কপি করতে হবে। যেসব থার্ড-পার্টি মডেল কাজ করে বলে জানা আছে, সেগুলোকে এই MediaPipe টাস্কের জন্য রূপান্তর করা এবং আপনার ডিভাইসে কপি করার বিষয়ে সবচেয়ে হালনাগাদ তথ্য পেতে, আপনি অফিসিয়াল ডকুমেন্টেশনের এই অংশটি পর্যালোচনা করতে পারেন।

আপনার ডেভেলপমেন্ট ডিভাইসে সরাসরি ফাইল কপি করার পাশাপাশি, রান টাইমে প্রয়োজনীয় ফাইলগুলো সরাসরি ব্যবহারকারীর ডিভাইসে ডাউনলোড করার জন্য ফায়ারবেস স্টোরেজ সেট আপ করাও সম্ভব।

৫. অ্যাপটি স্থাপন ও পরীক্ষা করুন

এই সবকিছুর পরে, আপনার কাছে এমন একটি কার্যকরী অ্যাপ থাকা উচিত যা টেক্সট প্রম্পট গ্রহণ করতে পারে এবং সম্পূর্ণরূপে ডিভাইসের মধ্যেই নতুন ছবি তৈরি করতে পারে! এটি পরীক্ষা করার জন্য অ্যাপটি একটি বাস্তব অ্যান্ড্রয়েড ডিভাইসে স্থাপন করুন, তবে মনে রাখবেন যে এটি করার জন্য আপনার কমপক্ষে ৮ জিবি মেমরিযুক্ত একটি ডিভাইস প্রয়োজন হবে।

  1. রান-এ ক্লিক করুন ( 7e15a9c9e1620fe7.png অ্যাপটি চালানোর জন্য অ্যান্ড্রয়েড স্টুডিও টুলবারে থাকা আইকনটি চাপুন।
  2. জেনারেশন ধাপের ধরন (চূড়ান্ত অথবা পুনরাবৃত্তিসহ) নির্বাচন করুন এবং তারপর ইনিশিয়ালাইজ বোতামটি চাপুন।
  3. পরবর্তী স্ক্রিনে, আপনার পছন্দসই বৈশিষ্ট্যগুলো সেট করুন এবং টুলটি কী ফলাফল দেয় তা দেখতে GENERATE বোতামে ক্লিক করুন।

e46cfaeb9d3fc235.gif

৬. অভিনন্দন!

আপনি পেরেছেন! এই কোডল্যাবে আপনি শিখেছেন কিভাবে একটি অ্যান্ড্রয়েড অ্যাপে ডিভাইসেই টেক্সট থেকে ছবি তৈরির সুবিধা যোগ করতে হয়।

পরবর্তী পদক্ষেপ

ইমেজ জেনারেশন টাস্কের সাথে আরও অনেক কিছু করা যায়, যার মধ্যে রয়েছে

  • একটি ভিত্তি চিত্র ব্যবহার করে প্লাগইনের মাধ্যমে তৈরি করা চিত্রগুলির কাঠামো তৈরি করুন, অথবা Vertex AI-এর মাধ্যমে আপনার নিজস্ব অতিরিক্ত LoRA ওয়েটগুলিকে প্রশিক্ষণ দিন।
  • ADB টুল ব্যবহার না করেই আপনার ডিভাইস থেকে মডেল ফাইলগুলো পুনরুদ্ধার করতে Firebase Storage ব্যবহার করুন।

এই পরীক্ষামূলক কাজটি দিয়ে আপনারা যে সব চমৎকার জিনিস তৈরি করবেন তা দেখার জন্য আমরা অধীর আগ্রহে অপেক্ষা করছি, এবং মিডিয়াপাইপ টিমের পক্ষ থেকে আরও কোডল্যাব ও কন্টেন্টের জন্য চোখ রাখুন!