ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • OpenCV와 Tesseract OCR을 사용하여 카메라로부터 입력된 영상에서 숫자를 탐지하고 인식하는 Python 프로그램
    PYTHON(파이썬)/파이썬 활용 2024. 11. 14. 06:05
    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
Designed by Tistory.