/// <summary> /// Conway's kis operator /// </summary> /// <returns>the kis as a new mesh</returns> public Mesh Kis() { // vertices and faces to vertices var vertexPoints = Enumerable.Concat(Vertices.Select(v => v.Position), Faces.Select(f => f.Centroid)); // vertex lookup Dictionary <string, int> vlookup = new Dictionary <string, int>(); int n = Vertices.Count; for (int i = 0; i < n; i++) { vlookup.Add(Vertices[i].Name, i); } // create new tri-faces (like a fan) var faceIndices = new List <IEnumerable <int> >(); // faces as vertex indices for (int i = 0; i < Faces.Count; i++) { foreach (var edge in Faces[i].GetHalfedges()) { // create new face from edge start, edge end and centroid faceIndices.Add(new int[] { vlookup[edge.Prev.Vertex.Name], vlookup[edge.Vertex.Name], i + n }); } } return(new Mesh(vertexPoints, faceIndices)); }
/// <summary> /// Returns the intersection point closest to the start of the line. /// </summary> /// <param name="line">The intersection line</param> /// <returns>The closest intersecting point, or null if the line doesn't intersect.</returns> public override Coordinate GetIntersectionPoint(Line line) { return(Faces.Select(x => x.GetIntersectionPoint(line)) .Where(x => x != null) .OrderBy(x => (x - line.Start).VectorMagnitude()) .FirstOrDefault()); }
SharpMesh GetSharpMesh(SharpDevice device) { SharpMesh mesh = new SharpMesh(device); List <int> indices = new List <int>( ); List <Face> faces = new List <Face>( ); List <string> texList = new List <string>( ); List <string> notFoundTexList = new List <string>( ); int icount = 0; foreach (Material item in Materials) { indices.AddRange(item.FlattenFace); int faceCount = item.FlattenFace.Count( ); SharpSubSet subSet = new SharpSubSet( ) { IndexCount = faceCount, StartIndex = icount, }; if (item.TexName != string.Empty) { var filename = TryGetResource(device, item.TexName); // 存在しないパスなら読まない filename.Match(() => notFoundTexList.Add(item.TexName), r => subSet.DiffuseMap = r); } if (item.SphereName != string.Empty) { var filename = TryGetResource(device, item.SphereName); filename.Match(() => notFoundTexList.Add(item.SphereName), r => subSet.SphereMap = r); } mesh.SubSets.Add(subSet); for (int i = icount; i < icount + faceCount; i += 3) { int ind1 = indices[i]; int ind2 = indices[i + 1]; int ind3 = indices[i + 2]; Face item1 = new Face(Vertice[ind1].Position, Vertice[ind2].Position, Vertice[ind3].Position, item.Name); //Debug.WriteLine("first " + item1.TriString); faces.Add(item1); } icount += faceCount; } Index = indices.ToArray( ); Faces = faces.ToArray( ); var inds = Index.Select(x => x.ToString( )); var facesS = Faces.Select(x => x.ToString( )); //inds.Concat( facesS ).Concat( texList ).WriteFile( DirPath + "loadedFile.txt" ); notFoundTexList.WriteFile(DirPath + "notFoundTextures.txt"); ModelStr = Faces.Select(f => f.TriString).ConcatStr( ); mesh.SetOnly(Vertice, Index); return(mesh); }
protected override object GetFieldValue(Item cognitiveIndexable) { var values = Faces?.Select(x => x.FaceAttributes?.Emotion?.Surprise).OrderBy(a => a).ToList(); return(values != null && values.Any() ? values.FirstOrDefault() : 0f); }
protected override object GetFieldValue(Item cognitiveIndexable) { var values = Faces?.Select(x => x.FaceAttributes?.Emotion?.Fear).OrderByDescending(a => a).ToList(); return(values != null && values.Any() && values.FirstOrDefault() > 0f ? values.FirstOrDefault() : 1f); }
protected override object GetFieldValue(Item cognitiveIndexable) { var ages = Faces?.Select(x => x.FaceAttributes.Age).OrderByDescending(a => a).ToList(); return(ages != null && ages.Any() ? ages.FirstOrDefault() : 100d); }
protected override object GetFieldValue(Item cognitiveIndexable) { if (Faces == null || Faces.Length == 0) { return(null); } List <int> returnValue = Faces?.Select(x => (int)x.FaceAttributes.Glasses).ToList(); return(returnValue); }
/// <summary> /// Sorts all the faces around an edge based on the angle /// The angle is measured using the first face normal in the list. /// </summary> public void SortFacesByAngle() { var normals = Faces.Select(x => x.Normal).ToList(); var refVect = new Vector3d(Vertices[1].Point - Vertices[0].Point); var angles = normals.Select(x => Angle(normals[0], x, refVect)); FaceAngle = new List <double>(angles); var joined = angles.Zip(Faces, (angle, face) => new { angle, face }).OrderBy(x => x.angle); Faces = joined.Select(x => x.face).ToList(); FaceAngle = joined.Select(x => x.angle).ToList(); }
/// <summary> /// Generates a resource descriptor for this resource. /// </summary> /// <returns>A resource descriptor.</returns> internal override IDescriptor GetDescriptor(Scheduler scheduler) { return(new Descriptor { SetState = (state) => SetLoadingState(state), SetResource = (resource) => Attachment = resource, Points = Points.Select(x => x.GetDescriptor()).ToArray(), Edges = Edges.Select(x => x.GetDescriptor(Points, Edges)).ToArray(), Faces = Faces.Select(x => x.GetDescriptor(Edges)).ToArray(), TesselationType = Tesselation, SourceScheduler = scheduler }); }
public override MapObject Clone() { var e = new Solid(ID); foreach (var f in Faces.Select(x => x.Clone())) { f.Parent = e; e.Faces.Add(f); f.UpdateBoundingBox(); } CopyBase(e, null, true); return(e); }
public override MapObject Copy(IDGenerator generator) { var e = new Solid(generator.GetNextObjectID()); foreach (var f in Faces.Select(x => x.Copy(generator))) { f.Parent = e; e.Faces.Add(f); f.UpdateBoundingBox(); f.CalculateTextureCoordinates(true); } CopyBase(e, generator); return(e); }
public void UpdateAnnotations(bool unused) { Children.Clear(); if (Faces == null || ImageRealSize == null) { return; } var ar = ImageRealSize.Height / this.ActualHeight; var replacedFaces = Faces.Select(f => new Rect(f.FaceBounds.Left / ar, f.FaceBounds.Top / ar, f.FaceBounds.Width / ar, f.FaceBounds.Height / ar)).ToArray(); var faceFrames = replacedFaces.Select(x => { var n = new Rectangle() { Width = x.Width, Height = x.Height }; n.SetValue(Canvas.LeftProperty, x.Left); n.SetValue(Canvas.TopProperty, x.Top); n.Stroke = new SolidColorBrush(Colors.Red); n.StrokeThickness = 3; return(n); }); var IPds = Faces.Where(f => f.IPD > 0).Select(f => { var n = new TextBox() { Text = f.IPD.ToString("0.##"), IsReadOnly = true, BorderThickness = new Thickness(0), }; n.SetValue(Canvas.LeftProperty, f.FaceBounds.Left / ar); n.SetValue(Canvas.TopProperty, f.FaceBounds.Top / ar - 30); return(n); }); foreach (var ipd in IPds) { Children.Add(ipd); } foreach (var faceFrame in faceFrames) { Children.Add(faceFrame); } }
/// <summary> /// Makes the vertices. /// </summary> /// <param name="vertices"></param> /// <param name="faceToVertexIndices">The face to vertex indices.</param> private void RestartVerticesToAvoidSingleSidedEdges() { var faceIndices = Faces.Select(f => f.Vertices.Select(v => v.IndexInList).ToArray()).ToArray(); var colors = Faces.Select(f => f.Color).ToArray(); var numDecimalPoints = 0; //Gets the number of decimal places. this is the crucial part where we consolidate vertices... while (Math.Round(SameTolerance, numDecimalPoints).IsPracticallySame(0.0)) { numDecimalPoints++; } var coords = new List <Vector3>(); var simpleCompareDict = new Dictionary <Vector3, int>(); //in order to reduce compare times we use a string comparer and dictionary foreach (var faceToVertexIndex in faceIndices) { for (var i = 0; i < faceToVertexIndex.Length; i++) { //Get vertex from list of vertices var vertex = Vertices[faceToVertexIndex[i]]; /* given the low precision in files like STL, this should be a sufficient way to detect identical points. * I believe comparing these lookupStrings will be quicker than comparing two 3d points.*/ //First, round the vertices. This will catch bidirectional tolerancing (+/-) var position = new Vector3(Math.Round(vertex.X, numDecimalPoints), Math.Round(vertex.Y, numDecimalPoints), Math.Round(vertex.Z, numDecimalPoints)); if (simpleCompareDict.ContainsKey(position)) { // if it's in the dictionary, update the faceToVertexIndex faceToVertexIndex[i] = simpleCompareDict[position]; } else { /* else, add a new vertex to the list, and a new entry to simpleCompareDict. Also, be sure to indicate * the position in the locationIndices. */ var newIndex = coords.Count; coords.Add(position); simpleCompareDict.Add(position, newIndex); faceToVertexIndex[i] = newIndex; } } } MakeVertices(coords); MakeFaces(faceIndices, colors); }
public void ComputeVertices() { if (Faces.Count < 4) { return; } Polyhedron poly = new Polyhedron(Faces.Select(x => new Plane(x.Plane.Normal.ToPrecisionVector3(), x.Plane.D))); foreach (Face face in Faces) { Polygon pg = poly.Polygons.FirstOrDefault(x => x.Plane.Normal.EquivalentTo(face.Plane.Normal.ToPrecisionVector3(), 0.0075f)); // Magic number that seems to match VHE if (pg != null) { face.Vertices.AddRange(pg.Vertices.Select(x => x.ToStandardVector3())); } } }
private void Timer_Tick(object sender, EventArgs e) { webCam.Retrieve(frame); var imageFrame = frame.ToImage <Gray, byte>(); if (TimerCounter < TimeLimit) { TimerCounter++; if (imageFrame != null) { var faces = faceDetection.DetectMultiScale(imageFrame, 1.3, 5); if (faces.Count() > 0) { var processedImage = imageFrame.Copy(faces[0]).Resize(ProcessedImageWidth, ProcessedImageHeight, Emgu.CV.CvEnum.Inter.Cubic); Faces.Add(processedImage); IDs.Add(Convert.ToInt32(IdBox.Text)); ScanCounter++; OutPutBox.AppendText($"{ScanCounter} Success Scan Taken... {Environment.NewLine}"); OutPutBox.ScrollToCaret(); } } } else { Mat[] faceImages = new Mat[Faces.Count]; faceImages = Faces.Select(c => c.Mat).ToArray(); faceRecognition.Train(faceImages, IDs.ToArray()); faceRecognition.Write(YMLPath); timer.Stop(); Trainbottom.Enabled = !Trainbottom.Enabled; IdBox.Enabled = !IdBox.Enabled; OutPutBox.AppendText($"Training Complete!{Environment.NewLine}"); MessageBox.Show("Training Completed!"); PredictButton.Enabled = true; } }
public Dictionary <string, object> SerializeDict() { //TODO see what happens for nulls Dictionary <string, object> props = new Dictionary <string, object> { { "Id", Id }, { "Vertices", Vertices.Select(x => x.Id).ToList() }, { "Edges", Edges.Select(x => x.Id).ToList() }, { "Faces", Faces.Select(x => x.Id).ToList() }, // neighbors is not used and not serialized { "Centroid", PVToDict(Centroid) }, // FMesh is not serialized - it will be recomputed { "Dual", Dual.Select(x => x.Id).ToList() }, { "Exterior", Exterior } }; return(props); }
public Dictionary <string, object> SerializeDict() { //TODO see what happens for nulls Dictionary <string, object> props = new Dictionary <string, object> { { "Id", Id }, { "Point", PVToDict(Point) }, { "External", External }, { "Edges", Edges.Select(x => x.Id).ToList() }, { "Faces", Faces.Select(x => x.Id).ToList() }, { "Cells", Cells.Select(x => x.Id).ToList() }, { "Dual", Dual?.Id ?? -1 }, { "SupportGuid", SupportGuid }, { "InfluenceCoef", InfluenceCoef }, { "Fixed", Fixed }, { "OnGeo", OnGeo } }; return(props); }
public Dictionary <string, object> SerializeDict() { //TODO see what happens for nulls Dictionary <string, object> props = new Dictionary <string, object> { { "Id", Id }, { "Vertices", Vertices.Select(x => x.Id).ToList() }, { "Pair", Pair?.Id ?? 0 }, { "Faces", Faces.Select(x => x.Id).ToList() }, { "FaceAngle", FaceAngle }, { "Dual", Dual?.Id ?? 0 }, { "External", External }, { "Deviation", Deviation }, { "TargetLength", TargetLength }, { "MinLength", MinLength }, { "MaxLength", MaxLength }, { "InfluenceCoef", InfluenceCoef } }; return(props); }
/// <summary> /// Splits this solid into two solids by intersecting against a plane. /// </summary> /// <param name="plane">The splitting plane</param> /// <param name="back">The back side of the solid</param> /// <param name="front">The front side of the solid</param> /// <param name="generator">The IDGenerator to use</param> /// <returns>True if the plane splits the solid, false if the plane doesn't intersect</returns> public bool Split(Plane plane, out Solid back, out Solid front, IDGenerator generator) { back = front = null; // Check that this solid actually spans the plane var classify = Faces.Select(x => x.ClassifyAgainstPlane(plane)).Distinct().ToList(); if (classify.All(x => x != PlaneClassification.Spanning)) { if (classify.Any(x => x == PlaneClassification.Back)) { back = this; } else if (classify.Any(x => x == PlaneClassification.Front)) { front = this; } return(false); } var backPlanes = new List <Plane> { plane }; var frontPlanes = new List <Plane> { new Plane(-plane.Normal, -plane.DistanceFromOrigin) }; foreach (var face in Faces) { var classification = face.ClassifyAgainstPlane(plane); if (classification != PlaneClassification.Back) { frontPlanes.Add(face.Plane); } if (classification != PlaneClassification.Front) { backPlanes.Add(face.Plane); } } back = CreateFromIntersectingPlanes(backPlanes, generator); front = CreateFromIntersectingPlanes(frontPlanes, generator); CopyBase(back, generator); CopyBase(front, generator); front.Faces.Union(back.Faces).ToList().ForEach(x => { x.Texture = Faces[0].Texture.Clone(); x.AlignTextureToFace(); x.Colour = Colour; }); // Restore textures (match the planes up on each face) foreach (var orig in Faces) { foreach (var face in back.Faces) { var classification = face.ClassifyAgainstPlane(orig.Plane); if (classification != PlaneClassification.OnPlane) { continue; } face.Texture = orig.Texture.Clone(); break; } foreach (var face in front.Faces) { var classification = face.ClassifyAgainstPlane(orig.Plane); if (classification != PlaneClassification.OnPlane) { continue; } face.Texture = orig.Texture.Clone(); break; } } front.Faces.Union(back.Faces).ToList().ForEach(x => x.CalculateTextureCoordinates(true)); return(true); }
public IList <Brep> CreateBrepsFromFaces() { return(Faces.Select(x => x.CreateBrep()).ToList()); }
public async Task Identify() { if (string.IsNullOrWhiteSpace(SelectedPersonGroupId)) { Error = "Person Group Id is not set!"; return; } Candidates = null; _identifyRequest = FaceRequestGenerator.Identify(SelectedPersonGroupId !, Faces.Select(f => f.faceId)); UpdateRequestList(); Candidates = await MakeRequest <List <IdentityCandidate> >(_identifyRequest).ConfigureAwait(false) ?? new List <IdentityCandidate>(0); }
protected override object GetFieldValue(Item cognitiveIndexable) { return(Faces?.Select(x => x.FaceAttributes.Age).OrderBy(a => a).FirstOrDefault() ?? 0d); }
/// <summary> /// Saves the foam object as a set of trimmed surfaces (one faced breps) /// For each brep it saves an entry in the user dictionary with the faceId /// For each vertex in the brep as Point an entry in the user dictionary is saved with the PFvertex Id /// </summary> /// <returns></returns> public IList <Guid> SaveAsFaces(bool asMesh = false) { // first determine if form or force // if foam has naked edges then it is form else it is force var doc = Rhino.RhinoDoc.ActiveDoc; doc.Views.RedrawEnabled = false; var form = Edges.Where(e => e.Id > 0).Any(x => x.Faces.Count < 2); var positiveFaces = Faces.Where(x => x.Id > 0); //var faceUserDict = new Dictionary<int, List<int>>(); bool foamSaved = false; var guids = new List <Guid>(); string primal = SerializeJson(); string dual = Dual?.SerializeJson() ?? ""; if (form) { // if the foam is a form then just save everything with the same color // except the exterior faces (applied forces and supports that will be printed with a different color var intFaces = new List <PFFace>(); var extFaces = new List <PFFace>(); foreach (var face in positiveFaces) { if (face.External) { extFaces.Add(face); } else { intFaces.Add(face); } } var intFaceLayer = new Rhino.DocObjects.Layer() { Name = "_Form_InternalFaces" }; if (doc.Layers.All(x => x.Name != intFaceLayer.Name)) { doc.Layers.Add(intFaceLayer); } intFaceLayer = doc.Layers.First(x => x.Name == "_Form_InternalFaces"); var extFaceLayer = new Rhino.DocObjects.Layer() { Name = "_Form_ExternalFaces" }; if (doc.Layers.All(x => x.Name != extFaceLayer.Name)) { doc.Layers.Add(extFaceLayer); } extFaceLayer = doc.Layers.First(x => x.Name == "_Form_ExternalFaces"); // go through internal faces foreach (var face in intFaces) { var attributes = new Rhino.DocObjects.ObjectAttributes { ObjectColor = System.Drawing.Color.SlateGray, ColorSource = Rhino.DocObjects.ObjectColorSource.ColorFromObject, Name = face.Id.ToString(), LayerIndex = intFaceLayer.LayerIndex, }; GeometryBase faceGeo; if (!asMesh) { faceGeo = face.CreateBrepMatched(); } else { faceGeo = face.FMesh; } // the foam will be serialized with the first interior face // this will include the dual if present if (!foamSaved) { faceGeo.UserDictionary.Set("Primal", primal); faceGeo.UserDictionary.Set("Dual", dual); foamSaved = true; } guids.Add(doc.Objects.Add(faceGeo, attributes)); } // go through the ext faces foreach (var face in extFaces) { var attributes = new Rhino.DocObjects.ObjectAttributes { ObjectColor = System.Drawing.Color.LightSlateGray, ColorSource = Rhino.DocObjects.ObjectColorSource.ColorFromObject, Name = face.Id.ToString(), LayerIndex = extFaceLayer.LayerIndex, }; GeometryBase faceGeo; if (!asMesh) { faceGeo = face.CreateBrepMatched(); } else { faceGeo = face.FMesh; } if (!foamSaved) { faceGeo.UserDictionary.Set("Primal", primal); faceGeo.UserDictionary.Set("Dual", dual); foamSaved = true; } guids.Add(doc.Objects.Add(faceGeo, attributes)); } } else // if force { var maxArea = Faces.Select(x => x.Area).Max(); var minArea = Faces.Select(x => x.Area).Min(); var forceFaceLayer = new Rhino.DocObjects.Layer() { Name = "_Force_Faces" }; if (doc.Layers.All(x => x.Name != forceFaceLayer.Name)) { doc.Layers.Add(forceFaceLayer); } forceFaceLayer = doc.Layers.First(x => x.Name == "_Force_Faces"); foreach (var face in positiveFaces) { var attributes = new Rhino.DocObjects.ObjectAttributes { ObjectColor = Util.CreateBlue(Util.ValueUnitizer(face.Area, new List <double> { minArea, maxArea }, new List <double> { 0.0, 1.0 })), ColorSource = Rhino.DocObjects.ObjectColorSource.ColorFromObject, Name = face.Id.ToString(), LayerIndex = forceFaceLayer.LayerIndex, }; GeometryBase faceGeo; if (!asMesh) { faceGeo = face.CreateBrepMatched(); } else { faceGeo = face.FMesh; } // the foam will be serialized with the first interior face // this will include the dual if present if (!foamSaved) { faceGeo.UserDictionary.Set("Primal", primal); faceGeo.UserDictionary.Set("Dual", dual); foamSaved = true; } guids.Add(doc.Objects.Add(faceGeo, attributes)); } } doc.Views.RedrawEnabled = true; doc.Groups.Add(Id.ToString(), guids); return(guids); }
/// <summary> /// Pick folder, then group detected faces by similarity /// </summary> /// <param name="sender">Event sender</param> /// <param name="e">Event arguments</param> private async void Grouping_Click(object sender, RoutedEventArgs e) { // Show folder picker FolderBrowserDialog dlg = new FolderBrowserDialog(); var result = dlg.ShowDialog(); // Set the suggestion count is intent to minimum the data preparetion step only, // it's not corresponding to service side constraint const int SuggestionCount = 10; if (result == DialogResult.OK) { // User picked one folder List <Task> tasks = new List <Task>(); int processCount = 0; bool forceContinue = false; // Clear previous grouping result GroupedFaces.Clear(); Faces.Clear(); Output = Output.AppendLine("Request: Preparing faces for grouping, detecting faces in choosen folder."); foreach (var img in Directory.EnumerateFiles(dlg.SelectedPath, "*.jpg", SearchOption.AllDirectories)) { tasks.Add(Task.Factory.StartNew( async(obj) => { var imgPath = obj as string; // Detect faces in image using (var fStream = File.OpenRead(imgPath)) { try { var faces = await App.Instance.DetectAsync(fStream); return(new Tuple <string, ClientContract.Face[]>(imgPath, faces)); } catch (ClientException) { // Here we simply ignore all detection failure in this sample // You may handle these exceptions by check the Error.Code and Error.Message property for ClientException object return(new Tuple <string, ClientContract.Face[]>(imgPath, null)); } } }, img).Unwrap().ContinueWith((detectTask) => { // Update detected faces on UI var res = detectTask.Result; if (res.Item2 == null) { return; } foreach (var f in res.Item2) { this.Dispatcher.Invoke( new Action <ObservableCollection <Face>, string, ClientContract.Face>(UIHelper.UpdateFace), Faces, res.Item1, f); } })); if (processCount >= SuggestionCount && !forceContinue) { var continueProcess = System.Windows.Forms.MessageBox.Show("Found many images under choosen folder, may take long time if proceed. Continue?", "Warning", MessageBoxButtons.YesNo); if (continueProcess == DialogResult.Yes) { forceContinue = true; } else { break; } } } await Task.WhenAll(tasks); Output = Output.AppendLine(string.Format("Response: Success. Total {0} faces are detected.", Faces.Count)); try { Output = Output.AppendLine(string.Format("Request: Grouping {0} faces.", Faces.Count)); // Call grouping, the grouping result is a group collection, each group contains similar faces var groupRes = await App.Instance.GroupAsync(Faces.Select(f => Guid.Parse(f.FaceId)).ToArray()); // Update grouping results for rendering foreach (var g in groupRes.Groups) { var gg = new GroupingResult() { Faces = new ObservableCollection <Face>(), IsMessyGroup = false, }; foreach (var fr in g) { gg.Faces.Add(Faces.First(f => f.FaceId == fr.ToString())); } GroupedFaces.Add(gg); } // MessyGroup contains all faces which are not similar to any other faces. // Take an extreme case for exampe: // On grouping faces which are not similar to any other faces, the grouping result will contains only one messy group if (groupRes.MessyGroup.Length > 0) { var messyGroup = new GroupingResult() { Faces = new ObservableCollection <Face>(), IsMessyGroup = true }; foreach (var messy in groupRes.MessyGroup) { messyGroup.Faces.Add(Faces.First(f => f.FaceId == messy.ToString())); } GroupedFaces.Add(messyGroup); } Output = Output.AppendLine(string.Format("Response: Success. {0} faces are grouped into {1} groups.", Faces.Count, GroupedFaces.Count)); } catch (ClientException ex) { Output = Output.AppendLine(string.Format("Response: {0}. {1}", ex.Error.Code, ex.Error.Message)); } } }
/// <summary> /// Pick folder, then group detected faces by similarity /// </summary> /// <param name="sender">Event sender</param> /// <param name="e">Event arguments</param> private async void Grouping_Click(object sender, RoutedEventArgs e) { // Show folder picker System.Windows.Forms.FolderBrowserDialog dlg = new System.Windows.Forms.FolderBrowserDialog(); var result = dlg.ShowDialog(); // Set the suggestion count is intent to minimum the data preparation step only, // it's not corresponding to service side constraint const int SuggestionCount = 10; if (result == System.Windows.Forms.DialogResult.OK) { // User picked one folder List <Task> tasks = new List <Task>(); int processCount = 0; bool forceContinue = false; // Clear previous grouping result GroupedFaces.Clear(); Faces.Clear(); MainWindow mainWindow = Window.GetWindow(this) as MainWindow; string subscriptionKey = mainWindow._scenariosControl.SubscriptionKey; string endpoint = mainWindow._scenariosControl.SubscriptionEndpoint; var faceServiceClient = new FaceServiceClient(subscriptionKey, endpoint); MainWindow.Log("Request: Preparing faces for grouping, detecting faces in chosen folder."); var imageList = new ConcurrentBag <string>( Directory.EnumerateFiles(dlg.SelectedPath, "*.*", SearchOption.AllDirectories) .Where(s => s.ToLower().EndsWith(".jpg") || s.ToLower().EndsWith(".png") || s.ToLower().EndsWith(".bmp") || s.ToLower().EndsWith(".gif"))); string img; while (imageList.TryTake(out img)) { tasks.Add(Task.Factory.StartNew( async(obj) => { var imgPath = obj as string; // Detect faces in image using (var fStream = File.OpenRead(imgPath)) { try { var faces = await faceServiceClient.DetectAsync(fStream); return(new Tuple <string, ClientContract.Face[]>(imgPath, faces)); } catch (FaceAPIException ex) { // if operation conflict, retry. if (ex.ErrorCode.Equals("ConcurrentOperationConflict")) { imageList.Add(imgPath); return(null); } // Here we simply ignore all detection failure in this sample // You may handle these exceptions by check the Error.Error.Code and Error.Message property for ClientException object return(new Tuple <string, ClientContract.Face[]>(imgPath, null)); } } }, img).Unwrap().ContinueWith((detectTask) => { // Update detected faces on UI var res = detectTask?.Result; if (res?.Item2 == null) { return; } foreach (var f in res.Item2) { this.Dispatcher.Invoke( new Action <ObservableCollection <Face>, string, ClientContract.Face>(UIHelper.UpdateFace), Faces, res.Item1, f); } })); if (processCount >= SuggestionCount && !forceContinue) { var continueProcess = System.Windows.Forms.MessageBox.Show("Found many images under chosen folder, may take long time if proceed. Continue?", "Warning", System.Windows.Forms.MessageBoxButtons.YesNo); if (continueProcess == System.Windows.Forms.DialogResult.Yes) { forceContinue = true; } else { break; } } if (tasks.Count >= _maxConcurrentProcesses || imageList.IsEmpty) { await Task.WhenAll(tasks); tasks.Clear(); } } MainWindow.Log("Response: Success. Total {0} faces are detected.", Faces.Count); try { MainWindow.Log("Request: Grouping {0} faces.", Faces.Count); // Call grouping, the grouping result is a group collection, each group contains similar faces var groupRes = await faceServiceClient.GroupAsync(Faces.Select(f => Guid.Parse(f.FaceId)).ToArray()); // Update grouping results for rendering foreach (var g in groupRes.Groups) { var gg = new GroupingResult() { Faces = new ObservableCollection <Face>(), IsMessyGroup = false, }; foreach (var fr in g) { gg.Faces.Add(Faces.First(f => f.FaceId == fr.ToString())); } GroupedFaces.Add(gg); } // MessyGroup contains all faces which are not similar to any other faces. // Take an extreme case for example: // On grouping faces which are not similar to any other faces, the grouping result will contains only one messy group if (groupRes.MessyGroup.Length > 0) { var messyGroup = new GroupingResult() { Faces = new ObservableCollection <Face>(), IsMessyGroup = true }; foreach (var messy in groupRes.MessyGroup) { messyGroup.Faces.Add(Faces.First(f => f.FaceId == messy.ToString())); } GroupedFaces.Add(messyGroup); } MainWindow.Log("Response: Success. {0} faces are grouped into {1} groups.", Faces.Count, GroupedFaces.Count); } catch (FaceAPIException ex) { MainWindow.Log("Response: {0}. {1}", ex.ErrorCode, ex.ErrorMessage); } } GC.Collect(); }
public override void UpdateBoundingBox(bool cascadeToParent = true) { BoundingBox = new Box(Faces.Select(x => x.BoundingBox)); base.UpdateBoundingBox(cascadeToParent); }
public IEnumerable <Emotion> GetEmotions() { return(Faces.Select(face => face.Emotion)); }