//Union-Find solution public int FindCircleNum(int[][] M) { int n = M.Length; var uf = new UnionFind(n); for (int i = 0; i < M.Length; i++) { for (int j = 0; j < M[0].Length; j++) { if (M[i][j] == 1 && i != j) // i != j (can't be friend to oneself) { uf.Union(i, j); } } } return(uf.ConnectedComponents()); }
private void RemoveBackground(Color[,] image, CIELAB[,] imageLAB) { //check perimeter to see if it's mostly black or white //RGB to LAB CIELAB black = new CIELAB(0, 0, 0); CIELAB white = new CIELAB(100, 0, 0); int width = image.GetLength(0); int height = image.GetLength(1); CIELAB[,] labs = imageLAB;//Util.Map<Color, CIELAB>(image, (c) => Util.RGBtoLAB(c)); int numBlack = 0; int numWhite = 0; int thresh = 3 * 3; List<Point> perimeterIdx = new List<Point>(); double totalPerimeter = 4 * width + 4 * height; double bgThresh = totalPerimeter*0.75; for (int i = 0; i < width; i++) { //top for (int j = 0; j < 2; j++) { if (black.SqDist(labs[i, j])<thresh) numBlack++; if (white.SqDist(labs[i, j]) < thresh) numWhite++; perimeterIdx.Add(new Point(i, j)); } //bottom for (int j = height - 2; j < height; j++) { perimeterIdx.Add(new Point(i, j)); if (black.SqDist(labs[i, j]) < thresh) numBlack++; if (white.SqDist(labs[i, j]) < thresh) numWhite++; } } for (int j = 0; j < height; j++) { //left for (int i=0; i<2; i++) { perimeterIdx.Add(new Point(i,j)); if (black.SqDist(labs[i, j]) < thresh) numBlack++; if (white.SqDist(labs[i, j]) < thresh) numWhite++; } //right for (int i=width-2; i<width; i++) { perimeterIdx.Add(new Point(i, j)); if (black.SqDist(labs[i, j]) < thresh) numBlack++; if (white.SqDist(labs[i, j]) < thresh) numWhite++; } } if (numBlack >= bgThresh || numWhite >= bgThresh) { //connected components UnionFind<CIELAB> uf = new UnionFind<CIELAB>((a,b) => a.SqDist(b)<thresh); int[,] cc = uf.ConnectedComponents(labs); SortedSet<int> ids = new SortedSet<int>(); //go around the perimeter to collect the right ids foreach (Point p in perimeterIdx) { if (numWhite > numBlack) { if (labs[p.X, p.Y].SqDist(white) < thresh) ids.Add(cc[p.X, p.Y]); } else { if (labs[p.X, p.Y].SqDist(black) < thresh) ids.Add(cc[p.X, p.Y]); } } //fill the bitmap with transparency for (int i = 0; i < width; i++) { for (int j = 0; j < height; j++) { if (ids.Contains(cc[i, j])) image[i, j] = Color.FromArgb(0, 0, 0, 0); } } } }
private bool ProcessImage(Color[,] image, CIELAB[,] imageLAB) { double thresh = 5; UnionFind<CIELAB> uf = new UnionFind<CIELAB>((a,b)=>(a.SqDist(b)<=thresh)); int[,] assignments = uf.ConnectedComponents(imageLAB);//Util.Map<Color, CIELAB>(image, Util.RGBtoLAB)); int numC = -1; for(int i=0; i<image.GetLength(0); i++) for (int j=0; j<image.GetLength(1); j++) numC = Math.Max(numC, assignments[i,j]+1); if (numC >= 2) RemoveBackground(image, imageLAB); //if it is a black and white image (with num connected components >= 2), it's not a valid color image return !(isBlackWhite(image, imageLAB) && numC >= 2); }