Firebase ML Kit ile Text Recognition

Firebase için ML Kit Duyurusu isimli makalemde, Google I/O 2018 etkinliğinde duyurulan ve mobil uygulamalara makine öğrenimi yeteneklerini kazandıran ML kiti hakkında sizlere temel bilgiler vermeye çalıştım. Bu yazıda ML kiti kullanarak uygulamaya yönelik bir proje geliştireceğiz. Amacımız, mobil uygulamamıza Text Recognition yani metin tanıma yeteneğini kazandırmaktır. Öncelikle Text Recognition hakkında bazı bilgiler vermek istiyorum.

Recognize Text yani metin tanıma işleminde amaç, herhangi bir resimde bulunan yazıları veya metinleri tanımayı sağlamaktır. ML kit ile bu işlemi yaparken makine öğrenimi hakkında temel bilgilere sahip olmanıza gerek yok. Çünkü bu kit arkaplanda geliştirilen modelleri kullanarak sizin yerinize metin tanıma işlemini yapmaktadır. ML kiti, cihazdaki veya buluttaki bir modeli kullanarak metin tanıma işlemini gerçekleştirir. Her iki yaklaşımın faydaları hakkında bilgi edinmek için aşağıda verilen tabloyu inceleyelim.

Yukarıda verilen tabloyu incelediğimizde, her iki yaklaşım arasındaki farkları daha iyi görebiliriz. On-device yaklaşımında metin tanıma işlemi yapılırken işlemlerin daha hızlı yapıldığını söyleyebiliriz. Cloud tarafında yapılan işlemler biraz daha zaman almaktadır. Yine basit metin tanıma işlemlerinde cihaz taraflı modelleri kullanmak daha isabetli bir karar olacaktır.

Android bir uygulamada metin tanıma işlemini yapmak için sırasıyla aşağıdaki adımları takip edeceğiz:

  1. Android Studio Ortamında Yeni Proje Oluşturmak
  2. Firebase Kullanımı
  3. CameraKit Kütüphanesini Projeye Eklemek
  4. Arayüz Tasarımı
  5. Cihaz Tabanlı Modeller ile Metin Algılama
  6. Bulut Tabanlı Modeller ile Metin Algılama
    1. Firebase Projesini Blaze Sürümüne Almak
    2. Cloud Vision API’nin Etkinleştirilmesi
    3. Kodlar
  7. Uygulamanın Test Edilmesi
  8. Kaynak Kodlarına Erişim

Android Studio Ortamında Yeni Proje Oluşturmak

Öncelikle Android Studio ortamını açalım ve yeni bir proje oluşturalım.

Yukarıda açılan pencerede uygulama ismini Text Recognition olarak girelim ve Next butonuna tıklayalım.

Uygulamanın API seviyesini 23 olarak seçelim ve Next butonuna tıklayalım.

Uygulama için ilk etkinliğimizi Empty Activity olarak belirleyelim ve Next butonuna tıklayalım.

Activity Name alanını MainActivity olarak girelim ve Finish butonuna tıklayalım. Bu işlemle birlikte projemizi oluşturmuş oluruz.

Firebase Kullanımı

Yapılması gereken bir diğer işlem Firebase Console ile Firebase projesi oluşturmaktır. Bunu mutlaka yapmamız gerekiyor. Aksi durumda Firebase ML kitini projemizde kullanamayız.

ML kitini oluşturmak için Firebase Console sayfasını açalım. Firebase bir Google hizmeti olduğu için Gmail hesabınızın olması gerekiyor. Sisteme giriş yaptıktan sonra aşağıdaki arayüz bizi karşılar.

Mavi alanda bulunan Proje ekle seçeneğine tıklayınız.

Proje adını giriniz ve ülke/bölge’yi Türkiye olarak değiştiriniz. Proje Oluştur seçeneğine tıklayınız.

Yukarıda görüleceği üzere projemiz hazırlanır. Devam diyerek Firebase proje alanına geçelim.

Amacımız Android uygulamasına metin tanıma yeteneği kazandırmaktır. Bunun için Android logosuna tıklayınız.

Açılan pencerede Android paket adını ilgili alana yapıştırınız. Uygulamanızın paket ismini AndroidManifest dosyasından alabilirsiniz.

Uygulamayı Kaydet diyerek devam edelim.

Yukarıda Firebase hizmetinden faydalanmak için projenize özel google-services.json  isimli bir dosya oluşturulur. Burada uygulamanızın paket ismi ve ihtiyacımız olan key ve id bilgileri bulunmaktadır. Bu dosyayı bilgisayarınıza indiriniz.

Android Studio ortamında bulunan projemize dönelim. Aşağıda görüleceği üzere Proje görünümünü Project olarak ayarlayalım ve indirdiğimiz json dosyasını aşağıda görülen alana yapıştıralım.

Dosyanın app klasöründe olduğundan emin olunuz. Bunu yaptıktan sonra yukarıda verdiğimiz Firebase sayfasındaki Devam butonuna tıklayalım.

Firebase sizlere yapmanız gereken diğer son ayarları listelemektedir. Android Studio ortamında bulunan projemizin görünümünü Android olarak değiştirelim.

Yukarıda işaretli olan build.gradle<project> isimli dosyamızı açalım ve aşağıdaki satırı dependencies  bloğuna ekleyelim.


dependencies {
  …
  classpath 'com.google.gms:google-services:3.2.0'
}

Daha sonra aşağıda gösterilen build.gradle<module> isimli aşağıdaki dosyamızı açalım.

Açılan dosyaya aşağıdaki satırları görüldüğü gibi ekleyelim.


dependencies {
  …
  implementation 'com.google.firebase:firebase-core:15.0.0'
  implementation 'com.google.firebase:firebase-ml-vision:15.0.0'
}
apply plugin: 'com.google.gms.google-services'

Bunları ekledikten sonra Build–>Rebuild ile projemizi yeniden oluşturup değişiklikleri projemize uygulayalım.

Tüm bu işlemleri yaptıktan sonra Firebase alanındaki pencereden devam ettiğimizde projemiz aşağıdaki gibi hazırlanmış olur.

CameraKit Kütüphanesini Projeye Eklemek

Uygulamanın amacı kameradan alınan bir resimde bulunan metinlerin tanınmasını sağlamaktır. Kamera kullanımı için ayrıca kod yazmamak adına açık kaynak olan ve kamera kullanımını sağlayan CameraKit kütüphanesini kullanacağız. Bu kütüphane oldukça kullanışlı olup ayrıca diğer projelerinizde de kullanabilir hatta destek vererek geliştirilmesini sağlayabilirsiniz.

Bu kütüphaneyi projenize kurmak için aşağıda gösterilen dosyayı açınız.

Açılan dosyaya aşağıdaki satırı ekleyelim.


dependencies {
  …
  compile 'com.wonderkiln:camerakit:0.13.1'
  …
}

Build–>Rebuild yolunu takip ederek kütüphaneyi projeye ekleyelim.

CameraKit kütüphanesini ekledikten sonra kodlarımıza geçebiliriz.

Uyarı: Burada cihaz ve bulut modellerini kullanarak metin algılama işlemlerini yapan temel kodlar hakkında bilgi vereceğim. Kodların tamamına erişmek için yazının sonunda vereceğim GitHub linkini kullanabilirsiniz. Kodların açıklamasına oradan da erişebilirsiniz.

Arayüz Tasarımı

Uygulama arayüzü için xml dosyamız aşağıdaki gibi olacaktır.


<xml version="1.0" encoding="utf-8"?>
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
 xmlns:tools="http://schemas.android.com/tools"
 android:layout_width="match_parent"
 android:layout_height="match_parent">

<com.wonderkiln.camerakit.CameraView
 android:id="@+id/cameraView"
 android:layout_width="match_parent"
 android:layout_height="match_parent" />

<!--GraphicOverlay sınıfı view olarak arayüze eklenir.
Metin algılama işlemlerinde yapacağımız çizimleri bu kontrol
üzerinde yapacağız.-->
<com.mas.textrecognition.GraphicOverlay
 android:id="@+id/graphicOverlay"
 android:layout_width="match_parent"
 android:layout_height="match_parent"
 android:layout_alignParentBottom="true"
 android:layout_alignParentLeft="true"
 android:layout_alignParentStart="true"
 android:layout_alignParentTop="true"/>

<Button
 android:id="@+id/btnOnDevice"
 android:layout_width="wrap_content"
 android:layout_height="wrap_content"
 android:layout_gravity="bottom"
 android:text="on Device"/>

<Button
 android:id="@+id/btnCloud"
 android:layout_width="wrap_content"
 android:layout_height="wrap_content"
 android:layout_gravity="right|bottom"
 android:text="on Cloud"/>

</FrameLayout>

Arayüze eklediğimiz CameraView kontrolü daha önce eklediğimiz CameraKit kütüphanesi ile gelen bir kontroldür. Bunu kullanarak kameranın önizlemesini izleyebiliriz. GraphicOverlay kontrolünü ise uygulama içinde View sınıfından türeterek oluşturduk. GraphicOverlay bir sınıf olup kodlara ve açıklamasına GitHub’tan erişebilirsiniz. İki butondan ilkini cihaz tabanlı, ikincisini ise bulut tabanlı metin algılama yapmak için ekledik.

Cihaz Tabanlı Modeller ile Metin Algılama

Cihaz tabanlı modelleri kullanarak metin algılama işlemini MainActivity isimli java dosyamızda yapacağız. Cihazda bulunan ML modelleri ile metin algılama için iki adet metot hazırladık. Bu metotlar ve görevleri şu şekildedir:

  • runTextRecognition: Alınan bitmap resimde, metin olup olmadığını kontrol eden metottur. Eğer resimde metin bulunuyorsa, elde edilen metinler FirebaseVisionText tipinde processTextRecognitionResult metoduna gönderilir.
  • processTextRecognitionResult: runTextRecognition metodundan gelen ve resimde tespit edilen metinleri ayrıştırıp ekranda göstermeyi sağlar.

Metotların kodları aşağıdaki gibidir.

runTextRecognition() Metodu


/*text recognition detector ile resimde bulunan 
metinlerin algılanması sağlanır.
Eğer resimde metin tespit edilirse, 
processTextRecognitionResult isimli metot çağrılır.*/
private void runTextRecognition(Bitmap bitmap) {

   /*Bitmap resimdeki metni algılamak için resimden,
   FirebaseVisionImage nesnesi oluşturmamız gerekiyor*/
   FirebaseVisionImage image = FirebaseVisionImage.fromBitmap(bitmap);

   /*FirebaseVisionTextDetector: Resimde bulunan karakterleri 
   tanımak için kullanılır.*/
   FirebaseVisionTextDetector detector = 
   FirebaseVision.getInstance().getVisionTextDetector();

   /*Aşağıdaki kod ile metinlerin algılanması işlemi icra edilir.*/
   detector.detectInImage(image).addOnSuccessListener(
   new OnSuccessListener&amp;amp;lt;FirebaseVisionText&amp;amp;gt;() {
       @Override
       public void onSuccess(FirebaseVisionText texts) {
       //Metin tespit edilirse,
       processTextRecognitionResult(texts);

       }
   }).addOnFailureListener(new OnFailureListener() {
       @Override
       public void onFailure(@NonNull Exception e) {
       //Metin tespit edilmediği zaman,
       e.printStackTrace();
       }
  });
}

 

processTextRecognitionResult() Metodu

/* On-device modellerini kullanarak resimde tespit 
edilen metinleri ayrıştırıp ekrana çizmeyi sağlar.*/
private void processTextRecognitionResult(FirebaseVisionText texts) {
  //getBlocks ile gelen metin bloğu liste olarak alınır.
  List<FirebaseVisionText.Block> blocks = texts.getBlocks();
  if (blocks.size() == 0) {
      return;
  }
  mGraphicOverlay.clear();

  //blok olarak alınan metinler ayrıştırılır ve ekranda gösterilir.
  for (int i = 0; i < blocks.size(); i++) {
      List<FirebaseVisionText.Line> lines = blocks.get(i).getLines();
      for(int j = 0; j < lines.size(); j++) {
          List<FirebaseVisionText.Element> elements = 
                 lines.get(j).getElements();
             for(int k = 0; k < elements.size(); k++) {
               GraphicOverlay.Graphic textGraphic = 
                   new TextGraphic(mGraphicOverlay, elements.get(k));
               mGraphicOverlay.add(textGraphic);

            }
       }
   }
}

Bu metotları kullanarak cihazdaki modeller yardımıyla metin algılama işlemini gerçekleştirebiliriz.

UYARI: Cihazdaki modeller ile sadece latin karakterlerin algılanması işlemi gerçekleşir. Örneğin Çince, Japonca veya Arapça karakterler bu yöntem ile algılanamaz. Bu karakterleri algılayan bir uygulama için bulut tabanlı modelleri kullanmanız gerekiyor.

Bulut Tabanlı Modeller ile Metin Algılama

Google Cloud ML altyapısını kullanarak, metin algılama yapabiliriz. Bu yöntemde latin karakterlerle birlikte Çince, Japonca veya Arapça gibi dillere ait karakterlerin algılanması da sağlanır. Yani amacınız global ölçekte bir uygulama geliştirmek ise bu durumda Google Cloud ML altyapısını kullanmanız gerekiyor. Bu yöntem, cihaz tabanlı modellere nazaran biraz daha zaman alabilmektedir. Bunun temel nedenleri şu şekildedir:

  • Google Cloud ML altyapısı kullanıldığı için görüntünün uzakta bulunan bir sunucuya gönderilmesi ve görüntüden elde edilen metinlerin sunucudan alınması zorunluluğu.
  • Bu yöntemde daha yoğun karakterlerin tespit edilmesi hedeflenmektedir. Bundan dolayı veri yoğunluğu fazladır.

Google Cloud ML altyapısından aylık, maksimum ilk 1000 kullanıma kadar ücretsiz faydalanabilirsiniz.  Daha fazla kullanım gereken durumlarda ücret ödemeniz gerekmektedir.

Bu yöntemi kullanmak için aşağıda verilen iki işlemi yapmanız gerekiyor. Aksi durumda birazdan vereceğimiz kodları kullansanız bile herhangi bir sonuç alamayacaksınız.

Firebase Projesini Blaze Sürümüne Almak

Yazının başında bir firebase projesi oluşturduk. Oluşturduğumuz bu projeyi Blaze sürümüne almamız gerekiyor. Bunu yapmak için şu adımları takip ediniz.

Firebase Console sayfasını açınız. Gmail hesabınızla giriş yapınız. 

Oluşturduğumuz proje yukarıdaki gibidir.

Projeye tıklayınız. Açılan sayfada sağ alt köşede bulunan aşağıdaki alana geliniz.

Burada Firebase için Spark sürümünü kullandığımızı görebilirsiniz. Bu sürüm tamamen ücretsiz olup, bulut modellerini bu sürümde kullanamayız. Bunu değiştirmek için Yeni Sürüme Geçin seçeneğine tıklayalım. Açılan pencerede mevcut tüm sürümlerin listelendiğini görebilirsiniz.

Yukarıda açılan pencerede Blaze ödeme yöntemine tıkladığınız zaman aşağıdaki pencere açılır.

Devam butonuna tıklayıp ilerleyebilirsiniz.

Yukarıda açılan pencerede ülke ve para birimi görülmektedir. Onayla butonuna tıklayarak devam edelim.

Açılan pencerede ad, soyad, adres ve kart bilgilerini girip satın almayı onayladıktan sonra Blaze sürümüne geçme işlemini tamamlamış oluruz. Bu ödeme yönteminde kullandığınız hizmet veya hizmetlerin belirli bir sayıya kadar ücretsiz kullanım hakkı bulunmaktadır. Örneğin burada Cloud Vision API hizmetini sadece metin algılama için kullanacağımız için başlangıçta herhangi bir ücret bizden alınmayacaktır. Yine bu hizmeti aylık ilk 1000 kullanım için ücretsiz olarak kullanabiliyoruz. Eğer bu sınırı aşarsanız sonraki her 1000 kullanım için sizden $1.5 dolar kesilir.

UYARI: Bu makaleyi yazarken Google bu şekilde bizlere bir kullanım hakkı tanıyordu. Ücretler Google tarafından tek taraflı olarak belirlendiği için Blaze ödeme yöntemine geçmeden önce kesinlikle aşağıda verilen linkleri ziyaret etmenizde fayda var.

https://firebase.google.com/pricing/

https://firebase.google.com/pricing/

https://cloud.google.com/vision/pricing

Cloud Vision API’nin Etkinleştirilmesi

Projemizi Blaze sürümünü aldıktan sonra yapılması gereken bir diğer işlem Cloud Vision API hizmetini etkinleştirmektir. Bunun için aşağıdaki adımları takip ediniz.

Cloud Vision API sayfasını açalım.

Açılan pencerede üstte bulunan Proje seçin seçeneğine tıklayalım ve açılan listeden projemizi seçelim.

Projenizi seçtikten sonra aşağıda görünen etkinleştir butonuna tıklayarak API’yi etkinleştirebilirsiniz.

Tüm bu işlemlerden sonra ihtiyacımız olan kodlara geçebiliriz.

Kodlar

Bulut tabanlı modelleri kullanarak metin algılama işlemini MainActivity isimli java dosyamızda yapacağız. Bulutta bulunan ML modelleri ile metin algılama için iki adet metot hazırladık. Bu metotlar ve görevleri şu şekildedir:

  • runCloudTextRecognition: Alınan bitmap resimde, metin olup olmadığını kontrol eden metottur. Eğer resimde metin bulunuyorsa, elde edilen metinler FirebaseVisionCloudText tipinde processCloudTextRecognitionResult metoduna gönderilir.
  • processCloudTextRecognitionResult: runCloudTextRecognition metodundan gelen ve resimde tespit edilen metinleri ayrıştırıp ekranda göstermeyi sağlar.

Metotların kodları aşağıdaki gibidir.

runCloudTextRecognition () Metodu


/*DocumentTextDetector ile resimde bulunan metinlerin algılanması sağlanır.
Eğer resimde metin tespit edilirse, processCloudTextRecognitionResult isimli metot çağrılır.*/
private void runCloudTextRecognition(Bitmap bitmap) {

  /*FirebaseVisionCloudDetectorOptions: Bulut modellerini kullanarak
  metin algılama yapabilmek için temel yapılandırmalar burada yapılır.
  setModelType(): Varsayılan olarak STABLE_MODEL değerine sahiptir.
  Bunu kullandığınızda stabil olan bulut modeli kullanılır. Eğer
  LATEST_MODEL seçilirse yayınlanan en son model kullanılır. Son modeller
  günceol olmaları bakımdan daha iyi sonuçlar verebilir.
  setMaxResults(): Maksimum sonuç sayısı belirlenir. Varsayılan 10'dur.
  build(): FirebaseVisionCloudDetectorOptions nesnesi oluşturmayı sağlar.*/
  FirebaseVisionCloudDetectorOptions options =
     new FirebaseVisionCloudDetectorOptions.Builder()
    .setModelType(FirebaseVisionCloudDetectorOptions.LATEST_MODEL)
    .setMaxResults(15)
    .build();

  mCameraButtonCloud.setEnabled(false);

  /*Bitmap resimdeki metni algılamak için resimden,
  FirebaseVisionImage nesnesi oluşturmamız gerekiyor*/
  FirebaseVisionImage image = FirebaseVisionImage.fromBitmap(bitmap);

  /*FirebaseVisionCloudDocumentTextDetector: Tanımladığımız yapılandırma 
  ayarlarını kullanarak görüntünün Google Cloud ML'ye gönderilmesini 
  sağlar. Özellikle yoğun metinler ile çalışırken bu yöntemi kullanmanızı 
  tavsiye ediyoruz. Bunun yerine FirebaseVisionCloudTextDetector sınıfını
  da kullanabilirsiniz.*/
  FirebaseVisionCloudDocumentTextDetector detector = 
  FirebaseVision.getInstance()
      .getVisionCloudDocumentTextDetector(options);

      /*Resimde bulunan metinlerin algılanmasını sağlar.*/
      detector.detectInImage(image)
       .addOnSuccessListener(
          new OnSuccessListener<FirebaseVisionCloudText>() {
           @Override
           public void onSuccess(FirebaseVisionCloudText texts) {
             mCameraButtonCloud.setEnabled(true);
             //Metin tespit edilirse,
             processCloudTextRecognitionResult(texts);
          }
        })
       .addOnFailureListener(
          new OnFailureListener() {
           @Override
            public void  onFailure(@NonNull Exception e) {
               // işlem başarısız olduğunda
               mCameraButtonCloud.setEnabled(true);
               e.printStackTrace();
           }
      });
}

processCloudTextRecognitionResult() Metodu

/*Cloud modellerini kullanarak resimde tespit edilen metinleri ayrıştırıp ekrana çizmeyi sağlar.*/
private void processCloudTextRecognitionResult(FirebaseVisionCloudText text) {

  if (text == null) {
     return;
  } 

  mGraphicOverlay.clear();
  /*FirebaseVisionCloudText: Resimde tanınan metnin tutulduğu yapıdır.*/
  List<FirebaseVisionCloudText.Page> pages = text.getPages();

  //blok olarak alınan metinler ayrıştırılır ve ekranda gösterilir.
  for(int i = 0; i < pages.size(); i++) {
    FirebaseVisionCloudText.Page page = pages.get(i);
    List<FirebaseVisionCloudText.Block> blocks = page.getBlocks();
    for(int j = 0; j < blocks.size(); j++) {
       List<FirebaseVisionCloudText.Paragraph> paragraphs = 
           blocks.get(j).getParagraphs();
       for(int k = 0; k < paragraphs.size(); k++) {
         FirebaseVisionCloudText.Paragraph paragraph = paragraphs.get(k);
         List<FirebaseVisionCloudText.Word> words = paragraph.getWords();
         for(int l = 0; l < words.size(); l++) {
             GraphicOverlay.Graphic cloudTextGraphic = 
                new CloudTextGraphic(mGraphicOverlay, words.get(l));
             mGraphicOverlay.add(cloudTextGraphic);
         }
      }
    }
  }
}

Bu metotları kullanarak buluttaki modeller yardımıyla metin algılama işlemini gerçekleştirebiliriz.

Uygulamanın Test Edilmesi

Uygulamayı akıllı telefonumuza yükledikten sonra ekran çıktısı aşağıdaki gibi olur.

Kaynak Kodlarına Erişim

Uygulamanın kaynak kodlarına GitHub üzerinden erişebilirsiniz.

Faydalandığımı kaynak: https://codelabs.developers.google.com/codelabs/mlkit-android/#0