Python으로 Microsoft Azure FaceAPI와 PC 카메라를 실시간 연결

후쿠오카에서 개최된 학생 하카손에서 발표한 작품입니다.



개요


  • PC의 카메라에 비친 영상을 컷 이송으로 FaceAPI에 송신
  • 판별 결과와 함께 카메라의 영상을 출력하는 것으로 되어 있습니다.
  • 판별은 성별, 연령, 감정 분석 결과를 반영합니다.
  • 실시간이라고 하면서, while문으로 그 때 그 때의 영상을
    사진으로 자르고 있기 때문에, 컷 이송의 출력 결과가 되었습니다.

  • 작품이라고 말해 두고, 가츠코시입니다만 이쪽을 꽤 참고로 해,
    믹스시킨 것이 되고 있습니다.
  • DATUM STUDIO의 Azure Computer Vision API 및 Face API를 Python에서 사용
  • qiita 내의 기사 파이썬으로 얼굴 인식을 폭속으로 자신의 PC로 실험해보기


  • 소스 코드



    FaceApi.ipynb
    write_file_name = './tmp.jpg'
    
    import http.client, urllib.request, urllib.parse, urllib.error, base64
    import json
    import matplotlib.pyplot as plt
    
    import cv2
    cap = cv2.VideoCapture(0) # 内臓のカメラを取得
    
    #### Request headers
    #'Content-Type': APIに送るメディアのタイプ. 
    #  'application/json'(URL指定の場合), 
    #  'application/octet-stream' (Local ファイル転送の場合)
    #'Ocp-Apim-Subscription-Key': APIキーを指定する
    headers = {
    #    'Content-Type': 'application/json',
        'Content-Type': 'application/octet-stream',
        'Ocp-Apim-Subscription-Key': '[APIキー]',
    #APIキー 無料体験版のため、1分間あたりに20回のトランザクション制限
    #当時、1週間の無料体験版でキーを2つ取得できた
    }
    
    #### Request parameters
    # 取得したい情報について、パラメータを指定する
    # 'returnFaceId': 入力した顔画像に付与されるIDを返すかどうか
    # 'returnFaceLandmarks' : 目や口などの特徴となる部分の座標を返すかどうか
    # 'returnFaceAttributes' : 認識した顔からわかる属性を返す
    #   指定できるパラメータは以下で、コンマで分けて複数指定可能
    #       age, gender, headPose, smile, facialHair, 
    #       glasses, emotion, hair, makeup, occlusion, 
    #       accessories, blur, exposure and noise
    #   今回はage,gender,emotion
    params = urllib.parse.urlencode({
        'returnFaceId': 'false',
        'returnFaceLandmarks': 'false',
        'returnFaceAttributes': 'age,gender,emotion'
    })
    
    #### Request body
    # 入力したい画像の指定をする. 画像URLの指定, local ファイルの指定から選択
    # 画像はJPEG, PNG, GIF, BMPに対応
    # サイズの上限は4MB
    # 認識可能な顔のサイズは 36x36 - 4096x4096 pixelsの範囲
    # 最大64個の顔を認識可能
    
    ## URL 指定の場合以下のコメントアウトを外すし、image_urlを指定する
    #image_url = 'https://XXXXX'
    #body = { 'url': image_url }
    #body = json.dumps(body)
    
    ## Local file指定の場合
    # 以下の image_file_path に読み込むファイルのパスを指定する
    # image_file_path = '0006601775396431-web.jpg'
    # image_file = open(image_file_path,'rb')
    # body = image_file.read()
    # image_file.close()
    
    #### API request
    # 接続先リージョンによっては, 以下HTTPSConnection の "westus.api.cognitive.microsoft.com" 部分は変更する.
    # この場合は「westus」なので北米西部リージョン
    # なお "/face/v1.0/detect?%s" の部分が接続先APIの機能を指定している
    
    while True:
        key = cv2.waitKey(1)
        # カメラはESCキーで終了できるように。
        if key == 27:
            print("stop!")
            break
    
        ret, frame = cap.read()
        cv2.imwrite(write_file_name, frame)
        with open(write_file_name, 'rb') as f:
            body = f.read()
    
    # 僕の場合は'westcentralus'でのAPI取得でしたが、ここには自分がキーを取得したリージョンを入れてください
    # DATUM STUDIO さんは「westus」なので北米西部リージョンとなっておりました。
        conn = http.client.HTTPSConnection('westcentralus.api.cognitive.microsoft.com')
        conn.request("POST", "/face/v1.0/detect?%s" % params, body, headers)
        response = conn.getresponse()
        data = json.loads(response.read())    #list型
    
        if len(data) > 0:
            for face in data:
                attr = face["faceAttributes"]
                rect = face['faceRectangle']
                left = rect['left']
                top = rect['top']
                right = left + rect['height']
                bottom = top + rect['width']
                text = attr['gender']+'/'+str(attr['age'])
                emots = attr['emotion']
    
                cv2.putText(
                        frame,
                        text,
                        (left, top - 10), # 位置を少し調整
                        cv2.FONT_HERSHEY_PLAIN,
                        2,
                        (0, 255,0),
                        2,
                        cv2.LINE_AA
                    )
    
                i = 0
                for emot in emots:
                    cv2.putText(
                            frame,
                            emot + ' : ' + str(emots[emot]),
                            (right + 10, top + i*40), # 位置を少し調整
                            cv2.FONT_HERSHEY_PLAIN,
                            2,
                            (225, 0, 225),
                            2,
                            cv2.LINE_AA
                        )
                    i += 1
    
                if attr["gender"] == "male":
                    cv2.rectangle(frame, (left, top), (right, bottom), (255, 0, 0), 2)    # male -> blue
                elif attr["gender"] == "female":
                    cv2.rectangle(frame, (left, top), (right, bottom), (0, 0, 225), 2)    # female -> red
    
        conn.close()
    
        %matplotlib inline
        img = cv2.cvtColor(frame, cv2.COLOR_BGR2RGB)
        plt.imshow(img)
    
        blur = cv2.GaussianBlur(frame, (0, 0), 1)
        cv2.imshow('camera capture', blur)
    
    # 一旦画像削除の命令
    cap.release()
    # カメラが立ち上がっているので、全てのウィンドウを閉じる
    cv2.destroyAllWindows()
    
    

    결과



    나이와 성별 표시





    감정 분석





    자신의 기여



    내가 한 일은 DATUM STUDIO持っている画像ファイル를 FaceAPI에 던지는 동작을,
    qiita 기사 를 참고로 PCカメラの映像を随時 FaceAPI에 던지기로 변경합니다.

    감상


  • 우선은 완성되어 좋았다
  • 그냥 더 슬러슬러 움직이고 싶다
  • 노기자카의 소녀들과 바나나 맨 아저씨들의 나이는 상당히 정확합니다.
  • 시효 경찰은 현재 방송중인 것에서 빌렸지만 두 사람 모두 너무 어린 추정 결과
  • 기리야마 슈이치로는 순도 100%의 무표정

  • 이번 하카소에서 처음으로 Python에서 Hello! World의 끝까지 왔습니다만,
    이것을 계기로 Python의 공부도 시작하려고 생각했습니다!

    좋은 웹페이지 즐겨찾기