AI 탐구노트

복수의 인원이 포함된 영상에서의 안면 비식별화 본문

DIY 테스트

복수의 인원이 포함된 영상에서의 안면 비식별화

42morrow 2024. 10. 4. 11:46

 

배경 사진:  Unsplash 의 Math

 

 

 

안면 비식별화

 

개인정보보호가 중요해진터라 수집된 영상에서 사람들의 안면을 비식별 처리하는 것이 중요해졌습니다.

불특정 다수가 포함되는 경우가 많은 CCTV의 경우에는 이러한 것이 이젠 의무화가 되다시피 했죠.

 

안면 비식별화는 인공지능이 확산되기 전부터 해 오던 작업이었습니다.

초기에는 컴퓨터 비전 (Computer Vision) 기술을 이용하곤 했었죠. 

그러다 딥러닝 기반으로 사람의 안면영역을 바운딩 박스나 윤곽형태를 감지하는 기술이 등장했습니다.

 

 

딥러닝 기반의 안면 비식별화 

 

객체감지, 안면감지 모델 등에 대해서는 또 다른 글이 필요할 것 같으니 목적에 맞게 건너 뛰고 

이번 글에서는 바운딩 박스 형태 감지와 안면 윤곽 기반 감지를 기준으로 비식별화를 하는 방식을 구현해 보겠습니다. 

 

하나는 바운딩 박스 형태 감지 후 blur 처리하는 것과 안면 윤곽을 인식하고 이에 맞춰 blur 처리하는 것을 보여 드리겠습니다. 

 

 

1.바운딩 박스 형태 감지 후 blur 처리

 

환경 구성

yolov7-face 모델을 이용할 예정입니다.

이를 위한 환경 구성이 필요하며 가상 환경을 생성 후 아래 절차를 진행하면 됩니다. 

# github repository 다운로드 
$ git clone https://github.com/derronqi/yolov7-face
$ cd yolov7-face

 

 

사전학습 가중치 파일 다운로드

github 링크에 걸려 있는 google 드라이브 상의 파일을 다운받습니다.

링크는 아래와 같이 되어 있고 직접 다운받거나 혹은 gdown 패키지를 설치한 후 이를 이용해 다운받습니다. 

 

사진 : 구글 드라이브 파일 다운받기 방식 설명

 

# yolov7-face 사전학습 가중치 파일 다운로드
# 구글 드라이브 URL: https://drive.google.com/file/d/1U_kH7Xa_9-2RK2hnyvsyMLKdYB0h4MJS/view?usp=sharing
$ gdown --id 1U_kH7Xa_9-2RK2hnyvsyMLKdYB0h4MJS

 

 

코드 예시

 

아래 코드는 yolo7 객체감지 모델을 이용해 얼굴 영역을 감지하는 yolov7-face라는 모델을 이용한 예시입니다.

얼굴 영역을 감지한 후 해당 부분에 단순히 OpenCV를 이용해 gaussian blur 처리를 컴퓨터 비전 기술을 이용해 하는 것이죠.

from pathlib import Path
import cv2
import torch
from models.experimental import attempt_load
from utils.datasets import LoadImages
from utils.general import non_max_suppression, scale_coords

device = 'cpu'
kpt_label = 5

def detect():
    # Load model
    model = attempt_load('yolov7-w6-face.pt', map_location='cpu') 
    stride = int(model.stride.max())
    names = model.module.names if hasattr(model, 'module') else model.names  # get class names
    dataset = LoadImages('./crowd.jpg', img_size=640, stride=stride)
    # Run inference
    for path, img, im0s, vid_cap in dataset:
        img = torch.from_numpy(img).to(device)
        img = img.float()  # uint8 to fp16/32
        img /= 255.0  # 0 - 255 to 0.0 - 1.0
        if img.ndimension() == 3: img = img.unsqueeze(0)

        # Inference
        pred = model(img, augment=False)[0]

        # Apply NMS
        pred = non_max_suppression(pred, 0.25, 0.45, classes=0, agnostic=False, kpt_label=kpt_label)

        # Process detections
        for i, det in enumerate(pred):  # detections per image
            p, s, im0, frame = path, '', im0s.copy(), getattr(dataset, 'frame', 0)
            gn = torch.tensor(im0.shape)[[1, 0, 1, 0]]  # normalization gain whwh
            if len(det):
                # Rescale boxes from img_size to im0 size
                scale_coords(img.shape[2:], det[:, :4], im0.shape, kpt_label=False)
                scale_coords(img.shape[2:], det[:, 6:], im0.shape, kpt_label=kpt_label, step=3)

                # Write results
                for det_index, (*xyxy, conf, cls) in enumerate(reversed(det[:,:6])):
                    c = int(cls)  # integer class
                    label =  f'{names[c]} {conf:.2f}'
                    kpts = det[det_index, 6:]

                    # replace face region with blurred one
                    left_pos, top_pos, right_pos, bottom_pos = int(xyxy[0]), int(xyxy[1]), int(xyxy[2]), int(xyxy[3])
                    face_image = im0[top_pos:bottom_pos, left_pos:right_pos]
                    face_image = cv2.GaussianBlur(face_image, (99,99), 30)
                    im0[top_pos:bottom_pos, left_pos:right_pos] = face_image

            cv2.imshow(str(p), im0)
            if cv2.waitKey(10000) == ord('q'): break

if __name__ == '__main__':
    with torch.no_grad():
        detect()

 

 

결과 확인

감지 영역 자체를 바운딩 박스 형태로 하기때문에 아래 결과물 또한 그렇게 나왔습니다.

아주 약간의 어색함은 있지만 기본적인 비식별화는 제대로 하고 있는 셈입니다.

 

 

흠... 하지만, 아쉬운 것은 하나 있습니다.

얼굴이 계랸형인 혹은 둥근형인 사람의 경우, 윤곽을 따르도록 하면 훨씬 더 자연스런 장면이 나올 것 같습니다.

 

 

2.안면 윤곽 형태 감지 후 blur 처리 

 

환경 구성

이번 방식은 face-blur라는 github 공개코드를 이용한 테스트를 진행합니다. 

이 모델은 안면 mask 감지를 위해 3D Dense Face Alignment의 공식 Pytorch 구현체인 3DDFA_V2를 사용합니다. 

이 때문에 이를 위한 so(라이브러리) 빌드하는 과정이 선행되어야 합니다. 

# 3DDFA 모델과 face-blur 모델 clone 및 cpu_nms so 파일 생성
$ git clone https://github.com/cleardusk/3DDFA_V2.git
$ cd 3DDFA_V2
$ sh ./build.sh  
$ cd ..

 

 

이후 face-blur 코드를 이용한 작업을 진행합니다.

3DDFA_V2와 face-blur는 같은 깊이 수준이니 헷갈리지 마세요. (예: ~/git/3DDFA_V2, ~/git/face-blur)

# face-blur 데모 실행 (결과는 위의 이미지)
$ git clone https://github.com/scoutant/face-blur.git
cd 3DDFA_V2
$ python ../face-blur/blur.py -f ../face-blur/data/friends_01.jpg

 

 

참고로 안면 윤곽을 추출하는 모델은 많이 나와 있습니다. 

mediapipe 조차 이런 역할을 훌륭하게 수행합니다.

다만, mediapipe 기본은 복수의 안면을 처리하지 못하므로 우리의 목적에는 맞지 않는다고 생각됩니다. 

 

코드 예시

코드 자체는 직접 github 링크에서 확인하시면 됩니다. 

단 여기서 사용한 샘플 이미지는 미국 드라마 프렌즈에서 나온 한 장면 이미지를 이용했습니다. 

 

 

결과 확인

얼굴 윤곽을 따라 잘 표현되고 있습니다. 

사진 : 프렌즈의 한 장면을 face-blur를 이용해 처리한 결과 예시

 

 

다른 사진(인터넷 어디선가 테스트 용으로 다운받았는데 출처가 불분명합니다 ^^;)을 가지고 테스트를 해 봤습니다.

 

이 사진은 위와는 달리 개별 사람들의 얼굴 크기가 3DDFA_V2 모델이 학습한 안면의 최소 크기(120x120)보다 작습니다. 

역시나 제대로 감지를 하지 못하는 제약 사항이 있네요.

즉, 120x120 이상 크기의 안면 얼굴을 보이는 경우에 적당하다는 결론을 내릴 수 있겠습니다. 

 

사진 : 안면영역이 작은 경우 적용 결과 예시.

 

 

영상 이미지에서의 안면 바운딩 박스와 안면 윤곽 인식 방식 2가지에 대해 비식별화를 하는 과정을 살펴 봤습니다.