1. ভূমিকা
মিডিয়াপাইপ কি?
MediaPipe সলিউশন আপনাকে আপনার অ্যাপে মেশিন-লার্নিং (ML) সমাধান প্রয়োগ করতে দেয়। এটি পূর্বনির্মাণ প্রক্রিয়াকরণ পাইপলাইনগুলি কনফিগার করার জন্য একটি কাঠামো প্রদান করে যা ব্যবহারকারীদের কাছে অবিলম্বে, আকর্ষক এবং দরকারী আউটপুট সরবরাহ করে। এমনকি আপনি ডিফল্ট মডেল আপডেট করতে MediaPipe মডেল মেকারের সাথে এই সমাধানগুলি কাস্টমাইজ করতে পারেন।
ছবি শ্রেণীবিভাগ হল মিডিয়াপাইপ সলিউশনের অফার করা বেশ কয়েকটি এমএল ভিশন টাস্কের মধ্যে একটি। মিডিয়াপাইপ টাস্ক অ্যান্ড্রয়েড, আইওএস, পাইথন (রাস্পবেরি পাই সহ!), এবং ওয়েবের জন্য উপলব্ধ।
এই কোডল্যাবে, আপনি একটি অ্যান্ড্রয়েড অ্যাপ দিয়ে শুরু করবেন যা আপনাকে স্ক্রিনে সংখ্যাসূচক অঙ্কগুলি আঁকতে দেয়, তারপরে আপনি কার্যকারিতা যোগ করবেন যা সেই অঙ্কনগুলিকে 0 থেকে 9 পর্যন্ত একক মান হিসাবে শ্রেণীবদ্ধ করে৷
আপনি কি শিখবেন
- মিডিয়াপাইপ টাস্ক সহ একটি অ্যান্ড্রয়েড অ্যাপে কীভাবে একটি চিত্র শ্রেণিবিন্যাসের কাজ অন্তর্ভুক্ত করবেন।
আপনি কি প্রয়োজন হবে
- অ্যান্ড্রয়েড স্টুডিওর একটি ইনস্টল করা সংস্করণ (এই কোডল্যাবটি অ্যান্ড্রয়েড স্টুডিও জিরাফের সাথে লেখা এবং পরীক্ষা করা হয়েছিল)।
- অ্যাপ চালানোর জন্য একটি অ্যান্ড্রয়েড ডিভাইস বা এমুলেটর।
- অ্যান্ড্রয়েড বিকাশের প্রাথমিক জ্ঞান (এটি "হ্যালো ওয়ার্ল্ড" নয়, তবে এটি খুব বেশি দূরে নয়!)
2. Android অ্যাপে MediaPipe টাস্ক যোগ করুন
অ্যান্ড্রয়েড স্টার্টার অ্যাপটি ডাউনলোড করুন
এই কোডল্যাবটি একটি প্রাক-তৈরি নমুনা দিয়ে শুরু হবে যা আপনাকে স্ক্রিনে আঁকতে দেয়। আপনি এখানে অফিসিয়াল MediaPipe স্যাম্পল রেপোতে সেই প্রারম্ভিক অ্যাপটি খুঁজে পেতে পারেন। রেপো ক্লোন করুন বা কোড > জিপ ডাউনলোড করুন ক্লিক করে জিপফাইলটি ডাউনলোড করুন।
অ্যাপটি অ্যান্ড্রয়েড স্টুডিওতে আমদানি করুন
- অ্যান্ড্রয়েড স্টুডিও খুলুন।
- ওয়েলকাম টু অ্যান্ড্রয়েড স্টুডিও স্ক্রীন থেকে, উপরের ডানদিকে কোণায় খুলুন নির্বাচন করুন।
- আপনি যেখানে সংগ্রহস্থলটি ক্লোন করেছেন বা ডাউনলোড করেছেন সেখানে নেভিগেট করুন এবং কোডল্যাবস/ডিজিটক্ল্যাসিফায়ার/অ্যান্ড্রয়েড/স্টার্ট ডিরেক্টরি খুলুন।
- সবুজ রান তীরটিতে ক্লিক করে সবকিছু সঠিকভাবে খোলা হয়েছে কিনা তা যাচাই করুন ( ) অ্যান্ড্রয়েড স্টুডিওর উপরের ডানদিকে
- আপনি একটি কালো স্ক্রীনের সাথে অ্যাপটি খুলতে দেখতে পাবেন যা আপনি আঁকতে পারেন, সেইসাথে সেই স্ক্রীনটি পুনরায় সেট করার জন্য একটি ক্লিয়ার বোতাম। আপনি যখন সেই স্ক্রীনে আঁকতে পারেন, এটি আর বেশি কিছু করে না, তাই আমরা এখন এটি ঠিক করা শুরু করব।
মডেল
আপনি যখন প্রথম অ্যাপটি চালান, তখন আপনি লক্ষ্য করতে পারেন যে mnist.tflite নামে একটি ফাইল ডাউনলোড করা হয়েছে এবং আপনার অ্যাপের সম্পদ ডিরেক্টরিতে সংরক্ষণ করা হয়েছে। সরলতার স্বার্থে, আমরা ইতিমধ্যেই একটি পরিচিত মডেল, MNIST নিয়েছি, যা অঙ্কগুলিকে শ্রেণীবদ্ধ করে এবং প্রকল্পে download_models.gradle স্ক্রিপ্ট ব্যবহারের মাধ্যমে অ্যাপে যুক্ত করেছি৷ আপনি যদি নিজের কাস্টম মডেলকে প্রশিক্ষণ দেওয়ার সিদ্ধান্ত নেন, যেমন হাতে লেখা অক্ষরের জন্য একটি, তাহলে আপনি download_models.gradle ফাইলটি সরিয়ে ফেলবেন, আপনার অ্যাপ স্তরের build.gradle ফাইলে এটির রেফারেন্স মুছে ফেলবেন এবং পরে মডেলটির নাম পরিবর্তন করবেন কোড (বিশেষ করে DigitClassifierHelper.kt ফাইলে)।
build.gradle আপডেট করুন
আপনি MediaPipe টাস্ক ব্যবহার শুরু করার আগে, আপনাকে লাইব্রেরি আমদানি করতে হবে।
- আপনার অ্যাপ মডিউলে অবস্থিত build.gradle ফাইলটি খুলুন, তারপর নির্ভরতা ব্লকে স্ক্রোল করুন।
- আপনি সেই ব্লকের নীচে একটি মন্তব্য দেখতে পাবেন যা বলে // STEP 1 নির্ভরতা আমদানি ।
- নিম্নলিখিত বাস্তবায়নের সাথে সেই লাইনটি প্রতিস্থাপন করুন
implementation("com.google.mediapipe:tasks-vision:latest.release")
- এই নির্ভরতা ডাউনলোড করতে অ্যান্ড্রয়েড স্টুডিওর শীর্ষে ব্যানারে প্রদর্শিত সিঙ্ক নাও বোতামটিতে ক্লিক করুন৷
3. একটি MediaPipe টাস্ক ডিজিট ক্লাসিফায়ার সাহায্যকারী তৈরি করুন৷
পরবর্তী ধাপের জন্য আপনি একটি ক্লাস পূরণ করবেন যা আপনার মেশিন লার্নিং শ্রেণীবিভাগের জন্য ভারী উত্তোলন করবে। DigitClassifierHelper.kt খুলুন এবং শুরু করা যাক!
- ক্লাসের শীর্ষে মন্তব্যটি খুঁজুন যা বলে // STEP 2 শ্রোতা তৈরি করুন
- নিম্নলিখিত কোড দিয়ে সেই লাইনটি প্রতিস্থাপন করুন। এটি একটি শ্রোতা তৈরি করবে যা DigitClassifierHelper ক্লাস থেকে ফলাফলগুলি যেখানেই শুনছে সেখানে ফিরে যেতে ব্যবহার করা হবে (এই ক্ষেত্রে এটি হবে আপনার DigitCanvasFragment ক্লাস, কিন্তু আমরা শীঘ্রই সেখানে পৌঁছব)
// STEP 2 Create listener
interface DigitClassifierListener {
fun onError(error: String)
fun onResults(
results: ImageClassifierResult,
inferenceTime: Long
)
}
- আপনাকে ক্লাসের জন্য একটি ঐচ্ছিক পরামিতি হিসাবে একটি DigitClassifierListener গ্রহণ করতে হবে:
class DigitClassifierHelper(
val context: Context,
val digitClassifierListener: DigitClassifierListener?
) {
- নিচের লাইনে গিয়ে // STEP 3 define classifier , এই অ্যাপের জন্য ব্যবহার করা ImageClassifier-এর জন্য একটি স্থানধারক তৈরি করতে নিম্নলিখিত লাইনটি যোগ করুন:
// ধাপ 3 ক্লাসিফায়ার সংজ্ঞায়িত করুন
private var digitClassifier: ImageClassifier? = null
- নিম্নলিখিত ফাংশন যোগ করুন যেখানে আপনি মন্তব্য দেখতে পাবেন // স্টেপ 4 সেট আপ ক্লাসিফায়ার :
// STEP 4 set up classifier
private fun setupDigitClassifier() {
val baseOptionsBuilder = BaseOptions.builder()
.setModelAssetPath("mnist.tflite")
// Describe additional options
val optionsBuilder = ImageClassifierOptions.builder()
.setRunningMode(RunningMode.IMAGE)
.setBaseOptions(baseOptionsBuilder.build())
try {
digitClassifier =
ImageClassifier.createFromOptions(
context,
optionsBuilder.build()
)
} catch (e: IllegalStateException) {
digitClassifierListener?.onError(
"Image classifier failed to initialize. See error logs for " +
"details"
)
Log.e(TAG, "MediaPipe failed to load model with error: " + e.message)
}
}
উপরের বিভাগে কিছু জিনিস চলছে, তাই আসলে কী ঘটছে তা বোঝার জন্য আসুন ছোট অংশগুলি দেখি।
val baseOptionsBuilder = BaseOptions.builder()
.setModelAssetPath("mnist.tflite")
// Describe additional options
val optionsBuilder = ImageClassifierOptions.builder()
.setRunningMode(RunningMode.IMAGE)
.setBaseOptions(baseOptionsBuilder.build())
এই ব্লকটি ImageClassifier দ্বারা ব্যবহৃত পরামিতিগুলিকে সংজ্ঞায়িত করবে। এর মধ্যে রয়েছে বেসঅপশনের অধীনে আপনার অ্যাপের ( mnist.tflite ) মধ্যে সংরক্ষিত মডেল এবং ImageClassifierOptions-এর অধীনে RunningMode, যা এই ক্ষেত্রে IMAGE, কিন্তু VIDEO এবং LIVE_STREAM হল অতিরিক্ত উপলব্ধ বিকল্প৷ অন্যান্য উপলব্ধ প্যারামিটারগুলি হল MaxResults, যা মডেলটিকে সর্বাধিক সংখ্যক ফলাফল ফেরাতে সীমাবদ্ধ করে এবং স্কোরথ্রেশহোল্ড, যা ফলাফলটি ফেরত দেওয়ার আগে মডেলটির ন্যূনতম আত্মবিশ্বাস সেট করে।
try {
digitClassifier =
ImageClassifier.createFromOptions(
context,
optionsBuilder.build()
)
} catch (e: IllegalStateException) {
digitClassifierListener?.onError(
"Image classifier failed to initialize. See error logs for " +
"details"
)
Log.e(TAG, "MediaPipe failed to load model with error: " + e.message)
}
আপনার কনফিগারেশন বিকল্পগুলি তৈরি করার পরে, আপনি একটি প্রসঙ্গ এবং বিকল্পগুলি পাস করে আপনার নতুন ইমেজক্ল্যাসিফায়ার তৈরি করতে পারেন। যদি সেই প্রারম্ভিক প্রক্রিয়ার সাথে কিছু ভুল হয়ে যায়, আপনার DigitClassifierListener এর মাধ্যমে একটি ত্রুটি ফেরত দেওয়া হবে।
- যেহেতু আমরা ইমেজক্ল্যাসিফায়ার ব্যবহার করার আগে এটিকে আরম্ভ করতে চাই, আপনি সেটআপডিজিটক্ল্যাসিফায়ার() কল করতে একটি ইনিট ব্লক যোগ করতে পারেন।
init {
setupDigitClassifier()
}
- সবশেষে, নিচের কমেন্টে স্ক্রোল করুন যা বলে // STEP 5 create classify function এবং নিম্নলিখিত কোড যোগ করুন। এই ফাংশনটি একটি বিটম্যাপ গ্রহণ করবে, যেটি এই ক্ষেত্রে অঙ্কিত অঙ্ক, এটিকে মিডিয়াপাইপ ইমেজ অবজেক্টে রূপান্তরিত করবে (MPImage), এবং তারপর সেই ছবিকে ImageClassifier ব্যবহার করে শ্রেণীবদ্ধ করবে, সেইসাথে সেই ফলাফলগুলি ফেরত দেওয়ার আগে কতক্ষণ অনুমান লাগে তা রেকর্ড করবে। DigitClassifier Listener.
// STEP 5 create classify function
fun classify(image: Bitmap) {
if (digitClassifier == null) {
setupDigitClassifier()
}
// Convert the input Bitmap object to an MPImage object to run inference.
// Rotating shouldn't be necessary because the text is being extracted from
// a view that should always be correctly positioned.
val mpImage = BitmapImageBuilder(image).build()
// Inference time is the difference between the system time at the start and finish of the
// process
val startTime = SystemClock.uptimeMillis()
// Run image classification using MediaPipe Image Classifier API
digitClassifier?.classify(mpImage)?.also { classificationResults ->
val inferenceTimeMs = SystemClock.uptimeMillis() - startTime
digitClassifierListener?.onResults(classificationResults, inferenceTimeMs)
}
}
এবং এটি সাহায্যকারী ফাইলের জন্য! পরবর্তী বিভাগে আপনি আপনার অঙ্কিত সংখ্যা শ্রেণীবিভাগ শুরু করার জন্য চূড়ান্ত পদক্ষেপগুলি পূরণ করবেন।
4. মিডিয়াপাইপ টাস্কগুলির সাথে অনুমান চালান৷
আপনি অ্যান্ড্রয়েড স্টুডিওতে DigitCanvasFragment ক্লাস খোলার মাধ্যমে এই বিভাগটি শুরু করতে পারেন, যেখানে সমস্ত কাজ হবে।
- এই ফাইলের একেবারে নীচে আপনি একটি মন্তব্য দেখতে পাবেন যা বলে // STEP 6 শ্রোতা সেট আপ করুন ৷ আপনি এখানে শ্রোতার সাথে যুক্ত onResults() এবং onError() ফাংশন যোগ করবেন।
// STEP 6 Set up listener
override fun onError(error: String) {
activity?.runOnUiThread {
Toast.makeText(requireActivity(), error, Toast.LENGTH_SHORT).show()
fragmentDigitCanvasBinding.tvResults.text = ""
}
}
override fun onResults(
results: ImageClassifierResult,
inferenceTime: Long
) {
activity?.runOnUiThread {
fragmentDigitCanvasBinding.tvResults.text = results
.classificationResult()
.classifications().get(0)
.categories().get(0)
.categoryName()
fragmentDigitCanvasBinding.tvInferenceTime.text = requireActivity()
.getString(R.string.inference_time, inferenceTime.toString())
}
}
onResults() বিশেষভাবে গুরুত্বপূর্ণ কারণ এটি ImageClassifier থেকে প্রাপ্ত ফলাফল প্রদর্শন করবে। যেহেতু এই কলব্যাকটি একটি ব্যাকগ্রাউন্ড থ্রেড থেকে ট্রিগার হয়েছে, তাই আপনাকে Android এর UI থ্রেডে আপনার UI আপডেটগুলি চালাতে হবে৷
- আপনি উপরের ধাপে একটি ইন্টারফেস থেকে নতুন ফাংশন যোগ করছেন, আপনাকে ক্লাসের শীর্ষে বাস্তবায়ন ঘোষণা যোগ করতে হবে।
class DigitCanvasFragment : Fragment(), DigitClassifierHelper.DigitClassifierListener
- ক্লাসের শীর্ষের দিকে আপনি একটি মন্তব্য দেখতে পাবেন যা বলে // STEP 7a প্রাথমিক শ্রেণিবদ্ধকারী । এখানে আপনি DigitClassifierHelper-এর জন্য ঘোষণা দেবেন।
// STEP 7a Initialize classifier.
private lateinit var digitClassifierHelper: DigitClassifierHelper
- // STEP 7b ইনিশিয়ালাইজ ক্লাসিফায়ারে গিয়ে, আপনি onViewCreated() ফাংশনের মধ্যে digitClassifierHelper শুরু করতে পারেন।
// STEP 7b Initialize classifier
// Initialize the digit classifier helper, which does all of the
// ML work. This uses the default values for the classifier.
digitClassifierHelper = DigitClassifierHelper(
context = requireContext(), digitClassifierListener = this
)
- শেষ ধাপের জন্য, মন্তব্যটি খুঁজুন // STEP 8a *: classify* এবং একটি নতুন ফাংশন কল করতে নিম্নলিখিত কোডটি যোগ করুন যা আপনি কিছুক্ষণের মধ্যে যোগ করবেন। আপনি যখন অ্যাপে অঙ্কন এলাকা থেকে আপনার আঙুল তুলবেন তখন এই কোড ব্লকটি শ্রেণিবিন্যাস শুরু করবে।
// STEP 8a: classify
classifyDrawing()
- সবশেষে, নতুন classifyDrawing() ফাংশন যোগ করতে মন্তব্য // STEP 8b শ্রেণীবিভাগ দেখুন। এটি ক্যানভাস থেকে একটি বিটম্যাপ বের করবে, তারপর onResults() ইন্টারফেস ফাংশনে ফলাফল পাওয়ার জন্য শ্রেণিবিন্যাস সম্পাদন করতে DigitClassifierHelper-এ পাস করবে।
// STEP 8b classify
private fun classifyDrawing() {
val bitmap = fragmentDigitCanvasBinding.digitCanvas.getBitmap()
digitClassifierHelper.classify(bitmap)
}
5. অ্যাপটি স্থাপন এবং পরীক্ষা করুন
এত কিছুর পরে, আপনার একটি কার্যকরী অ্যাপ থাকা উচিত যা স্ক্রিনে আঁকা অঙ্কগুলিকে শ্রেণীবদ্ধ করতে পারে! এগিয়ে যান এবং এটি পরীক্ষা করার জন্য একটি Android এমুলেটর বা একটি শারীরিক Android ডিভাইসে অ্যাপটি স্থাপন করুন।
- রান ক্লিক করুন ( ) অ্যাপটি চালানোর জন্য অ্যান্ড্রয়েড স্টুডিও টুলবারে।
- ড্রয়িং প্যাডে যেকোনো ডিজিট আঁকুন এবং অ্যাপটি চিনতে পারে কিনা দেখুন। এটি উভয়ই সেই অঙ্কটি প্রদর্শন করবে যা মডেলটি বিশ্বাস করে যে অঙ্কনটি আঁকা হয়েছে, সেইসাথে সেই অঙ্কটি ভবিষ্যদ্বাণী করতে কত সময় লেগেছে।
6. অভিনন্দন!
আপনি এটা করেছেন! এই কোডল্যাবে আপনি শিখেছেন কিভাবে একটি অ্যান্ড্রয়েড অ্যাপে ইমেজ শ্রেণীবিভাগ যোগ করতে হয় এবং বিশেষভাবে MNIST মডেল ব্যবহার করে হাতে আঁকা অঙ্কগুলিকে কীভাবে শ্রেণীবদ্ধ করতে হয়।
পরবর্তী পদক্ষেপ
- এখন আপনি অঙ্কগুলিকে শ্রেণীবদ্ধ করতে পারেন, আপনি আঁকা অক্ষরগুলিকে শ্রেণীবদ্ধ করতে, বা প্রাণীদের শ্রেণীবদ্ধ করতে বা অন্যান্য আইটেমগুলির একটি অবিরাম সংখ্যক শ্রেণীবদ্ধ করতে আপনার নিজের মডেলকে প্রশিক্ষণ দিতে চাইতে পারেন। আপনি developers.google.com/mediapipe পৃষ্ঠায় MediaPipe মডেল মেকারের সাথে একটি নতুন চিত্র শ্রেণীবিভাগের মডেল প্রশিক্ষণের জন্য ডকুমেন্টেশন খুঁজে পেতে পারেন৷
- ফেস ল্যান্ডমার্ক ডিটেকশন, জেসচার রিকগনিশন এবং অডিও ক্লাসিফিকেশন সহ Android এর জন্য উপলব্ধ অন্যান্য MediaPipe টাস্ক সম্পর্কে জানুন।
আমরা আপনার তৈরি করা দুর্দান্ত জিনিসগুলির জন্য অপেক্ষা করছি!