콘텐츠로 건너뛰기

OpenCV를 이용한 숫자 인식 및 이를 이용한 로그인 시스템 설계

1. 프로젝트 목표

컴퓨터 비젼으로, 사용자가 입력하는 숫자(300*300픽셀)를 4개 인식, 기존에 설정된 패스워드와 일치하는 지 확인하는 로그인 시스템을 만든다.

  • 프로그램 요구사항 분석:
  1. 숫자 이미지(28*28), 60,000개를 구글 사이트에서 불러와 머신러닝 후, 머신러닝 한 학습파라메타를 저장한다.
  2. 저장된 파라메타를 불러들여서 입력한 손글씨의 숫자를 인식하게 한다.
  3. 입력은 웹캠으로 입력받으며 4각형 안에 손으로 쓴 손글씨를 캡쳐하는 방식으로 4번 반복한다.
  4. 성공하면 웹캠화면은 사라지고 웹서버의 특정 페이지를 로딩해서 보여준다.
  5. 실패 1회, 2회 남음을 알려주고, 실패 2회면 1회 남음을 알려준 후, 3회 실패시 10분동안 캡쳐가 안되도록 한다.
  • 프로젝트 발표 및 준비사항 분석:
  1. PPT준비
  2. 동영상 저장
  3. youtube링크
  4. git hub에 링크
  5. 발표 시간 10분 이내

2. Dev 환경 설정

2.1. GitHub에서 리포지토리 생성

가장 먼저 원격 저장소를 만든다.

  1. GitHub에 로그인 후 New Repository 클릭.
  2. Repository Name 입력 (예: OpenCV_Project02).
  3. Public/Private 설정.
  4. 중요: Initialize this repository with a README, .gitignore, License 항목은 체크하지 않는다. (이미 로컬에 코드가 있으므로 충돌 방지를 위해 빈 저장소로 시작하는 것이 좋다.)
  5. OpenCV를 사용했으므로 OpenCV의 라이센스인 Apache 2 License로 라이센스 설정했다.
  6. 생성 후 https://github.com/jalanwang/OpenCV_Project02.git 형태의 URL을 복사해 둔다.

2.2 WSL에서 VS Code 실행 및 환경 확인

Windows 탐색기나 CMD가 아닌, WSL 터미널에서 VS Code를 열어야 한다.

  1. WSL 터미널을 실행하고 프로젝트 폴더로 이동.
cd ~/work/OpenCV_Project01
  1. VS Code 실행
code .
  1. VS Code 좌측 하단에 Checking Remote 혹은 WSL: Ubuntu라고 표시되어 있는지 확인한다.

6. 가상환경 복사

가상 환경을 그대로 복사해서 사용하려고 했는데 폴더 및 파일의 절대 및 상대 경로로 지정된 주소를 가지므로 다시 깔아주어야 한다.

    2.3. Git 초기화 및 환경 설정 (VS Code 터미널)

    VS Code 내의 터미널(Ctrl + ~)을 열고 아래 명령어를 순차적으로 수행한다.

    Git 사용자 설정 (최초 1회)

    git config --global user.name "본인ID"
    git config --global user.email "본인이메일"
    robot@kimsh:~/work/OpenCV_Project02$ git config --global user.name "jalanwang"
    robot@kimsh:~/work/OpenCV_Project02$ git config --global user.email "jalalwang@gmail.com"
    robot@kimsh:~/work/OpenCV_Project02$ ls -al
    total 2884
    drwxr-xr-x 4 robot robot    4096 Jan 14 10:05 .
    drwxr-xr-x 7 robot robot    4096 Jan 14 09:57 ..
    drwxr-xr-x 6 robot robot    4096 Jan 14 10:05 .venv
    drwxr-xr-x 2 robot robot    4096 Jan 14 10:05 .vscode
    -rw-r--r-- 1 robot robot 2932438 Jan 13 16:27 my_first_DNN_model.keras
    -rw-r--r-- 1 robot robot    3281 Jan 14 10:01 show_me_your_password.php

    초기화

    git init

    이 명령어를 치면 폴더 내에 .git 숨김 폴더가 생성된다.

    robot@kimsh:~/work/OpenCV_Project02$ git init
    hint: Using 'master' as the name for the initial branch. This default branch name
    hint: is subject to change. To configure the initial branch name to use in all
    hint: of your new repositories, which will suppress this warning, call:
    hint:
    hint:   git config --global init.defaultBranch <name>
    hint:
    hint: Names commonly chosen instead of 'master' are 'main', 'trunk' and
    hint: 'development'. The just-created branch can be renamed via this command:
    hint:
    hint:   git branch -m <name>
    Initialized empty Git repository in /home/robot/work/OpenCV_Project02/.git/
    robot@kimsh:~/work/OpenCV_Project02$ ls -al
    total 2888
    drwxr-xr-x 5 robot robot    4096 Jan 14 11:44 .
    drwxr-xr-x 7 robot robot    4096 Jan 14 09:57 ..
    drwxr-xr-x 7 robot robot    4096 Jan 14 11:44 .git
    drwxr-xr-x 6 robot robot    4096 Jan 14 10:05 .venv
    drwxr-xr-x 2 robot robot    4096 Jan 14 10:05 .vscode
    -rw-r--r-- 1 robot robot 2932438 Jan 13 16:27 my_first_DNN_model.keras
    -rw-r--r-- 1 robot robot    3281 Jan 14 10:01 show_me_your_password.php

    2.4. .gitignore 파일 생성 (C++ 필수)

    C++ 빌드 부산물(실행 파일, 오브젝트 파일 등)이 업로드되지 않도록 프로젝트 루트에 .gitignore 파일을 만들고 아래 내용을 추가한다. C/C++와 Python 모두 공통으로 사용해되 되는 .gitignore 파일이다.

    파일명: .gitignore

    # ------------------------------------------------
    # Editor & System
    # ------------------------------------------------
    .vscode/
    # 협업 시 공유해야 하는 설정이 있다면 아래처럼 예외 처리(!) 가능
    # !.vscode/launch.json
    # !.vscode/tasks.json
    
    # Workspace files
    *.code-workspace
    
    # ------------------------------------------------
    # C/C++ Build Artifacts
    # ------------------------------------------------
    # Object files
    *.o
    *.obj
    
    # Libraries
    *.lib
    *.a
    *.dll
    *.so
    *.dylib
    
    # Executables
    *.exe
    *.out
    *.app
    
    # Build Directories (CMake 등을 쓸 때 주로 생성되는 폴더)
    build/
    bin/
    **/bin/
    
    # ------------------------------------------------
    # Python
    # ------------------------------------------------
    # Byte-compiled / Optimized / DLL files
    __pycache__/
    *.py[cod]
    *$py.class
    
    # Virtual Environments
    .venv/
    venv/
    ENV/
    
    # ------------------------------------------------
    # Data & Logs (Whitelist 방식 권장)
    # ------------------------------------------------
    *.csv
    *.log
    
    # *.txt와 *.json을 무시하되, 필수 설정 파일은 추적하도록 예외 처리
    *.txt
    !CMakeLists.txt
    !requirements.txt
    
    *.json
    !package.json
    # 필요한 경우 특정 json 설정 파일 추가 예외 처리 (!settings.json 등)
    
    # ------------------------------------------------
    # Self-configuration (Do NOT ignore)
    # ------------------------------------------------
    # .gitignore 파일 자체는 목록에 넣지 않음

    2.5. 원격 저장소 연결 및 첫 푸시

    이제 로컬 Git과 GitHub를 연결한다.

    1. 스테이징 및 커밋
    git add .
    git commit -m "Initial commit: OpenCV Project02 setup"
    1. 브랜치명 변경 (관례상 main 사용)
    git branch -M main
    1. 원격 저장소 연결 (아까 복사한 URL 붙여넣기)
    git remote add origin https://github.com/jalanwang/OpenCV_Project02.git
    1. 푸시(Push)
    robot@kimsh:~/work/OpenCV_Project02$ git push -u origin main
    Username for 'https://github.com': jalanwang
    Password for 'https://jalanwang@github.com':
    remote: Invalid username or token. Password authentication is not supported for Git operations.
    fatal: Authentication failed for 'https://github.com/jalanwang/OpenCV_Project02.git/'

    PAT라는 토큰을 만들어서 들어가는 것을 잊었다. 저장해 놓은 토큰을 꺼내와서 패스워드에 입력했다.

    robot@kimsh:~/work/OpenCV_Project02$ git push -u origin main
    Username for 'https://github.com': jalanwang
    Password for 'https://jalanwang@github.com':
    Enumerating objects: 5, done.
    Counting objects: 100% (5/5), done.
    Delta compression using up to 12 threads
    Compressing objects: 100% (5/5), done.
    Writing objects: 100% (5/5), 2.48 MiB | 6.45 MiB/s, done.
    Total 5 (delta 0), reused 0 (delta 0), pack-reused 0
    To https://github.com/jalanwang/OpenCV_Project02.git
     * [new branch]      main -> main
    branch 'main' set up to track 'origin/main'.
    robot@kimsh:~/work/OpenCV_Project02$

    2.6 확인

    3. 소스코드

    이 프로젝트는 전략 패턴(Strategy Pattern)을 기반으로 설계되어 있다. 즉, main 함수가 구체적인 구현 내용을 알 필요 없이, 인터페이스만으로 다양한 알고리즘(게임 모드)을 교체하며 실행하는 구조다.

    3.1 모듈별 기능

    • console.py
      • 프로그램의 진입점이다.
      • WebcamManager를 초기화하고, 네비게이션 메뉴를 이용해서 사용자와 대화한다.
    • show_me_your_password.py
      • 사용자가 보여주는 이미지를 읽고, 이를 저장해서 리턴하는 함수이다.
      • def get_password_image(): # 이미지를 사용자가 직접 캡쳐해서 넘겨주는 펑션이다.
      • def get_password_image(2): # 사용자에게 가이드라인을 제공해서 이미지를 캡쳐하는데 도움을 주는 펑션이다.
    • login.py & login2.py
      • 로그인을 위해서 이미지 캡쳐 파일을 불러 들여, 패스워드와 비교하는 루틴이다.
      • login.py: def get_password_image(): 모듈을 이용해서 로그인한다.
      • login.py: def get_password_image2(): 모듈을 이용해서 로그인한다.
    • machine_learning.py
      • 핸드라이팅 이미지(7만장)을 불러들여 머신 러닝을 수행하는 코드다.
      • 머신 러닝 후, 학습된 파라미터와 출력뉴런을 저장하고 있는 인공지능 모델이다.
      • my_first_DNN_model.keras를 생성한다.

    3.2 하드웨어

    • WebcamManager.hpp (Driver/Adapter)
      • OpenCV의 VideoCapture 클래스를 래핑(Wrapping)한 클래스다.
      • 카메라 장치 열기, 해상도 설정, 프레임 획득 같은 하드웨어 I/O 로직을 캡슐화해서 다른 코드들이 OpenCV API에 직접 의존하지 않토록한다.

    3.3 핵심 엔지의 개선 과정 및 결과

    • padding 추가
    padding 10, dilate=1
    padding20, no dilate and no erosion
    • 바운딩 박스의 제시
    이미지를 잡을 수 있음을 나타냄
    • 바운딩 박스의 일정 크기 담보
    일정 크기가 되어야 자동 캡쳐를 수행 함

    4. 수학 및 머신러닝

    이 프로젝트는 미적분학, 선형대수학, 위상수학, 통계학이라는 네 가지 수학적 기둥 위에 설계된 OpenCV API를 이용해서 구축되었다. 소스코드의 각 모듈이 어떤 수학적 원리를 바탕으로 작동하는지 여기서 확인 할 수 있다.

    5.1. 미적분학 (Calculus): 움직임과 밀도

    • 미분 (Differentiation) – RedBallGame

    움직임(Motion)을 감지하기 위해 시간($t$)에 따른 픽셀 밝기($I$)의 변화율을 계산해. 연속된 프레임 간의 차이는 시간에 대한 편미분의 근사치다.

    $$\frac{\partial I}{\partial t} \approx | I_t(x,y) – I_{t-1}(x,y) |$$

    • 적분 (Integration) – TransformGame

    충돌 감지는 단순히 좌표가 겹치는 것이 아니라, 유효 영역($R$) 내부의 움직임 밀도(Density)를 적분하여 판단해. 이는 노이즈로 인한 오작동을 방지하는 강건한(Robust)한 설계다.

    $$S = \iint_{R} M(x,y) \,dx\,dy$$

    5.2. 머신러닝

    • 신경망 모델 구성
    # 신경망 모델 구성
    model = keras.Sequential([
        keras.layers.Input(shape=(28, 28)), #입력층: 28x28 크기의 2차원 배열임
        keras.layers.Flatten(), #28x28 2차원 배열을 784 1차원 배열로 변환. 뉴런 연결을 위해 필요
        keras.layers.Dense(1024, activation='relu'), #뉴런 활성화는 relu 사용
        keras.layers.Dense(512, activation='relu'), #뉴런 활성화는 relu 사용
        keras.layers.Dense(256, activation='relu'), #뉴런 활성화는 relu 사용
        keras.layers.Dense(128, activation='relu'), #뉴런 활성화는 relu 사용
        keras.layers.Dense(64, activation='relu'), #뉴런 활성화는 relu 사용
        keras.layers.Dense(10, activation='softmax') #출력이 2개 이상에서는 softmax 사용
    ])
    • 학습
    model.fit(train_images, train_labels, epochs=5) #모델 학습. 5회 반복
    • 저장
    model.save('my_first_DNN_model.keras') #모델 파일명 지정하여 저장

    6. 관련자료

    6.1 Release 페이지

    https://github.com/jalanwang/OpenCV_Project02/releases/tag/v1.0.0

    6.2 동영상

    6.3 본 문서의 위치

    https://coffeecrawlers.com/?p=2176

    6.4 구글슬라이드

    6.5 학습 및 관련 도구

    답글 남기기

    이메일 주소는 공개되지 않습니다. 필수 필드는 *로 표시됩니다