人の顔を追従するカメラアプリ

はじめに

以前サーボモーターを使って物体がある方向を向くカメラを作りました。
touch-sp.hatenablog.com


それとは別に16:9のカメラ入力を1:1に切り取ってあたかもカメラを動かしているような感じになる、なんちゃって首振りカメラアプリを作りました。
touch-sp.hatenablog.com


今回はそれを組み合わせて、あたかも人の顔を追従しているようなカメラアプリを作ります。

仕組みは簡単で人の顔を検出して、それが中心にくるように16:9の画像を1:1に切り取るだけです。

方法

顔検出モデルを作る

MXNetを使いました。
Pascal VOC datasetを使って学習しています。
過去記事のままです。
touch-sp.hatenablog.com
touch-sp.hatenablog.com

Pythonスクリプト

import mxnet as mx
import gluoncv

import time
import cv2

ctx = mx.gpu() if mx.context.num_gpus() >0 else mx.cpu()

# Load the model
classes = ['face']
net = gluoncv.model_zoo.get_model('ssd_512_mobilenet1.0_custom', classes=classes, pretrained=False, root='./model')
net.load_parameters('ssd_512_mobilenet1.0_face.params')
net.collect_params().reset_ctx(ctx)

# Compile the model for faster speed
net.hybridize()

leftside = 280

# Load the webcam handler
w=1280
h=720
cap = cv2.VideoCapture(0)
cap.set(cv2.CAP_PROP_FOURCC, cv2.VideoWriter_fourcc('M', 'J', 'P', 'G'))
cap.set(cv2.CAP_PROP_FRAME_WIDTH, w)
cap.set(cv2.CAP_PROP_FRAME_HEIGHT, h)
# letting the camera autofocus
time.sleep(1)

while(True):
    # Load frame from the camera
    ret, frame = cap.read()

    # Image pre-processing  frame (720, 1280) => (576, 1024)
    frame_mx = mx.nd.array(cv2.cvtColor(frame, cv2.COLOR_BGR2RGB)).astype('uint8')
    rgb_nd,  resized_frame = gluoncv.data.transforms.presets.ssd.transform_test(frame_mx, short=576)

    # Run frame through network
    class_IDs, scores, bounding_boxes = net(rgb_nd.as_in_context(ctx))

    if scores[0][0] > 0.6:
        
        x_min = bounding_boxes[0][0][0]
        x_max = bounding_boxes[0][0][2]

        centerposition = int((((x_max + x_min) / 2) * 720 / 576 ).asscalar())

        if centerposition < leftside + 360 - 40:
            leftside -= 3

        if centerposition > leftside + 360 + 40:
            leftside += 3

        leftside = 10 if leftside < 10  else leftside
        leftside = 550 if leftside > 550 else leftside
    
    frame = frame[:, leftside:leftside+720, :]

    # Display the result
    cv2.imshow('camera', frame)

    # escを押したら終了
    if cv2.waitKey(1) & 0xFF == 27:
        break

cap.release()
cv2.destroyAllWindows()

動作環境

Ubuntu 22.04 on WSL2
CUDA 11.3.1
python 3.10.4

Python環境にインストールしたのは「mxnet-cu112」と「gluoncv」のみです。
両方ともpipでインストール可能です。

pip install mxnet-cu112
pip install gluoncv
autocfg==0.0.8
certifi==2022.6.15
charset-normalizer==2.1.0
cycler==0.11.0
fonttools==4.34.4
gluoncv==0.10.5.post0
graphviz==0.8.4
idna==3.3
kiwisolver==1.4.3
matplotlib==3.5.2
mxnet-cu112==1.9.1
numpy==1.23.1
opencv-python==4.6.0.66
packaging==21.3
pandas==1.4.3
Pillow==9.2.0
portalocker==2.5.1
pyparsing==3.0.9
python-dateutil==2.8.2
pytz==2022.1
PyYAML==6.0
requests==2.28.1
scipy==1.8.1
six==1.16.0
tqdm==4.64.0
urllib3==1.26.10
yacs==0.1.8

MXNetを使うところでつまづいたら

こちらを参照して下さい。
touch-sp.hatenablog.com

Webカメラを使うところでつまづいたら

こちらを参照して下さい。
touch-sp.hatenablog.com