先日参加したCrossOverGameJam04で使用したMicrosoftのFaceAPIについてまとめてみましたよ。
この記事にはUnity2017.1.0f3を使用しています。
FaceAPIとは
どんなものなの
顔の画像から、年齢や感情などの情報を取得できちゃう楽しいものですぜ。
アプリ内にSDKを組み込まなくても、ネットワーク経由で画像情報を送ることで簡単に情報が取得できちゃう。
逆から言えば、ネットワークに繋がっている状態が必須だよ。
送られてくる顔認識の情報はJson形式になっているみたい。
MicrosoftAzureの機能なので、MicrosoftAzureへの登録が必須だよ。
どういう風に登録するの
MicrosoftAzureへの登録とFaceAPIの登録のやり方については、参加したCrossOverGameJamの運営さんのブログが分かりやすいかな。
こちらを参考にしてみてくださいね。
CrossOver GameJam 4回目 はじまるよ〜crossoverlink.wordpress.com
顔認識情報を取得しよう
ではスクリプトを組んでいきますよ。
今回のFaceAPIを使うためのベースのクラスがこちらです。
TestFaceAPI.cs
using UnityEngine; using System.Collections; public class TestFaceAPI : MonoBehaviour { private IEnumerator Start() { yield return null; } } // class TestFaceAPI
これにいろいろな機能を組み込んでいきますよー。
まずはリクエストするURLを作成する必要がありますね。
private IEnumerator Start() { string url = GetFaceAPIURL(); yield return null; } private string GetFaceAPIURL() { return string.Empty; }
地域指定しなきゃ
MicrosoftAzureにてFaceAPIを登録した際に、どの地域にするかを指定したと思います。
地域ごとでリスエストするURLが違うため、その対応を行いましょう。
こんな感じにURLは作られます。
https://[location].api.cognitive.microsoft.com/face/v1.0/detect[?returnFaceId][&returnFaceLandmarks][&returnFaceAttributes]
この[location]の部分に地域用の文字列を仕込みます。
地域用の変数などを用意しましょう。
private enum ELocation { WestUS, EastUS2, WestCentralUS, WestEurope, SoutheastAsia, } [SerializeField] private ELocation m_location = default( ELocation );
あとはこれらを利用してURLを作成します。
private string GetFaceAPIURL() { string localURL = GetLocationURL( m_location ); Debug.AssertFormat( !string.IsNullOrEmpty( localURL ), "不正な地域設定です。m_location={0}", m_location ); return string.Format( "https://{0}.api.cognitive.microsoft.com/face/v1.0/detect", localURL ); } private string GetLocationURL( ELocation i_location ) { return i_location.ToString().ToLower(); }
取得するパラメーターを追加しなきゃ
地域を指定すれば基本的なリクエストするURLを完成なのですが、取得する顔認識情報が寂しいものになります。
URLの部分に追加でパラメーターを指定してあげることで、もっといろいろな情報が送られてくるようになります。
FaceId
FaceIdそのものについては後述。
FaceIdを取得するかどうかをtrue
かfalse
で指定できます。
指定しない場合はtrue
になります。
[SerializeField] private bool m_requestFaceId = true; private string GetFaceIdField( bool i_flag ) { return string.Format( "?returnFaceId={0}", i_flag ); }
FaceLandmarks
FaceLandmarksそのものについては後述。
FaceLandmarksを取得するかどうかをtrue
かfalse
で指定できます。
指定しない場合はfalse
になります。
[SerializeField] private bool m_requestFaceLandmarks = false; private string GetFaceLandmarksField( bool i_flag ) { return string.Format( "&returnFaceLandmarks={0}", i_flag ); }
FaceAttributes
FaceAttributesそのものについては後述。
この情報が一番楽しいはず。
FaceAttributesにはいろいろな種類があり、欲しい分だけパラメーターを追加してあげる必要がありますよ。
文字列でガンガン足していけばいいのですが、外部からしてしやすいようにFlagsタイプのEnum
を使いましょう。
FlagsタイプのEnum
をエディタ上で使いやすくするために、以下の記事のエディタ拡張を使わせてもらっています。
baba-s.hatenablog.com
[System.Flags] private enum EFaceAttributes { age = 1 << 0, gender = 1 << 1, smile = 1 << 2, facialHair = 1 << 3, headPose = 1 << 4, glasses = 1 << 5, emotion = 1 << 6, hair = 1 << 7, makeup = 1 << 8, accessories = 1 << 9, occlusion = 1 << 10, blur = 1 << 11, exposure = 1 << 12, noise = 1 << 13, } [SerializeField, EnumFlags] private EFaceAttributes m_requestFaceAttributes = 0; private string GetFaceAttributesField( EFaceAttributes i_attributes ) { string attributesStr = string.Empty; foreach( EFaceAttributes attribute in System.Enum.GetValues( typeof( EFaceAttributes ) ) ) { if( ( i_attributes & attribute ) != 0 ) { attributesStr += string.Format( "{0},", attribute ); } } if( string.IsNullOrEmpty( attributesStr ) ) { return string.Empty; } // 最後の","はいらないので削除(もっといい方法があるような気がするけど……)。 attributesStr = attributesStr.Remove( attributesStr.Length - 1 ); return string.Format( "&returnFaceAttributes={0}", attributesStr ); }
取得するパラメーターを追加しなきゃ2
上記で作成したパラメーターをリクエストするURLに合体させてみましょう。
private string GetFaceAPIURL() { string localURL = GetLocationURL( m_location ); string idField = GetFaceIdField( m_requestFaceId ); string landmarksField = GetFaceLandmarksField( m_requestFaceLandmarks ); string attributesField = GetFaceAttributesField( m_requestFaceAttributes ); Debug.AssertFormat( !string.IsNullOrEmpty( localURL ), "不正な地域設定です。m_location={0}", m_location ); return string.Format( "https://{0}.api.cognitive.microsoft.com/face/v1.0/detect{1}{2}{3}", localURL, idField, landmarksField, attributesField ); }
これでリクエストするURLの完成です。
ヘッダー情報を追加しなきゃ
情報を送る際にヘッダー情報もカスタマイズする必要があるのです。
FaceAPIには二種類の方法で顔の画像を送ることが出来ます。
- 画像を直接送る
- 画像のURLを送る
送る方法にて、ヘッダーの情報が変わってきます。
どちらの方法でもFaceAPIのサブスクリプションキーは絶対に送る必要があります。
サブスクリプションキーはMicrosoftAzureからFaceAPIを登録した際に取得できると思いますよ。
[SerializeField] private string m_subscriptionKey = string.Empty;
では顔の画像を送る方法毎のヘッダー情報を作成していきましょう。
画像を直接送る場合
画像データを直接送る場合のヘッダー情報はこんな感じになります。
private Dictionary<string, string> GetBinaryTypeHeader( string i_key ) { var header = new Dictionary<string, string>() { { "Content-Type", "application/octet-stream" }, { "Ocp-Apim-Subscription-Key", i_key }, }; return header; }
画像のURLを送る場合
画像のURLを送る場合のヘッダー情報はこんな感じになります。
private Dictionary<string, string> GetURLTypeHeader( string i_key ) { var header = new Dictionary<string, string>() { { "Content-Type", "application/json; charset=UTF-8" }, { "Ocp-Apim-Subscription-Key", i_key }, }; return header; }
ヘッダー情報を追加しなきゃ2
折角なので、上記二種の送り方をエディタ上で設定できるようにしましょう。
private enum EPostType { Binary, URL, } [SerializeField] private EPostType m_postType = default( EPostType );
そして、送る方式によって先ほど作ったヘッダー取得関数を切り替わるようにします。
private IEnumerator Start() { string url = GetFaceAPIURL(); Dictionary<string, string> headers = null; if( m_postType == EPostType.Binary ) { headers = GetBinaryTypeHeader( m_subscriptionKey ); } else { headers = GetURTypeLHeader( m_subscriptionKey ); } yield return null; }
画像の情報を作らなきゃ
さて最後に、送る顔の画像情報を作成しましょう。
これも直接送るかURLを送るかで違っていきますよ。
画像を直接送る場合
バイト型の配列にしなくてはいけません。
Texture2D
なら簡単に取得できるので、Texture2D
で送る顔の画像を指定するようにしてみましょう。
[SerializeField] private Texture2D m_texture = null; private byte[] GetTextureBinary( Texture2D i_texture ) { if( i_texture == null ) { return null; } return i_texture.EncodeToPNG(); }
画像のURLを送る場合
URLを送る場合でも、やっぱりバイト型の配列にしなくてはいけません。
[SerializeField] private string m_textureURL = null; private byte[] GetTextureURLBinary( string i_url ) { if( string.IsNullOrEmpty( i_url ) ) { return null; } string json = string.Format( "{{ \"url\":\"{0}\" }}", i_url ); return System.Text.Encoding.UTF8.GetBytes( json ); }
画像の情報を作らなきゃ2
上記の二種の関数をヘッダー情報を取得した際と同じように使用できるようにします。
private IEnumerator Start() { string url = GetFaceAPIURL(); Dictionary<string, string> headers = null; byte[] postData = null; if( m_postType == EPostType.Binary ) { headers = GetBinaryTypeHeader( m_subscriptionKey ); postData = GetTextureBinary( m_texture ); } else { headers = GetURTypeLHeader( m_subscriptionKey ); postData = GetTextureURLBinary( m_textureURL ); } Debug.AssertFormat( postData != null && postData.Length > 0, "Postデータが不正です。" ); yield return null; }
WWWを使って情報を送らなきゃ
さて、下準備が整いました。
作成したすべての情報をWWW
を使って送信しましょう。
……本当はUnityWebRequest
を使って送信しようかと思ったのですが、UnityWebRequest
はまだまだ勉強不足なので旧型WWW
でいきます。
private IEnumerator Start() { string url = GetFaceAPIURL(); Dictionary<string, string> headers = null; byte[] postData = null; if( m_postType == EPostType.Binary ) { headers = GetBinaryTypeHeader( m_subscriptionKey ); postData = GetTextureBinary( m_texture ); } else { headers = GetURTypeLHeader( m_subscriptionKey ); postData = GetTextureURLBinary( m_textureURL ); } Debug.AssertFormat( postData != null && postData.Length > 0, "Postデータが不正です。" ); string receivedJson = null; using( WWW www = new WWW( url, postData, headers ) ) { yield return www; receivedJson = www.text; } Debug.Log( receivedJson ); }
これでJson形式にて情報が取得出来ているのが分かります。
やったね。
取得した顔認識情報にて
送った顔画像の情報の取得に成功しました。
おめでとうございます。
あとはごゆるりとお使いくださいませ……、と言いたいところですが、Jsonデータのままだと情報が扱いにくいので、クラスか何かに変換して使いやすい形にしましょう。
意地でもJsonUtilityを使わなきゃ
Jsonを変換するにはMiniJson
やLitJson
を使えばいいと思いますが、Unityで作業しているならJsonUtility
を使えばSDKなどを組み込まずに済むので楽ちんそうです。
ただ、受け取った顔認識のJsonデータはJsonUtility
で使えるフォーマットではなかったりします。
ぐぬぬ、これは厄介。
いや、大丈夫だ。
受けとったJsonデータを改竄してしまえば、JsonUtility
でも変換できるようになるはずだ!
早速やってみよう。
※ 筆者はJsonUtility
を意地でも使うという謎の使命感に取りつかれています。
以下の内容は参考程度にとどめておいたほうがよいかと思われます。
まずJsonデータは以下のような形で受け取れます。
[{"faceId":"d241307e-a331-4664-a3cf-63bfffed2ca5","faceRectangle":{"top":298,"left":694,"width":234,"height":234},"faceAttributes":{"age":29.0}}]
この情報のJsonUtility
を使った変換先のクラスを以下のように作成しましょう。(各クラスの詳細は後述)
[System.Serializable] public class FacePersonData { [SerializeField] public string faceId = null; [SerializeField] public FaceRectangle faceRectangle = null; [SerializeField] public FaceLandmarks faceLandmarks = null; [SerializeField] public FaceAttributes faceAttributes = null; } // class FacePersonData
送った顔の画像情報に複数の顔がある場合は以下のように複数の情報が記述された状態で受け取れます。
[{"faceId":"13472612-1001-4d8d-8470-d2caf6e4ca76","faceRectangle":{"top":140,"left":242,"width":64,"height":64},"faceAttributes":{"age":28.5}},{"faceId":"a67283ef-684a-4857-8208-7001557f4896","faceRectangle":{"top":168,"left":436,"width":61,"height":61},"faceAttributes":{"age":30.9}}]
これは先ほど作成したFacePersonData
を配列で持っている形になっています。
そのためFacePersonData
を配列として持っているクラスを作成します。
[System.Serializable] public class FaceData { [SerializeField] public FacePersonData[] persons = null; } // class FaceData
しかし、このままでは最初に話した通り、JsonUtility
では変換できません。
JsonUtility
を使用するにはフィールド名が必ず必要になります。
すなわち、受け取ったJsonデータにフィールド名を足してやれば問題なく変換できるようになるのです。
private FaceData ConvertJson( string i_json ) { Debug.AssertFormat( !string.IsNullOrEmpty( i_json ), "Json情報が設定されていません。" ); // 無理やりJsonUtilityで使える形に変更する。 string json = string.Format( "{{\"persons\":{0}}}", i_json ); FaceData faceData = null; try { faceData = JsonUtility.FromJson<FaceData>( json ); } catch( System.Exception i_exception ) { Debug.LogWarningFormat( "Json情報をクラス情報へ変換することに失敗しました。exception={0}", i_exception ); faceData = null; } return faceData; }
この形なら変換が可能になります。
ついでにエラーの対応も行いましょう。
FaceAPIが何らかの理由でエラーを吐き出す可能性もあります。
その場合はエラー専用のJsonデータを受け取ることになります。
エラー用のJsonデータと受け取りクラスを作成しましょう。
[System.Serializable] public class FaceError { [SerializeField] public FaceErrorDetail error = null; } // class FaceError [System.Serializable] public class FaceErrorDetail { [SerializeField] public string code = null; [SerializeField] public string message = null; } // class FaceErrorDetail
private FaceData ConvertJson( string i_json ) { Debug.AssertFormat( !string.IsNullOrEmpty( i_json ), "Json情報が設定されていません。" ); // Jsonデータがエラーの場合(もっといいエラーの判定があればいいんだけど……)。 if( i_json.IndexOf( "error" ) > 0 ) { FaceError faceError = null; try { faceError = JsonUtility.FromJson<FaceError>( i_json ); } catch( System.Exception ) { faceError = new FaceError(); } Debug.LogWarningFormat( "顔情報の取得に失敗しているJson情報です。code={0}, message={1}", faceError.error.code, faceError.error.message ); return null; } // 無理やりJsonUtilityで使える形に変更する。 string json = string.Format( "{{\"persons\":{0}}}", i_json ); FaceData faceData = null; try { faceData = JsonUtility.FromJson<FaceData>( json ); } catch( System.Exception i_exception ) { Debug.LogWarningFormat( "Json情報をクラス情報へ変換することに失敗しました。exception={0}", i_exception ); faceData = null; } return faceData; }
これを顔画像を送る際の流れに組み込みましょう。
private IEnumerator Start() { string url = GetFaceAPIURL(); Dictionary<string, string> headers = null; byte[] postData = null; if( m_postType == EPostType.Binary ) { headers = GetBinaryTypeHeader( m_subscriptionKey ); postData = GetTextureBinary( m_texture ); } else { headers = GetURTypeLHeader( m_subscriptionKey ); postData = GetTextureURLBinary( m_textureURL ); } Debug.AssertFormat( postData != null && postData.Length > 0, "Postデータが不正です。" ); string receivedJson = null; using( WWW www = new WWW( url, postData, headers ) ) { yield return www; receivedJson = www.text; } FaceData faceData = ConvertJson( receivedJson ); }
これで完成です。
FaceAPIに顔の画像を送り、Jsonデータとして受け取り、クラスに変換するという流れが完了しました。
あとはFaceAPIを使ってどんな情報が取得できるのかを、JsonUtility
を使った変換先クラスと一緒に簡単にまとめてみます。
faceId
顔のIDです。
取得するパラメータでfaceIdの取得をtrue
にすることで受け取れます。
受け取って何に使えばいいのかはわかりませんが……。
Jsonとしては以下のように受け取れます。
"faceId": "bd872b53-289b-46d1-9fe6-7ac707e6135e"
単純なstring
型なのでクラスは必要ないです。
faceRectangle
送った画像の顔部分の範囲情報です。
なんの追加パラメータを指定しなくても、この情報は受け取れます。
Jsonとしては以下のように受け取れます。
"faceRectangle": { "top": 189, "left": 444, "width": 152, "height": 152 },
以下のクラスでJsonUtility
を使って変換できます。
[System.Serializable] public class FaceRectangle { [SerializeField] public int top = 0; [SerializeField] public int left = 0; [SerializeField] public int width = 0; [SerializeField] public int height = 0; } // class FaceRectangle
faceLandmarks
目や鼻などの位置情報です。
取得するパラメータでfaceLandmarksの取得をtrue
にすることで受け取れます。
結構種類数がありますが、個別指定はできないようです。
Jsonとしては以下のように受け取れます。
"faceLandmarks": { "pupilLeft": { "x": 486.2, "y": 230.0 }, "pupilRight": { "x": 553.8, "y": 230.1 }, "noseTip": { "x": 523.0, "y": 266.3 }, },
以下のクラスでJsonUtility
を使って変換できます。
[System.Serializable] public class FaceLandmarks { [SerializeField] public Vector2 pupilLeft = Vector2.zero; [SerializeField] public Vector2 pupilRight = Vector2.zero; [SerializeField] public Vector2 noseTip = Vector2.zero; [SerializeField] public Vector2 mouthLeft = Vector2.zero; [SerializeField] public Vector2 mouthRight = Vector2.zero; [SerializeField] public Vector2 eyebrowLeftOuter = Vector2.zero; [SerializeField] public Vector2 eyebrowLeftInner = Vector2.zero; [SerializeField] public Vector2 eyeLeftOuter = Vector2.zero; [SerializeField] public Vector2 eyeLeftTop = Vector2.zero; [SerializeField] public Vector2 eyeLeftBottom = Vector2.zero; [SerializeField] public Vector2 eyeLeftInner = Vector2.zero; [SerializeField] public Vector2 eyebrowRightInner = Vector2.zero; [SerializeField] public Vector2 eyebrowRightOuter = Vector2.zero; [SerializeField] public Vector2 eyeRightInner = Vector2.zero; [SerializeField] public Vector2 eyeRightTop = Vector2.zero; [SerializeField] public Vector2 eyeRightBottom = Vector2.zero; [SerializeField] public Vector2 eyeRightOuter = Vector2.zero; [SerializeField] public Vector2 noseRootLeft = Vector2.zero; [SerializeField] public Vector2 noseRootRight = Vector2.zero; [SerializeField] public Vector2 noseLeftAlarTop = Vector2.zero; [SerializeField] public Vector2 noseRightAlarTop = Vector2.zero; [SerializeField] public Vector2 noseLeftAlarOutTip = Vector2.zero; [SerializeField] public Vector2 noseRightAlarOutTip = Vector2.zero; [SerializeField] public Vector2 upperLipTop = Vector2.zero; [SerializeField] public Vector2 upperLipBottom = Vector2.zero; [SerializeField] public Vector2 underLipTop = Vector2.zero; [SerializeField] public Vector2 underLipBottom = Vector2.zero; } // class FaceLandmarks
faceAttributes
顔についてのいろいろな情報群です。
取得するパラメータでFaceAttributesとして指定した分だけ受け取ることが出来ます。
[System.Serializable] public class FaceAttributes { [SerializeField] public float age = 0.0f; [SerializeField] public string gender = null; [SerializeField] public float smile = 0.0f; [SerializeField] public FacialHair facialHair = null; [SerializeField] public HeadPose headPose = null; [SerializeField] public string glasses = null; [SerializeField] public Emotion emotion = null; [SerializeField] public Hair hair = null; [SerializeField] public Makeup makeup = null; [SerializeField] public Accessories[] accessories = null; [SerializeField] public Occlusion occlusion = null; [SerializeField] public Blur blur = null; [SerializeField] public Exposure exposure = null; [SerializeField] public Noise noise = null; } // class FaceAttributes
age
年齢情報です。
Jsonとしては以下のように受け取れます。
"age": 29.9,
単純なfloat
型なのでクラスは必要ないです。
gender
性別情報です。
"male"か"female"の文字列で格納されています。
Jsonとしては以下のように受け取れます。
"gender": "male",
単純なstring
型なのでクラスは必要ないです。
smile
笑顔情報です。
0から1のfloat
値で格納されています。
後述のemotionのhappinessも同等な値と思われます。
Jsonとしては以下のように受け取れます。
"smile": 0.007,
単純なfloat
型なのでクラスは必要ないです。
facialHair
口ひげなどの毛領域の情報がfloat
値で格納されています。
Jsonとしては以下のように受け取れます。
"facialHair": { "moustache": 0.3, "beard": 0.1, "sideburns": 0.1 },
以下のクラスでJsonUtility
を使って変換できます。
[System.Serializable] public class FacialHair { [SerializeField] public float moustache = 0.0f; [SerializeField] public float beard = 0.0f; [SerializeField] public float sideburns = 0.0f; } // class FacialHair
headPose
顔の回転情報がfloat
値で格納されています。
Jsonとしては以下のように受け取れます。
"headPose": { "pitch": 0.0, "roll": -0.1, "yaw": 4.3 },
以下のクラスでJsonUtility
を使って変換できます。
[System.Serializable] public class HeadPose { [SerializeField] public float pitch = 0.0f; [SerializeField] public float roll = 0.0f; [SerializeField] public float yaw = 0.0f; } // class HeadPose
glasses
メガネ情報が文字列で格納されています。
以下のような種類があるみたいですよ。
- NoGlasses
- ReadingGlasses
- Sunglasses
- SwimmingGoggles
Jsonとしては以下のように受け取れます。
"glasses": "NoGlasses",
単純なstring
型なのでクラスは必要ないです。
emotion
感情情報がfloat
値で合計が1になるように格納されています。
Jsonとしては以下のように受け取れます。
"emotion": { "anger": 0.002, "contempt": 0.0, "disgust": 0.0, "fear": 0.014, "happiness": 0.007, "neutral": 0.0, "sadness": 0.0, "surprise": 0.977 },
以下のクラスでJsonUtility
を使って変換できます。
[System.Serializable] public class Emotion { [SerializeField] public float anger = 0.0f; [SerializeField] public float contempt = 0.0f; [SerializeField] public float disgust = 0.0f; [SerializeField] public float fear = 0.0f; [SerializeField] public float happiness = 0.0f; [SerializeField] public float neutral = 0.0f; [SerializeField] public float sadness = 0.0f; [SerializeField] public float surprise = 0.0f; } // class Emotion
hair
髪の色や有無などの髪情報が格納されています。
Jsonとしては以下のように受け取れます。
"hair": { "bald": 0.05, "invisible": false, "hairColor": [ { "color": "black", "confidence": 1.0 }, ] }
以下のクラスでJsonUtility
を使って変換できます。
[System.Serializable] public class Hair { [SerializeField] public float bald = 0.0f; [SerializeField] public bool invisible = false; [SerializeField] public HairColor[] hairColor = null; } // class Hair [System.Serializable] public class HairColor { [SerializeField] public string color = null; [SerializeField] public float confidence = 0.0f; } // class HairColor
makeup
目元と唇の化粧の有無が格納されています。
Jsonとしては以下のように受け取れます。
"makeup": { "eyeMakeup": true, "lipMakeup": false },
以下のクラスでJsonUtility
を使って変換できます。
[System.Serializable] public class Makeup { [SerializeField] public bool eyeMakeup = false; [SerializeField] public bool lipMakeup = false; } // class Makeup
accessories
顔にあるアクセサリー情報が配列で含まれています。無い場合は空です。
以下のような種類があるみたいですよ。
- headWear
- glasses
- mask
Jsonとしては以下のように受け取れます。
"accessories": [ { "type": "mask", "confidence": 0.99 } ],
以下のクラスでJsonUtility
を使って変換できます。
[System.Serializable] public class Accessories { [SerializeField] public string type = null; [SerializeField] public float confidence = 0.0f; } // class Accessories
occlusion
目や口などが塞がれているかの有無の情報が格納されています。
Jsonとしては以下のように受け取れます。
"occlusion": { "foreheadOccluded": false, "eyeOccluded": false, "mouthOccluded": false },
以下のクラスでJsonUtility
を使って変換できます。
[System.Serializable] public class Occlusion { [SerializeField] public bool foreheadOccluded = false; [SerializeField] public bool eyeOccluded = false; [SerializeField] public bool mouthOccluded = false; } // class Occlusion
blur
顔のぼかしレベルが格納されています。
レベルは以下のような段階があるようです。
- Low
- Medium
- High
Jsonとしては以下のように受け取れます。
"blur": { "blurLevel": "low", "value": 0.25 },
以下のクラスでJsonUtility
を使って変換できます。
[System.Serializable] public class Blur { [SerializeField] public string blurLevel = null; [SerializeField] public float value = 0.0f; } // class Blur
exposure
顔の露出レベルが格納されています。
レベルは以下のような段階があるようです。
- GoodExposure
- OverExposure
- UnderExposure
Jsonとしては以下のように受け取れます。
"exposure": { "exposureLevel": "overExposure", "value": 0.8 },
以下のクラスでJsonUtility
を使って変換できます。
[System.Serializable] public class Exposure { [SerializeField] public string exposureLevel = null; [SerializeField] public float value = 0.0f; } // class Exposure
noise
顔のノイズ(?)レベルが格納されています。
レベルは以下のような段階があるようです。
- Low
- Medium
- High
Jsonとしては以下のように受け取れます。
"noise": { "noiseLevel": "low", "value": 0.0 },
以下のクラスでJsonUtility
を使って変換できます。
[System.Serializable] public class Noise { [SerializeField] public string noiseLevel = null; [SerializeField] public float value = 0.0f; } // class Noise
振り返り
僕がこのFaceAPIを使った、CrossOverGameJam04では主にemotionの値を利用していました。
happinessなど喜んでいる感情は読み取りやすかったのですが、sadnessなど悲しいなど感情はなかなか読み取りにくいみたいです。
そしてアニメのキャラクターの顔画像などでは、なかなか顔と認識してくれないみたいです。
というわけで、FaceAPIを使って手軽に顔認識を楽しんでみてくださいね。
コード完全版
【Unity】MicrosoftのFaceAPIを使って顔認識で遊んでみよう
参考リンク
azure.microsoft.com
westus.dev.cognitive.microsoft.com
www.atmarkit.co.jp