전공/인공지능(입문)

2. OpenCV와 Raspberry Pi를 활용한 얼굴 인식

문정훈 2022. 6. 27. 08:49
더보기

목차

1. 작품 설명
2. 모델 설명
3. 웹사이트 소
4. 얼굴인식을 실행한 모습
5. 웹서버

 

1. 작품 설명

라즈베리 파이와 OpenCV 라이브러리를 활용한 사람 얼굴 인식 프로젝트입니다. 

필요한 하드웨어 장비로는 라즈베리파이에는 카메라 모듈, 3개의 LED(빨, 파, 노) 및 저항입니다. 

라즈베리 OS 환경에 OpenCV라이브러리를 설치한 뒤 얼굴을 인식해주는 라이브러리를 사용하여 사람의 얼굴을 인식합니다. 사람의 얼굴을 3가지 카테고리로 분류하는데 시스템에 등록한 사람 중 Owner와 Owner가 아닌 사람(Other) 그리고 시스템에 등록되지 않은 사람인 None으로 구별합니다. 사용자의 관리는 파일로 그 정보를 관리하도록 하였습니다. 

 

<요약>

 라즈베리 파이에 연결된 카메라 모듈로 사람의 얼굴을 비추면 얼굴을 인식한다.

 

웹 사이트에서 등록된 사용자라면 얼굴을 비출 시 등록된 이름을 출력해준다.
만약 등록되지 않는 사람이라면 None을 출력한다.

 

Onwer, Other, None 이렇게 3가지 카테고리고 사람을 분류한다.  OnwerOther인 경우는 카메라에 상에 등록된 이름을 옆 그림과 같이 출력해준다. None인 경우 unknown을 출력한다.

 

▶ 라즈베리 파이에 연결된 3개의 LED(빨, 파, 노)로 Owner, Other, None을 각각 출력해준다. 

Onwer인 경우 -> 파란색, Other인 경우 -> 노란색, None인 경우 빨간색 LED 불을 켜준다.


 

 

2. 딥러닝 모델 설명

얼굴인식 과정은 총 3가지 단계를 거친다.

 

단계1. 데이터 수집

hearcasecades/haarcascade_frontalface_default.xml 파일을 사용해 카메라로 사람의 얼굴을 인식한다.
사용자 등록 버튼을 통해 30장 가량의 얼굴 이미지가 수집된다.

 

단계2. 학습 데이터를 통해 딥러닝 모델 생성

각 사용자는 30장의 사진 데이터를 각각 가지고 있다. 이 학습 데이터를 통해 단계1에서는 등록된 사용자의 얼굴을 구별해주는 딥러닝 모델을 생성한다.

 

단계3. 사용자의 얼굴을 인식한다.

등록된 사용자는 파일로 그 정보가 관리 된다. 또한 누가 owner인지 정보를 저장하는 파일이 존재한다. 이 정보에 따라 사용자의 Owner, Other, None여부를 LED 등을 통해 알려준다.


 

 

3. 웹 사이트 소개 

1) 메인 화면

Python Flask를 통해 웹 서버를 구현하였고 위 사진은 메인 화면이다. 

 

 

2) Owner 버튼을 클릭할 시 

Owner 페이지는 현재 등록된 사용자들을 가로 스크롤을 통해 보여준다. User IdUser name필드를 가진다.

▶ 아래 Id를 입력하고 submit을 하면 Owner가 변경된다.

 

 

3) Remove 버튼을 클릭할 시 

▶ 현재 등록된 사용자들을 가로 스크롤을 통해 보여준다. User IdUser name필드를 가진다.

▶ 아래 Id를 입력하고 submit을 하면 사용자가 제거된다.

 

 

 

4) Registration 버튼 클릭 및 Recognition 버튼 클릭

▶ 새로 등록할 사용자의 이름을 입력하고 submit을 한다.

▶ 잠시 후 카메라 화면에 나타나고 얼굴을 카메라 비추고 있으면 30장 가량의 이미지 데이터를 수집한다.

▶ 새로운 사용자가 등록된다.

Recognition 버튼을 클릭하면 웹 사이트에는 변화가 없고 잠시 후 카메라가 출력되어 얼굴 인식을 시작한다.


 

 

4. 얼굴 인식을 실행한 모습

1) Face Recognition 버튼 클릭한 경우(Owner인 경우)

▶ 수집된 사용자 학습 데이터를 통해 딥러닝 모델을 생성한다.

▶ 잠시 후 카메라라 나오며 임의의 얼굴을 비추면 Owner, Other, None으로 분류해주고 화면에는 사용자의 이름(또는 None)을 화면상에 보여준다.

Onwer인 경우 파란색LED가 켜진다.

 

 

2) Face Recognition 버튼 클릭한 경우(Ohter인 경우)

▶ 수집된 사용자 학습 데이터를 통해 딥러닝 모델을 생성한다.

Ohter인 경우 등록된 이름으로 이름을 화면에 출력해주고 노란색LED가 켜진다.

 

 

3) Face Recognition 버튼 클릭한 경우(None인 경우)

▶ 수집된 사용자 학습 데이터를 통해 딥러닝 모델을 생성한다.

None인 경우 등록되지 않은 사용자 이므로 화면에 None이라고 알려주고 LED로 빨간 등을 밝힌다.


 

5.  사용자 정보를 파일로 관리

▶ 사용자의 정보는 root 디렉토리의 하위 디렉토리에서 txt 파일로 관리된다.

왼쪽 이미지인 infor.txt은 사용자 한 명당 한 줄로 id와 이름을 공백으로 구분하여 저장한다.

▶ 오른쪽 이미지인 owner.txt 파일은 현재 누가 owner인지 id를 저장한다.

▶ 사용자의 추가 및 제거 시 infor.txt파일은 그 순서가 재조정된다.


 

6.  웹서버 

  웹서버

import cv2
import os
import numpy as np
import RPi.GPIO as GPIO
import time
from flask import Flask, redirect, url_for, render_template, request
#app = Flask(__name__, static_url_path='/static')
app = Flask(__name__)

GPIO.setmode(GPIO.BCM)
GPIO.setup(2,GPIO.OUT) # blue
GPIO.setup(17,GPIO.OUT) # yellow
GPIO.setup(7,GPIO.OUT) # red


def your_name():
	yn = txt.get() 
	lbl2.configure(text="your name: "+yn) 
	messagebox.showinfo("name",yn) 

def f():
    os.system("python 03_face_recognition.py")
    return 1


@app.route('/')
def home():
    return render_template('index.html')

@app.route('/owner', methods=['GET', 'POST'])
def  owner():
    if request.method == 'GET':
        #Informatin data from infor.txt
        f1 = open('/home/pi/fdCam/userInformation/infor.txt', 'r')
        inforArray = [] #user inform array
        while True:
            line = f1.readline()
            if not line: break
            inforArray.append(line)
        f1.close()
        print(inforArray)
        
        #who is Owner?
        f2 = open('/home/pi/fdCam/owner/owner.txt', 'r')
        # if owner file is null return '' 
        # if owner file  is not null reutnr <owner>\n'
        
        owner = f2.readline()
        f2.close()
        print(owner)
        return render_template('owner.html', inform = inforArray, ownerId = owner)
    
    elif request.method == 'POST':
        userId = request.form['id'] # id entered by user
        # write 
        f1 = open('/home/pi/fdCam/owner/owner.txt', 'w')
        
        f1.write("{0}\n".format(userId))
        f1.close()
        return redirect(url_for('home'))


@app.route('/registration', methods=['GET', 'POST'])
def registration():
    if request.method == 'GET':
        return render_template('registration.html')
    elif request.method == 'POST':
        name = request.form['name'] # Name entered by user
        # Read an existing member from a file
        id = 0
        f1 = open('/home/pi/fdCam/userInformation/infor.txt', 'r')
        id = len(f1.readlines())
        
        sub_face_id = 0
        if  f1.tell() == 1: # tell() is current Cursor point
            f2 = open('/home/pi/fdCam/userInformation/infor.txt', 'w')
            f2.write("{0} {1}\n".format(1, name))
            sub_face_id = 1
        else:
            f2 = open('/home/pi/fdCam/userInformation/infor.txt', 'a')
            f2.write("{0} {1}\n".format(id+1, name))
            sub_face_id = id+1
        
        f2.close() 
        f1.close
        
        #### Start: Collect data from new user with opencv and Create a new model!
        cam = cv2.VideoCapture(0)
        cam.set(3, 640) # set video width
        cam.set(4, 480) # set video height
        face_detector = cv2.CascadeClassifier('haarcascades/haarcascade_frontalface_default.xml')

        face_id = sub_face_id # id+1
        print("\n [INFO] Initializing face capture. Look the camera and wait ...")

        # Initialize individual sampling face count
        count = 0
        while(True):
            ret, img = cam.read()
            #img = cv2.flip(img, -1) # flip video image vertically
            gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
            faces = face_detector.detectMultiScale(gray, 1.3, 5)
            for (x,y,w,h) in faces:
                cv2.rectangle(img, (x,y), (x+w,y+h), (255,0,0), 2)     
                count += 1
                # Save the captured image into the datasets folder
                cv2.imwrite("faseDataSet/User." + str(face_id) + '.' + str(count) + ".jpg", gray[y:y+h,x:x+w])
                cv2.imshow('image', img)
            k = cv2.waitKey(100) & 0xff # Press 'ESC' for exiting video
            if k == 27:
                break
            elif count >= 30: # Take 30 face sample and stop video
                 break
        # Do a bit of cleanup
        print("\n [INFO] Exiting Program and cleanup stuff")
        cam.release()
        cv2.destroyAllWindows()
        #### end: Collect data from new user with opencv and Create a new model!
        
        return redirect(url_for('home'))
    
@app.route('/remove', methods=['GET', 'POST'])
def Remove():
    if request.method == 'GET':
        #Informatin data from infor.txt
        f1 = open('/home/pi/fdCam/userInformation/infor.txt', 'r')
        inforArray = [] #user inform array
        while True:
            line = f1.readline()
            if not line: break
            inforArray.append(line)
        f1.close()
        print(inforArray)
        
        #who is Owner?
        f2 = open('/home/pi/fdCam/owner/owner.txt', 'r')
        # if file is null return '' 
        # if file  is not null reutnr <owner>\n'
        owner = f2.readline()
        f2.close()
        print(owner)
        return render_template('remove.html', inform = inforArray, ownerId = owner)
        
    elif request.method == 'POST':
        userId = request.form['id'] # (remove) id entered by user
        # write 
        f1 = open('/home/pi/fdCam/userInformation/infor.txt', 'r')
        informations = f1.readlines()
        print(informations)
        newInformations = []
        count = 1
        exitFlag = 1
        for i in informations:
            if userId != "" and count != int(userId) and len(informations) >= int(userId) and int(userId) > 0 :
                information = i.split()
                newInformations.append(information)
                exitFlag = -1
            elif int(userId) == count:
                exitFlag = -1
            count +=1
            
        print('hello')
        print(exitFlag)
        if exitFlag == 1:
            return redirect(url_for('home')) # It's case of no users
        
        else:
            print(newInformations) # this variable is new users for the old users
            count2 = 0
            for i in newInformations: #The process of matching the user's id from 1 to 1
                newInformations[count2] = str(count2 + 1) + " " + newInformations[count2][1]+"\n"
                count2 +=1
            print(newInformations)
            f1.close()
            
            f2 = open('/home/pi/fdCam/userInformation/infor.txt', 'w')
            for i in newInformations:
                f2.write(i) # Update user file information
            f2.close()
            
            #user face dataset remove!!
            for i in range(1, 31):
                os.remove('/home/pi/fdCam/faseDataSet/User.{0}.{1}.jpg'.format(userId, i))
            
            #All file name upadate
            for i in range(int(userId) + 1, len(newInformations) + 2):
                for j in range(1, 31):
                    os.rename('/home/pi/fdCam/faseDataSet/User.{0}.{1}.jpg'.format(i, j),'/home/pi/fdCam/faseDataSet/User.{0}.{1}.jpg'.format(i-1, j))
            
            return redirect(url_for('home'))
            
@app.route('/face_recognition')
def Face_Recognition():    
    os.system("python 02_face_training.py")
    recognizer = cv2.face.LBPHFaceRecognizer_create()
    recognizer.read('trainer/trainer.yml')
    cascadePath = "haarcascades/haarcascade_frontalface_default.xml"
    faceCascade = cv2.CascadeClassifier(cascadePath);
    font = cv2.FONT_HERSHEY_SIMPLEX

    #iniciate id counter
    id = 0

    # names related to ids: example ==> loze: id=1,  etc
    # add to array of user name 
    names = ['None']
    f1 = open('/home/pi/fdCam/userInformation/infor.txt', 'r')
    inforArray = [] #user inform array
    ownerID = 0
    while True:
        line = f1.readline()
        if not line: break
        inforArray.append(line)
    f1.close()
    print(inforArray)
    
    for i in inforArray:
        names.append(i.split()[1])
    print(names)
    f1.close()
    
    f2 = open('/home/pi/fdCam/owner/owner.txt', 'r')
    ownerID = f2.read(1) # not owner-> '\n'
    if ownerID == '\n':
        ownerID = -1
    else:
        ownerID = int(ownerID)
    print(ownerID)
    f2.close()
    
    # Initialize and start realtime video capture
    cam = cv2.VideoCapture(0)
    cam.set(3, 640) # set video widht
    cam.set(4, 480) # set video height

    # Define min window size to be recognized as a face
    minW = 0.1*cam.get(3)
    minH = 0.1*cam.get(4)

    recog_flags = -1
    while True:
        ret, img =cam.read()
        img = cv2.flip(img, 1) # Flip vertically
        gray = cv2.cvtColor(img,cv2.COLOR_BGR2GRAY)
        
        faces = faceCascade.detectMultiScale( 
            gray,
            scaleFactor = 1.2,
            minNeighbors = 5,
            minSize = (int(minW), int(minH)),
           )

        for(x,y,w,h) in faces:
            cv2.rectangle(img, (x,y), (x+w,y+h), (0,255,0), 2)
            id, confidence = recognizer.predict(gray[y:y+h,x:x+w])
            # Check if confidence is less them 100 ==> "0" is perfect match
            
            
            if (confidence < 100):
                id = names[id]
                confidence = "  {0}%".format(round(100 - confidence))
                if(names.index(id) == ownerID):
                    print('You  owner: ' + id)
                    GPIO.output(2,True)   # Blue LED ON
                    GPIO.output(17,False) # yellow off
                    GPIO.output(7,False)  # red off
                else:
                    print('Not Owner!!!')
                    GPIO.output(2,False)   # Blue LED off
                    GPIO.output(17,True) # yellow ON
                    GPIO.output(7,False)  # red off
            else:
                id = "unknown"
                confidence = "  {0}%".format(round(100 - confidence))
                print('who are you?')
                GPIO.output(2,False)   # Blue LED off
                GPIO.output(17,False)  # yellow off
                GPIO.output(7,True)    # red ON
            
            cv2.putText(img, str(id), (x+5,y-5), font, 1, (255,255,255), 2)
            cv2.putText(img, str(confidence), (x+5,y+h-5), font, 1, (255,255,0), 1)  
        
        cv2.imshow('camera',img) 
        k = cv2.waitKey(10) & 0xff # Press 'ESC' for exiting video
        if k == 27:
            break
    # Do a bit of cleanup
    print("\n [INFO] Exiting Program and cleanup stuff")
    cam.release()
    cv2.destroyAllWindows()
    
    GPIO.output(2,False)   
    GPIO.output(17,False)
    GPIO.output(7,False)  
    return redirect(url_for('home'))

@app.route('/gohome', methods=['GET', 'POST'])
def Gohome():
    if request.method == 'POST':
        return redirect(url_for('home'))
        
if __name__ == '__main__':
    app.run()

 


 

 

7.  실행 영상

 

 

'전공 > 인공지능(입문)' 카테고리의 다른 글

1. Teachable Machine - 마스크 착용 인식 모델  (0) 2022.05.24