Example #1
0
        /// <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));
        }