/// <summary> /// Label the connected components of an image. /// </summary> public static int label_components(ref Intarray image, bool four_connected = false) { int w = image.Dim(0), h = image.Dim(1); // We slice the image into columns and call make_set() // for every continuous segment within each column. // Maximal number of segments per column is (h + 1) / 2. // We do it `w' times, so it's w * (h + 1) / 2. // We also need to add 1 because index 0 is not used, but counted. UnionFind uf = new UnionFind(w * (h + 1) / 2 + 1); uf.make_set(0); int top = 1; for (int i = 0; i < image.Length1d(); i++) { image.Put1d(i, (image.At1d(i) > 0 ? 1 : 0)); } //for(int i=0;i<w;i++) {image(i,0) = 0; image(i,h-1) = 0;} //for(int j=0;j<h;j++) {image(0,j) = 0; image(w-1,j) = 0;} for (int i = 0; i < w; i++) { int current_label = 0; for (int j = 0; j < h; j++) { int pixel = image[i, j]; int range = four_connected ? 0 : 1; for (int delta = -range; delta <= range; delta++) { int adj_label = NarrayUtil.Bat(image, i - 1, j + delta, 0); if (pixel == 0) { current_label = 0; continue; } if (current_label == 0) { current_label = top; uf.make_set(top); top++; } if (adj_label > 0) { current_label = uf.find_set(current_label); adj_label = uf.find_set(adj_label); if (current_label != adj_label) { uf.make_union(current_label, adj_label); current_label = uf.find_set(current_label); adj_label = uf.find_set(adj_label); } } image[i, j] = current_label; } } } for (int i = 0; i < image.Length1d(); i++) { if (image.At1d(i) == 0) { continue; } image.Put1d(i, uf.find_set(image.At1d(i))); } return(renumber_labels(image, 1)); }