본문 바로가기
PYTHON(파이썬)/파이썬 활용

OpenCV와 Tesseract OCR을 사용하여 카메라로부터 입력된 영상에서 숫자를 탐지하고 인식하는 Python 프로그램

by eplus 2024. 11. 14.
728x90
반응형
import cv2
import pytesseract
import logging

# Tesseract의 경로를 지정합니다. (윈도우에서 사용 시 필요)
pytesseract.pytesseract.tesseract_cmd = r'e:\Tesseract\tesseract.exe'

# 로그 설정
logging.basicConfig(filename='number_detection.log', level=logging.INFO, format='%(asctime)s - %(message)s')

# 카메라 초기화
cap = cv2.VideoCapture(1)

last_recognized_text = ""

while True:
    # 카메라에서 프레임 읽기
    ret, frame = cap.read()
    if not ret:
        break

    # 이미지를 그레이스케일로 변환하여 전처리
    gray = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY)
   
    # 임계값을 이용한 이진화 처리
    _, thresh = cv2.threshold(gray, 150, 255, cv2.THRESH_BINARY_INV)
   
    # 컨투어 찾기 (윤곽선 검출)
    contours, _ = cv2.findContours(thresh, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)

    for contour in contours:
        # 컨투어의 경계 사각형을 계산합니다.
        x, y, w, h = cv2.boundingRect(contour)
        # 사각형 크기 제한 (너무 작은 노이즈 제거)
        if 350 > w > 200 and 100 > h > 50:
            # 숫자가 있는 영역에 대해 OCR 수행
            roi = gray[y:y + h, x:x + w]
            text = pytesseract.image_to_string(roi, config='--psm 8 digits').strip()

            # 숫자 인식 결과를 로그로 남기기 및 출력
            if text and text != last_recognized_text:
                logging.info(f'Recognized number: {text}')
                print(f'Recognized number: {text}')
                last_recognized_text = text

            # 숫자 인식 결과를 화면에 출력
            cv2.rectangle(frame, (x, y), (x + w, y + h), (0, 255, 0), 2)
            cv2.putText(frame, text, (x, y - 10), cv2.FONT_HERSHEY_SIMPLEX, 0.9, (36, 255, 12), 2)

    # 결과 프레임 보여주기
    cv2.imshow('Number Detection', frame)

    # 'q' 키를 누르면 종료
    if cv2.waitKey(1) & 0xFF == ord('q'):
        break

# 카메라 해제 및 창 닫기
cap.release()
cv2.destroyAllWindows()

이 코드는 OpenCV와 Tesseract OCR을 사용하여 카메라로부터 입력된 영상에서 숫자를 탐지하고 인식하는 Python 프로그램입니다. 카메라로부터 프레임을 캡처하여 그레이스케일로 변환하고, 윤곽선(contour) 검출을 통해 특정 영역을 찾은 후, 그 영역에 대해 Tesseract를 사용해 숫자를 인식합니다. 아래는 코드의 주요 부분에 대한 분석입니다.

### 주요 기능 및 흐름
1. **Tesseract 설정**
   ```python
   pytesseract.pytesseract.tesseract_cmd = r'e:\Tesseract\tesseract.exe'
   ```
   - 이 줄은 Tesseract의 실행 파일 경로를 지정하는 부분으로, Tesseract의 설치 경로를 설정해야 합니다. 윈도우 시스템에서 필요합니다.

2. **로그 설정**
   ```python
   logging.basicConfig(filename='number_detection.log', level=logging.INFO, format='%(asctime)s - %(message)s')
   ```
   - 숫자 인식 결과를 기록하기 위해 로그 설정을 합니다. 로그 파일 이름은 `number_detection.log`이며, 각 인식된 숫자와 관련된 정보를 저장합니다.

3. **카메라 초기화**
   ```python
   cap = cv2.VideoCapture(1)
   ```
   - 카메라를 초기화합니다. `VideoCapture(1)`은 기본적으로 카메라 장치 ID가 `1`인 장치를 사용합니다. 대부분의 경우, 내장 카메라는 `0`으로 설정됩니다.

4. **프레임 처리 및 전처리**
   ```python
   gray = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY)
   ```
   - 각 프레임을 그레이스케일로 변환하여 윤곽선을 검출하기 쉽게 만듭니다. 그레이스케일 변환은 이미지의 처리 속도를 빠르게 하고 불필요한 컬러 정보를 제거합니다.

   ```python
   _, thresh = cv2.threshold(gray, 150, 255, cv2.THRESH_BINARY_INV)
   ```
   - 임계값을 사용하여 이진화 처리를 합니다. `THRESH_BINARY_INV`를 사용하여 픽셀 값을 반전시킵니다(흰색 배경, 검은색 문자).

5. **윤곽선 검출**
   ```python
   contours, _ = cv2.findContours(thresh, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)
   ```
   - `findContours`를 사용하여 이진화된 이미지에서 윤곽선을 검출합니다. 윤곽선은 이미지에서 밝기 차이가 나는 부분의 경계를 의미합니다.

6. **영역 필터링 및 OCR 수행**
   ```python
   for contour in contours:
       x, y, w, h = cv2.boundingRect(contour)
       if 350 > w > 200 and 100 > h > 50:
           roi = gray[y:y + h, x:x + w]
           text = pytesseract.image_to_string(roi, config='--psm 8 digits').strip()
   ```
   - 각 윤곽선에 대해 경계 사각형을 계산합니다. 사각형의 크기에 따라 유효한 영역(너무 작은 노이즈 제거)을 필터링합니다.
   - ROI(Region of Interest)에서 텍스트를 추출하기 위해 `pytesseract`를 사용합니다. 여기서 `config='--psm 8 digits'`는 Tesseract가 숫자 인식만 하도록 설정합니다.
   - `strip()`을 사용해 OCR 결과의 불필요한 공백을 제거합니다.

7. **중복 인식 방지 및 로그 기록**
   ```python
   if text and text != last_recognized_text:
       logging.info(f'Recognized number: {text}')
       print(f'Recognized number: {text}')
       last_recognized_text = text
   ```
   - 인식된 텍스트가 이전에 인식된 텍스트와 다를 경우, 로그 파일에 기록하고 콘솔에 출력합니다. 이를 통해 중복된 인식 결과를 피합니다.

8. **결과 표시**
   ```python
   cv2.rectangle(frame, (x, y), (x + w, y + h), (0, 255, 0), 2)
   cv2.putText(frame, text, (x, y - 10), cv2.FONT_HERSHEY_SIMPLEX, 0.9, (36, 255, 12), 2)
   ```
   - 인식된 숫자 영역에 사각형을 그려 표시하고, 숫자 텍스트를 이미지에 출력합니다.
   - `rectangle()`은 사각형을 그리고, `putText()`는 인식된 숫자를 이미지 상단에 표시하는 역할을 합니다.

9. **종료 조건**
   ```python
   if cv2.waitKey(1) & 0xFF == ord('q'):
       break
   ```
   - 'q' 키를 누르면 루프가 종료되고 프로그램이 종료됩니다.

10. **리소스 해제**
    ```python
    cap.release()
    cv2.destroyAllWindows()
    ```
    - 카메라 장치를 해제하고, 모든 창을 닫아 리소스를 해제합니다.

### 개선 및 주의점
1. **윤곽선 필터링 로직**:
   - 현재 사각형 크기 제한 (`w`와 `h`)은 하드코딩되어 있습니다. 이 부분은 숫자의 크기와 카메라 설정에 따라 동적으로 조정될 필요가 있습니다.
   - 다른 경우의 수에 대해서도 잘 동작하도록 동적인 크기 계산 또는 학습 기반 모델을 사용할 수 있습니다.

2. **OCR 설정 및 정확도**:
   - OCR의 정확도를 높이기 위해 전처리 단계를 더 개선할 수 있습니다. 예를 들어, 노이즈를 제거하거나 대비를 높이는 필터링을 추가할 수 있습니다.
   - 숫자 인식에 특화된 옵션이나 모델을 사용하면 더 좋은 결과를 얻을 수 있습니다.

3. **성능 최적화**:
   - 실시간 인식을 위해 프레임 처리를 최적화해야 합니다. 여러 가지 전처리와 OCR 작업을 각 프레임에서 수행하므로, 성능 문제가 발생할 수 있습니다. GPU 가속을 활용하거나 Tesseract 대신 경량의 OCR 라이브러리를 사용하는 방법도 고려할 수 있습니다.

4. **안정성 및 사용자 경험**:
   - 갑작스러운 종료를 방지하기 위해 예외 처리가 필요합니다. 카메라 장치가 올바르지 않을 때의 예외 처리 등 안정성 부분을 개선해야 합니다.

이와 같이, 이 코드는 기본적으로 카메라 영상에서 숫자를 검출하고 인식하는 기능을 수행하지만, 더 많은 전처리와 성능 개선이 필요할 수 있습니다. 추가적으로, 다양한 환경에서 정확도를 높이기 위해 다양한 조건을 고려해야 합니다.

728x90