반응형

EasyOCR은 문자 영역 인식(Detection), 문자 인식(Recognition)을 손쉽게 수행 할 수 있도록 하는 Python 패키지 입니다. EasyOCR은 구현이 간단하고 매우 직관적입니다. 현재 80개이상의 언어를 지원하고 있으며, 꾸준히 Releases 되고 있습니다. 최근에는 손글씨 인식을 목표로 하고 있습니다.

 

  • EasyOCR은 OCR 오픈소스로 Detection과 Recognition부분으로 나누어져 있으며 Text Detection은 CRAFT를 사용하고 Recognition은 CRNN사용합니다.
  • Framework는 모든 소스가 pytorch로 작성되어있습니다. 
  • OCR 수행결과와 텍스트의 Bounding Box 좌표를 얻을 수 있습니다.

또한 한번에 여러 개의 언어 인식도 가능합니다.

무엇보다 사용이 간단합니다.


설치

pip를 이용하여 설치가 가능합니다.

pip install easyocr

Import Packages

from matplotlib import pyplot as plt
from imutils.perspective import four_point_transform
from imutils.contours import sort_contours
import imutils
from easyocr import Reader
import cv2
import requests
import numpy as np
from PIL import ImageFont, ImageDraw, Image

Function

Colab 또는 Jupyter Notebook에서 이미지를 확인하기위한 Function과 이전 글에서 설명한 Scan 이미지로 변환하는 방법을 Function으로 만들어 사용하도록 하겠습니다. 

def plt_imshow(title='image', img=None, figsize=(8 ,5)):
    plt.figure(figsize=figsize)

    if type(img) == list:
        if type(title) == list:
            titles = title
        else:
            titles = []

            for i in range(len(img)):
                titles.append(title)

        for i in range(len(img)):
            if len(img[i].shape) <= 2:
                rgbImg = cv2.cvtColor(img[i], cv2.COLOR_GRAY2RGB)
            else:
                rgbImg = cv2.cvtColor(img[i], cv2.COLOR_BGR2RGB)

            plt.subplot(1, len(img), i + 1), plt.imshow(rgbImg)
            plt.title(titles[i])
            plt.xticks([]), plt.yticks([])

        plt.show()
    else:
        if len(img.shape) < 3:
            rgbImg = cv2.cvtColor(img, cv2.COLOR_GRAY2RGB)
        else:
            rgbImg = cv2.cvtColor(img, cv2.COLOR_BGR2RGB)

        plt.imshow(rgbImg)
        plt.title(title)
        plt.xticks([]), plt.yticks([])
        plt.show()


def make_scan_image(image, width, ksize=(5,5), min_threshold=75, max_threshold=200):
  image_list_title = []
  image_list = []

  image = imutils.resize(image, width=width)
  ratio = org_image.shape[1] / float(image.shape[1])

  # 이미지를 grayscale로 변환하고 blur를 적용
  # 모서리를 찾기위한 이미지 연산
  gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)
  blurred = cv2.GaussianBlur(gray, ksize, 0)
  edged = cv2.Canny(blurred, min_threshold, max_threshold)

  image_list_title = ['gray', 'blurred', 'edged']
  image_list = [gray, blurred, edged]

  # contours를 찾아 크기순으로 정렬
  cnts = cv2.findContours(edged.copy(), cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)
  cnts = imutils.grab_contours(cnts)
  cnts = sorted(cnts, key=cv2.contourArea, reverse=True)

  findCnt = None

  # 정렬된 contours를 반복문으로 수행하며 4개의 꼭지점을 갖는 도형을 검출
  for c in cnts:
    peri = cv2.arcLength(c, True)
    approx = cv2.approxPolyDP(c, 0.02 * peri, True)

    # contours가 크기순으로 정렬되어 있기때문에 제일 첫번째 사각형을 영역으로 판단하고 break
    if len(approx) == 4:
      findCnt = approx
      break


  # 만약 추출한 윤곽이 없을 경우 오류
  if findCnt is None:
    raise Exception(("Could not find outline."))


  output = image.copy()
  cv2.drawContours(output, [findCnt], -1, (0, 255, 0), 2)
  
  image_list_title.append("Outline")
  image_list.append(output)

  # 원본 이미지에 찾은 윤곽을 기준으로 이미지를 보정
  transform_image = four_point_transform(org_image, findCnt.reshape(4, 2) * ratio)

  plt_imshow(image_list_title, image_list)
  plt_imshow("Transform", transform_image)

  return transform_image

추가로 OpenCV putText의 경우 한글지원이 되지 않기때문에 한글을 표기하기 위한 Function을 만들어 사용합니다.

def putText(cv_img, text, x, y, color=(0, 0, 0), font_size=22):
  # Colab이 아닌 Local에서 수행 시에는 gulim.ttc 를 사용하면 됩니다.
  # font = ImageFont.truetype("fonts/gulim.ttc", font_size)
  font = ImageFont.truetype('/usr/share/fonts/truetype/nanum/NanumGothicBold.ttf', font_size)
  img = Image.fromarray(cv_img)
   
  draw = ImageDraw.Draw(img)
  draw.text((x, y), text, font=font, fill=color)

  cv_img = np.array(img)
  
  return cv_img

Load Image

url = 'https://user-images.githubusercontent.com/69428232/155486780-55525c3c-8f5f-4313-8590-dd69d4ce4111.jpg'

image_nparray = np.asarray(bytearray(requests.get(url).content), dtype=np.uint8)
org_image = cv2.imdecode(image_nparray, cv2.IMREAD_COLOR) 
plt_imshow("orignal image", org_image)

business_card_image = make_scan_image(org_image, width=200, ksize=(5, 5), min_threshold=20, max_threshold=100)

Using EasyOCR for Optical Character Recognition

EasyOCR의 사용은 매우 간단합니다. 언어와 GPU 사용여부를 선택하고 이미지를 넣기만 하면 됩니다. GPU 사용여부에 따라 속도차이가 있습니다. 경험해보기 위해 Colab의 경우 런타임 유형에서 하드웨어 가속을 None으로 하여 수행해보고, 다시 GPU로 변경하여 수행해보시기 바랍니다.

langs = ['ko', 'en']

print("[INFO] OCR'ing input image...")
reader = Reader(lang_list=langs, gpu=True)
results = reader.readtext(business_card_image)
더보기

Downloading detection model, please wait. This may take several minutes depending upon your network connection.
[INFO] OCR'ing input image...
Downloading recognition model, please wait. This may take several minutes depending upon your network connection.

결과값은 추출된 글자에 대해 각 4개의 꼭지점 좌표(Top-Left, Top-Right, Bottom-Right, Bottom-Left)와 인식한 글자, 확률(Probability)을 리스트 형태로 Return 합니다.

results
더보기

[([[1139, 173], [1305, 173], [1305, 309], [1139, 309]],
  '김',
  0.999889376838837),
 ([[1345, 169], [1513, 169], [1513, 307], [1345, 307]],
  '운',
  0.9915481144402207),
 ([[1562, 166], [1708, 166], [1708, 310], [1562, 310]],
  '움',
  0.47896254506264313),
 ([[1143, 313], [1287, 313], [1287, 403], [1143, 403]],
  '수석',
  0.9993128226626171),
 ([[1140, 394], [1922, 394], [1922, 490], [1140, 490]],
  'T Biz. Digital그룹 | C8C',
  0.7773774592934385),
 ([[263, 444], [658, 444], [658, 710], [263, 710]], 'SK', 0.9998046128015431),
 ([[1138, 542], [1876, 542], [1876, 711], [1138, 711]],
  'SK 주식회사',
  0.9257217344818329),
 ([[1147, 717], [2347, 717], [2347, 803], [1147, 803]],
  '13486, 경기도 성남시 분당구 판교로 255번길 38',
  0.816556452005966),
 ([[1142, 797], [1762, 797], [1762, 877], [1142, 877]],
  'SK 주식회사 판교캠퍼스',
  0.9869482225115002),
 ([[1144, 904], [1690, 904], [1690, 982], [1144, 982]],
  'Tel ',
  0.9754529844412072),
 ([[1148, 996], [1914, 996], [1914, 1072], [1148, 1072]],
  'Mobile ',
  0.8223556633827955),
 ([[1149, 1187], [1575, 1187], [1575, 1255], [1149, 1255]],
  'WWWskcokr',
  0.9689943777924663)]

detail=0으로 설정하면 인식된 글자만 추출 List 형태로 Return 됩니다.

simple_results = reader.readtext(business_card_image, detail = 0)
simple_results
더보기

['김',
 '운',
 '움',
 '수석',
 'T Biz. Digital그룹 | C8C',
 'SK',
 'SK 주식회사',
 '13486, 경기도 성남시 분당구 판교로 255번길 38',
 'SK 주식회사 판교캠퍼스',
 'Tel,
 'Mobile',
 'WWWskcokr']

# loop over the results
for (bbox, text, prob) in results:
  print("[INFO] {:.4f}: {}".format(prob, text))
  
  (tl, tr, br, bl) = bbox
  tl = (int(tl[0]), int(tl[1]))
  tr = (int(tr[0]), int(tr[1]))
  br = (int(br[0]), int(br[1]))
  bl = (int(bl[0]), int(bl[1]))

	# 추출한 영역에 사각형을 그리고 인식한 글자를 표기합니다.
  cv2.rectangle(business_card_image, tl, br, (0, 255, 0), 2)
  business_card_image = putText(business_card_image, text, tl[0], tl[1] - 60, (0, 255, 0), 50)
	# cv2.putText(business_card_image, text, (tl[0], tl[1] - 10), cv2.FONT_HERSHEY_SIMPLEX, 0.8, (0, 255, 0), 2)
더보기

[INFO] 0.9999: 김
[INFO] 0.9915: 운
[INFO] 0.4790: 움
[INFO] 0.9993: 수석
[INFO] 0.7774: T Biz. Digital그룹 | C8C
[INFO] 0.9998: SK
[INFO] 0.9257: SK 주식회사
[INFO] 0.8166: 13486, 경기도 성남시 분당구 판교로 255번길 38
[INFO] 0.9869: SK 주식회사 판교캠퍼스
[INFO] 0.9755: Tel 
[INFO] 0.8224: Mobile 
[INFO] 0.9690: WWWskcokr

plt_imshow("Image", business_card_image, figsize=(16,10))

Source Code

[ Colab ] Use EasyOCR


약간 오인식된 글자도 있지만 인식이 나쁘지 않은 것 같습니다. 한글이라서 그럴 수 있다고 생각합니다. 영어는 꽤 괜찮네요.

(이름이..김..운..움..ㅎ)


EasyOCR를 이용하여 kakaobrain에서 개발한 OCR이 있습니다. pororo라는 라이브러리로 제공하고 있으며 OCR 이외에도 이미지 캡셔닝, 번역, 텍스트 요약, 감정 분석등의 기능을 제공합니다.

[ OCR ] kakaobrain pororo OCR 사용하기 - Python

반응형