바로 대표적인 오픈소스 광학문자인식 (OCR, Optical Character Recognition) 라이브러리인 tesseract-ocr 과 안드로이드 문자인식 앱인 mezzofanti 입니다.
프로그램을 개발하신 분들과 도움을 주신 intruder 님께 감사드립니다.
tesseract-ocr (http://code.google.com/p/tesseract-ocr/) 은 2.03 버전까지 일부 언어만 지원되다가, 현재 3.00 버전부터 한글도 지원되고 내부적으로 leptonica (http://www.leptonica.com/) 라는 오픈소소 이미지 처리 라이브러리를 활용하고 있습니다. tesseract-ocr 은 심지어 AOSP(http://android.git.kernel.org) 및 eyes-free project 등에서도 이미 빌드하여 사용하고 있습니다.
mezzofanti (http://code.google.com/p/mezzofanti/) 는 카메라로 찍은 이미지 내의 글자를 tesseract 라이브러리를 이용해서 인식하는 오픈소스 안드로이드 앱입니다. 이 앱은 현재 1.0.3 버전까지 나와 있는데, 개발된지 1년도 더 지났고 tesseract 2.03 버전을 활용하므로 한글인식을 지원하지 않는 단점이 있습니다. 그래서, 한글 등이 지원될 수 있도록 mezzofanti 를 tesseract 3.0 버전에 적용해 보았습니다.
아래에 그렇게 구현하는 방법에 대해 순서적으로 정리했습니다.
1. 개발환경 구축
개발환경은 리눅스 우분투 10.04(Lucid) 이고, 안드로이드 NDK (r5b), SDK, JDK 등이 이미 설치되어 있어야 합니다.
2. mezzofanti 설치
mezzofanti 홈페이지 (http://code.google.com/p/mezzofanti/downloads/list) 로부터 Mezzofanti_java_code_1_0_3.zip 파일을 다운로드받습니다.
그리고, mezzofanti 디렉토리를 만들어 압축을 풉니다.
$ unzip Mezzofanti_java_code_1_0_3.zip -d mezzofanti
다음은 tesseract 3.0 소스를 가져와서 ndk 로 빌드하여야 합니다. 그런데, 이미 AOSP 내에 이 소스 패키지가 포함되어 있으므로 이 소스를 활용하도록 합니다. 그래서, 다음 명령을 사용하여 tesseract 와 관련된 패키지의 소스코드를 다운받습니다.
$ git clone https://android.googlesource.com/platform/external/tesseract.git $ git clone https://android.googlesource.com/platform/external/jpeg.git $ git clone https://android.googlesource.com/platform/system/core.git
mezzofanti 디렉토리 아래 jni 서브디렉토리, 그 아래 include 서브디렉토리를 만듭니다.
$ mkdir -p mezzofanti/jni/include
tesseract 와 jpeg 소스를 통째로 mezzofanti/jni 디렉토리로 복사 또는 옮깁니다.
$ cp -r tesseract mezzofanti/jni $ cp -r jpeg mezzofanti/jni
core/include/cutils 및 core/i 디렉토리를 통째로 mezzofanti/jni/include 로 복사 또는 옮깁니다.
$ cp -r core/include/cutils/ mezzofanti/jni/include/ $ cp -r core/include/log/ mezzofanti/jni/include/
$ cp core/libcutils/ashmem-dev.c mezzofanti/jni/jpeg
mezzofanti/jni/Android.mk 파일을 만듭니다.
LOCAL_PATH := $(my-dir) include $(addprefix $(LOCAL_PATH)/,$(addsuffix /Android.mk, \ jpeg \ tesseract \ ))
mezzofanti/jni/tesseract/Android.mk 와 mezzofanti/jni/jpeg/Android.mk 파일을 수정합니다.
$ diff tesseract/Android.mk mezzofanti/jni/tesseract/Android.mk 406c406,407 < external/jpeg --- > $(LOCAL_PATH)/../jpeg \ > $(LOCAL_PATH)/../include 433c434,435 < LOCAL_STATIC_LIBRARIES:=$(LOCAL_STATIC_LIBRARIES_) < libjpeg --- > #LOCAL_STATIC_LIBRARIES:=$(LOCAL_STATIC_LIBRARIES_) > # libjpeg 436c437,439 < liblog --- > libjpeg > # liblog > LOCAL_LDLIBS := -llog
$ diff jpeg/Android.mk mezzofanti/jni/jpeg/Android.mk 14c14 < jquant2.c jutils.c jmemmgr.c armv6_idct.S --- > jquant2.c jutils.c jmemmgr.c ashmem-dev.c armv6_idct.S 16a17 > LOCAL_C_INCLUDES := $(LOCAL_PATH)/../include
mezzofanti/jni/tesseract/api/jni.cpp 파일에서는 mezzofanti 에서 활용하는 추가적인 함수를 위해 많은 부분을 수정해야 합니다. 이 부분은 첨부파일을 다운로드해서 덮어쓰면 되겠습니다.
(jni.cpp 파일의 DEBUG 매크로를 1로 하면 인식된 결과가 /sdcard/out.txt 에 저장됩니다)
이제 mezzofanti 디렉토리에서 ndk-build 를 하면 tesseract 빌드과정이 끝납니다.
(android-ndk-r9 에서는 "error: format not a string literal and no format arguments [-Werror=format-security]"라는 오류가 발생합니다. 그럴 때는 android-ndk-r9/build/core/default-build-commands.mk 파일을 고쳐 "-Werror=format-security" 을 삭제해 줍니다.)
$ cd mezzofanti; ndk-build … SharedLibrary : libjpeg.so Install : libjpeg.so => libs/armeabi/libjpeg.so ... SharedLibrary : libocr.so Install : libocr.so => libs/armeabi/libocr.so
4. mezzofanti 소스 수정
이제 tesseract 및 jpeg 라이브러리가 준비되었으니 이클립스 또는 ant 로 mezzofanti 를 빌드하면 됩니다. 그런데, 업그레이드된 tesseract 버전과도 잘 동작하도록 하기 위해 소스코드의 일부를 수정하여야 합니다. 이클립스 또는 리눅스에서 다음 부분들을 수정합니다.
먼저 mezzofanti/AndroidManifest.xml 파일에서 카메라 장치와 외부 메모리 장치(sd 카드)에 대한 쓰기 권한을 추가해 줍니다.
<uses-feature android:name="android.hardware.camera"/> ... <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"></uses-permission>
다음은 mezzofanti/src/com/itwizard/mezzofanti/OCR.java 파일을 수정해 줍니다.
OCR.java 의 OCR 클래스는 JNI 를 통해 tesseract 라이브러리와 연동되는 객체이며, 각종 native 메소드와 변수를 정의하고 있습니다.
diff mezzofanti-orig/src/com/itwizard/mezzofanti/OCR.java mezzofanti/src/com/itwizard/mezzofanti/OCR.java 278a279,280 > if ( lang.compareTo("kor") == 0 ) > return "Korean"; 384c386 < closeDebug(); // clean close debug --- > // closeDebug(); // clean close debug 735a738 > /* 836a840 > */ 1006c1010 < public native void setVariableNative( // set a lib variable --- > public native boolean setVariableNative( // set a lib variable 1017a1022,1025 > // aux functions for liblept > public native void setEncodedNative(byte[] image); > public native void normalizeBgNative(int reduction, int size, int bgval); > 1043c1051 < public native String getBoxText(); // get the box for each letter --- > // public native String getBoxText(); // get the box for each letter 1047c1055 < public native void closeDebug(); // clean close the debug (if any) --- > // public native void closeDebug(); // clean close the debug (if any)
각각의 부분에 대한 설명은 다음과 같습니다.
- 735 라인부터 836라인까지 주석으로 막은 이유는 이 부분은 인식된 결과를 결과 액티비티로 보내기 전에 한번 가공해 주는 부분인데, 가공하지 않고 바로 결과로 보여주어야 한글 등이 제대로 보이더군요. 더욱 검토가 필요한 부분입니다.
- 나머지 부분은 native 메소드들과 관련하여 제거하거나 수정하거나 추가하는 부분들입니다.
그리고, "
Not enough space for installation on external strage"
와 같은 오류가 발생할 때는, mezzofanti/src/com/itwizard/mezzofanti/AssetsManager.java 파일을 수정하여 다음 부분 코드를 막아주면 됩니다.diff mezzofanti-orig/src/com/itwizard/mezzofanti/AssetsManager.java mezzofanti/src/com/itwizard/mezzofanti/AssetsManager.java 146a146 > /* 159a160 > */
또 하나, 기기에 따라 카메라의 setParameters 와 관련된 오류가 발생할 수 있습니다. 그런 경우를 위해 화면 크기를 고려해 카메라 프리뷰 사이즈를 지정하도록 하는 부분이 추가된 mezzofanti/src/com/itwizard/mezzofanti/CameraManager.java 파일을 첨부합니다.
5. mezzofanti 앱과 사전/학습 데이터파일 설치
이제 mezzofanti 를 이클립스 또는 ant 로 빌드하고, 안드로이드 스마트폰에 설치합니다.
앱을 설치하고 난 후에 곧바로 실행하면 제대로 동작하지 않는데, 사전/학습 데이터파일을 설치하지 않았기 때문입니다. 그래서 새로 빌드한 tesseract 3.0 버전에 맞는 영어, 한글 등의 사전/학습 데이터파일들(eng.traineddata.gz, kor.traineddata.gz 등)을 다음 링크들로부터 가져와서 /sdcard/tessdata 디렉토리에 넣고 압축을 풀어줍니다.
여기서 메뉴버튼을 눌러 Menu->Settings 메뉴의 "Set OCR dictionary language" 항목을 선택하면 영어와 한글 항목이 나타납니다. (내부 “Download new languages” 메뉴는 예전 버전의 데이터 파일이 다운되므로 활용하면 안됩니다.)
원하는 언어를 선택한 다음 다시 카메라 화면으로 되돌아가서 사진을 찍으면 이미지파일이 만들어지고 이것을 tesseract 를 통해 인식하게 됩니다. 찍는 모드는 전체 화면과 한줄라인 모드 2가지가 있습니다. 다음은 인식된 결과를 보여주는 예입니다.

적용된 앱에서는 여전히 예전 언어 인식 데이터파일을 다운로드하거나 참조하는 등의 코드가 있어 불완전하고 버그도 많고, 또 인식률도 50%가 안될 정도로 형편없지만 기본적인 기능을 확인했다는 데 의의를 둡니다. (중국어 한자가 오히려 인식률이 높은데 학습데이터파일이 문제인지도 모르겠습니다)
오히려, 관심있으신 분들께서 여기 오픈소스 자료들을 활용하여 훌륭한 앱을 만드셔서 무료로 배포해 주시길 기대합니다.
그런데 저대로 따라했을때 jconfig.h 에러가 났었습니다 (ndk-build 할때...)
분명 지난번에는 이상이 없는데 말이죠...
뭐 근데 단순 파일이 없다는 오류여서... liblept 안에 jconfig.h 파일 복사 붙여넣어서 에러를 없애는 방식으로 넘어갔구요~~
따라하실분 참고 하시라구^^ ㅋㅋ 뭔가... 쫌... 이상하긴 하네요... 리눅스상에서는 한글 인식했을때.. 이정도는 아니였는데...
제 디자이어에서는 영... 인식률이... 완전 낮네요 ㅋㅋㅋ..
뭔가 ..... 문자코드부분도 확인해봐야될꺼같구요..
가공하는 주석처리 부분..좀 확인 해봐야겠네요.. 요놈때문에 1~2주를 골머리 쌓고 있었는데... 그렇다고 이것만 하는것도 아니고.. ㅠㅠ..
매발톱님 덕분에 많은거 배워 갑니다~^^
수정할 부분을 수정하고 테스트하였는데
[ Menu->Settings 메뉴의 "Set OCR dictionary language" 항목을 선택하면 영어와 한글 항목이 나타납니다. ]
한글 및 영어 메뉴가 안나옵니다 ㅠㅠ
혹 죄송하지만 윈도우 환경의 이클립스에서 사용할 수 있는 수정된 소스 파일 lsy2xerx@naver.com로 보내주실 수 없나요??
부탁 드립니다.
빌드하는 과정에서 libcutils.so 파일이 없어서 멈추고 맙니다.ㅜㅜ
혹시 빌드 끝난 mezzofanti를 이메일로(p3jin@nate.com) 보내주실수 있나요??
libcutils.so 파일이 없어서 멈추고 맙니다.ㅜㅜ
libcutils.so 참조해서 그런것인데, mezzofanti/jni/jpeg/Android.mk에서 빼주면 됩니다.
제가 잘 몰라서 그런데
윈도우에서 tesseract-3.0만 활용하고 싶은데 방법좀 알려주세요ㅠㅠ
윈도우에서 이클립스나 비쥬얼스튜디오로 돌려보고 싶은데 방법이 없나요>?
다운로드 기간이 11월 24일까지라네요.
http://bigmail.mail.daum.net/Mail-bin/bigfile_down?uid=VsZWySwpHVQBhiVZJnF396LIdF7yUwwB
/home/usr/android-ndk-r7b/toolchains/arm-linux-androideabi-4.4.3/prebuilt/linux-x86/bin/../lib/gcc/arm-linux-androideabi/4.4.3/../../../../arm-linux-androideabi/bin/as: error while loading shared libraries: libz.so.1: cannot open shared object file: No such file or directory
make: *** [obj/local/armeabi/objs/jpeg/jcapimin.o] 오류 1
이에러는 어떻게 처리해야하나요.. T_T
intruder님 진짜 열심히 파보고도 안되서 이렇게 질문을 올립니다.
mk 파일 수정하는 부분이요...eclipse로 열어서 수정하는 건가요??어떻게 수정을 해야 할지를 잘 모를겠어서욤.ㅜㅜ 좀 알려주실수 있나요??
내용이 많거나 복잡하시다면 gjwjqdk@nate.com으로 연락주셔도 감사할 따름인데...
저는 윈도우내에서 cygwin을 통해서 환경설정을 하고, 이클립스를 실행시켜 위에 있는대로 실행시켰거든요
그리고 apk를 만들어 실행시켰는데 예상치 못한 오류라고 자꾸 떠서 왜그런지 ..ㅠㅠ
<
uses-permission
android:name
=
"android.permission.WRITE_EXTERNAL_STORAGE"
></
uses-permission
>
그리고 이부분을
<?xml version="1.0" encoding="utf-8"?>
...
<uses-permission android:name="android.permission.VIBRATE"/>
<uses-permission android:name="android.permission.CAMERA"/>
<uses-permission android:name="android.permission.INTERNET"/>
<uses-permission android:name="android.permission.READ_CONTACTS"/>
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
</manifest>
이런식으로 추가시켰는데도 자꾸 Not enough space for installation on external strage - reqested:0[MB] free:-6[MB] 이렇게 뜨네요..
물론 용량은 충분히 있구요.. 이거 어떻게 해결해야하는지 좀 알려주세요 ㅠㅠㅠㅠㅠㅠ
저도 위와같이 not enough ~라고 뜨는데 머가 문제나여? 그리고 한글 영문 사전학습 데이터 파일을 받아서 핸드폰 sdcard에 깔았는데 읽어들이지는 못하는군요.. 어떤문제인지좀 가르쳐줄수있을까여?
졸업작품 관련해서 3일간 window환경으로 빌드중인데.. .so파일 생성관련하여 오류가 있습니다 ㅜ.ㅜ 혹시 이 게시물의 전체 소스 있으신분은 쪽지 부탁드려요..
ndk-build하면 아래와 같이 중지됩니다.. 어떻게 해결해야 하는지 혹시 아시는 분 답변 좀 부탁드립니다...
make: *** [obj/local/armeabi/objs/ocr/api/jni.o] Error 1
좋은 정보 감사합니다! 그런데 구동에 실패하네요... ㅠ
혹시 성공한 소스파일 공유 가능하신가요?
kimsj1321@gmail.com 가능하시다면 부탁드리겠습니다...
error: cutils/log.h: No such file or directory
jni.cpp 파일 ndk 중에 이렇게 뜨네요... 파일이 잇는거도확인햇는데 왜그런지좀알수잇을까요 ㅠ
안녕하세요.. 시그윈으로 ndk-build 명령어를 때리면
jni/jpeg/Android.mk:108: *** 분리기호 이(가) 빠졌음. 멈춤.
이렇게 뜨네요... Android.mk의 108 번째 줄은
$ diff jpeg/Android.mk mezzofanti/jni/jpeg/Android.mk
이것인데.. 띄워 쓰기 다되어이써요.. $하고 띄우고 diff 띄우고 jpeg/Android.mk 띄우고 mezzofanti/jni/jpeg/Android.mk
이렇게 되어있는데.. 분리기호가 빠졌다고 뜨는데.. 어떻게해야할지 답이안나와요... 왜이런건가요??...예제 실행도 못하고..gg치게 생겼어요 ㅠㅠ도와주세요..
android.mk 수정부분..
위의 그 명령어 코드를 치니까 이렇게 떠버려요.. 이미지파일 첩부했습니다 ㅠㅠ
이상태에서 ndk-build하면 에러가 뜨네요..
$ cd mezzofanti; ndk-build
Android NDK: WARNING: Unsupported source file extensions in jni/jpeg/Android.mk for module cjpeg
Android NDK: cdjpeg.h jinclude.h jconfig.h jpeglib.h jmorecfg.h jerror.h cderror.h jversion.h
Android NDK: WARNING: Unsupported source file extensions in jni/jpeg/Android.mk for module djpeg
Android NDK: cdjpeg.h jinclude.h jconfig.h jpeglib.h jmorecfg.h jerror.h cderror.h jversion.h
Compile arm : jpeg_static <= jmem-ashmem.c
jni/jpeg/jmem-ashmem.c:22:27: fatal error: cutils/ashmem.h: No such file or directory
compilation terminated.
/home/p/android-ndk-r8-crystax-1/build/core/build-binary.mk:309: recipe for target 'obj/local/armeabi/objs/jpeg_static/jmem-ashmem.o' failed
make: *** [obj/local/armeabi/objs/jpeg_static/jmem-ashmem.o] Error 1
이런에러가 떠버려요...ㅠㅠ
어떻게해야할지...해결책이없을까요??..
안그러면..완성된 프로젝트라도 구할수 없을까요??..ㅠㅠ부탁드립니다.
안녕하세요 좋은 자료 감사합니다.
그런데 혹시 윈도우 이클립스에서 쓸 수 있는 소스 파일이 있으시다면 보내주실 수 있으신가요?
메일 주소 qjarmsdl33@naver.com 으로 부탁드립니다.
안녕하세요. 초보 안드로이드개발자입니다.
올려주신 내용에 따라 OCR 프로그램을 설치하고 있습니다.
C:/Android/android-ndk-r10c/toolchains/arm-linux-androideabi-4.6/prebuilt/windows-x86_64/bin/../lib/gcc/arm-linux-androideabi/4.6/../../../../arm-linux-androideabi/bin/ld.exe: ./obj/local/armeabi/objs/ocr/liblept/_open_memstream.o: in function open_memstream:jni/tesseract/liblept/_open_memstream.c:188: error: undefined reference to '__sfp'
C:/Android/android-ndk-r10c/toolchains/arm-linux-androideabi-4.6/prebuilt/windows-x86_64/bin/../lib/gcc/arm-linux-androideabi/4.6/../../../../arm-linux-androideabi/bin/ld.exe: ./obj/local/armeabi/objs/ocr/liblept/_fopencookie.o: in function fopencookie:jni/tesseract/liblept/_fopencookie.c:154: error: undefined reference to '__sflags'
C:/Android/android-ndk-r10c/toolchains/arm-linux-androideabi-4.6/prebuilt/windows-x86_64/bin/../lib/gcc/arm-linux-androideabi/4.6/../../../../arm-linux-androideabi/bin/ld.exe: ./obj/local/armeabi/objs/ocr/liblept/_fopencookie.o: in function fopencookie:jni/tesseract/liblept/_fopencookie.c:161: error: undefined reference to '__sfp'
C:/Android/android-ndk-r10c/toolchains/arm-linux-androideabi-4.6/prebuilt/windows-x86_64/bin/../lib/gcc/arm-linux-androideabi/4.6/../../../../arm-linux-androideabi/bin/ld.exe: ./obj/local/armeabi/objs/ocr/liblept/_fmemopen.o: in function fmemopen:jni/tesseract/liblept/_fmemopen.c:209: error: undefined reference to '__sflags'
C:/Android/android-ndk-r10c/toolchains/arm-linux-androideabi-4.6/prebuilt/windows-x86_64/bin/../lib/gcc/arm-linux-androideabi/4.6/../../../../arm-linux-androideabi/bin/ld.exe: ./obj/local/armeabi/objs/ocr/liblept/_fmemopen.o: in function fmemopen:jni/tesseract/liblept/_fmemopen.c:215: error: undefined reference to '__sfp'
collect2: ld returned 1 exit status
/cygdrive/c/Android/android-ndk-r10c/build/core/build-binary.mk:647: recipe for target 'obj/local/armeabi/libocr.so' failed
make: *** [obj/local/armeabi/libocr.so] Error 1
안녕하세요
안드로이드 ocr 을 이용해 뭘 좀 만들어보려고합니다.
Open Declaration net.bitquill.ocr.weocr.WeOCRServerList.WeOCRServerList(Context context, int xmlResId) throws IOException, XmlPullParserException
그런데 위와 같은 에러들이 발생합니다.
많은 분들이 요청하신 것같은데 저도 성공한 파일을 받아볼수있을까요?
제 메일이고 꼭 좀 부탁드리겠습니다.
ndk-build하는데서 계속 실패하네요.
혹시 성공하신분들 ndk 빌드된것만이라도 메일로 보내주시면 감사하겠습니다.
나머지는 앱부분은 제가 어떻게 해볼수 있을꺼 같아서요.
메일주소는 kyhwan362@naver.com 입니다.
안녕하세요.
좋은글에 감사드립니다.
시간이 꽤 흘러지만 많은 도움이 되는군요.
님의 글대로 단지 따라하기 수준으로 우분투에서 어찌어찌 작업하여 근 2주만에 앱이 실행되는 것 까지 확인하였습니다.
앱 실행은 윈도우즈에서 이클립스를 통해 하고 있습니다.
그런데 안드로이드 경험이 일천하여 현재 2가지 문제에 직면했습니다.
혹시 도와 주실수 있는 지 감히 문의 드립니다.
1.'OCR dictionary language'를 선택시 에러가 떠서 로그를 보니, 웹에서 languages.txt 파일을 가져와야 되는데,
"http://www.itwizard.ro/mezzolang/" 사이트가 더 이상 접속이 되지 않아 불가능합니다.
languages.txt 파일을 보내주시거나 혹은 이 파일을 어떻게 구성해야하는 지 알 수 있을까요 ?
2.테스트하는 폰이 갤럭시 S3 입니다.
sdcard에 트레이닝 데이터를 다운로드해야 하는 데 혹시 구체적인 방법을 알 수 있을까요 ?
DDMS를 통해 해보니 Read Only 권한 밖에 없는 것 같기도하고...웹에서 다운로드하여 저장을 sdcard를 지정해야 하나요?
저는 폰도 아이폰을 쓰다보니 안드로이드 폰은 너무생소해서여.
혹시 메일로 연락주시다면 sangwoonc@gmail.com으로 연락 부탁 드립니다.
다시한 번 너무나 멋진 글에 경의를 표합니다.
좋은정보 감사합니다 ^^