التعرف على النصوص من خلال مكتبة الفايربيز - ML Kit

درس جديد من سلسلة دروس الفايربيز و بالتحديد فرع MLkit و  اليوم لنا موعد مع خاصية تحديد النصوص  من خلال الجهاز لا من خلال الكلاود و لتفهم محتوى هذه التدوينة خد فكرة عامة عن الموضوع في تدوينة سابقة لنا  سلسلة دروس شرح مكتبة ML Kit  حسنا الان انت مستعد لتجربة هذه الخاصية الرائعة و الفعالة حسنا لا احب اعادة المواضيع لان سبق و نُشرت تذوينة في عالم برو  لكن ساحاول انا توفير هذا الدرس بالكوتلن .

التعرف على النصوص من خلال مكتبة الفايربيز

الصفر  : المشروع موجود على github .

اولا  : نظرة عامة عن الخاصية ←
حسنا مع هذه الخاصية سيستطيع هاتفك تحديد النصوص الاتنية اما ان استخدمت الكلاود فسيستطيع تحديد عدد لا باس به من اللغات من خلال كاميرا هاتفك فقط حقا خاصية رهيبة اذا كنت تريد تجربتها فهي موجودة google photo او المساعد الصوتي لاندرويد و ايضا مع مترجم جوجل و لان لنبدا .

ثانيا : اضافة الخاصية الى مشروعك ←
  1-يجب عليك ربط  التطبيق بالفايربيز .
   2-اضف الكود التالي الى ملف build.gradle ↓
implementation 'com.google.firebase:firebase-ml-vision:16.0.0'
     3-نقوم باضافة الكود التالي الى ملف Manifest
<meta-data android:name="com.google.firebase.ml.vision.DEPENDENCIES" android:value="text"/>
  دور هذا الكود هو تحميل الملفات التي يحتاجها تطبيقك اثناء التنصيب كي لا تحدث معك اي مشكلة .اما ان لم تضفه فلا مشكلة فسيتم تحميل الملفات المرغوب فيها عند اول تشغيل لتطبيقك على هاتف المستخدم لكن لا ينصح بهذا .
4-اضف الكود التالي الى ملف manifest ان كنت ستستخدم الكاميرا↓

<manifest ..>
...
    <uses-permission android:name="android.permission.CAMERA" />
    <uses-feature android:name="android.hardware.camera" />

</manifest>
وفي حال واجهة مشكلة اضف الكود التالي الى ملف build.gradle ↓

 build.gradle -> Project

    repositories {
        //...
        maven { url 'https://jitpack.io' }
    }

ثالثا : الواجهة ←
الواجهة القبيحة كما العادة يمكنك تعديلها :


<?xml version="1.0" encoding="utf-8"?>
<android.support.design.widget.CoordinatorLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:background="#efefef">

    <android.support.design.widget.AppBarLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:theme="@style/ThemeOverlay.AppCompat.Dark.ActionBar">

        <android.support.v7.widget.Toolbar
            android:id="@+id/toolbar"
            android:layout_width="match_parent"
            android:layout_height="?attr/actionBarSize"
            android:background="?attr/colorPrimary"
            app:popupTheme="@style/ThemeOverlay.AppCompat.Light"/>

    </android.support.design.widget.AppBarLayout>

    <io.fotoapparat.view.CameraView
        android:id="@+id/camera_view"
        android:layout_width="match_parent"
        android:layout_height="match_parent"/>

    <!-- Adding bottom sheet after main content -->
    <include layout="@layout/bottom_sheet" />
    <android.support.design.widget.FloatingActionButton
        android:id="@+id/takePic"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        app:layout_anchor="@+id/bottom_sheet"
        app:srcCompat="@drawable/ic_camera"
        android:layout_margin="10dp"
        app:fabSize="normal"
        app:layout_anchorGravity="top|start" />
    <android.support.design.widget.FloatingActionButton
        android:id="@+id/fromDevice"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        app:layout_anchor="@+id/bottom_sheet"
        app:srcCompat="@drawable/ic_upload"
        android:layout_margin="10dp"
        app:fabSize="normal"
        app:layout_anchorGravity="top|center" />

</android.support.design.widget.CoordinatorLayout>

نضيف الان الواجهة السفلية :
bottom_sheet.xml

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    android:id="@+id/bottom_sheet"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:minHeight="100dp"
    android:background="#fff"
    android:orientation="vertical"
    app:behavior_hideable="false"
    app:behavior_peekHeight="56dp"
    app:layout_behavior="android.support.design.widget.BottomSheetBehavior">
    <TextView
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:text="@string/pic"
        android:textColor="#444"
        android:textSize="18dp"
        android:textStyle="bold"/>
    <ImageView
        android:id="@+id/mImage"
        android:layout_width="match_parent"
        android:layout_height="300dp"
        android:contentDescription="@string/app_name"
        android:visibility="gone"/>
    <TextView
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:text="@string/text"
        android:textColor="#444"
        android:textSize="18dp"
        android:textStyle="bold" />
<TextView
    android:id="@+id/mtextRec"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:layout_marginBottom="10dp"/>
   
</LinearLayout>


رابعا : الحصول على النصوص من الصورة ←
لكي تعمل لديك الكاميرا لابد من الحصول على اذن المستخدم من اصدار الولي بوب 5
1-بما ان api الكاميرا في الاندرويد كانه برمج في اخر الشارع لذا فانا ساستعمل هذه المكتبة fotoapparat .
2- اضافة كود اخد الاذن للوصول للكاميرا اليك الطريقة .
3-الان يمكنك الموت بسلام او اضافة الكود :

class textRec:AppCompatActivity() {
 lateinit var sheetBehavior:BottomSheetBehavior<View>

 override fun onCreate(savedInstanceState: Bundle?) {
  super.onCreate(savedInstanceState)
  setContentView(R.layout.image_labeling)
  setSupportActionBar(toolbar)
  sheetBehavior = BottomSheetBehavior.from(bottom_sheet)
  val fotoapparat = Fotoapparat(context = this, view = camera_view)
  fotoapparat.start()
  //اخد صورة 
  //يمكنك عدم استخدمها
  takePic.setOnClickListener {
   val photoResult =fotoapparat.takePicture()
   photoResult
     .toBitmap()
     .whenAvailable { bitmapPhoto ->
      getLabelsFromDevice(bitmapPhoto!!.bitmap)
     }
  }
  //اخد الصورة من الهاتف
  fromDevice.setOnClickListener {
   val photoPickerIntent = Intent(Intent.ACTION_GET_CONTENT)
   photoPickerIntent.type = "image/*"
   startActivityForResult(photoPickerIntent, 1)
  }
 }

 private fun getLabelsFromDevice(bitmap: Bitmap) {
  //الحصول على الصورة
  val image : FirebaseVisionImage = FirebaseVisionImage.fromBitmap(bitmap)
  val detector = FirebaseVision.getInstance().visionTextDetector
  detector.detectInImage(image)
    .addOnSuccessListener {
     var text=""
     for (block in it.blocks) {
      text += block.text
      
     }
     mtextRec.text=text
     mImage.setImageBitmap(bitmap)
     mImage.visibility=View.VISIBLE
    }
    .addOnFailureListener {
     // خطا ما وقع
     Toast.makeText(baseContext,"Sorry, something went wrong!", Toast.LENGTH_SHORT).show()
    }
 }

 override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent) {
  super.onActivityResult(requestCode, resultCode, data)
  if (resultCode == RESULT_OK) {
   val chosenImageUri = data.data
   try {
    val mBitmap= MediaStore.Images.Media.getBitmap(this.contentResolver, chosenImageUri)
    getLabelsFromDevice(mBitmap)
   } catch (e: IOException) {
    e.printStackTrace()
   }
  }
 }
}


النتيجة←
مكتبة ML Kit للتعرف على النصوص مكتبة ML Kit للتعرف على النصوص



و الان ماذا ان كنا نريد مثلا تحديد نص معين او سطر معين او حتى كلمة معينة في فاتورة مثلا لمعرفة مجموع الاثمان .
صورة توضح اقسام تحديد النصوص Ml Kit
صورة توضح اقسام تحديد النصوص

سنضيف دالة ترسم اطارات على المناطق المحددة البلوك بالاحمر و السطر بالاسود و الكلمات بالابيض
نسميها دالة getpaint وقد اخدتها من موقع عالم برو لانها فكرة رائعة:

//ماخود من موقع عالم برو بتصرف
 private fun getPaint(color:Int,width:Float=1f): Paint {
  val p = Paint()
  p.style = Paint.Style.STROKE
  p.strokeWidth = width
  p.isAntiAlias = true
  p.isFilterBitmap = true
  p.isDither = true
  p.color = color
  return p
 }


حسنا في كل منطقة يوجد فيها نص فهو يسمى بلوك  و كل سطر يسمى Line و كل كلمة تسمى element لنرى هذا في الكود فسنغير بعض الاشياء في دالة ()recognizeText ←

private fun recognizeText(bitmap: Bitmap) {
  //تحويل بيتماب الى بيتماب قابل للتعديل
  val mBitmap = bitmap.copy(Bitmap.Config.ARGB_8888, true)
  val canvas = Canvas(mBitmap)
  //الحصول على الكود
  val image : FirebaseVisionImage = FirebaseVisionImage.fromBitmap(bitmap)
  val detector = FirebaseVision.getInstance().visionTextDetector
  detector.detectInImage(image)
    .addOnSuccessListener {
     // انتهى بنجاح
     val redPaint=getPaint(Color.RED,20f)
     val bluePaint=getPaint(Color.BLACK,12f)
     val greenPaint=getPaint(Color.WHITE,5f)
     var text=""
     //تجلب البلوكس
     for (block in it.blocks) {
      //احدثيات النص
      val boundingBox = block.boundingBox
      canvas.drawRect(boundingBox, redPaint)
      text += block.text
      //تجلب الاسطر داخل كل بلوك
      for (line in block.lines) {
       canvas.drawRect(line.boundingBox, bluePaint)
       //تجلب العناصر او الكلمات داخل كل سطر
       for (element in line.elements) {
        canvas.drawRect(element.boundingBox, greenPaint)
       }
      }
     }
     mtextRec.text=text
     mImage.setImageBitmap(mBitmap)
     mImage.visibility=View.VISIBLE
    }
    .addOnFailureListener {
     // خطا ما وقع
     Toast.makeText(baseContext,"Sorry, something went wrong!", Toast.LENGTH_SHORT).show()
    }
 }




النتيجة←
التعرف على النصوص من خلال مكتبة الفايربيز التعرف على النصوص من خلال مكتبة الفايربيز

اتمنى ان تعجبك هذه التدوينة من سلسلة شرح الفايربيز و لكن للاسف التعرف على النصوص على الجهاز لا يدعم اللغة العربية لكن يمكنك استعمال الكلاود ل 1000 مرة كل شهر مجانا  و هو يدعم اللغة العربية سلسلة الكلاود قادمة باذن واحد احد
اترككم مع المصادر :
عربي


هل ترغب في مثل هذه التدوينات

اسماعيل ايت بلا

ببساطة ارغب في تجربة جديدة من التعلم من خلال مشاركة ما تعلمه يجبرني ذلك على البحث لمدة طويلة مما يجعل الموقع جديرا بالثقة

اترك لنا تعليقا

الاشتراك بالقائمة البريدية

توصل باحدث مواضيعنا و كن على اطلاع باخر اخبار وتقنيات الاندرويد