가끔 구글에 검색을 해봤는 데 최근에도 Tesseract를 사용한 OCR의 인식률을 높힐 수 있는 방법에 대한 포스팅이 없는 것 같아서 

인식률을 높히기 위해 고생 중인 Tesseract 사용자 분들을 위해 제 경험을 토대로 알려드리고자 합니다.


시작하기에 앞서, 이번 포스팅은 제가 Tesseract를 약 4개월동안 사용하고 낸 결론을 바탕으로하며 모바일 기준으로 적는 것임을 알려드립니다.



1. 모바일 Tesseract 활용을 위한 프로세스


모바일을 통해 OCR을 돌린다는 것은 PC에서 돌리는 것과 활용의 폭 차이가 매우 큽니다.

PC처럼 이미 가진 이미지 파일을 불러와서 OCR을 실행하는 것이 아니라 인쇄된 문서와 같은 것을 카메라로 촬영하여 즉시 텍스트로 출력시킬 수 있기 때문입니다. 이러한 활용 방식은 이미 많이 알려져있는 방식이지만, 아무래도 카메라로 촬영해서는 인식률 차이가 엄청나게 차이나서 많이들 고민하시는 부분입니다.


이 부분을 해결하기 위해서는 영상처리 기술이 필요하게 되는 데, 이중 가장 중요한 기법을 하나 소개하겠습니다.

바로 'Perspective Transform' 이라는 기술입니다.

자세히 이해할 필요는 없기 때문에 그냥 어떤 기술인지 알 수 있도록 링크를 하나 걸어드리겠습니다.


Perspective Transform 소개


간단히 줄여서 말씀드리자면 눕혀져있는 문서이미지를 정확하게 펴는 기술로, 캠스캐너라는 앱에서 체험하실 수 있는 기술입니다.

사용해보지 않으신 분들은 무료버전이 존재하니 한 번 설치해서 A4용지를 촬영해보시기를 권장합니다.


OpenCV에서 getPerspectiveTransform 함수를 활용하여 기능을 구현할 수 있는 데, 요즘 안드로이드 스튜디오에서 워낙 NDK개발을 쉽게할 수 있도록 만들어 놓기도 하였고 Android 버전의 OpenCV도 나왔기 때문에 영상처리라고 겁먹지 마시고 구현해보려고 노력하신다면 충분히 기본적인 기능 구현은 가능합니다.


이후 만약 문서에 깔끔하게 글자만 있는 게 아니라 잡영이나 홀로그램 등, OCR 인식에 방해할만한 요소가 있다면 원래대로라면 이를 없애줄 전처리가 필요하지만 그 부분은 영상처리의 전문지식을 요하는 터라 그나마 보완해줄 수 있는 방법으로 GrayScale을 Tesseract 실행 전에 이미지에 적용해주는 방법이 있습니다.



요약해드리자면

Perspective Transform - GrayScale(외 전처리 기술) - Tesseract - (후처리)순입니다. 

별거 없어 보이지만 매우 큰 차이를 보이고, 실제 기업들도 OCR 관련 기술들은 비슷한 프로세스를 따르고 있으니 시도해보시면 좋을 것 같습니다.



2. Tesseract에서 권장하는 환경


1) 폰트 크기 약 11-13pt 사이

2) 300dpi 이상의 이미지

3) 글자가 반듯하게 나오도록 Rotation

4) 글자 외의 Table이나 Border 삭제

5) 문장별로 적절하게 분할



다음 포스팅은 이번 포스팅에서 소개한 프로세스를 직접 실행하는 것을 보여드리는 것으로 할 것 같습니다.

이미 만들어 둔게 있긴 한데 저도 좀 정리를 해야할 것 같아서 언제 업데이트 해드릴지는 잘 모르겠네요.. ㅠㅠ



참고

1) Perspective Transform 소개 : http://miatistory.tistory.com/5

2) Tesseract 권장 환경 : https://github.com/tesseract-ocr/tesseract/wiki/ImproveQuality


OCR의 경우 관련지식이 없으면 API의 이해가 힘들 수 있으므로 소개해 보고자합니다.

버전은 Tesseract 3.05이며 모든 함수명은 tess-two에서 제공하는 TessBaseAPI를 기준으로 합니다. C코드로 되어있는 Tesseract 원본의 경우 함수명이 약간 다릅니다만, 함수명이 비슷하고 매개변수도 포인터로 되어있다 뿐이지 원하는 정보는 크게 다를 게 없기 때문에 원본 Tesseract를 사용하시는 분도 이해하시는 데 큰 문제는 없을겁니다.



1. 가장 기본적인 API

- init(String datapath, String language) : Tesseract를 사용하도록 초기화합니다. datapath는 traineddata가 있는 주소, language는 사용할 언어를 입력하시면 됩니다.( ex. eng / kor / eng+kor )

- setImage(Bitmap bitmap) : 읽어들일 이미지를 지정합니다. 입력값으로 활용할 수 있는 타입은 비트맵, 파일주소, Leptonica에서 사용하는 pix, byte[]로 된 이미지 데이터가 있습니다.)

- getUTF8Text() : 인식한 결과값을 String형으로 출력합니다.

- end() : 메모리를 해제합니다.


2. 추가 기능 API

- setRectangle(Rect rect) : 전체 이미지에서 원하는 영역만 지정해서 OCR 인식할 때 사용합니다. x, y, width, height값으로 영역을 지정할 수 있고 동일한 결과를 낼 수 있는 방법으로는 전체 이미지에서 createBitmap으로 원하는 영역의 이미지만 crop해서 setImage 후 getUTF8Text를 실행하는 방법이 있습니다.

- setVariable(String var, String value) : 일반적으로 Whitelist나 Blacklist를 사용할 때 사용합니다. WhiteList는 입력한 값만 출력되도록 하는 것이고 BlackList는 입력한 값을 출력에서 배제하는 것입니다. var에는 API에서 제공하는 속성값을 넣고 value에 값을 넣으시면 됩니다.

*setVariable("VAR_CHAR_WHITELIST", "1234567890") -> 숫자만 출력하고 싶을 때 사용합니다.

*setVariable("VAR_CHAR_BLACKLIST", "1234567890") -> 출력값에서 숫자를 배제하고 싶을 때 사용합니다.

- setPageSegMode(int mode) : 텍스트 이미지를 인식할 때 분할 방법을 결정합니다. 이부분은 OCR의 구동 원리와 가까운 내용이라 자세한 건 나중에 원리에 대해 설명하게 되면 다시 언급하겠습니다. 전체를 인식할 땐 기본 모드를 쓰는 게 낫기 때문에 그대로 두시고, 한줄만 읽고 싶으시다면 PSM_SINGLE_LINE을 사용하시는 것을 추천드립니다.



실제로 쓰이는 건 이정도입니다. 그나마도 setVariable은 전처리가 완벽히 확보된 이미지가 아니라면 안쓰시는 것이 인식결과가 좋기 때문에 실제로 자주 사용되는 것은 필수적인 API를 제외하고는 setRectangle과 setPageSegMode 정도입니다. 다음 Tesseract 관련 포스팅은 Tesseract로 가장 인식률을 높힐 수 있는 방법과 인식률이 떨어지는 사례가 될 것 같습니다.



참고

Android Tesseract Github : https://github.com/rmtheis/tess-two

+ Recent posts