본문 바로가기
Programming/Code Archive

파이썬 Tesseract로 OCR(광학식 문자 판독기) 구현하기

by 지표덕후 2022. 5. 8.

광학 문자 판독기(OCR)는 스캔한 문서 및 사진과 같은 '이미지에서 텍스트'를 인식해내는 기술입니다. 대개 메모를 하는 것보다는 사진을 찍는 것이 훨씬 시간이 덜 걸리기 때문에 게으른 우리에게는 OCR이 참 고마운 기술입니다. 사진으로 찍은 텍스트를 쓰거나 다시 타이핑할 필요 없이 스마트폰으로 찍은 텍스트의 복사본을 곧바로 획득할 수 있습니다.

 

파이썬(Python) 코드 몇 줄로 이런 OCR 기술을 구현할 수 있습니다. 이 목적으로 자주 활용되는 툴 중 하나가 Tesseract입니다. Tesseract는 다양한 운영체제에서 구동 가능한 광학 문자 판독 엔진입니다. 원래 Hewlett-Packard(HP)에서 독점 소프트웨어로 개발했습니다만 나중에 Google이 인수했습니다.

 

 

 

 

설치


▼ 현재 Tesseract는 Windows, macOS 및 Linux 다양한 OS에서 잘 구동됩니다. Tesseract는 유니코드(UTF-8)를 지원하며 100개 이상의 언어를 지원합니다. 이번 포스팅에서는 Tesseract OCR을 설치하고 이미지에서 텍스트가 잘 추출되는지 테스트해보겠습니다.

 

첫 번째 단계는 Tesseract를 설치하는 것입니다. Tesseract 라이브러리를 사용하려면 먼저 시스템에 설치해야 합니다. Ubuntu를 사용하는 경우 apt-get을 사용하여 Tesseract OCR을 설치할 수 있습니다. 윈도우의 경우 Tesseract 공식문서를 참고해주세요. 아래 코드는 공식문서에서 Tesseract를 설치한 후에 실행해야 합니다.

pip install pytesseract # Tesseract 설치
pip install opencv-python # cv2 설치

 

 

설치가 완료되면 필요한 라이브러리를 임포트합니다.

import numpy as np
from pytesseract import Output
import pytesseract
import cv2

 

 

 

이미지에 OCR 적용


▼ 테스트를 위해 사용할 이미지는 단순한 이미지입니다. 아래의 이미지를 사용할 예정입니다.

 

 

▼ 이미지를 불러와서 텍스트로 변환해봅시다.

filename = 'image_01.png'
img1 = np.array(Image.open(filename))
text = pytesseract.image_to_string(img1)
print(text)

▲ 워낙 단순한 이미지를 사용했기 때문에 Tesseract는 텍스트를 잘 추출해냅니다.

 

 

 

노이즈 낀 이미지에 OCR 적용


▼ 그러나 실제로 위의 것처럼 단순한 이미지에 OCR을 적용하는 경우는 잘 없기 때문에 테서렉트의 성능을 보기 위해 노이즈 낀 이미지를 테스트해보겠습니다. 아래 이미지입니다.

 

 

▼ 샘플 이미지를 먼저와 같이 처리해보겠습니다.

filename = 'image_02.png'
img2 = np.array(Image.open(filename))
text = pytesseract.image_to_string(img2)
print(text)

결과물이 비어있습니다. 이 말인즉슨, 테서렉트가 노이즈 낀 이미지에서는 글자를 인식하지 못 한다는 것을 의미합니다.

 

 

▼ 해서 이미지에 약간의 전처리를 가하여 노이즈를 제거하려 합니다. 여기서는 Open CV 라이브러리를 사용하겠습니다. 이번 포스팅에서는 정규화(mormalization), 임계값 설정(thresholding) 및 이미지 흐림 효과(image blur)를 사용합니다.

norm_img = np.zeros((img2.shape[0], img2.shape[1]))
img = cv2.normalize(img2, norm_img, 0, 255, cv2.NORM_MINMAX)
img = cv2.threshold(img, 100, 255, cv2.THRESH_BINARY)[1]
img = cv2.GaussianBlur(img, (1, 1), 0)
text = pytesseract.image_to_string(img)
print(text)

이미지가 충분히 깨끗해졌습니다. 이걸 가지고 아까 코드 스니펫 다시 적용했습니다. 그 결과는 위와 같습니다. 우리가 기대했던 대로 텍스트가 추출된 것을 알 수 있습니다.

 

 

 

텍스트 감지 및 위치 측정


▼ 테서렉트를 가지고 우리는 텍스트를 감지해내고 위치를 측정할 수 있습니다. 필요한 라이브러리를 불러오겠습니다.

from pytesseract import Output
import pytesseract
import cv2

 

 

▼ 최초에 사용했던 샘플 이미지를 그대로 사용해보겠습니다.

 

 

▼ 이미지를 불러와 데이터를 추출합니다.

filename = 'image_01.png'
image = cv2.imread(filename)

 

 

▼ 이전 예제에서 수행한 작업과 달리 이번 예제에서는 이미지를 즉시 문자열로 변경했습니다. 이 포스팅에서 우리는 이미지를 dictionary 타입 데이터로 변환하겠습니다.

results = pytesseract.image_to_data(image, output_type=Output.DICT)
results

▲ Dict 데이터의 각 값이 무엇을 의미하는지 하나하나 설명하지는 않겠습니다. left, top, width, height 값을 가지고 텍스트 하나하나를 감싸는 박스를 그려보겠습니다. 감지된 텍스트의 경계를 결정하기 위해 conf 키를 설정할 필요가 있습니다.

 

 

▼ 현재 결과에서 텍스트 영역을 둘러싼 박스의 좌표를 추출하고 원하는 신뢰도 값(confidence value)을 지정합니다. 여기서는 conf = 70. 값을 사용합니다. 코드는 다음과 같습니다.

for i in range(0, len(results[“text”])):
   x = results[“left”][i]
   y = results[“top”][i]
  
   w = results[“width”][i]
   h = results[“height”][i]
   text = results[“text”][i]
   conf = int(results[“conf”][i])
   if conf > 70:
       text = "".join([c if ord(c) < 128 else "" for c in text]).strip()
       cv2.rectangle(image, (x, y), (x + w, y + h), (0, 255, 0), 2)
       cv2.putText(image, text, (x, y - 10), cv2.FONT_HERSHEY_SIMPLEX, 0.5, (0, 0, 200), 2)

 

 

▼ 코드 완료되었습니다. 아래 코드를 실행하면 화면이 출력됩니다.

cv2.imshow('custom window name', image)
cv2.waitKey(0)

 

 

 

보셨다시피 이미지를 스캔하고 처리하는 문서 처리 파이프라인을 구축할 때 Tesseract는 괜찮은 선택지입니다. 다만 텍스트가 배경에서 깔끔하게 분리되는 즉, 소위 말하는 '누끼 따기 좋은' 고해상도 이미지를 입력물(input)로 받을 때 가장 좋은 성능을 보이긴 합니다.

 

텍스트 감지 및 위치 측정의 경우, 여러분이 몇 개 파라미터를 조작하긴 해야 합니다. 가령 보여드린 신뢰 값 같은 수치요. 원한다면 텍스트 박스나 텍스트의 색상 혹은 두께도 조절하실 수 있습니다.

댓글