FaceDetails CreateFaceDetails(Person person)
        {
            FaceDetails face = new FaceDetails();

            face.questUID         = person.ParentQuest.UID;
            face.targetPerson     = person.Symbol;
            face.targetRace       = person.Race;
            face.gender           = person.Gender;
            face.isChild          = person.FactionData.id == (int)FactionFile.FactionIDs.Children;
            face.faceIndex        = person.FaceIndex;
            face.factionFaceIndex = -1;

            // Read faction face index for fixed NPCs
            if (person.IsIndividualNPC)
            {
                FactionFile.FactionData fd;
                if (GameManager.Instance.PlayerEntity.FactionData.GetFactionData(person.FactionIndex, out fd))
                {
                    face.factionFaceIndex = fd.face;
                }
            }

            // Determine child faction portrait - there are only 2 variants of each gender indexed 0-3
            if (face.isChild)
            {
                UnityEngine.Random.InitState(Time.frameCount);
                int variantOffset = (UnityEngine.Random.Range(0, 2) == 0) ? 0 : 2;
                face.faceIndex = variantOffset + (int)face.gender;
            }

            return(face);
        }
        FaceDetails CreateFaceDetails(Person person)
        {
            // TODO: Support child portrait selection

            FaceDetails face = new FaceDetails();

            face.questUID         = person.ParentQuest.UID;
            face.targetPerson     = person.Symbol;
            face.targetRace       = person.Race;
            face.gender           = person.Gender;
            face.faceIndex        = person.FaceIndex;
            face.factionFaceIndex = -1;

            // Read faction face index for fixed NPCs
            if (person.IsIndividualNPC)
            {
                FactionFile.FactionData fd;
                if (GameManager.Instance.PlayerEntity.FactionData.GetFactionData(person.FactionIndex, out fd))
                {
                    face.factionFaceIndex = fd.face;
                }
            }

            return(face);
        }
예제 #3
0
        private static FaceDetails MapToDomain(this Microsoft.ProjectOxford.Face.Contract.Face face)
        {
            var emotion = GetEmotionValueFromScores(face.FaceAttributes.Emotion);

            var domainEntity = new FaceDetails()
            {
                FaceId         = face.FaceId.ToString(),
                Age            = face.FaceAttributes.Age,
                Emotion        = emotion.emotionValue,
                EmotionScore   = emotion.emotionScore,
                HasBeard       = face.FaceAttributes.FacialHair.Beard > FacialHairThreshold,
                BeardScore     = face.FaceAttributes.FacialHair.Beard,
                HasMoustache   = face.FaceAttributes.FacialHair.Moustache > FacialHairThreshold,
                MoustacheScore = face.FaceAttributes.FacialHair.Moustache,
                HasSideburns   = face.FaceAttributes.FacialHair.Sideburns > FacialHairThreshold,
                SideburnsScore = face.FaceAttributes.FacialHair.Sideburns,
                Gender         = face.FaceAttributes.Gender == "male" ? Gender.Male : Gender.Female,
                HasGlasses     = face.FaceAttributes.Glasses != Microsoft.ProjectOxford.Face.Contract.Glasses.NoGlasses,
                GlassesType    = (GlassesType)face.FaceAttributes.Glasses,
                HeadPose       = new HeadPose()
                {
                    Pitch = face.FaceAttributes.HeadPose.Pitch, Roll = face.FaceAttributes.HeadPose.Roll, Yaw = face.FaceAttributes.HeadPose.Yaw
                },
                SmileScore  = face.FaceAttributes.Smile,
                BoundingBox = new Rectangle {
                    X = face.FaceRectangle.Left, Y = face.FaceRectangle.Top, Width = face.FaceRectangle.Width, Height = face.FaceRectangle.Height
                },
            };

            return(domainEntity);
        }
        FaceDetails CreateFaceDetails(Person person)
        {
            FaceDetails face = new FaceDetails();

            face.questUID     = person.ParentQuest.UID;
            face.targetPerson = person.Symbol;
            face.targetRace   = person.HUDRace;
            face.gender       = person.Gender;
            face.faceIndex    = person.FaceIndex;

            return(face);
        }
예제 #5
0
 public static bool ReflectedEquals(FaceDetails a, FaceDetails b)
 {
     return((a.topLeft == b.topRight) &&
            (a.top == b.top) &&
            (a.topRight == b.topLeft) &&
            (a.left == b.right) &&
            (a.center == b.center) &&
            (a.right == b.left) &&
            (a.bottomLeft == b.bottomRight) &&
            (a.bottom == b.bottom) &&
            (a.bottomRight == b.bottomLeft));
 }
예제 #6
0
        private void TargetImage_SizeChanged(object sender, SizeChangedEventArgs e)
        {
            Faces.Children.Clear();
            if (CurrentPhoto.DetectedFaces != null && CurrentPhoto.DetectedFaces.Any())
            {
                foreach (var face in CurrentPhoto.DetectedFaces)
                {
                    var rect = new FaceDetails(face, TargetImage.RenderSize, photoFile.PixelWidth, photoFile.PixelHeight);

                    Faces.Children.Add(rect);
                }
            }
        }
        FaceDetails CreateFaceDetails(Foe foe)
        {
            UnityEngine.Random.InitState(Time.frameCount);

            FaceDetails face = new FaceDetails();

            face.questUID         = foe.ParentQuest.UID;
            face.targetFoe        = foe.Symbol;
            face.targetRace       = Races.Breton;
            face.gender           = foe.Gender;
            face.faceIndex        = UnityEngine.Random.Range(0, faceCount);
            face.factionFaceIndex = -1;

            return(face);
        }
예제 #8
0
        /// <summary>
        /// Given a FaceDetails on given face of the cube,
        /// rotates the cube, and returns the new face and correctly oriented FaceDetails
        /// </summary>
        internal static (FaceDir, FaceDetails) ApplyRotator(FaceDir faceDir, FaceDetails faceDetails, MatrixInt3x3 rotator)
        {
            var rotatedFaceDirForward = rotator.Multiply(faceDir.Forward());
            var rotatedFaceDirUp      = rotator.Multiply(faceDir.Up());
            var rotatedFaceDirRight   = rotator.Multiply(Vector3.Cross(faceDir.Forward(), faceDir.Up()));
            var rotatedFaceDir        = FromNormal(rotatedFaceDirForward);
            var trueUp      = rotatedFaceDir.Up();
            var trueForward = rotatedFaceDirForward; // =  rotatedFaceDir.Forward();
            var trueRight   = Vector3.Cross(trueForward, trueUp);
            // Find the rotation that will map rotatedFaceDirUp to trueUp
            // and rotatedFaceDirRight to trueRight
            var      dot   = Vector3.Dot(rotatedFaceDirUp, trueUp);
            var      cross = Vector3.Dot(rotatedFaceDirUp, trueRight);
            Rotation faceRot;

            if (dot == 1)
            {
                faceRot = new Rotation();
            }
            else if (dot == -1)
            {
                faceRot = new Rotation(180);
            }
            else if (cross == 1)
            {
                faceRot = new Rotation(270);
            }
            else if (cross == -1)
            {
                faceRot = new Rotation(90);
            }
            else
            {
                throw new Exception();
            }
            if (Vector3.Dot(Vector3.Cross(rotatedFaceDirForward, rotatedFaceDirUp), rotatedFaceDirRight) < 0)
            {
                faceRot = new Rotation(360 - faceRot.RotateCw, true);
            }


            var rotatedFaceDetails = faceDetails.RotateBy(faceRot);

            return(rotatedFaceDir, rotatedFaceDetails);
        }
    // By calling this function, Unity will draw the box plane around the face at the correct position
    void DrawPlane(BoundingBox[] boxes, FaceDetails[] faces)
    {
        // First loops through the amount of boxes there are
        for (int i = 0; i < boxCount; i++)
        {
            // Get all the boxes and faces
            BoundingBox box    = boxes[i];
            FaceDetails face   = faces[i];
            GameObject  plane  = planes[i];
            TextMesh    script = texts[i].GetComponent <TextMesh>();

            // Get screen point to world space
            Ray ray = firstPersonCamera.ScreenPointToRay(new Vector3((float)box.CenterX, (float)box.CenterY, 0.15f));

            // Put ray until 0.5f
            Vector3 worldPoint = ray.GetPoint(0.5f);

            // Scale things correctly since the original box around the face is too big
            plane.transform.localScale = new Vector3((float)(box.Width) / 2800, (float)(box.Height) / 2800, 0.0001f); // 2800 and 6000
            plane.transform.position   = worldPoint;
            plane.transform.LookAt(firstPersonCamera.transform);

            // Section for displaying text
            script.text = "Age: " + (int)face.AgeLow + " - " + (int)face.AgeHigh + "\n"
                          + "Smile - " + face.SmileValue + " (" + ((float)face.SmileConfidence).ToString("F2") + "%)\n"
                          + face.GenderValue + " (" + ((float)face.GenderConfidence).ToString("F2") + "%)\n";

            // Make the text have the same rotation as the plane
            script.transform.rotation = new Quaternion(0, 1, 0, 0) * plane.transform.rotation;

            // Put the text relative to the plane
            script.transform.position = plane.transform.position + plane.transform.TransformDirection(new Vector3(-0.01f - ((float)box.Width / 5600), 0.07f, 0));

            // Enable all renderers
            plane.GetComponent <Renderer>().enabled  = true;
            script.GetComponent <Renderer>().enabled = true;
        }
    }
    // This function is the same as the one above except that it parses for facial details instead
    public FaceDetails[] ParseResponseFace(string responseText)
    {
        // FaceDetails array
        FaceDetails[] faces = new FaceDetails[100];

        // Face Details
        string boundingbox      = "BoundingBox";
        string ageLow           = "'Low': ";
        string ageHigh          = "'High': ";
        string smileValue       = "'Smile': {'Value': ";
        string smileConfidence  = "'Smile': {'Value': ";
        string genderValue      = "'Gender': {'Value': '";
        string genderConfidence = "'Gender': {'Value': '";

        int  wordOccurence = 0;
        int  count         = 0;
        int  index         = 0;
        long ten           = 1;

        // Check for multiple bounding boxes
        while ((wordOccurence = responseText.IndexOf(boundingbox, wordOccurence)) != -1)
        {
            // Create new face detail after deleting the old ones
            FaceDetails face = new FaceDetails();

            if (texts[count] != null)
            {
                Destroy(texts[count]);
            }

            GameObject text = new GameObject();
            text.transform.SetParent(this.transform);
            text.transform.localScale = new Vector3(0.01f, 0.01f, 0.01f);
            TextMesh textMesh = text.AddComponent <TextMesh>();
            textMesh.color = Color.red;

            // Check for Age
            if (responseText.Contains(ageLow) && responseText.Contains(ageHigh))
            {
                // Check for age low
                while (responseText[responseText.IndexOf(ageLow, wordOccurence) + ageLow.Length + index] != ',')
                {
                    face.AgeLow += (decimal)(char.GetNumericValue(responseText[responseText.IndexOf(ageLow, wordOccurence) + ageLow.Length + index]) / ten);
                    ten         *= 10;
                    index++;
                }
                index = 0;
                ten   = 1;

                // Check for age high
                while (responseText[responseText.IndexOf(ageHigh, wordOccurence) + ageHigh.Length + index] != ',')
                {
                    face.AgeHigh += (decimal)(char.GetNumericValue(responseText[responseText.IndexOf(ageHigh, wordOccurence) + ageHigh.Length + index]) / ten);
                    ten          *= 10;
                    index++;
                }
                index = 0;
                ten   = 1;

                // Modulate ageLow and ageHigh
                face.AgeLow  *= 10;
                face.AgeHigh *= 10;
                face.AgeHigh += 1;
            }

            // Check for Smile
            if (responseText.Contains(smileValue))
            {
                // Check for age low
                while (responseText[responseText.IndexOf(smileValue, wordOccurence) + smileValue.Length + index] != ',')
                {
                    face.SmileValue += responseText[responseText.IndexOf(smileValue, wordOccurence) + smileValue.Length + index];
                    index++;
                }
                index            = 0;
                ten              = 1;
                smileConfidence += face.SmileValue + ", 'Confidence': ";

                // Check for age high
                while (responseText[responseText.IndexOf(smileConfidence, wordOccurence) + smileConfidence.Length + index] != ',')
                {
                    if (responseText[responseText.IndexOf(smileConfidence, wordOccurence) + smileConfidence.Length + index] == '.')
                    {
                        index++;
                    }
                    face.SmileConfidence += (decimal)(char.GetNumericValue(responseText[responseText.IndexOf(smileConfidence, wordOccurence) + smileConfidence.Length + index]) / ten);
                    ten *= 10;
                    index++;
                }
                index = 0;
                ten   = 1;

                // Modlulate confidence
                face.SmileConfidence *= 10;
            }

            // Check for gender
            if (responseText.Contains(genderValue))
            {
                // Check for age low
                while (responseText[responseText.IndexOf(genderValue, wordOccurence) + genderValue.Length + index] != '\'')
                {
                    face.GenderValue += responseText[responseText.IndexOf(genderValue, wordOccurence) + genderValue.Length + index];
                    index++;
                }
                index             = 0;
                ten               = 1;
                genderConfidence += face.GenderValue + "', 'Confidence': ";

                // Check for age high
                while (responseText[responseText.IndexOf(genderConfidence, wordOccurence) + genderConfidence.Length + index] != ',')
                {
                    if (responseText[responseText.IndexOf(genderConfidence, wordOccurence) + genderConfidence.Length + index] == '.')
                    {
                        index++;
                    }
                    face.GenderConfidence += (decimal)(char.GetNumericValue(responseText[responseText.IndexOf(genderConfidence, wordOccurence) + genderConfidence.Length + index]) / ten);
                    ten *= 10;
                    index++;
                }
                index = 0;
                ten   = 1;

                // Modulate confidence
                face.GenderConfidence *= 10;
            }

            // Face logs
            //Debug.Log("face.AgeLow = " + (int)face.AgeLow + " face.AgeHigh = " + (int)face.AgeHigh);
            //Debug.Log("face.SmileValue = " + face.SmileValue + " face.SmileConfidence = " + face.SmileConfidence);
            //Debug.Log("face.GenderValue = " + face.GenderValue + " face.GenderConfidence = " + face.GenderConfidence);

            // Increase number of wordOccurence
            wordOccurence += responseText.IndexOf(boundingbox, wordOccurence);

            // Add the boxes to the array
            faces[count] = face;
            texts[count] = text;

            // Increase count
            count++;
        }

        // Return the faces detected (ie info)
        return(faces);
    }
예제 #11
0
        public async Task <FaceResult> GetFaceResult(Stream imageStream)
        {
            try
            {
                var result =
                    await _faceClient.Face.DetectWithStreamAsync(imageStream, true, true,
                                                                 new List <FaceAttributeType> {
                    FaceAttributeType.Emotion, FaceAttributeType.Gender, FaceAttributeType.Age
                });


                var faceResult = new FaceResult();
                foreach (var face in result)
                {
                    var emotionType  = string.Empty;
                    var emotionValue = 0.0;
                    var emotion      = face.FaceAttributes.Emotion;
                    if (emotion.Anger > emotionValue)
                    {
                        emotionValue = emotion.Anger; emotionType = "Anger";
                    }
                    if (emotion.Contempt > emotionValue)
                    {
                        emotionValue = emotion.Contempt; emotionType = "Contempt";
                    }
                    if (emotion.Disgust > emotionValue)
                    {
                        emotionValue = emotion.Disgust; emotionType = "Disgust";
                    }
                    if (emotion.Fear > emotionValue)
                    {
                        emotionValue = emotion.Fear; emotionType = "Fear";
                    }
                    if (emotion.Happiness > emotionValue)
                    {
                        emotionValue = emotion.Happiness; emotionType = "Happiness";
                    }
                    if (emotion.Neutral > emotionValue)
                    {
                        emotionValue = emotion.Neutral; emotionType = "Neutral";
                    }
                    if (emotion.Sadness > emotionValue)
                    {
                        emotionValue = emotion.Sadness; emotionType = "Sadness";
                    }
                    if (emotion.Surprise > emotionValue)
                    {
                        emotionType = "Surprise";
                    }

                    var faceDetails = new FaceDetails
                    {
                        Gender  = face.FaceAttributes.Gender.ToString(),
                        Emotion = emotionType
                    };
                    faceResult.Details.Add(faceDetails);
                }

                return(faceResult);
            }
            catch (Exception ex)
            {
                return(new FaceResult());
            }
        }
예제 #12
0
 public void Deconstruct(out Vector3Int offset, out FaceDir faceDir, out FaceDetails faceDetails)
 {
     offset      = this.offset;
     faceDir     = this.faceDir;
     faceDetails = this.faceDetails;
 }
예제 #13
0
 public OrientedFace(Vector3Int offset, FaceDir faceDir, FaceDetails faceDetails)
 {
     this.offset      = offset;
     this.faceDir     = faceDir;
     this.faceDetails = faceDetails;
 }
예제 #14
0
 /// <summary>
 /// Finds the face details for a cell with a given offeset.
 /// </summary>
 public bool TryGet(Vector3Int offset, FaceDir faceDir, out FaceDetails details)
 {
     details = faceDetails.SingleOrDefault(x => x.offset == offset && x.faceDir == faceDir).faceDetails;
     return(details != null);
 }