공부/AIFFEL

Exploration 18 : 문자를 읽을 수 있는 딥러닝

dong_dong_2 2021. 3. 16. 20:33

1. 기계가 읽을 수 있나요?
    - 사람이 문자를 읽으려면 어떤 과정을 거칠까?
       1) 문자가 있다는 것을 인식하고,
       2) 해독하는 과정을 거치는 것이 일반적이다.
    - 기계가 문자를 읽는 과정도 다르지 않다.
       1) Detection 하고,
       2) 어떤 문자인지 판독하는 Recognition
    - 오늘 사용해볼 것 중 첫번째는 구글 OCR API이다. 이 API를 이용하여 어플리케이션을 만들 수 있다.
       1) 구글의 파이썬 API 인터페이스 모듈을 설치한다.
       2) Google Cloud Vision API 사용
          (1) 서비스 계정 및 인증키를 생성한다. (자세한 내용은 구글링을 통해 쉽게 알 수 있다.)
          (2) 다운로드한 인증키는 원하는 경로에 my_google_api_key라고 파일명을 저장한다. (코드나 환경변수 설정을 쉽게 따라하기 위해 그대로 했지만 굳이 파일명 변경을 필요하지 않을 듯 하다.)
       3) 인증키 경로 등록후 커널 재가동
          (1) 터미널을 열고 아래와 같이 인증키 경로 변수를 등록한 후 커널을 종료하고 재가동한다.
               export GOOGLE_APPLICATION_CREDENTIALS = 인증키파일 경로와 파일명(확장자까지 써야한다.) ex) $HOME/aiffel/ocr_python/인증키파일
          (2) 만약 구글 API를 계속 사용하고 싶다면 아래와 같이 환경변수에 등록해 주면 위와 같이 매번 경로 변수 설정을 하지 않아도 된다.
               echo "export GOOGLE_APPLICATION_CREDENTIALS = 인증키파일 경로와 파일명 >> ~/.bashrc (os가 우분투인 경우)
    - 코드구현으로 구글의 API를 사용해봤다.
2. 어떤 과정으로 읽을까요?
    - 구글 API에서는 문자의 영역을 사각형으로 표현하고 우측에 Block과 Paragraph로 구분해서 인식결과를 나타내고 있었다.
    - 구글 API가 이미지에 박스를 친 다음 박스별 텍스트의 내요을 알려준 것처럼, 문자 모델은 보통 두 단계로 이루어진다.
       1) 먼저 입력받은 사진 속에서 문자의 위치를 찾아낸다. 이 과정을 Text Detection(문자검출) 이라고 한다.
       2) 찾은 문자 영역으로부터 문자를 읽어내는 것은 Text Recognition(문자인식)이라 한다.
    - 이렇게 문자 인식 모델은 Text Detection과 Recognition 두 과정을 통해서 사진 속의 문자를 읽을 수 있게 된다.
3. 딥러닝 문자인식의 시작
    - 지금까지 몇번 MNIST 데이터셋을 사용해봤다. 주로 0부터 9까지의 손으로 쓰인 숫자가 있는 이미지를 이미지 분류 문제로 딥러닝을 이용하여 풀어봤다.
    - MNIST가 딥러닝 데이터셋의 "hello, world!" 라면, LeNet은 CNN의 "hello, world!"라 할 수 있다.
    - 컴퓨터에서 언어를 배울 때 그 언어로 hello, world! 를 출력해보는 것이 시작이라고 알고 있다.
    - 1998년에 발표된 LeNet은 우편번호나 손글씨를 읽기 위해서 만들어졌다.
    - 앞서 학습한 MNIST로 LeNet을 훈련시킨다면 우편번호를 읽을 수 있을 것이다. LeNet-5의 구조를 보면 간단한 모델인 것을 알 수 있다.
    - 하지만 단순한 분류 모델만으로는 위에서 구글 API로 테스트해 봤던 복잡한 결과는 얻을 수 없다.
    - 넓고 복잡한 이미지에서 글자 영역을 찾을 수 없을 뿐더러 글자를 영역별로 잘라서 넣더라도 우리가 인식하기를 원하는 사진은 여러 글자가 모여있기 때문에 단순한 분류 문제로 표현이 불가능하다.
4. 사진 속 문자 찾아내기 - detection
    - 사진 속 문자를 찾아내는 최근의 딥러닝 모델은 일반적인 Object Detection(객체 인식) 방법으로 접근한다.
    - 딥러닝 기반 객체 검출 방법에는 Regression(회귀) 방식이나 Segmentation(세그멘테이션) 방식이 있다.
       1) Regression은 기준으로 하는 박스 대비 문자의 박스가 얼마나 차이가 나는지 학습한다.
       2) Segmentation은 픽셀단위로 해당 픽셀이 문자를 표현하는지를 분류하는 문제(pixel-wise classification)이라 볼 수 있다.
    - 객체 검출과 세그멘테이션에 대한 자세한 방법은 다른 강의에서 배우는 것으로 하고 여기서는 문자를 찾아내는 딥러닝 모델이 흔히 들어본 Object Detection과 큰 차이가 없다는 것만 알아두면 되겠다.
    - 문자는 일반적인 객체와 어떤 특성이 다를까?
       1) 일반적인 객체는 물체에 따라서 크기가 일정한 특징을 가진다. 하지만 문자는 영역과 배치가 자유로워 문자를 검출하기 위한 설정이 필요하다.
       2) 또한 객체는 물체간 거리가 충분히 확보되는데에 반해 글자는 매우 촘촘하게 배치되어 있다.
5. 사진 속 문자 읽어내기 - recognition
    - 문자 인식은 사진 속에서 문자를 검출해내는 검출 모델이 영역을 잘라서 주면 그 영역에 어떤 글자가 포함되어있는지 읽어내는 과정이다.
    - 이 과정은 이미지 문제보다는 자연어처리에서 많은 영감을 받았다. 자연어 처리를 한다면 RNN이 떠오를 것이다. 
    - 이미지 내의 문자 인식 모델의 기본적인 방법 중 하나가 바로 CNN과 RNN을 결합한 CRNN 모델이다. 이미지 내의 텍스트와 연관된 특징을 CNN을 통해 추출한 후에 스텝 단위의 문자 정보를 RNN으로 인식하는 것이다.
    - 이렇게 검출 결과로부터 인식 모델을 통해 문자를 인식하고 나면 구글 API의 결과처럼 사진 속 영역에 표시를 하고 그 영역에 어떤 문자가 적혀있는지 알 수 있는 OCR 시스템이 된다.
    - Detection, Recognition 모델만으로는 단어별 문자를 인식할 수는 있어도 사람의 의미를 가지고 읽어내는 문단("Paragraph") 또는 블록("Block") 정보를 알 수 없을 것 같은데 구글은 어떻게 풀었을까? (정답이 아닌 의견임)
       1) 이미지 내에서 검출된 단어 영역의 위치정보를 기준으로 분리해낼 수 있을 듯 하다.
       2) X, Y 축으로 L2 Distance가 일정 이내의 단어 또는 문자들의 그룹을 만들어 단락으로 만들어낼 수 있을 것 같다.
    - 이상으로 OCR에서 고려해야 할 기술적 단계들의 개요만 간단히 살펴봤다. OCR은 이미 실용적인 단계로의 연구가 많이 진척되어, 실전 레벨의 구체적인 정보를 접하는 것이 훨씬 도움이 될 거라 한다.
    - 그래서 OCR 영역에서 아주 도움이 될만한 영상을 권했다. 2개의 영상을 봤는데 네이버 이활석님의 데뷰 2018 발표영상은 꼭 보길 권한다. 길지만 시청한 후 개념정리가 된 느낌이였다.
6. keras-ocr 써보기
    - 위에서 구글 API를 쓰듯이 OCR을 데모로 써볼 수 있지만 직접 OCR 모델을 만들어 돌려보고 싶을 때가 있을 수 있다.
    - 지금까지 텐서플로우 기반의 모델을 주로 다뤄왔으니 텐서플로우를 기반으로 모델을 구현해서 OCR을 직접 돌려보도록 하겠다.
    - keras-ocr은 텐서플로우의 케라스 API를 기반으로 이미지 속 문자를 읽는 End-to-End OCR을 할 수 있게 해준다.
    - 공식 문서에도 나와있지만, 검출 모델로는 네이버 데뷰 2018 영상에서 소개한 CRAFT(Character Region Awareness for Text Detection)를 사용하고, 인식 모델로는 CRNN을 사용한다.
    - 주의할 점은 keras-ocr은 tensorflow 버전 2.2.0에서 구동된다. 2.3.x 이상 버전에서는 미리 학습된 모델에서 오류가 발생할 수 있으니 주의해야 한다.
    - 사용하기 앞서 tensorflow 버전을 확인하고, keras-ocr을 설치했다.
    - keras_ocr의 pipeline의 Pipeline()은 인식을 위한 파이프라인을 생성하는데 이 때 초기화 과정에서 미리 학습된 모델의 가중치(weight)를 불러오게 된다. 검출기와 인식기를 위한 가중치 하나씩을 불러오게되겠다.
    - keras_ocr을 사용해보고 pyplot을 이용하여 시각화도 해봤다.
    - 또 주의할 사항은 keras-ocr은 한글 데이터셋으로 훈련이 되어있지 않은 모델이다. 한글 텍스트의 detection은 정상적으로 진행되어도 recognition 결과가 엉뚱하게 나올 수 있다.
7. 테서랙트 써보기
    - 이번에는 테서랙트(Tesseract) 라이브러리로 이미지에서 문자를 인식해 보겠다.
    - 테서랙트는 구글에서 후원하는 OCR 오픈소스 라이브러리로 현재는 버전 4와 Tesseract.js등으로 확장되는 등 많은 곳에서 사용되고 있다.
    - 버전 4에서는 LSTM이 엔진에 추가되었고 현재 한국어를 포함한 116개 국어를 지원하고 있다.
    - 오픈소스라는 점은 우리가 원하는 프로젝트에 활용하기 쉽다는 것을 뜻하니, 직접 해 보면서 익혀두면 나중에 간단한 OCR 모델이 필요할 때 빠르게 활용할 수 있을 것이다.
    - 테서랙트 실습은 아래의 과정으로 진행했다.
       1) 테서랙트 설치하기
       2) 테서랙트 파이썬 wrapper 설치하기
          (1) Pytesseract는 OS에 설치된 테서랙트를 파이썬에서 쉽게 사용할 수 있도록 해주는 래퍼 라이브러리(wrapper library)이다. 파이썬 내에서 컴퓨터에 설치된 테서랙트 엔진의 기능을 바로 쓸 수 있도록 해준다.
       3) 테서랙트로 문자 검출하고 이미지 자르기 (detection)
          (1) 테서랙트를 사용하면 한 번에 이미지 내의 문자 검출과 인식을 할 수 있는데, 우리는 OCR이 이뤄지는 전체과정을 직접 거쳐보기 위해 검출을 먼저 해봤다.
          (2) 기본적으로 pytesseract의 image_to_data()를 사용한다. 파이썬에서 편하게 사용하기 위해서 pytesseract의 Output을 사용해서 결과값의 형식을 딕셔너리(DICT) 형식으로 설정해주게 된다.
          (3) 이렇게 인식된 결과는 바운딩 박스의 left, top, width, height 정보를 가지게 된다. 바운딩 박스를 사용해 이미지의 문자 영역들의 파이썬 PIL(pillow) 또는 opencv 라이브러리를 사용해 잘라냈다.
       4) 테서랙트로 잘린 이미지에서 단어 인식하기
          (1) 문자 인식을 해 볼 차례이다.
          (2) 검출된 바운딩 박스 별로 잘린 이미지를 넣어주면 영역별 텍스트가 결과값으로 나오는 image_to_string()를 사용했다.
8. 프로젝트 : 다양한 OCR 모델 비교하기
    - 지금까지 Google OCR API, keras-ocr, Tesseract 이상 3가지의 OCR 기능을 간단히 활용해 봤다.
    - 지금까지 살펴본 바로는 무료로 사용할 수 있는 기능들이지만 모두 준수한 성능을 갖추고 있었다.
    - OCR 분야가 이미 실용적인 수준에까지 기술이 발전했기 때문에 이것들을 잘 활용하면 실전에 쓸 수 있는 좋은 서비스를 만들수 있을 것 같다.
    - 그래서 오늘 다뤄본 위 3가지를 검증해 보는 프로젝트를 진행할 것이다.
       1) 나는 OCR 기능을 활용한 서비스를 빨리 개발해야하는 임무를 가진 엔지니어이다. 어떤 모듈을 도입하면 좋을지 기술검증을 하는 역할을 맡게 되었다고 가정한다.
       2) 첫 번째로는 OCR 관련해서 텍스트의 모양과 크기, 배치, 노이즈 등 OCR의 성능에 영향을 미치는 요인들에 관한 것이다.
          (1) 위 3가지 기능들이 이미지에 나타난 특징에 따라 얼마나 정확하게 문자를 detect하고 recognize하는지 검증하기 위해 이미지 데이터를 모으자.
          (2) 이미지가 많을수록 좋겠지만 검증해야 할 항목별로 고루 갖추는 것도 중요하다. 또 시간상 너무 많으면 힘드니 20장이 넘지 않도록 데이터를 모은다.
       3) 두 번째로는 위 3가지 기능들로 테스트를 진행한다.
          (1) 위 3가지 모듈을 활용하고 이미지 리스트를 정리한 후 반복문을 실행하여 모듈이 출력한 결과를 모아보자.
       4) 세 번째로는 테스트 결과를 정리한다.
          (1) 모듈들마다 출력 형태가 다를 것이다. 분석을 위해 결과를 정리해보면 도움이 될 것이다. 시각화 하는것도 좋은 방법이다.
       5) 네 번째로는 결과 분석과 결론을 제시한다.
          (1) 우선 구현하고자 하는 서비스의 목적과 내용을 먼저 정리한다.
          (2) 우리가 검토한 OCR 모델들이 그 목적에 부합하는지 확인하기 위해 필요한 평가기준을 제사한다.
          (3) 그 기준에 따라 위에서 정리한 테스트 결과를 분석하여 가장 나은 대안의 모델을 선정한다.