[하루 1시간] 실시간 OCR 번역기 만들기

2023. 11. 24. 12:13·Dev/Python

목표

실시간으로 화면을 캡쳐하고, OCR로 인식한 문자를 번역한다.

아이디어 & 솔루션

  • 화면을 실시간으로 캡쳐한다.
    • PIL 라이브러리의 ImageGrab을 사용
  • OCR을 이용해서 문자를 인식한다.
    • 오픈소스 OCR 라이브러리 Tesseract
  • 인식한 문장를 번역한다.
    • Papago API (넉넉한 무료 플랜)
  • GUI로 캡쳐한 화면, 인식한 문자, 번역된 문장을 표시한다.
    • Python GUI 프레임워크 Tkinter

 


Step 1. GUI 설계

  1. 메인 프레임
    1. 캡쳐한 화면
    2. 인식한 문자열
    3. 번역한 문자열
  2. 캡쳐할 영역 프레임

코드

import tkinter as tk

class TranslateApp:
    def __init__(self, root):
        self.root = root
        self.setup_frame_A()
        self.setup_frame_B()

    def setup_frame_A(self):
        self.frame_A = tk.Toplevel(self.root)
        self.frame_A.title('캡쳐')
        self.frame_A.geometry('300x200') # 창 크기 설정
        self.frame_A.wm_attributes('-transparentcolor', self.frame_A['bg']) # 뒤 화면이 보이기 위해선 배경이 투명하게

    def setup_frame_B(self):
        self.frame_B = tk.Toplevel(self.root)
        self.frame_B.geometry('300x600+400+100')
        self.frame_B.title('메인')

        self.label = tk.Label(self.frame_B) # 캡쳐한 이미지를 보여줄 예정이라 빈칸
        self.label.pack(fill=tk.BOTH, expand=True)

        # OCR 인식 텍스트를 보여줄 레이블
        self.ocr_text_label = tk.Label(self.frame_B, text="OCR 인식 텍스트", bg="white", height=10)
        self.ocr_text_label.pack(fill=tk.X, expand=True)


        # 번역된 텍스트를 보여줄 레이블
        self.trans_text_label = tk.Label(self.frame_B, text="번역 텍스트", bg="white", height=10)
        self.trans_text_label.pack(fill=tk.X, expand=True)

    def set_text(self, text):
        self.ocr_text_label.config(text=text)

    def set_trans_text(self, text):
        self.trans_text_label.config(text=text)


root = tk.Tk()
root.withdraw() # 프레임만 띄울거라 메인 루트는 가린다.
app = TranslateApp(root)

# Run the app
root.mainloop()

 

결과물

 


Step 2. 스크린 캡쳐

ImageGrep 사용해보기

from PIL import ImageGrab
from PIL import Image, ImageTk

image = ImageGrab.grab(bbox=(100, 100 ,300, 300),all_screens=True)
image.save("image.png")

 

image.png 파일로 화면의 (100,100) 에서 (300, 300) 까지의 영역이 캡쳐되어 저장된다.

Tkinter에 적용

# 사용할 라이브러리를 추가
from PIL import ImageGrab
from PIL import Image, ImageTk
from io import BytesIO

class TranslateApp:
    def __init__(self, root):
        self.root = root
        self.setup_frame_A()
        self.setup_frame_B()
        # GUI를 초기화 하면 이미지 캡쳐를 시작한다.
        self.update_capture()

	# ... 생략

	def update_capture(self):
        title_bar_height = 31  # 윈도우의 타이틀바 높이
        border_width = 8       # 윈도우 프레임

        # Frame A의 위치와 넓이, 높이
        x = self.frame_A.winfo_x()
        y = self.frame_A.winfo_y()
        width = self.frame_A.winfo_width()
        height = self.frame_A.winfo_height()

		# 프레임 내부 영역을 캡쳐
        image = ImageGrab.grab(bbox=(x+border_width, y+title_bar_height, x + border_width+ width, y + title_bar_height + height),all_screens=True)

		# 이미지를 캡쳐하지 못한 경우 아무것도 하지 않음
        if image == None:
            self.label.config(image=None)
            return

		# Tkinter의 PhotoImage로 사용하기 위해
		# 이미지를 BytesIO 오브젝트로 변환한다.
        img_byte_arr = BytesIO()
        image.save(img_byte_arr, format='PNG')
        img_byte_arr.seek(0)
        photo = tk.PhotoImage(data=img_byte_arr.read())

        # 이미지 컴포넌트를 업데이트 한다.
        self.label.config(image=photo)
        self.label.image = photo  # Keep a reference

        # 1000ms 마다 재귀적으로 호출한다.
        self.frame_A.after(1000, self.update_capture)

 

 

결과물

 

 


Step 3. OCR

Tesseract 라이브러리 사용법은 따로 다루지 않고 아래 문서로 대체

(https://pypi.org/project/pytesseract/)

 

캡쳐한 이미지를 OpenCV 형식에 맞게 변환한 후 Tesseract로 문자를 감지한다.

이미지를 입력받으면 블록 단위로 문자열을 묶은 뒤, 탐지한 영역을 초록색 박스로 표시한다.

 

코드

import pytesseract
import numpy as np
import cv2
from collections import defaultdict

# Tesseract가 설치된 경로를 설정해줘야한다.
pytesseract.pytesseract.tesseract_cmd = r'C:/Program Files/Tesseract-OCR/tesseract.exe'

def ocr_box(image):
    text_data = pytesseract.image_to_data(image, lang='eng')
    data = defaultdict(list)

    # pytesseract로 OCR을 하게 되면, 라인별, 블록별 그룹을 지을 수 있도록 데이터를 출력해준다.
    for i, line in enumerate(text_data.splitlines()):
        # 내용이 궁금하다면 print를 해보자.
        # print(line)
        if i == 0:
            continue  # 첫 번째 줄은 컬럼 이름이므로 스킵
        line = line.split()
        block_num = line[2] * 1000000 + line[3]*1000 + line[4]
        if len(line) == 12: # 정상적으로 인식됐다면 12개의 컬럼이 나온다.
            x, y, w, h = int(line[6]), int(line[7]), int(line[8]), int(line[9]) # 각각 좌표와 넓이 높이를 나타낸다.
            # 이왕 이미지를 받았으니 인식한 부분을 박스로 그려주자.
            cv2.rectangle(image, (x, y), (x + w, y + h), (0, 255, 0), 1)
            # 우리는 블록번호를 기준으로 문자열을 묶을 예정
            data[block_num].append(line[-1])

	# 그림을 그린 이미지와 문자열을 리턴한다.
    return image, [" ".join(data[k])for k in data.keys() ]

 

결과물

 

 

 


Step 4. 번역

 

파파고 API를 사용할 예정이다.

사용하기 위해선 네이버 파파고 API 문서를 참고하자. (https://developers.naver.com/docs/papago/papago-nmt-overview.md)

 

파파고 API 활용 코드

import requests

# 파파고 번역 API
url = "https://openapi.naver.com/v1/papago/n2mt"
# 발급받은 API키를 꼭 넣어야한다.
headers = {
    "Content-Type": "application/x-www-form-urlencoded; charset=UTF-8",
    "X-Naver-Client-Id": "########################",
    "X-Naver-Client-Secret": "###########"
}

# 심플하게 text를 입력받으면 번역 결과물을 리턴해주는 함수.
def translate(text):
    data = {
        "source": "en",
        "target": "ko",
        "text": text
    }

    response = requests.post(url, headers=headers, data=data)
    translated_json = response.json()

    return translated_json['message']['result']['translatedText']

 

기존 코드에 추가

class TranslateApp:
    def __init__(self, root):
        self.root = root
        self.setup_frame_A()
        self.setup_frame_B()
        self.update_capture()
        # 1초마다 쓸데 없이 번역API를 사용하는건 낭비이므로
        # 이전 문장과 같으면 번역하지 않기 위해 저장해둔다.
        self.last_text = ""
        
    # ....
    
    # OCR 처리된 문장이 표시될 때 처리를 한다.
    def set_text(self, text):
        self.ocr_text_label.config(text=text)
        # 이전 문장과 같거나, 10자 미만인 글자는 번역하지 않는다.
        if len(text) > 10 and text!= self.last_text:
        	# 번역 라벨에 번역된 문장을 넣는다.
            self.set_trans_text(translate(text))
            self.last_text = text

 

결과물

 


최종 결과물

반응형
저작자표시 (새창열림)

'Dev > Python' 카테고리의 다른 글

[SublimeText] 플러그인 만들기 - URL Decoder  (0) 2022.01.08
Python 접근제어자  (1) 2018.05.28
카카오톡 챗봇 (2)  (2) 2017.12.22
카카오톡 챗봇 (1)  (3) 2017.12.15
'Dev/Python' 카테고리의 다른 글
  • [SublimeText] 플러그인 만들기 - URL Decoder
  • Python 접근제어자
  • 카카오톡 챗봇 (2)
  • 카카오톡 챗봇 (1)
우르슬라
우르슬라
    반응형
  • 우르슬라
    저장소
    우르슬라
  • 전체
    오늘
    어제
    • 분류 전체보기 (29)
      • AI (1)
      • Dev (17)
        • Python (5)
        • Javascript (3)
        • Tools (5)
        • React (1)
        • 공부 (1)
      • 메타버스2 (2)
      • NFT (0)
      • 판매용 (0)
      • IT 이슈 (2)
      • 금융 이슈 (3)
  • 블로그 메뉴

    • 홈
    • 태그
    • 미디어로그
    • 위치로그
    • 방명록
  • 링크

  • 공지사항

  • 인기 글

  • 태그

    hd중공업
    ssml
    deepseek r1-lite-preview
    랭그래프
    agenda47
    NFT
    메타버스2
    ks54
    clarksea
    시스템프롬프트
    linyuvo
    deepseek
    가상부동산
    javascript
    wp engine 차단
    아젠다47
    프롬프트 강화
    prompt enchance
    speech synthesis markup language
    티스토리챌린지
    암호화폐차트
    화면 번역
    discord
    랜드마크
    java se programmer
    오블완
    oracle certified professional
    linyuvo ks54
    metaverse2
    크립토트레이딩
  • 최근 댓글

  • 최근 글

  • hELLO· Designed By정상우.v4.10.3
우르슬라
[하루 1시간] 실시간 OCR 번역기 만들기
상단으로

티스토리툴바