Python 라이브러리 Streamlit을 사용하여 얼굴 감지 앱 만들기

개요



Youtube 동영상을 참고로 Streamlit과 Microsoft Azure의 Face API를 사용하여 웹 앱을 만들었습니다.
동영상에서는 얼굴 부분에 테두리를 그리는 곳까지였습니다만, 추가로 성별과 나이를 그리도록 하고 있습니다.

출처



소스 전문입니다.
Github UP.

main.py

import io
import requests
import streamlit as st
from PIL import Image
from PIL import ImageDraw
from PIL import ImageFont

st.title('顔認証アプリ')

subscription_key = '' # AzureのAPIキー
endpoint = ''         # AzureのAPIエンドポイント
face_api_url = endpoint + 'face/v1.0/detect'
headers = {
    'Content-Type': 'application/octet-stream',
    'Ocp-Apim-Subscription-Key': subscription_key
}
params = {
    'returnFaceId': 'true',
    'returnFaceAttributes': 'age,gender',
}

# 検出した顔に描く長方形の座標を取得
def get_rectangle(faceDictionary):
    rect = faceDictionary['faceRectangle']
    left = rect['left']
    top = rect['top']
    right = left + rect['width']
    bottom = top + rect['height']

    return ((left, top), (right, bottom))


# 描画するテキストを取得
def get_draw_text(faceDictionary):
    rect = faceDictionary['faceRectangle']
    faceAttr = faceDictionary['faceAttributes']
    age = int(faceAttr['age'])
    gender = faceAttr['gender']
    text = f'{gender} {age}'

    # 枠に合わせてフォントサイズを調整
    font_size = max(16, int(rect['width'] / len(text)))
    font = ImageFont.truetype(r'C:\windows\fonts\meiryo.ttc', font_size)

    return (text, font)


# 認識された顔の上にテキストを描く座標を取得
def get_text_rectangle(faceDictionary, text, font):
    rect = faceDictionary['faceRectangle']
    text_width, text_height = font.getsize(text)
    left = rect['left'] + rect['width'] / 2 - text_width / 2
    top = rect['top'] - text_height - 1

    return (left, top)


# テキストを描画
def draw_text(faceDictionary):
    text, font = get_draw_text(faceDictionary)
    text_rect = get_text_rectangle(faceDictionary, text, font)
    draw.text(text_rect, text, align='center', font=font, fill='red')


uploaded_file = st.file_uploader("Choose an image...", type="jpg")

if uploaded_file is not None:
    img = Image.open(uploaded_file)

    with io.BytesIO() as output:
        img.save(output, format='JPEG')
        binary_img = output.getvalue()

    res = requests.post(face_api_url, params=params,
                        headers=headers, data=binary_img)
    results = res.json()

    if not results:
        raise Exception('画像から顔を検出できませんでした。')

    for result in results:
        draw = ImageDraw.Draw(img)
        draw.rectangle(get_rectangle(result), outline='green', width=3)

        draw_text(result)

    st.image(img, caption='Uploaded Image.', use_column_width=True)

기본적인 흐름은 동영상을 시청하기 위해 성별과 나이를 그리는 부분을 설명합니다.

그릴 텍스트를 가져옵니다.



Face API의 반환 값에서 성별과 나이를 가져와서 그리는 텍스트를 가져옵니다.
그런 다음 테두리 크기에 맞게 글꼴 크기를 변경합니다.
폰트 사이즈가 작다고 보이지 않기 때문에, 16 이상이 되도록 16과 산출한 사이즈를 비교해, 값이 큰 쪽을 선택하고 있습니다.
def get_draw_text(faceDictionary):
    rect = faceDictionary['faceRectangle']
    faceAttr = faceDictionary['faceAttributes']
    age = int(faceAttr['age'])
    gender = faceAttr['gender']
    text = f'{gender} {age}'

    # 枠に合わせてフォントサイズを調整
    font_size = max(16, int(rect['width'] / len(text)))
    font = ImageFont.truetype(r'C:\windows\fonts\meiryo.ttc', font_size)

    return (text, font)

인식된 얼굴 위에 텍스트를 그리는 좌표를 가져옵니다.



Face API의 반환 값에서 테두리의 위치와 그려지는 텍스트의 크기를 사용하여 테두리 상단에 가운데 정렬되는 좌표를 계산합니다.
# 認識された顔の上にテキストを描く座標を取得
def get_text_rectangle(faceDictionary, text, font):
    rect = faceDictionary['faceRectangle']
    text_width, text_height = font.getsize(text)
    left = rect['left'] + rect['width'] / 2 - text_width / 2
    top = rect['top'] - text_height - 1

    return (left, top)

텍스트 그리기



텍스트를 이미지에 그립니다.
# テキストを描画
def draw_text(faceDictionary):
    text, font = get_draw_text(faceDictionary)
    text_rect = get_text_rectangle(faceDictionary, text, font)
    draw.text(text_rect, text, align='center', font=font, fill='red')

실행 결과



테두리 위에 성별과 나이가 그려졌습니다.
이미지는 photoAC의 무료 소재를 사용합니다.

좋은 웹페이지 즐겨찾기