Face Detection

id card 비식별화를 위해 여권, 주민등록증, 운전면허증 등에서 주체의 얼굴이미지를 가리려고 한다. 이를 위해 어디가 얼굴인지 식별하는 과정이 우선되어야 한다. 프로젝트에서는 두가지 방법으로 얼굴 인식을 진행하고 성능이 괜찮은 방법을 택하고자한다.

  1. YOLO v3
  2. Open Cv cascade haar

우선 이번 포스트에서는 YOLO v3를 통해 얼굴인식을 진행한다.

———————————————————————————–

YOLO v3

yolo 간단한 설명

0. pre-trained model

이번 프로젝트에는 pre-trained 모델을 불러와서 얼굴인식에 바로 사용할 것이다. 즉, COCO 데이터셋으로 미리 훈련된 Darknet이라는 Backbone network을 사용한 YOLO v3 모델을 불러와서 우리프로젝트에 그대로 적용하는 방식으로 택할 것이다. 파라미터를 수정(fine tuning)하지 않고 사용하기 때문에 빠르게 프로젝트에 적용할 수 있다는 장점이 있다. 그리고 이미 성능은 어느정도 보장된다.

(추후에는 pre train모델을 가져와서 fine tuning을 통해 전이학습을 진행하는 과정도 소개해볼까 한다.)

1. 모델 불러오기

YOLO 모델의 파라미터와 config 파일을 불러온다. 그리고 coco 데이터셋의 label 이 입력된 파일을 불러온다.

net = cv2.dnn.readNet("yolov3.weights",  "yolov3.cfg")

classes = []
with  open("coco.names",  "r")  as f:
	classes = [line.strip()  for line in f.readlines()]

layer_names = net.getLayerNames()
output_layers = [layer_names[i[0] - 1]  for i in net.getUnconnectedOutLayers()]

2. Object detection

본격적으로 object detection을 위해 net이라고 명명한 모델에 blopping한 이미지를 넣어주었다.

blob = cv2.dnn.blobFromImage(img,  0.00392,  (416,  416),  (0,  0,  0),  True, crop=False)
net.setInput(blob)
outs = net.forward(output_layers)

이때 outs에는 layer를 거쳐가며 탐지된 객체의 좌표와 확률값을 담고 있다.

3. 정보 표시

outs에 담겨있는 결과 중 confidence가 높은 detection결과만을 표시하기 위해 다음의 코드를 사용하였다.

confidence level의 threshold를 낮출수록 낮은 확률의 객체도 이미지에 표시된다.

class_ids = []
confidences = []
boxes = []

for out in outs:
	for detection in out:
		scores = detection[5:]
		class_id = np.argmax(scores)
		confidence = scores[class_id]
		if confidence > 0.5:
			# Object detected
			center_x = int(detection[0] * width)
			center_y = int(detection[1] * height)
			w = int(detection[2] * width)
			h = int(detection[3] * height)
			
			# 좌표
			x = int(center_x - w / 2)
			y = int(center_y - h / 2)
			boxes.append([x, y, w, h])
			confidences.append(float(confidence))
			class_ids.append(class_id)

4. Non-Maximum-Suppresion

여러 Bounding box가 동시에 존재할 것이므로 NMS를 통해 하나의 박스만을 표출하면 깔끔할 것이다.

indexes = cv2.dnn.NMSBoxes(boxes, confidences,  0.5,  0.4)

5. output

open cv를 사용하여 최종 탐지된 객체의 정보를 이미지에 표시하였다.

for i in  range(len(boxes)):
	if i in indexes:
		x, y, w, h = boxes[i]
		label = str(classes[class_ids[i]])
		cv2.rectangle(img,  (x, y),  (x + w, y + h), (0,0,255),  2)
		cv2.putText(img, label,  (x, y + 30), cv2.FONT_HERSHEY_PLAIN,  3, (0,0,255),  3)

cv2_imshow(img)

image

사진에서 보이는 것과 같이 person이라는 코코데이터셋의 라벨로 detection이 잘 되었다는 것을 알 수 있다. 프로젝트 적용은 아래와 같은 사진으로 담아야 할것이다.

image

다만 아쉬운점은 우측에 작은 얼굴이미지가 검출되지 않은 점이다. 이점은 향후 threshold를 조절해가면서 수정해 보고자 한다.

[참고자료]