Simple OCR Android App Tutorial (Dùng Tesseract OCR)

Như đã đề cập ở bài trước, chúng ta đã biết Tesseract hỗ trợ cho việc nhận diện chữ viết trên hình ảnh khá là hiệu quả, đặc biệt là các ngôn ngữ thông dụng như tiếng Anh. Bên cạnh đó, công cụ này còn hỗ trợ rất nhiều ngôn ngữ, bao gồm cả tiếng Việt.

Với bài này, mình sẽ trình bày một bài hướng dẫn step-by-step với mục đích là xây dựng một ứng dụng Android đơn giản, có thể nhận biết tiếng Việt trong hình ảnh với sự hỗ trợ của Tesseract OCR.

Để có thể sử dụng bài hướng dẫn này một cách dễ dàng, người đọc sẽ cần có một số phương tiện cơ bản sau:

  • Android Studio: IDE hỗ trợ lập trình Android
  • Tập tin chứa dữ liệu ngôn ngữ
  • Hình ảnh chữ

Bài hướng dẫn này sẽ gồm các bước chính như sau:

  1. Tạo dự án Android
  2. Khai báo dependency
  3. Chuẩn bị hình ảnh
  4. Thiết kế Activity
  5. Khởi tạo các phương thức cơ bản
  6. Copy training data vào thiết bị
  7. Xử lý hình ảnh
  8. Chạy ứng dụng

1. Tạo dự án Android

Khởi động Android Studio, khởi tạo một dự án với khởi đầu là một Empty Activity.

createnew

2. Khai báo dependency

Chúng ta sẽ khai báo dependency cho ứng dụng trong tập tin gradle.build của thư mục app với nội dung như sau:

compile 'com.rmtheis:tess-two:5.4.1'

Như vậy, tập tin gradle.build của chúng ta sẽ có nội dung phần dependency như sau:

dependencies {
    compile fileTree(dir: 'libs', include: ['*.jar'])
    androidTestCompile('com.android.support.test.espresso:espresso-core:2.2.2', {
        exclude group: 'com.android.support', module: 'support-annotations'
    })
    compile 'com.android.support:appcompat-v7:25.3.1'
    compile 'com.rmtheis:tess-two:5.4.1'
    testCompile 'junit:junit:4.12'
}

3. Chuẩn bị hình ảnh

Với một ứng dụng OCR đơn giản, ta nên chuẩn bị một hình ảnh đơn giản với chữ đen, rõ ràng trên nền trắng.

vie_tnq

4. Thiết kế Activity

Trong bài hướng dẫn này, chúng ta sẽ xây dựng ứng dụng Android nhận diện văn bản đơn giản gồm 01 ImageView, 01 button và 01 TextView

Screenshot_2017-07-30-19-37-28

Như vậy, giao diện trên có thể sẽ được định nghĩa bởi file layout như sau

<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
 xmlns:tools="http://schemas.android.com/tools"
 android:id="@+id/activity_main"
 android:layout_width="match_parent"
 android:layout_height="match_parent"
 android:paddingBottom="@dimen/activity_vertical_margin"
 android:paddingLeft="@dimen/activity_horizontal_margin"
 android:paddingRight="@dimen/activity_horizontal_margin"
 android:paddingTop="@dimen/activity_vertical_margin"
 tools:context="sample.tesseract.tesseractocrdemo.MainActivity">

<ImageView
 android:id="@+id/img_input"
 android:layout_width="match_parent"
 android:layout_height="wrap_content" />

<Button
 android:id="@+id/btn_rec"
 android:layout_width="match_parent"
 android:layout_height="wrap_content"
 android:onClick="doRecognize"
 android:text="@string/btn_action_name"
 android:layout_below="@id/img_input"/>

<TextView
 android:id="@+id/txt_result"
 android:layout_width="wrap_content"
 android:layout_height="wrap_content"
 android:text="Your result is here..."
 android:layout_below="@id/btn_rec"/>
</RelativeLayout>

5. Khởi tạo các phương thức cơ bản

Trước hết, bên cạnh các phương thức cơ bản để hiển thị một activity trong ứng dụng Android, bạn sẽ cần phải khởi tạo một biến thuộc class TessBaseAPI để sử dụng các chức năng liên quan đến Tesseract OCR. Ở đây, mình sẽ thực hiện như sau:

public class MainActivity extends AppCompatActivity {
 private TessBaseAPI m_tess;

 @Override
 protected void onCreate(Bundle savedInstanceState) {
   super.onCreate(savedInstanceState);
   setContentView(R.layout.activity_main);
   initImageView();
   try {
     prepareLanguageDir();
     m_tess = new TessBaseAPI();
     m_tess.init(getFilesDir(), "vie");
   } catch (Exception e) {
     // Logging here
   }
 }

 private void initImageView() {
   ImageView imgView = (ImageView) findViewById(R.id.img_input);
   Bitmap input = BitmapFactory.decodeResource(getResources(), R.drawable.vie_tnq);
   imgView.setImageBitmap(input);
 }
}

Ta có thể thấy được các API của Tesseract sẽ được truy cập thông qua biến m_tess (class TessBaseAPI) và để khởi tạo biến này, ta sẽ cần chỉ định đường dẫn của thư mục chứa tập tin dữ liệu ngôn ngữ và loại ngôn ngữ được sử dụng. Ở đây, chúng ta sẽ dùng thư mục bên trong thư mục data của ứng dụng và ngôn ngữ là tiếng Việt.

Nên lưu ý rằng, thư mục được chỉ định phải chứa thư mục con có tên tessdata. Thư mục tessdata đó sẽ chứa các tập tin dữ liệu ngôn ngữ.

6. Copy training data vào thiết bị

Trước tiên, chúng ta cần phải chuẩn bị tập tin dữ liệu ngôn ngữ. Bạn có thể download dữ liệu cần thiết được chia sẻ trên Github tessdata. Ở đây, mình sẽ download tập tin vie.trainneddata và lưu trong thư mục assets/tessdata của ứng dụng.

assetsFolder

Như đã nói, chúng ta sẽ lưu tập tin trong thư mục assets nên ứng dụng sẽ không thể truy cập trên thiết bị. Do đó, chúng ta sẽ cần có một bước chuyển file vào thiết bị thông qua phương thức prepareLanguageDir() như sau:

public class MainActivity extends AppCompatActivity {
 // Other methods...

 // copy file from assets to another folder due to accessible
 private void copyFile() throws IOException {
   // work with assets folder
   AssetManager assMng = getAssets();
   InputStream is = assMng.open("tessdata/vie.traineddata");
   OutputStream os = new FileOutputStream(getFilesDir() + 
                                          "/tessdata/vie.traineddata");
   byte[] buffer = new byte[1024];
   int read;
   while ((read = is.read(buffer)) != -1) {
     os.write(buffer, 0, read);
   }

   is.close();
   os.flush();
   os.close();
 }

 private void prepareLanguageDir() throws IOException {
   File dir = new File(getFilesDir() + "/tessdata");
   if (!dir.exists()) {
     dir.mkdirs();
   }

   File trainedData = new File(getFilesDir() + "/tessdata/vie.traineddata");
   if (!trainedData.exists()) {
     copyFile();
   }
 }

7. Xử lý hình ảnh

Tới bước này, chúng ta đã hoàn tất những điều kiện cơ bản để có thể nhận diện ký tự trên một hình ảnh rõ ràng. Tiếp theo, chúng ta sẽ sử dụng API của Tesseract để nhận diện các kí tự. Với bài hướng dẫn này, việc nhận diện sẽ được khởi động bởi sự kiện nhấn button “Do Recognize” như sau:

public class MainActivity extends AppCompatActivity {
 // Other methods ...
 public void doRecognize() {
   if (m_tess == null) {
     return;
   }

   try {
     m_tess.setImage(BitmapFactory.decodeResource(getResources(), R.drawable.vie_tnq));
     String result = m_tess.getUTF8Text();
     TextView resultView = (TextView) findViewById(R.id.txt_result);
     resultView.setText(result);
   } catch (Exception e) {
     // Do what you like here...
   }
  }
 }

8. Chạy ứng dụng

Và bây giờ, bạn chạy thử ứng dụng và xem xem có đạt được kết quả mong muôn

Advertisements

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s