[OpenCV]顔認識プログラム


ソース:ドアベル

1.顔検出

import cv2
import numpy as np

#분류기
faceCascade = cv2.CascadeClassifier('haarcascade_frontalface_default.xml')

#카메라 세팅
capture = cv2.VideoCapture(0) #초기화, 카메라 번호 (0:내장, 1:외장)
capture.set(cv2.CAP_PROP_FRAME_WIDTH,1280) #3
capture.set(cv2.CAP_PROP_FRAME_HEIGHT,720) #4

#console
face_id = input('\n enter user id and press <return> ==>') #사용자 id 입력 받기
print("\n [INFO] Initializing face capture. Look the CAMERA and wait")

count = 0 #데이터로 저장할 얼굴의 수

#영상 처리 및 출력
while True:
    ret, frame = capture.read() #카메라 상태, 프레임
    #frame = cv2.flip(frame, -1) #상하반전 
    
    gray = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY) #흑백으로
    faces = faceCascade.detectMultiScale(gray, 1.2, 6)
    #원본이미지,scaleFactor = 1.2 #검색 윈도우 확대 비율 1보다 커야함, minNeighbors #얼굴 사이 최소 간격(픽셀),minSize #얼굴 최소 크기. 이것보다 작으면 무시
    
    #얼굴에 대해 rectangle 출력
    if len(faces):
        for (x,y,w,h) in faces: #(x,y):얼굴의 좌상단 위치, (w,h):가로,세로
            cv2.rectangle(frame,(x,y),(x+w,y+h),(255,0,0),2) #이미지,좌상단좌표, 우하단좌표, 색상, 선두께)
            count += 1
            cv2.imwrite("/Users/imchaeli/WEB/practice in vs/face/dataset/data."+str(face_id)+'.'+str(count)+".jpg", gray[y:y+h, x:x+w])
        
    cv2.imshow('image',frame)
    
    #종료조건
    if cv2.waitKey(1)>0: break
    elif count>=100: break #100 face sample
    
capture.release() #메모리 해제
cv2.destroyAllWindows() #모든 윈도우 창 닫기

2.顔の勉強

import cv2
import numpy as np
from PIL import Image
import os


detector = cv2.CascadeClassifier('haarcascade_frontalface_default.xml')

path = '/Users/imchaeli/WEB/practice in vs/face/dataset' #경로: dataset폴더
recognizer = cv2.face.LBPHFaceRecognizer_create()


def getImagesAndLabels(path):
    imagePaths = [os.path.join(path,f) for f in os.listdir(path)]
    #os.listdir : 해당 디렉토리 내 파일 리스트
    #path + file Name : 경로 list 만들기
    
    faceSamples = []
    ids = []
    for imagePath in imagePaths: #각 파일마다
        #흑백 변환
        PIL_img = Image.open(imagePath).convert('L')
        img_numpy = np.array(PIL_img, 'uint8')
        
        #user id
        id = int(os.path.split(imagePath)[-1].split(".")[1])
        #마지막 index: -1
        #split(file full path)[-1]: user.1.99.jpg 형식의 파일 처리
        #split(file full path)[-1].split(".")[1]: (0번째 user) 1번째 id값
        
        #학습을 위한 얼굴 샘플
        faces = detector.detectMultiScale(img_numpy)
        for(x,y,w,h) in faces:
            faceSamples.append(img_numpy[y:y+h,x:x+w])
            ids.append(id)
            
    return faceSamples, ids

print('\n [INFO] Training Faces. wait...')
faces, ids = getImagesAndLabels(path)

recognizer.train(faces, np.array(ids)) #학습

recognizer.write('trainer/trainer.yml')
print('\n [INFO] {0} faces trained. Exiting Program'.format(len(np.unique(ids))))

3.今の顔を見つけ出す

import cv2
import numpy as np




recognizer = cv2.face.LBPHFaceRecognizer_create()
recognizer.read('trainer/trainer.yml')
cascadePath = 'haarcascade_frontalface_default.xml'
faceCascade = cv2.CascadeClassifier(cascadePath)

font = cv2.FONT_HERSHEY_COMPLEX
id = 0

names = ['None','cherry','changmin','karina','sunoo']

cam = cv2.VideoCapture(0)
cam.set(cv2.CAP_PROP_FRAME_WIDTH, 1980)
cam.set(cv2.CAP_PROP_FRAME_HEIGHT, 720)

minW = 0.1 * cam.get(cv2.CAP_PROP_FRAME_WIDTH)
minH = 0.1 * cam.get(cv2.CAP_PROP_FRAME_HEIGHT)

while True:
    ret, img = cam.read()
    gray = cv2.cvtColor(img,cv2.COLOR_BGR2GRAY)

    faces = faceCascade.detectMultiScale(
        gray,
        scaleFactor = 1.2,
        minNeighbors = 6,
        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])
        #recognizer.predict(src) : 얼굴 예측 (id와 확률값 반환)
        #confidence가 0에 가까울수록 label과 일치
        
        if confidence < 55:
            id = names[id]
        else:
            id = "unknown"
            
        confidence = "  {0}%".format(round(100-confidence))
        
        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.putText(img, text, bottom-left corner, font, fontScale, color, thickness) : label과 예측값을 이미지에 폰트로 출력한다
        
        
    cv2.imshow('camera',img)
    if cv2.waitKey(1)>0: break
    
print("\n [INFO] Exiting Program")
cam.release()
cv2.destroyAllWindows()

誤った部分

  • [学習顔]章の
    id = int(os.path.split(imagePath)[-1].split(".")[1])
  • int型なので、初めて人の顔を認識するときは、数字のidを入力する必要があります

    👎 解決したいこと


    :現在の方法は、予め入力した名前配列アドレス値と一致するidをコードに入力することで、名前による学習が可能になります.
    idを書く時に名前を入力して、名前によって分類して学習したいです
  • ...xmlファイルを同じディレクトリに配置...
    これをしなかったなんて、でたらめだ...
  • 結果



    マスクをしてもマスクをしなくても認識できます
    同じ性別だけで、違う名前も出てきます.
    また,電子機器における顔も認識できるが,認識率は低い.