Android

[Android] Firebase MLKit로 OCR 사용해보기

배현진 2022. 6. 8. 16:02

OCR 사용방법 중 오픈 엔진인 tesseract를 사용해 프로젝트를 만들던 도중,

Firebase의 MLKit OCR이 글자 인식률이 좋다는 얘기를 듣고 한번 도전해보게되었다.

 

우선, Firebase 계정을 만들어주고 사용해야하는데, 이전에 사용해본 적이 있었기 때문에 그 계정을 사용했다.

 

Firebase에서 로그인을 한 후, 새로운 프로젝트를 만들기를 눌러준다.

그러면 프로젝트 생성을 위해 입력해야하는 몇가지 단계가 만들어지는데 하라는데로 하면 프로젝트가 생성된다.

(프로젝트 이름은 본인 마음대로 설정해주면 된다)

 

프로젝트 생성 후, 해당 프로젝트에 들어가면 프로젝트 이름 밑에 앱 추가 버튼이 있는데 여기서 나는 안드로이드 기반 어플을 만들것이기때문에 안드로이드를 선택해주었다. 

 

그러면 Android 앱에 Firebase 추가 창이 뜨는데 각각 알맞은 값들을 입력하면 된다.

- Android 패키지 이름

- 앱 닉네임 (내 맘대로 생성)

- SHA-1 인증

 

각각의 값을 입력한 후, 제공되는 파일을 다운받아 안드로이드 스튜디오의 해당 프로젝트에서 Android -> Project로 바꾼 후, app 폴더안에 넣어준다. 나머지는 또 시키는 대로 진행하면 앱 등록이 끝난다.

 

 

이제 Firebase MLKit 사용법이 나와있는 공식 사이트를 참고하여 안드로이드 스튜디오에 코드를 작성해주었다.

 

 

FirebaseMLKitOCR 프로젝트

더보기

- MainActivity.java

package com.example.firebasemlkitocr;

import androidx.annotation.NonNull;
import androidx.appcompat.app.AppCompatActivity;

import android.content.Intent;
import android.graphics.Bitmap;
import android.os.Bundle;
import android.provider.MediaStore;
import android.view.View;
import android.widget.Button;
import android.widget.ImageView;
import android.widget.TextView;
import android.widget.Toast;

import com.google.android.gms.tasks.OnFailureListener;
import com.google.android.gms.tasks.OnSuccessListener;
import com.google.firebase.ml.vision.FirebaseVision;
import com.google.firebase.ml.vision.common.FirebaseVisionImage;
import com.google.firebase.ml.vision.text.FirebaseVisionText;
import com.google.firebase.ml.vision.text.FirebaseVisionTextRecognizer;

import java.util.List;

public class MainActivity extends AppCompatActivity {

    // creating variables for our
    // image view, text view and two buttons.
    private ImageView imageView;
    private TextView textView;
    private Button CaptureImageBtn;
    private Button detectTextBtn;

    static final int REQUEST_IMAGE_CAPTURE = 1;

//    private static final int CAMERA = 100;

    // variable for our image bitmap.
    private Bitmap imageBitmap;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        // on below line we are initializing our variables.
        imageView = (ImageView) findViewById(R.id.image_view);
        textView = (TextView) findViewById(R.id.text_display);
        CaptureImageBtn = (Button) findViewById(R.id.capture_image);
        detectTextBtn = (Button) findViewById(R.id.detect_text_image_btn);


        CaptureImageBtn.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                // calling a method to capture our image.
                dispatchTakePictureIntent();
                textView.setText("");
            }
        });

        // adding on click listener for detect button.
        detectTextBtn.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                // calling a method to
                // detect a text .
                detectTxtFromImage();
            }
        });
    }


    private void dispatchTakePictureIntent() {
        // in the method we are displaying an intent to capture our image.
        Intent takePictureIntent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
        try {
            startActivityForResult(takePictureIntent, REQUEST_IMAGE_CAPTURE);
        } catch (Exception e) {

        }
        // on below line we are calling a start activity
        // for result method to get the image captured.
//        if (takePictureIntent.resolveActivity(getPackageManager()) != null) {
//            startActivityForResult(takePictureIntent, REQUEST_IMAGE_CAPTURE);
//        }
    }

    @Override
    protected void onActivityResult(int requestCode, int resultCode, Intent data) {
        super.onActivityResult(requestCode, resultCode, data);
        // calling on activity result method.
        if (requestCode == REQUEST_IMAGE_CAPTURE && resultCode == RESULT_OK) {
            // on below line we are getting
            // data from our bundles. .
            Bundle extras = data.getExtras();
            imageBitmap = (Bitmap) extras.get("data");

            // below line is to set the
            // image bitmap to our image.
            imageView.setImageBitmap(imageBitmap);
        }
    }

    private void detectTxtFromImage() {
        // this is a method to detect a text from image.
        // below line is to create variable for firebase
        // vision image and we are getting image bitmap.
        FirebaseVisionImage firebaseVisionImage = FirebaseVisionImage.fromBitmap(imageBitmap);

        // below line is to create a variable for detector and we
        // are getting vision text detector from our firebase vision.
        FirebaseVisionTextRecognizer firebaseVisionTextRecognizer = FirebaseVision.getInstance().getOnDeviceTextRecognizer();

        // adding on success listener method to detect the text from image.
        firebaseVisionTextRecognizer.processImage(firebaseVisionImage).addOnSuccessListener(new OnSuccessListener<FirebaseVisionText>() {
            @Override
            public void onSuccess(FirebaseVisionText firebaseVisionText) {
                // calling a method to process
                // our text after extracting.
                displayTextFromImage(firebaseVisionText);
            }
        }).addOnFailureListener(new OnFailureListener() {
            @Override
            public void onFailure(@NonNull Exception e) {
                // handling an error listener.
                Toast.makeText(MainActivity.this, "Fail to detect the text from image..", Toast.LENGTH_SHORT).show();
            }
        });
    }

    private void displayTextFromImage(FirebaseVisionText text) {
        // below line is to create a list of vision blocks which
        // we will get from our firebase vision text.
        List<FirebaseVisionText.TextBlock> blocks = text.getTextBlocks();

        // checking if the size of the
        // block is not equal to zero.
        if (blocks.size() == 0) {
            // if the size of blocks is zero then we are displaying
            // a toast message as no text detected.
            Toast.makeText(MainActivity.this, "No Text ", Toast.LENGTH_LONG).show();
            return;
        }
        // extracting data from each block using a for loop.
        for (FirebaseVisionText.TextBlock block : text.getTextBlocks()) {
            // below line is to get text
            // from each block.
            String txt = block.getText();

            // below line is to set our
            // string to our text view.
            textView.setText(txt);
        }
    }
}

 

 

 

실행결과

 

-> 좀 더 복잡한 글이 쓰여있는 사진을 찍었을 경우, 사진의 화질이 깨지며 인식이 잘 되지 않았다.

     이미지를 불러올 때 화질을 개선할 수 있는 방법을 적용시켜야할것같다.

 

 

 

+) Firebase OCR 참고 사이트

https://firebase.google.com/docs/ml-kit/android/recognize-text?hl=ko 

 

Android에서 ML Kit를 사용한 이미지 속 텍스트 인식  |  Firebase Documentation

Check out what’s new from Firebase at Google I/O 2022. Learn more 의견 보내기 Android에서 ML Kit를 사용한 이미지 속 텍스트 인식 This page describes an old version of the Text Recognition API, which was part of ML Kit for Firebase. The

firebase.google.com

 

+) FirebaseMLKitOCR 프로젝트 참고 영상

해당 영상에서 보여주는 코드에서 사용된 것들 중 Deprecated 되거나 변경된 부분들이 있어 수정하여 사용하였다.

https://www.youtube.com/watch?v=sA6gmvveswA&t=12s