1. OCR
OCR(Optical Character Recognition, 광학 문자 인식) 는 이미지나 문서에서 문자를 식별하고 디지털 텍스트로 변환하는 기술입니다. OCR은 주로 스캔된 문서, 사진 속 글자, 번호판, 손글씨 등의 텍스트를 자동으로 인식하는 데 사용됩니다.
기본적인 OCR 방식은 이미지 전처리(그레이스케일 변환, 이진화, 노이즈 제거) 후 문자 영역을 감지하고, 문자 패턴을 데이터베이스와 비교하여 최적의 텍스트를 추출하는 과정으로 이루어집니다.
OpenCV와 Tesseract OCR을 사용하면 Python에서 쉽게 구현할 수 있으며, 딥러닝 기반의 EasyOCR, PaddleOCR, Google Vision OCR 등을 활용하면 한글과 다양한 언어의 인식률을 더욱 높일 수 있습니다.
OCR은 문서 자동화, 차량 번호판 인식(LPR), CAPTCHA 해독, 서류 디지털화 등 다양한 분야에서 활용됩니다.
옛날부터 지금까지 되게 많이 사용하고있는 모듈이라는 생각이 듭니다.
모듈마다 추가로 학습을 할 수 있기때문에 나중에는 모듈을 추가로 할 수 있는 부분까지 있다고 합니다.
2. Tesseract OCR
설치를 먼저 해야되는데 다운받아야하는 깃허브입니다.
이 오픈소스를 가져다가 수정해서 쓸수도 있겠죠?
여기서 설치를 하고 환경변수라는곳에 등록을 해주고 설치된 위치를 확인해야한다.
그리고 설치할때 hangul 2개를 모두 설치하고 그 밑에 또 트리를 열어보면 kroean이있다 이 부분까지 다운받아야한다.(★)
저같은 경우는 노트북에 C:\Program Files\Tesseract-OCR 에 설치되어있습니다.
이 경로 매우매우 중요해요. 파이썬처럼 아무장소에서 실행할 수 있는 방법을 환경변수라고 하는데
환경변수를 등록해주어야합니다.
환경변수 등록하기
win+e (내컴퓨터) 파일 우클릭 -> 속성 -> 고급 시스템 설정 -> 환경변수 -> 시스템변수(s) -> Path -> 편집 -> 경로 붙여넣기 -> 확인모두 누르기
여기서 짤막지식을 한 스푼 뜨자면, Program Files랑 (x86)이 두개가 있다. 이 둘의 차이는
Program Files는 64비트에서도 돌아가는거고 (x86)는 32bit만 돌아갑니다.
단 vscode는 한번껐다가 켜야 적용됩니다.
pytorch도 한번 껐다가다시 켜줬고 처음시작하는거기때문에 터미널에 pip install pytesseract를 해줍니다.
▶ ocr실습
위 이미지를 가지고 text추출을 해보려고합니다.
import cv2
import pytesseract
img = cv2.imread('C:/AIProject2/DAY12/hello.png')
#테서렉트도 RGB임
dst= cv2.cvtColor(img, cv2.COLOR_BGR2RGB)
#lang = 'kor', lang='eng'
text = pytesseract.image_to_string(dst, lang='kor+eng')
print(text)
img를 불러오고 pytesseract.image_to_string(img, lang='koreng')를 해주었더니 결과가
= 19
om
녕하세요
가 나왔다. 뭔가 많이 다른거같다. 강사님이 준 예제파일은 정말 깔끔하게 잘 따졌는데, 왜 안되나 해서 좀 생각을 해보니,
이미지가 내가 보는거랑 컴퓨터가 보는것이 당연히 다르기때문에, 컴퓨터가 읽기 좋게끔 이미지 전처리를 해주었어야했다. 나는 뒷배경과 글자가 완벽하게 분리가 되는 png파일로 배경을 없앤 이미지 전처리 과정을 진행했다.
글씨체가 문제가 있는건가 싶어서 글씨체도 바꿔보고, png도 바꿔보고 했는데 그래도 text가 생각처럼 추출되지는 않아서 답답했다. 즉 인식률이 너무 낮았다.
그래서 어떤부분이 문제인지 비교를 해보고싶었다.
구글에 좀 검색해보니 MSER이라는 알고리즘을 통해서 텍스트로인식된 영역의 위치를 bounding box로 표시해 볼 수 있다고 해서 detecRegions()함수를 이용해서 cv2.rectangle() 함수를 이용해서 bounding box로 표현해보았다.
강사님이 주신 이미지파일은 너무 완벽하게 잘 되는데, 내가 한 png이미지에서는 제대로 인식이 안됐다.
이 부분은 한글이 좀 많이 약하다는걸 알고있었기때문에 영어로 한번 더 실험을 해보려고 한다.
영어로만 했는데도 인식률이 너무 낮았다.
▶ 좀 더 잘 읽는 모델 EASY OCR
이것도 임포트가 되어있지 않기때문에 터미널창에서 pip install easyocr을 해주었다.
이후 CV로 결과값을 보려고하는데,
여기서 imshow()가 작동하지 않을때는
터미널에 아래 코드를 붙여넣으면 된다.
pip uninstall opencv-python-headless
pip install opencv-python
위 opencv가 설치되지 않는 경우
pip install --upgrade --force-reinstall opencv-python
▶ 위 이미지를EASY OCR로 돌려보기
✅ Tesseract OCR 결과:
I fo
Of
Oli
[세요
✅ EasyOCR 결과:
- 안녕하세요 (정확도: 1.00)
- Hi (정확도: 0.99)위 이미지는 잘 찍히지 않았다.
다른이미지인
를 해봤는데
✅ Tesseract OCR 결과:
으르 하세요
그.
ak ocr] Sa LIL.
| learning to OCR
✅ EasyOCR 결과:
- 안녕하세요 (정확도: 1.00)
- hi (정확도: 1.00)
- 저논 0Cr학습중입니다. (정확도: 0.40) - 1 (정확도: 0.99) >>>>>>> 소문자 i인데 1로 인식함
- learning to OCR (정확도: 0.89)
라는 결과가 나온다 확실히 easy ocr이 성능이 좋다는것을 체감했다.
▶ EASY OCR로 자동차 번호판 읽기
import cv2
import easyocr
# EasyOCR 리더 초기화
ocr_reader = easyocr.Reader(['ko'])
# 이미지 경로 리스트
image_file_paths = ['D:/PJ/DLHJ/test1.jpg', 'D:/PJ/DLHJ/test2.jpg', 'D:/PJ/DLHJ/test3.jpg', 'D:/PJ/DLHJ/test4.jpg', 'D:/PJ/DLHJ/test5.jpg']
for image_path in image_file_paths:
print(f"Processing {image_path}")
# 이미지 읽기
input_image = cv2.imread(image_path)
if input_image is None:
print(f"이미지를 불러올 수 없습니다: {image_path}")
continue
# 그레이스케일 변환
gray_image = cv2.cvtColor(input_image, cv2.COLOR_BGR2GRAY)
# Bilateral 필터 적용 (노이즈 감소 + 가장자리 보존)
denoised_image = cv2.bilateralFilter(gray_image, 9, 75, 75)
# Otsu 이진화 적용 (자동 임계값 설정)
_, binary_image = cv2.threshold(denoised_image, 0, 255, cv2.THRESH_BINARY + cv2.THRESH_OTSU)
# 번호판 ROI(관심 영역) 감지를 위한 Canny 엣지 검출
edges = cv2.Canny(binary_image, 50, 150)
# OCR을 원본 및 전처리된 이미지에서 수행
ocr_images = [input_image, binary_image, edges]
detected_license_plates = {}
for ocr_img in ocr_images:
detected_texts = ocr_reader.readtext(ocr_img)
for (bbox, text, prob) in detected_texts:
if len(text) >= 7 and any(char.isdigit() for char in text): # 번호판 형식 필터링
# 바운딩 박스 좌표 변환
(tl, tr, br, bl) = bbox
tl, tr, br, bl = tuple(map(tuple, [tl, tr, br, bl]))
width = br[0] - tl[0]
height = br[1] - tl[1]
aspect_ratio = width / height if height > 0 else 0
# 번호판 가로/세로 비율이 너무 작거나 크면 제외 (일반적으로 2~5 범위)
if 2.0 <= aspect_ratio <= 5.0:
if text not in detected_license_plates or detected_license_plates[text][1] < prob:
detected_license_plates[text] = (bbox, prob)
# 최종 감지된 번호판 중 신뢰도 높은 것 하나만 시각화
if detected_license_plates:
best_text = max(detected_license_plates, key=lambda x: detected_license_plates[x][1])
best_bbox, best_prob = detected_license_plates[best_text]
(tl, tr, br, bl) = best_bbox
tl = tuple(map(int, tl))
br = tuple(map(int, br))
# 텍스트 영역에 사각형 그리기
cv2.rectangle(input_image, tl, br, (0, 255, 0), 2)
# 텍스트 출력
cv2.putText(input_image, best_text, (tl[0], tl[1] - 10), cv2.FONT_HERSHEY_SIMPLEX, 0.8, (0, 255, 0), 2)
print(f"감지된 번호판: {best_text} (신뢰도: {best_prob:.2f})")
else:
print("감지된 번호판이 없습니다.")
# 결과 이미지 표시
cv2.imshow('Detected License Plates', input_image)
cv2.waitKey()
print()
Processing D:/PJ/DLHJ/test1.jpg
감지된 번호판: 99845006 (신뢰도: 0.99)
Processing D:/PJ/DLHJ/test2.jpg
감지된 번호판: 154러 7070 (신뢰도: 0.90)
Processing D:/PJ/DLHJ/test3.jpg
감지된 번호판: 157고4895 (신뢰도: 0.75)
Processing D:/PJ/DLHJ/test4.jpg
감지된 번호판이 없습니다.
Processing D:/PJ/DLHJ/test5.jpg
감지된 번호판: 403수 7975' (신뢰도: 0.29)
결과를 돌려봤는데 한글은 사실 별로 잘 되진 않는것같다.
어느정도 모델이 성능이 좋을줄알고 ocr은 사실 그렇게 크게 어렵게 생각하지 않았던거같은데, 막상 직접 해보니
모델의 성능이 아직 많이 낮아서 내가 사용하려면 테서렉트랑 이지ocr에대한 파인튜닝이필수적으로 필요할 것 같다.
이후에 학습하는 방법을 좀 찾아봐야할거같아서 찾은 후 아래에 참고자료로 넣어놓으려한다.
알아보니 easy ocr은 gpu가 사용이 된다. 그래서 파이참에서 사용할때도 계속 워닝이 떴었다.
테서렉트ocr은 cpu도 사용가능하고 레퍼런스도 많다는 장점이 있다고 한다.
'AI > 컴퓨터 비전' 카테고리의 다른 글
OpenCV - Morphological | Diagonal Approximation (0) | 2025.03.21 |
---|---|
OpenCV 영상처리 | 영상이진화 | 오츠이진화 | 적응형 이진화 (0) | 2025.03.19 |
OpenCV - getRotationMatrix2D| getPerspectiveTransform (0) | 2025.03.17 |
OpenCV 정리_Grayscale, Color, Matplotlib, NumPy 활용법 (0) | 2025.03.12 |
OpenCV & 영상 처리 핵심 개념 | Grayscale, RGB, True Color (0) | 2025.03.11 |