private List <int[]> FaceEdgePairs()
        {
            var allEdgePairs   = new List <int[]>();
            var edgePairCounts = new Dictionary <int, int>();

            var i = 0;

            do
            {
                var numInFace = (Faces[i] == 0) ? 3 : 4;
                if ((i + numInFace) < Faces.Count())
                {
                    i++;
                    for (var v = 0; v < numInFace; v++)
                    {
                        var pair       = (new int[] { Faces[i + v], Faces[((v + 1) == numInFace) ? i : i + v + 1] }).OrderBy(n => n).ToArray();
                        var foundIndex = allEdgePairs.FindIndex(ep => EqualPair(ep, pair));
                        if (foundIndex >= 0)
                        {
                            edgePairCounts[foundIndex]++;
                        }
                        else
                        {
                            allEdgePairs.Add(pair);
                            edgePairCounts.Add(allEdgePairs.IndexOf(pair), 1);
                        }
                    }
                }
                i += numInFace;
            } while (i < Faces.Count());

            var edgePairIndices = edgePairCounts.Where(kvp => kvp.Value == 1).Select(kvp => kvp.Key).ToList();

            return(edgePairIndices.Select(pi => allEdgePairs[pi]).ToList());
        }
        public Structural2DElement[] Explode()
        {
            var elements = new List <Structural2DElement>();

            var faceCounter = 0;

            for (var i = 0; i < Faces.Count(); i++)
            {
                var vertices = new List <double>();
                var colors   = new List <int>();

                var numVertices = Faces[i++] + 3;
                for (var j = 0; j < numVertices; j++)
                {
                    if (Colors != null && Colors.Count() > Faces[i])
                    {
                        colors.Add(Colors[Faces[i]]);
                    }
                    vertices.AddRange(Vertices.Skip(Faces[i++] * 3).Take(3));
                }
                i--;

                var element = new Structural2DElement(
                    vertices.ToArray(),
                    (new List <int>()
                {
                    numVertices - 3
                }).Concat(Enumerable.Range(0, numVertices)).ToArray(),
                    colors.Count() == vertices.Count() / 3 ? colors.ToArray() : new int[0],
                    ElementType,
                    PropertyRef,
                    Axis != null && Axis.Count() > faceCounter ? Axis[faceCounter] : null,
                    Offset != null && Offset.Count() > faceCounter ? Offset[faceCounter] : 0,
                    ElementApplicationId != null && ElementApplicationId.Count() > faceCounter
              ? ElementApplicationId[faceCounter]
              : Helper.CreateChildApplicationId(i, ApplicationId + "-" + faceCounter.ToString())
                    )
                {
                    GSADummy    = GSADummy,
                    GSAMeshSize = GSAMeshSize
                };
                elements.Add(element);

                faceCounter++;
            }

            return(elements.ToArray());
        }
        /// <summary>
        /// Converts a hexahedron to a list of tetrahedons
        /// </summary>
        /// <returns></returns>
        public List <Cell> ToTetrahedons(Mesh mesh)
        {
            //return object
            List <Cell> ret = new List <Cell>();

            try
            {
                LocationTimeValue[] vert = GetVertices(mesh);

                CreateFaces(mesh);

                LocationTimeValue loc1 = vert[0];
                LocationTimeValue loc2 = vert.OrderByDescending(x => GeographyHelper.EuclideanDistance(x, loc1)).First();

                for (int i = 0; i < Faces.Count(); i++)
                {
                    Faces[i].Vertices.OrderBy(x => GeographyHelper.EuclideanDistance(x, Faces[i].Vertices[0]));

                    Tetrahedron tet = new Tetrahedron();
                    tet.Vertices = new List <int>()
                    {
                        mesh.Vertices.IndexOf(Faces[i].Vertices[0]),
                        mesh.Vertices.IndexOf(Faces[i].Vertices[1]),
                        mesh.Vertices.IndexOf(Faces[i].Vertices[2])
                    };

                    if (Faces[i].Vertices.Contains(loc1))
                    {
                        tet.Vertices.Add(mesh.Vertices.IndexOf(loc2));
                    }
                    else
                    {
                        tet.Vertices.Add(mesh.Vertices.IndexOf(loc1));
                    }

                    tet.CreateFaces(mesh);

                    tet          = new Tetrahedron();
                    tet.Vertices = new List <int>()
                    {
                        mesh.Vertices.IndexOf(Faces[i].Vertices[3]),
                        mesh.Vertices.IndexOf(Faces[i].Vertices[1]),
                        mesh.Vertices.IndexOf(Faces[i].Vertices[2])
                    };

                    if (Faces[i].Vertices.Contains(loc1))
                    {
                        tet.Vertices.Add(mesh.Vertices.IndexOf(loc2));
                    }
                    else
                    {
                        tet.Vertices.Add(mesh.Vertices.IndexOf(loc1));
                    }

                    tet.CreateFaces(mesh);

                    ret.Add(tet);
                }
            }
            catch
            {
                ret = new List <Cell>();
            }

            return(ret);
        }
예제 #4
0
        private void _updateFacesList(JArray ja)
        {
            ObservableCollection <Face> newColl = new ObservableCollection <Face>();

            // Main face computation
            int   mainFaceID  = -1;
            float maxHeadSize = -1;

            // Copy new faces in existing list
            if (ja != null)
            {
                foreach (var v in ja)
                {
                    // Parse basic info
                    int    id     = int.Parse(v["id"].ToString());
                    string gender = v["gender"].ToString();

                    string age        = v["age"].ToString();
                    var    ageInteger = Int16.Parse(age);
                    string ageRange   = ageInteger <= 16 ? "child" :
                                        ageInteger <= 30 ? "young adult" :
                                        ageInteger <= 45 ? "middle-aged adult" : "old-aged adult";

                    var x = float.Parse(v["location"]["x"].ToString(), CultureInfo.InvariantCulture); // TODO: normalize? (or on C++ side?)
                    var y = float.Parse(v["location"]["y"].ToString(), CultureInfo.InvariantCulture);

                    var width  = float.Parse(v["location"]["width"].ToString(), CultureInfo.InvariantCulture);
                    var height = float.Parse(v["location"]["height"].ToString(), CultureInfo.InvariantCulture);

                    // Intuiface coordinates system: move X&Y coords to represent the center of the head, not the top left corner
                    x += width / 2;
                    y += height / 2;

                    // TODO: estimate distance in cm based on head size and camera focal / calibration step ??
                    var faceSize = (int)(width * height * 100 * 100); // Current value: % of head area over total image area

                    var mainEmotion           = v["mainEmotion"]["emotion"].ToString();
                    var mainEmotionConfidence = float.Parse(v["mainEmotion"]["confidence"].ToString(), CultureInfo.InvariantCulture);

                    // Parse additional emotions
                    EmotionConfidence emotionConfidence = new EmotionConfidence();
                    emotionConfidence.Angry     = float.Parse(v["emotions"]["anger"].ToString(), CultureInfo.InvariantCulture);
                    emotionConfidence.Happy     = float.Parse(v["emotions"]["happy"].ToString(), CultureInfo.InvariantCulture);
                    emotionConfidence.Neutral   = float.Parse(v["emotions"]["neutral"].ToString(), CultureInfo.InvariantCulture);
                    emotionConfidence.Sad       = float.Parse(v["emotions"]["sad"].ToString(), CultureInfo.InvariantCulture);
                    emotionConfidence.Surprised = float.Parse(v["emotions"]["surprise"].ToString(), CultureInfo.InvariantCulture);

                    // Parse head pose estimation
                    HeadPoseEstimation headPoseEstimation = new HeadPoseEstimation();
                    headPoseEstimation.Pitch = float.Parse(v["headpose"]["pitch"].ToString(), CultureInfo.InvariantCulture);
                    headPoseEstimation.Yaw   = float.Parse(v["headpose"]["yaw"].ToString(), CultureInfo.InvariantCulture);
                    headPoseEstimation.Roll  = float.Parse(v["headpose"]["roll"].ToString(), CultureInfo.InvariantCulture);

                    // If face size filtering is active, check is head is bigger than threshold
                    if (faceSize < m_dMinimumFaceSize)
                    {
                        // Don't add face to list
                        continue;
                    }

                    // TODO: use real "distance" and take the min one.
                    if (faceSize > maxHeadSize)
                    {
                        maxHeadSize = faceSize;
                        mainFaceID  = id;
                    }

                    newColl.Add(new Face()
                    {
                        Id                    = id,
                        X                     = x,
                        Y                     = y,
                        Width                 = width,
                        Height                = height,
                        FaceSize              = faceSize,
                        Gender                = gender,
                        Age                   = age,
                        AgeRange              = ageRange,
                        MainEmotion           = mainEmotion,
                        MainEmotionConfidence = mainEmotionConfidence,
                        EmotionConfidence     = emotionConfidence,
                        HeadPoseEstimation    = headPoseEstimation
                    });
                }
            }

            // Order by ID
            newColl = new ObservableCollection <Face>(newColl.OrderBy(i => i.Id));

            // Compare old (current) list and new list

            var removed = Faces.Except(newColl);
            var added   = newColl.Except(Faces);

            if (removed.Count() > 0)
            {
                foreach (var face in removed)
                {
                    // Raise face lost event
                    Console.WriteLine("Face lost: " + face);
                    RaiseFaceLost(face.Id, face.Gender, face.Age, face.DwellTime);
                    m_startTimeMap.Remove(face.Id);
                }
            }
            if (added.Count() > 0)
            {
                foreach (var face in added)
                {
                    // Raise face added event
                    Console.WriteLine("Face added: " + face);
                    RaiseFaceDetected(face.Id, face.Gender, face.Age);
                    m_startTimeMap.Add(face.Id, DateTime.Now);
                }
            }

            // Update elements in current list with new list

            int newCount = newColl.Count;
            int oldCount = Faces.Count;

            if (newCount != oldCount)
            {
                // Raise face count changed event
                Console.WriteLine("Face count changed: " + newCount);
                RaiseFaceCountChanged(newCount);
            }

            // Adjust number of faces in Faces
            // New users to add
            if (newCount > oldCount)
            {
                for (int i = 0; i < newCount - oldCount; i++)
                {
                    Faces.Add(new Face());
                }
            }
            // Users to remove
            else if (newCount < oldCount)
            {
                for (int i = newCount; i < oldCount; i++)
                {
                    Faces.RemoveAt(newCount);
                }
            }

            // Copy new coll properties in existing faces list.
            int index = 0;

            foreach (var item in newColl)
            {
                try
                {
                    Faces[index].Id        = item.Id;
                    Faces[index].X         = item.X;
                    Faces[index].Y         = item.Y;
                    Faces[index].Width     = item.Width;
                    Faces[index].Height    = item.Height;
                    Faces[index].Gender    = item.Gender;
                    Faces[index].Age       = item.Age;
                    Faces[index].AgeRange  = item.AgeRange;
                    Faces[index].DwellTime = (DateTime.Now - m_startTimeMap[item.Id]).TotalSeconds;

                    Faces[index].FaceSize = item.FaceSize;

                    Faces[index].MainEmotion           = item.MainEmotion;
                    Faces[index].MainEmotionConfidence = item.MainEmotionConfidence;

                    // Additional emotions
                    Faces[index].EmotionConfidence = item.EmotionConfidence;

                    // Head pose estimation
                    Faces[index].HeadPoseEstimation = item.HeadPoseEstimation;
                }
                catch (Exception ex)
                {
                    ActivityLog += ex.Message + "\n";

                    throw;
                }

                index++;
            }

            // Update face count
            FaceCount = Faces.Count();

            // Copy main face info
            if (FaceCount > 0)
            {
                var item = Faces.FirstOrDefault(i => i.Id == mainFaceID);
                if (item != null)
                {
                    MainFace.Id       = item.Id;
                    MainFace.X        = item.X;
                    MainFace.Y        = item.Y;
                    MainFace.Width    = item.Width;
                    MainFace.Height   = item.Height;
                    MainFace.FaceSize = item.FaceSize;
                    MainFace.Gender   = item.Gender;

                    MainFace.Age       = item.Age;
                    MainFace.AgeRange  = item.AgeRange;
                    MainFace.DwellTime = (DateTime.Now - m_startTimeMap[item.Id]).TotalSeconds;

                    MainFace.MainEmotion           = item.MainEmotion;
                    MainFace.MainEmotionConfidence = item.MainEmotionConfidence;

                    // Additional emotions
                    MainFace.EmotionConfidence = item.EmotionConfidence;

                    // Head pose estimation
                    MainFace.HeadPoseEstimation = item.HeadPoseEstimation;

                    // Mark the face detected
                    IsMainFaceDetected = true;
                }
                else
                {
                    IsMainFaceDetected = false;
                }
            }
            else
            {
                IsMainFaceDetected = false;
            }
        }
예제 #5
0
        public List <int[]> Edges()
        {
            var edgeConnectivities = new List <int[]>();

            // Get face connectivities and close loop
            var faceConnnectivities = new List <int[]>();

            for (var i = 0; i < Faces.Count(); i++)
            {
                var numVertices = Faces[i] + 3;
                i++;
                faceConnnectivities.Add(Faces.Skip(i).Take(numVertices).Concat(Faces.Skip(i).Take(1)).ToArray());
                i += numVertices - 1;
            }

            // Get distinct edges
            var edges = new List <Tuple <int, int, string, string, double> >();

            foreach (var conn in faceConnnectivities)
            {
                for (var i = 0; i < conn.Length - 1; i++)
                {
                    var c1     = string.Join(",", Vertices.Skip(conn[i] * 3).Take(3).Select(x => Math.Round(x, 4).ToString()));
                    var c2     = string.Join(",", Vertices.Skip(conn[i + 1] * 3).Take(3).Select(x => Math.Round(x, 4).ToString()));
                    var length = Math.Pow(Vertices.Skip(conn[i] * 3).Take(1).First() - Vertices.Skip(conn[i + 1] * 3).Take(1).First(), 2) +
                                 Math.Pow(Vertices.Skip(conn[i] * 3 + 1).Take(1).First() - Vertices.Skip(conn[i + 1] * 3 + 1).Take(1).First(), 2) +
                                 Math.Pow(Vertices.Skip(conn[i] * 3 + 2).Take(1).First() - Vertices.Skip(conn[i + 1] * 3 + 2).Take(1).First(), 2);
                    length = Math.Sqrt(length);

                    if (edges.Any(e => (e.Item3 == c1 && e.Item4 == c2) |
                                  (e.Item3 == c2 && e.Item4 == c1)))
                    {
                        edges.RemoveAll(x => (x.Item3 == c1 && x.Item4 == c2) || (x.Item3 == c2 && x.Item4 == c1));
                    }
                    else
                    {
                        if (conn[i] < conn[i + 1])
                        {
                            edges.Add(new Tuple <int, int, string, string, double>(conn[i], conn[i + 1], c1, c2, length));
                        }
                        else
                        {
                            edges.Add(new Tuple <int, int, string, string, double>(conn[i + 1], conn[i], c2, c1, length));
                        }
                    }
                }
            }

            // Reorder the edges
            var    lengthsOfEdges = new List <double>();
            double currentLength  = 0;

            var currentLoop = new List <int>();
            var flatCoor    = new List <string>();

            currentLoop.Add(edges[0].Item1);
            currentLoop.Add(edges[0].Item2);
            flatCoor.Add(edges[0].Item3);
            flatCoor.Add(edges[0].Item4);

            edges.RemoveAt(0);

            while (edges.Count > 0)
            {
                var commonVertex = flatCoor.Last();

                var nextEdge = edges.Where(e => e.Item3 == commonVertex | e.Item4 == commonVertex).ToList();

                if (nextEdge.Count > 0)
                {
                    currentLoop.Add(nextEdge[0].Item3 == commonVertex ? nextEdge[0].Item2 : nextEdge[0].Item1);
                    flatCoor.Add(nextEdge[0].Item3 == commonVertex ? nextEdge[0].Item4 : nextEdge[0].Item3);
                    edges.Remove(nextEdge[0]);
                    currentLength += nextEdge[0].Item5;
                }
                else
                {
                    // Next edge not found. Stop looking for more
                    break;
                }

                if (currentLoop[0] == currentLoop.Last())
                {
                    currentLoop.RemoveAt(0);

                    edgeConnectivities.Add(currentLoop.ToArray());
                    lengthsOfEdges.Add(currentLength);

                    currentLength       = 0;
                    currentLoop         = new List <int>();
                    faceConnnectivities = new List <int[]>();

                    if (edges.Count > 0)
                    {
                        currentLoop.Add(edges[0].Item1);
                        currentLoop.Add(edges[0].Item2);
                        flatCoor.Add(edges[0].Item3);
                        flatCoor.Add(edges[0].Item4);

                        edges.RemoveAt(0);
                    }
                }
            }

            // Sort based on length
            var ordered = lengthsOfEdges
                          .Select((x, i) => new KeyValuePair <double, int>(x, i))
                          .OrderBy(x => x.Key)
                          .Select(x => x.Value)
                          .Reverse();

            var sortedEdgeConnectivities = new List <int[]>();

            foreach (var i in ordered)
            {
                sortedEdgeConnectivities.Add(edgeConnectivities[i]);
            }

            return(sortedEdgeConnectivities);
        }