티스토리 뷰

  • 이번 시간에는 실제 Tesseract 엔진을 Android 상에서 사용하는 방법을 한 번 알아보겠습니다.
    • Tesseract의 자세한 원리는 아래 글에서 확인할 수 있습니다.
 

(Android) 광학 문자 인식 라이브러리 Tesseract OCR 의 원리

Teseract OCR(광학 문자 인식) 오픈 소스 라이브러리인 Tesseract 에 대해서 알아보겠습니다. Tesseract 란 다양한 OS를 지원하기 위한 OCR 엔진으로. Free Software이고 Apache 라이선스이다. 2006년에 부터 Goog..

jinseongsoft.tistory.com

tess-two

  • tess-two 란 Android 상에서 사용하기 위해서 몇몇 기능이 추가된 형태의 Tesseract Tools 들에서 파생된 형태입니다.
  • Android API들과 build file들로 이루어져 있습니다. 
 

rmtheis/tess-two

Fork of Tesseract Tools for Android. Contribute to rmtheis/tess-two development by creating an account on GitHub.

github.com


구현방법

tess-two 라이브러리 적용

  • gradle dependancy를 추가해줍니다.
dependencies {
    compile 'com.rmtheis:tess-two:9.1.0'
}

tess-two training data 적용 방법

  •  트레이닝 데이터를 만들어주거나 아래 위치 에서 데이터를 다운받아 적용 시켜 보겠습니다. 
 

tesseract-ocr/langdata

Source training data for Tesseract for lots of languages - tesseract-ocr/langdata

github.com

 

  • raw 리소스 폴더에 트레이닝 데이터를 넣어줍니다. 아래 그림 처럼 말이죠


코드상에서 트레이닝 데이터 불러오기

  • 코드상에서 트레이닝 데이터를 불러오는 방법은 아래와 같습니다.
import android.content.Context;
import android.util.Log;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;

public class TessDataManager {
    static final String TAG = "DBG_" + TessDataManager.class.getName();

    private static final String tessdir = "tesseract";
    private static final String subdir = "tessdata";
    private static final String filename = "eng.traineddata";

    private static String trainedDataPath;
    private static String tesseractFolder;

    public static String getTesseractFolder() {
        return tesseractFolder;
    }
    public static String getTrainedDataPath(){
        return initiated ? trainedDataPath : null;
    }

    private static boolean initiated;

    public static void initTessTrainedData(Context context){
        if(initiated)
            return;

        File appFolder = context.getFilesDir();        //할당된 디렉토리 경로 및 임의의 파일명을 지정
        File folder = new File(appFolder, tessdir);        //파일의 경로와 이름을 따로 분리해서 지정할 수 있도록 한 생성자.
        if(!folder.exists())
            folder.mkdir();
        tesseractFolder = folder.getAbsolutePath();    

        File subfolder = new File(folder, subdir); 
        if(!subfolder.exists())
            subfolder.mkdir();

        File file = new File(subfolder, filename);    
        trainedDataPath = file.getAbsolutePath();   // 현재 위치의 절대경로를 tessdata의 path로 지정해준다.
        Log.d(TAG, "Trained data filepath: " + trainedDataPath);

        if(!file.exists()) {
            try {
                FileOutputStream fileOutputStream;          //tessdata를 쓸 filOutputStream을 생성했다.
                byte[] bytes = readRawTrainingData(context);        //raw폴더에서 tessdata를 가져온다.
                if (bytes == null)
                    return;
                fileOutputStream = new FileOutputStream(file);
                fileOutputStream.write(bytes);
                fileOutputStream.close();       
                initiated = true;
                Log.d(TAG, "Prepared training data file");
            } catch (FileNotFoundException e) {
                Log.e(TAG, "Error opening training data file\n" + e.getMessage());
            } catch (IOException e) {
                Log.e(TAG, "Error opening training data file\n" + e.getMessage());
            }
        }
        else{
            initiated = true;
        }
    }

    private static byte[] readRawTrainingData(Context context){

        try {
            InputStream fileInputStream = context.getResources()
                    .openRawResource(R.raw.eng_traineddata);

            ByteArrayOutputStream bos = new ByteArrayOutputStream();

            byte[] b = new byte[1024];

            int bytesRead;

            while (( bytesRead = fileInputStream.read(b))!=-1){
                bos.write(b, 0, bytesRead);
            }

            fileInputStream.close();

            return bos.toByteArray();

        } catch (FileNotFoundException e) {
            Log.e(TAG, "Error reading raw training data file\n"+e.getMessage());
            return null;
        } catch (IOException e) {
            Log.e(TAG, "Error reading raw training data file\n" + e.getMessage());
        }
        return null;
    }

}

tesss-two 라이브러리 사용 방법

  • TessBaseAPI 라는 라이브러리 클래스를 통해서 기능을 사용할 수 있다.
import android.content.Context;
import android.graphics.Bitmap;
import android.util.Log;

import com.googlecode.tesseract.android.TessBaseAPI;

import java.util.Arrays;
import java.util.List;

public class TessCore {
    static final String TAG = "DBG_" + TessCore.class.getName();
    private Context mCtx;

    public TessCore(Context context) {
        this.mCtx = context;
    }

    public List<String> detectText(Bitmap bitmap) {          
        Log.d(TAG, "Initialization of TessBaseApi");
        TessDataManager.initTessTrainedData(mCtx);      //DataManager클래스의 initTessTrainedData 메소드를 통해 트레이닝 데이터를 읽는다.
        TessBaseAPI tessBaseAPI = new TessBaseAPI();        
        String path = TessDataManager.getTesseractFolder();     //path에는 tesseract라는 이름의 디렉토리의 경로가 저장된다.
        Log.d(TAG, "Tess folder: " + path);
        tessBaseAPI.setDebug(true);
        tessBaseAPI.init(path, "eng");
        // 추천 글자들
        tessBaseAPI.setVariable(TessBaseAPI.VAR_CHAR_WHITELIST, "1234567890abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ");
        // 비추천 글자들
        tessBaseAPI.setVariable(TessBaseAPI.VAR_CHAR_BLACKLIST, "!@#$%^&*()_+=-[]}{;:'\"\\|~`,./<>?");
        tessBaseAPI.setPageSegMode(TessBaseAPI.OEM_TESSERACT_CUBE_COMBINED);
        Log.d(TAG, "Ended initialization of TessEngine");
        Log.d(TAG, "Running inspection on bitmap");
        tessBaseAPI.setImage(bitmap);         
        String inspection = tessBaseAPI.getUTF8Text();     
        Log.d(TAG, "=====Got data=====" + inspection);
        List<String> recogText = Arrays.asList(inspection.split("\n|\\u0020"));    //반환된 문자열은 공백 아니면 엔터로 구분되므로 split을 통해 배열에 넣어 반환한다.
        tessBaseAPI.end();
        return recogText;              // 글자를 반환한다.
    }
}

관련글

 

(Android) Tmap 경로 API를 통해 (출발, 도착)경로 Point 리스트 가져오기

Android Tmap 경로 API 프로젝트 진행중 걸은 거리를 추적해서 이동 경로를 지도상에 선 형태로 그려주는 기능을 구현하려고 했다. 처음에는 GPS 값만 가져와 Google Map에서 지원해주는 Polyline 형태로 그려주는..

jinseongsoft.tistory.com

 

(Android) Dialog Fragment 구현 방법 및 예제

Android Dialog Fragment Android에서 팝업창을 통해서 간단하게 사용자의 입력을 받을 때 Dialog 라는 컴포넌트를 사용합니다. Dialog의 형태는 여러가지임 이때 Dialog를 Fragment 형태로 구현하는 방법에 대해

jinseongsoft.tistory.com

 

[Android] Jsoup 을 이용한 영어 단어 정보 Parsing

Jsoup 을 이용한 영어 단어 정보 Parsing 이번에는 Android 에서 Jsoup 을 이용하여 다음 단어사전 Page를 Parsing 하여 단어의 정보들을 가져오는 방법에 대해서 알아보겠습니다. 일단 Jsoup을 사용하기 위해서는..

jinseongsoft.tistory.com

 

 

[Android] 안드로이드 6.0 이상 Wifi Scanning 하여 Dialog 에 보여주기

Wifi Scanning 이번 시간에는 Android 에서 Wifi Scanning을 하여 결과를 Dialog 에 띄워주는 방법에 대해서 알아보겠습니다. 일단 Wifi를 Scanning하는 방법은 Wifi Manager Class 를 이용하는 방법이 있습니다.W..

jinseongsoft.tistory.com

 

[Android] Action Bar Hide가 안될 때( getActionBar() 가 null 일 때)

Action Bar Hide가 안될 때 동적으로 ActionBar를 가리기 위해서 hide() 를 많이 사용하는데요. 아래와 같은 코드를 많이 사용합니다. 이때 숨겨지지가 않을 때가 있습니다. 1 getActionBar().hide(); 원인은 바로..

jinseongsoft.tistory.com


끝으로

이 글이 도움이 되었다면, 하단의 Google 광고 👎👎👎 한번씩 클릭 부탁 드립니다. 🙏🙏🙏

광고 클릭은 많은 힘이 됩니다! 

반응형
댓글