CastleJo의 개발일지

Face Recognition 라이브러리의 문제점, 사람 인식

|

Face Recongnition의 작동 방식

Face Recognition(일명 얼굴인식 라이브러리)는 DLib 이라는 라이브러리를 사용한다.
DLib은 CNN(합성 곱 신경망, Convolutional Neural Network)을 사용하는 머신러닝 라이브러리 이다.
CNN은 최소한의 전처리를 하는 신경망으로 가볍고, 좋은 성능을 보여준다.
얼굴인식 라이브러리는 이 DLib을 이용하여 프레임에서 얼굴의 48가지(아마?) 특징점을 추출한 뒤 학습된 데이터들 중 가장 일치하는 이미지를 찾고(임계점 설정으로 어느정도 제한선에 맞추지 못하면 Unknown으로 처리되게 함) 이름을 표출해준다.
이 라이브러리는 매우 가볍고 나름 정확하다. 하지만 문제점이 몇 개 있다.

Face Recongnition의 문제점

문제점은… 마스크를 끼면 사람이라고 인식 자체를 안한다. 당연한 결과이긴 하지만.. 마스크를 끼고있는지 유무를 확인하는 프로젝트를 하는 내 입장에선 매우 치명적인 결함이다.
따라서 나는 dlib으로는 특징점을 추출만 하고, 얼굴 인식 자체는 OpenCV DNN 라이브러리를 이용하고, 가장 상용화되어 있는 face detector.caffemodel 로 잘 알려져있는 모델을 사용할 예정이다.

아직 코드를 개발 단계에만 있어서 전체적인 코드는 공개하기가 좀 그렇고, 단편적인 부분만 떼어 볼 생각이다.

코드 설명

net = cv2.dnn.readNet('server/face_detector/deploy.prototxt',
'server/face_detector/res10_300x300_ssd_iter_140000.caffemodel')

Opencv dnn의 readNet 라이브러리로, 미리 학습된 모델을 불러온다.
참고로 OpenCV dnn 라이브러리는 학습은 지원하지 않고 순전파(forward)와 추론(inference)만을 지원한다. 여기 사용하는 caffe 모델도 미리 잘 학습된 데이터이다.
readNet의 매개변수로는 (config파일(.proto),model파일(.caffemodel)) 을 사용한다. 물론 다른 확장자 명도 있지만, 여기서는 다루지 않겠다.

이렇게 하면 retval 타입의 cv2.dnn_Net 클래스 객체가 생성된다.

blob = cv2.dnn.blobFromImage(frame, 1.0, (300, 300),(104.0, 177.0, 123.0))

다음엔 미리 카메라로 받는중인 영상인 frame을 blob화 시켜야된다.
이 떄, 아무렇게나 하면 되는것이 아니고, 모델을 어떻게 학습시켰는지에 따라 맞춰서 해야한다.
모델 이름을 보면 뒤에 300x300이라고 되어있는데, 이미지 크기를 300x300으로 학습시켰다는 뜻인거 같다. 따라서 프레임을 blob시킬 때도 크기를 300x300에 맞춰 리사이징 해줘야 한다.
위 함수의 매개변수로는 (프레임, scalefactor(입력영상 픽셀 값에 곱할 값), 사이즈, 각 채널에서 뺄 평균 값, 학습할 때 104,177,123을 각 채널에서 뺀 모양이다.)

이렇게 frame을 blob화 했다.

net.setInput(blob)

cv2.dnn_Net 클래스의 메소드인 setInput으로 blob화 된 이미지를 신경망에 넣는다.
이름과 같은 추가적인 매개변수들이 있지만, 설정할 필요가 없으므로 신경쓰지 않는다.


detections = net.forward()

cv2.dnn_Net 클래스의 메소드인 순방향 추론을 사용하는 메소드이다.
네트워크를 어떻게 생성했냐에 따라 출력을 여러개 지정할 수도 있다.
이렇게 추론된 blob 이미지 파일을 detections 변수에 저장한다.


 for i in range(0, detections.shape[2]):
        confidence = detections[0,0,i,2]

        if confidence < 0.5: #임계점 이하일시 continue
            continue

파이썬 image의 메소드의 shape에는 이미지의 가로, 세로, 채널 이 저장되어 있다.
따라서 이미지에서 각 채널을 추출하면(detections.shape[2]), 얼굴인식 모델이 얼굴이라고 인식한 채널들에 각각 접근할 수 있다.

ndarray 자료형에서 detection[0,0,i] 까지는 해당 채널에서의 이미지를 뜻한다. 앞에 [0,0]은 무엇을 의미하는 걸까…
일단 image=detection[0,0,i] 라고 가정하자.

image[2] 에는 모델에서 저장된 정확도(confidence)가 저장되어 있다.

face_location = detections[0,0,i,3:7] * np.array([w,h,w,h])

또한 image[3,4,5,6] 에는 startX, startY, endX, endY의 정보가 들어있다.
여기에 이미지의 길이만큼 곱하고 int타입으로 형변환하여 이미지의 좌표를 접근한다.

image[0:1]에는 무엇이 들어있는지 아직 잘 모르겠다.. 다음에 서버 컴퓨터를 만지면 한번 테스트 해봐야겠다.

이렇게 얼굴 인식 모델의 정제 과정을 파헤쳐봤다. 이 코드를 이용하여 DLib도 더 잘 이용할 방법을 찾아봐야 겠다.

여담

드디어 뭔가 가속이 붙는거같다!!!