// find objects public static Dictionary <Tuple <int, int>, List <Tuple <int, int> > > Groups(int[,] image) { // union find to store sets of all pixels in object UnionFind <Tuple <int, int> > unionFind = new UnionFind <Tuple <int, int> >(); for (int x = 0; x < image.GetLength(0); x++) { for (int y = 0; y < image.GetLength(1); y++) { if (image[x, y] == 0) { continue; } Tuple <int, int> xy = new Tuple <int, int>(x, y); unionFind.Make(xy); if (x > 0) { unionFind.Union(xy, new Tuple <int, int>(x - 1, y)); } if (y > 0) { unionFind.Union(xy, new Tuple <int, int>(x, y - 1)); } } } // turns union find "inside out": (pixel->set identifier)->(set identifier->all pixels in set) Dictionary <Tuple <int, int>, List <Tuple <int, int> > > labels = new Dictionary <Tuple <int, int>, List <Tuple <int, int> > >(); for (int x = 0; x < image.GetLength(0); x++) { for (int y = 0; y < image.GetLength(1); y++) { if (image[x, y] == 0) { continue; } Tuple <int, int> xy = new Tuple <int, int>(x, y), label = unionFind.Find(xy); List <Tuple <int, int> > list; if (!labels.TryGetValue(label, out list)) { list = new List <Tuple <int, int> >(); labels[label] = list; } list.Add(xy); } } return(labels); }
private void inputImageBox_MouseDown(object sender, MouseEventArgs e) { if (this.data == null) { return; } int xx = e.X - (inputImageBox.Width - inputImageBox.Image.Width) / 2; int yy = e.Y - (inputImageBox.Height - inputImageBox.Image.Height) / 2; switch (currentStep) { case 5: // Compactness decimal r = (decimal)Operations.Compactness(this.prevData, xx, yy); decimal rLow = Math.Floor(r * 100) / 100; decimal rHigh = Math.Ceiling(r * 100) / 100; minComp.Value = Math.Min(minComp.Value, rLow); maxComp.Value = Math.Max(maxComp.Value, rHigh); break; case 6: // Area decimal a = (decimal)Operations.Area(Operations.Perimeter(this.prevData, xx, yy)); decimal aLow = Math.Floor(a * 100) / 100; decimal aHigh = Math.Ceiling(a * 100) / 100; minArea.Value = Math.Min(minArea.Value, aLow); maxArea.Value = Math.Max(maxArea.Value, aHigh); break; case 7: // Convexity UnionFind <Tuple <int, int> > unionFind = new UnionFind <Tuple <int, int> >(); for (int x = 0; x < this.prevData.GetLength(0); x++) { for (int y = 0; y < this.prevData.GetLength(1); y++) { if (this.prevData[x, y] == 0) { continue; } Tuple <int, int> xy = new Tuple <int, int>(x, y); unionFind.Make(xy); if (x > 0) { unionFind.Union(xy, new Tuple <int, int>(x - 1, y)); } if (y > 0) { unionFind.Union(xy, new Tuple <int, int>(x, y - 1)); } } } Tuple <int, int> root; try { root = unionFind.Find(new Tuple <int, int>(xx, yy)); } catch { return; } List <Tuple <int, int> > points = new List <Tuple <int, int> >(); for (int x = 0; x < this.prevData.GetLength(0); x++) { for (int y = 0; y < this.prevData.GetLength(1); y++) { if (this.prevData[x, y] == 0) { continue; } Tuple <int, int> pos = new Tuple <int, int>(x, y); if (unionFind.Find(pos) == root) { points.Add(pos); } } } double hullArea = Operations.PolygonArea(Operations.ConvexHull(points)); double area = Operations.Area(Operations.Perimeter(this.prevData, xx, yy)); decimal c = (decimal)(area / hullArea); decimal cLow = Math.Floor(c * 100) / 100; decimal cHigh = Math.Ceiling(c * 100) / 100; minConv.Value = Math.Min(minConv.Value, cLow); maxConv.Value = Math.Max(maxConv.Value, cHigh); break; default: break; } }