public void Init(int n = 0) { _keys.Resize(n); for (int i = 0; i < n; i++) { _keys.Put1d(i, i); } _values.Resize(n); _values.Fill <float>(0.0f); }
/// <summary> /// Merge segments from start to end. /// </summary> /// <param name="cseg">Output</param> /// <param name="rseg">Input</param> /// <param name="start">start merge position</param> /// <param name="end">end merge position</param> public static void rseg_to_cseg(Intarray cseg, Intarray rseg, int start, int end) { int maxSegNum = NarrayUtil.Max(rseg); if (start > end) { throw new Exception("segmentation encoded in IDs looks seriously broken!"); } if (start > maxSegNum || end > maxSegNum) { throw new Exception("segmentation encoded in IDs doesn't fit!"); } Intarray map = new Intarray(maxSegNum + 1); map.Fill(0); int color = 1; for (int i = 1; i <= maxSegNum; i++) { map[i] = color; if (i < start || i >= end) { color++; } } cseg.MakeLike(rseg); for (int i = 0; i < cseg.Length1d(); i++) { cseg.Put1d(i, map[rseg.At1d(i)]); } }
public static void rseg_to_cseg(Intarray cseg, Intarray rseg, Intarray ids) { Intarray map = new Intarray(NarrayUtil.Max(rseg) + 1); map.Fill(0); int color = 0; for (int i = 0; i < ids.Length(); i++) { if (ids[i] == 0) { continue; } color++; int start = ids[i] >> 16; int end = ids[i] & 0xFFFF; if (start > end) { throw new Exception("segmentation encoded in IDs looks seriously broken!"); } if (start >= map.Length() || end >= map.Length()) { throw new Exception("segmentation encoded in IDs doesn't fit!"); } for (int j = start; j <= end; j++) { map[j] = color; } } cseg.MakeLike(rseg); for (int i = 0; i < cseg.Length1d(); i++) { cseg.Put1d(i, map[rseg.At1d(i)]); } }
public override void Charseg(ref Intarray outimage, Bytearray inimage) { int swidth = PGeti("swidth"); int sheight = PGeti("sheight"); Bytearray image = new Bytearray(); image.Copy(inimage); OcrRoutine.binarize_simple(image); OcrRoutine.Invert(image); outimage.Copy(image); if (swidth > 0 || sheight > 0) { Morph.binary_close_rect(image, swidth, sheight); } Intarray labels = new Intarray(); labels.Copy(image); ImgLabels.label_components(ref labels); for (int i = 0; i < outimage.Length1d(); i++) { if (outimage.At1d(i) > 0) { outimage.Put1d(i, SegmRoutine.cseg_pixel(labels.At1d(i))); } } SegmRoutine.make_line_segmentation_white(outimage); SegmRoutine.check_line_segmentation(outimage); }
public static void make_line_segmentation_black(Intarray a) { check_line_segmentation(a); ImgMisc.replace_values(a, 0xFFFFFF, 0); for (int i = 0; i < a.Length1d(); i++) { a.Put1d(i, a.At1d(i) & 0xFFF); } }
public override void Charseg(ref Intarray outimage, Bytearray inarray) { Bytearray image = new Bytearray(); image.Copy(inarray); OcrRoutine.binarize_simple(image); OcrRoutine.Invert(image); outimage.Copy(image); Intarray labels = new Intarray(); labels.Copy(image); ImgLabels.label_components(ref labels); Narray <Rect> boxes = new Narray <Rect>(); ImgLabels.bounding_boxes(ref boxes, labels); Intarray equiv = new Intarray(boxes.Length()); for (int i = 0; i < boxes.Length(); i++) { equiv[i] = i; } for (int i = 1; i < boxes.Length(); i++) { Rect p = boxes[i]; for (int j = 1; j < boxes.Length(); j++) { if (i == j) { continue; } Rect q = boxes[j]; int x0 = Math.Max(p.x0, q.x0); int x1 = Math.Min(p.x1, q.x1); int iw = x1 - x0; if (iw <= 0) { continue; // no overlap } int ow = Math.Min(p.Width(), q.Width()); float frac = iw / (float)(ow); if (frac < 0.5f) { continue; // insufficient overlap } // printf("%d %d : %d %d : %g\n",i,j,iw,ow,frac); equiv.Put1d(Math.Max(i, j), Math.Min(i, j)); } } for (int i = 0; i < labels.Length(); i++) { labels.Put1d(i, equiv.At1d(labels.At1d(i))); } ImgLabels.renumber_labels(labels, 1); outimage.Move(labels); SegmRoutine.make_line_segmentation_white(outimage); SegmRoutine.check_line_segmentation(outimage); }
public TestDataset() { classes = new int[sClasses.Length]; aclasses = new Intarray(sClasses.Length); for (int i = 0; i < sClasses.Length; i++) { classes[i] = (int)sClasses[i]; aclasses.Put1d(i, classes[i]); } }
public static void combine_segmentations(ref Intarray dst, Intarray src) { dst.SameDims(src); int n = NarrayUtil.Max(dst) + 1; for (int i = 0; i < dst.Length1d(); i++) { dst.Put1d(i, (dst.At1d(i) + src.At1d(i) * n)); } ImgLabels.renumber_labels(dst, 1); }
public override void SplitIndices(Intarray result1, Intarray result2, Intarray indices) { result1.MakeLike(indices); result2.MakeLike(indices); int k = l2.nStates(); for (int i = 0; i < indices.Length(); i++) { result1.Put1d(i, indices.At1d(i) / k); result2.Put1d(i, indices.At1d(i) % k); } }
public static void propagate_labels_to(ref Intarray target, Intarray seed) { Floatarray dist = new Floatarray(); Narray <Point> source = new Narray <Point>(); dist.Copy(seed); BrushFire.brushfire_2(ref dist, ref source, 1000000); for (int i = 0; i < dist.Length1d(); i++) { Point p = source.At1d(i); if (target.At1d(i) > 0) { target.Put1d(i, seed[p.X, p.Y]); } } }
/// <summary> /// Propagate labels across the entire image from a set of non-zero seeds. /// </summary> public static void propagate_labels(ref Intarray image) { Floatarray dist = new Floatarray(); Narray <Point> source = new Narray <Point>(); dist.Copy(image); BrushFire.brushfire_2(ref dist, ref source, 1000000); for (int i = 0; i < dist.Length1d(); i++) { Point p = source.At1d(i); if (image.At1d(i) == 0) { image.Put1d(i, image[p.X, p.Y]); } } }
/// <summary> /// Remove segments from start to end. /// </summary> /// <param name="cseg">Output</param> /// <param name="rseg">Input</param> /// <param name="start">start remove position</param> /// <param name="end">end remove position</param> public static void rseg_to_cseg_remove(Intarray cseg, Intarray rseg, Bytearray outimg, Bytearray img, int start, int end) { int maxSegNum = NarrayUtil.Max(rseg); if (start > end) { throw new Exception("segmentation encoded in IDs looks seriously broken!"); } if (start > maxSegNum || end > maxSegNum) { throw new Exception("segmentation encoded in IDs doesn't fit!"); } if (rseg.Length1d() != img.Length1d()) { throw new Exception("rseg and img must have same a dimension!"); } Intarray map = new Intarray(maxSegNum + 1); map.Fill(0); int color = 1; for (int i = 1; i <= maxSegNum; i++) { map[i] = color; if (i < start || i > end) { color++; } else { map[i] = 0; } } cseg.MakeLike(rseg); outimg.Copy(img); for (int i = 0; i < cseg.Length1d(); i++) { int val = rseg.At1d(i); cseg.Put1d(i, map[val]); if (val > 0 && map[val] == 0) { outimg.Put1d(i, 255); } } }
public static void line_segmentation_sort_x(Intarray segmentation) { if (NarrayUtil.Max(segmentation) > 100000) { throw new Exception("line_segmentation_merge_small_components: to many segments"); } Narray <Rect> bboxes = new Narray <Rect>(); ImgLabels.bounding_boxes(ref bboxes, segmentation); Floatarray x0s = new Floatarray(); unchecked { x0s.Push((float)-999999); } for (int i = 1; i < bboxes.Length(); i++) { if (bboxes[i].Empty()) { x0s.Push(999999); } else { x0s.Push(bboxes[i].x0); } } // dprint(x0s,1000); printf("\n"); Narray <int> permutation = new Intarray(); Narray <int> rpermutation = new Intarray(); NarrayUtil.Quicksort(permutation, x0s); rpermutation.Resize(permutation.Length()); for (int i = 0; i < permutation.Length(); i++) { rpermutation[permutation[i]] = i; } // dprint(rpermutation,1000); printf("\n"); for (int i = 0; i < segmentation.Length1d(); i++) { if (segmentation.At1d(i) == 0) { continue; } segmentation.Put1d(i, rpermutation[segmentation.At1d(i)]); } }
public static void simple_recolor(Intarray image) { /*for (int i = 0; i < image.Length1d(); i++) * { * if (image.At1d(i) == 0) continue; * image.At1d(i) = enumerator[image.at1d(i)]; * }*/ for (int i = 0; i < image.Length1d(); i++) { int value = image.At1d(i); if (value == 0 || value == 0xffffff) { continue; } image.Put1d(i, interesting_colors(1 + value % 19)); } }
public override void Charseg(ref Intarray outimage, Bytearray inimage) { int swidth = PGeti("swidth"); int sheight = PGeti("sheight"); Bytearray image = new Bytearray(); image.Copy(inimage); OcrRoutine.binarize_simple(image); OcrRoutine.Invert(image); outimage.Copy(image); if (swidth > 0 || sheight > 0) Morph.binary_close_rect(image, swidth, sheight); Intarray labels = new Intarray(); labels.Copy(image); ImgLabels.label_components(ref labels); for(int i=0; i<outimage.Length1d(); i++) if (outimage.At1d(i) > 0) outimage.Put1d(i, SegmRoutine.cseg_pixel(labels.At1d(i))); SegmRoutine.make_line_segmentation_white(outimage); SegmRoutine.check_line_segmentation(outimage); }
public static void remove_small_components <T>(Narray <T> bimage, int mw, int mh) { Intarray image = new Intarray(); image.Copy(bimage); ImgLabels.label_components(ref image); Narray <Rect> rects = new Narray <Rect>(); ImgLabels.bounding_boxes(ref rects, image); Bytearray good = new Bytearray(rects.Length()); for (int i = 0; i < good.Length(); i++) { good[i] = 1; } for (int i = 0; i < rects.Length(); i++) { if (rects[i].Width() < mw && rects[i].Height() < mh) { // printf("*** %d %d %d\n",i,rects[i].width(),rects[i].height()); good[i] = 0; } } for (int i = 0; i < image.Length1d(); i++) { if (good[image.At1d(i)] == 0) { image.Put1d(i, 0); } } for (int i = 0; i < image.Length1d(); i++) { if (image.At1d(i) == 0) { bimage.Put1d(i, default(T)); // default(T) - 0 } } }
public override void Charseg(ref Intarray outimage, Bytearray inarray) { Bytearray image = new Bytearray(); image.Copy(inarray); OcrRoutine.binarize_simple(image); OcrRoutine.Invert(image); outimage.Copy(image); Intarray labels = new Intarray(); labels.Copy(image); ImgLabels.label_components(ref labels); Narray<Rect> boxes = new Narray<Rect>(); ImgLabels.bounding_boxes(ref boxes, labels); Intarray equiv = new Intarray(boxes.Length()); for(int i=0; i<boxes.Length(); i++) equiv[i] = i; for(int i=1; i<boxes.Length(); i++) { Rect p = boxes[i]; for(int j=1;j<boxes.Length();j++) { if(i==j) continue; Rect q = boxes[j]; int x0 = Math.Max(p.x0, q.x0); int x1 = Math.Min(p.x1, q.x1); int iw = x1-x0; if(iw <= 0) continue; // no overlap int ow = Math.Min(p.Width(), q.Width()); float frac = iw/(float)(ow); if(frac < 0.5f) continue; // insufficient overlap // printf("%d %d : %d %d : %g\n",i,j,iw,ow,frac); equiv.Put1d(Math.Max(i, j), Math.Min(i, j)); } } for(int i=0; i<labels.Length(); i++) labels.Put1d(i, equiv.At1d(labels.At1d(i))); ImgLabels.renumber_labels(labels, 1); outimage.Move(labels); SegmRoutine.make_line_segmentation_white(outimage); SegmRoutine.check_line_segmentation(outimage); }
public static void remove_dontcares(ref Intarray image) { Floatarray dist = new Floatarray(); Narray <Point> source = new Narray <Point>(); dist.Resize(image.Dim(0), image.Dim(1)); for (int i = 0; i < dist.Length1d(); i++) { if (!dontcare(image.At1d(i))) { dist.Put1d(i, (image.At1d(i) > 0 ? 1 : 0)); } } BrushFire.brushfire_2(ref dist, ref source, 1000000); for (int i = 0; i < dist.Length1d(); i++) { Point p = source.At1d(i); if (dontcare(image.At1d(i))) { image.Put1d(i, image[p.X, p.Y]); } } }
/// <summary> /// Renumber the non-zero pixels in an image to start with pixel value start. /// The numerical order of pixels is preserved. /// </summary> public static int renumber_labels(Intarray image, int start = 1) { //SortedList<int, int> translation = new SortedList<int, int>(256); Dictionary <int, int> translation = new Dictionary <int, int>(256); int n = start; for (int i = 0; i < image.Length1d(); i++) { int pixel = image.At1d(i); if (pixel == 0 || pixel == 0xffffff) { continue; } if (!translation.ContainsKey(pixel)) { translation.Add(pixel, n); n++; } } n = start; int[] keys = translation.Keys.ToArray(); foreach (int key in keys) { translation[key] = n++; } for (int i = 0; i < image.Length1d(); i++) { int pixel = image.At1d(i); if (pixel == 0 || pixel == 0xffffff) { continue; } image.Put1d(i, translation[pixel]); } return(n); }
public override void Charseg(ref Intarray segmentation, Bytearray inraw) { setParams(); //Logger.Default.Image("segmenting", inraw); int PADDING = 3; OcrRoutine.optional_check_background_is_lighter(inraw); Bytearray image = new Bytearray(); image.Copy(inraw); OcrRoutine.binarize_simple(image); OcrRoutine.Invert(image); SetImage(image); FindAllCuts(); FindBestCuts(); Intarray seg = new Intarray(); seg.MakeLike(image); seg.Fill(255); for (int r = 0; r < bestcuts.Length(); r++) { int w = seg.Dim(0); int c = bestcuts[r]; Narray <Point> cut = cuts[c]; for (int y = 0; y < image.Dim(1); y++) { for (int i = -1; i <= 1; i++) { int x = cut[y].X; if (x < 1 || x >= w - 1) { continue; } seg[x + i, y] = 0; } } } ImgLabels.label_components(ref seg); // dshowr(seg,"YY"); dwait(); segmentation.Copy(image); for (int i = 0; i < seg.Length1d(); i++) { if (segmentation.At1d(i) == 0) { seg.Put1d(i, 0); } } ImgLabels.propagate_labels_to(ref segmentation, seg); if (PGeti("component_segmentation") > 0) { Intarray ccseg = new Intarray(); ccseg.Copy(image); ImgLabels.label_components(ref ccseg); SegmRoutine.combine_segmentations(ref segmentation, ccseg); if (PGeti("fix_diacritics") > 0) { SegmRoutine.fix_diacritics(segmentation); } } #if false SegmRoutine.line_segmentation_merge_small_components(ref segmentation, small_merge_threshold); SegmRoutine.line_segmentation_sort_x(segmentation); #endif SegmRoutine.make_line_segmentation_white(segmentation); // set_line_number(segmentation, 1); //Logger.Default.Image("resulting segmentation", segmentation); }
public override void Charseg(ref Intarray segmentation, Bytearray inraw) { setParams(); //Logger.Default.Image("segmenting", inraw); int PADDING = 3; OcrRoutine.optional_check_background_is_lighter(inraw); Bytearray image = new Bytearray(); image.Copy(inraw); OcrRoutine.binarize_simple(image); OcrRoutine.Invert(image); SetImage(image); FindAllCuts(); FindBestCuts(); Intarray seg = new Intarray(); seg.MakeLike(image); seg.Fill(255); for (int r = 0; r < bestcuts.Length(); r++) { int w = seg.Dim(0); int c = bestcuts[r]; Narray<Point> cut = cuts[c]; for (int y = 0; y < image.Dim(1); y++) { for (int i = -1; i <= 1; i++) { int x = cut[y].X; if (x < 1 || x >= w - 1) continue; seg[x + i, y] = 0; } } } ImgLabels.label_components(ref seg); // dshowr(seg,"YY"); dwait(); segmentation.Copy(image); for (int i = 0; i < seg.Length1d(); i++) if (segmentation.At1d(i) == 0) seg.Put1d(i, 0); ImgLabels.propagate_labels_to(ref segmentation, seg); if (PGeti("component_segmentation") > 0) { Intarray ccseg = new Intarray(); ccseg.Copy(image); ImgLabels.label_components(ref ccseg); SegmRoutine.combine_segmentations(ref segmentation, ccseg); if (PGeti("fix_diacritics") > 0) { SegmRoutine.fix_diacritics(segmentation); } } #if false SegmRoutine.line_segmentation_merge_small_components(ref segmentation, small_merge_threshold); SegmRoutine.line_segmentation_sort_x(segmentation); #endif SegmRoutine.make_line_segmentation_white(segmentation); // set_line_number(segmentation, 1); //Logger.Default.Image("resulting segmentation", segmentation); }
/// <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)); }
/// <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); }
public static void simple_recolor(Intarray image) { /*for (int i = 0; i < image.Length1d(); i++) { if (image.At1d(i) == 0) continue; image.At1d(i) = enumerator[image.at1d(i)]; }*/ for (int i = 0; i < image.Length1d(); i++) { int value = image.At1d(i); if (value == 0 || value == 0xffffff) continue; image.Put1d(i, interesting_colors(1 + value % 19)); } }
/// <summary> /// Renumber the non-zero pixels in an image to start with pixel value start. /// The numerical order of pixels is preserved. /// </summary> public static int renumber_labels(Intarray image, int start=1) { //SortedList<int, int> translation = new SortedList<int, int>(256); Dictionary<int, int> translation = new Dictionary<int, int>(256); int n = start; for(int i=0; i<image.Length1d(); i++) { int pixel = image.At1d(i); if(pixel==0 || pixel==0xffffff) continue; if (!translation.ContainsKey(pixel)) { translation.Add(pixel, n); n++; } } n = start; int[] keys = translation.Keys.ToArray(); foreach (int key in keys) translation[key] = n++; for(int i=0;i<image.Length1d();i++) { int pixel = image.At1d(i); if(pixel==0 || pixel==0xffffff) continue; image.Put1d(i, translation[pixel]); } return n; }
public static void remove_dontcares(ref Intarray image) { Floatarray dist = new Floatarray(); Narray<Point> source = new Narray<Point>(); dist.Resize(image.Dim(0), image.Dim(1)); for (int i = 0; i < dist.Length1d(); i++) if (!dontcare(image.At1d(i))) dist.Put1d(i, (image.At1d(i) > 0 ? 1 : 0)); BrushFire.brushfire_2(ref dist, ref source, 1000000); for (int i = 0; i < dist.Length1d(); i++) { Point p = source.At1d(i); if (dontcare(image.At1d(i))) image.Put1d(i, image[p.X, p.Y]); } }
public static void propagate_labels_to(ref Intarray target, Intarray seed) { Floatarray dist = new Floatarray(); Narray<Point> source = new Narray<Point>(); dist.Copy(seed); BrushFire.brushfire_2(ref dist, ref source, 1000000); for (int i = 0; i < dist.Length1d(); i++) { Point p = source.At1d(i); if (target.At1d(i) > 0) target.Put1d(i, seed[p.X, p.Y]); } }
/// <summary> /// Propagate labels across the entire image from a set of non-zero seeds. /// </summary> public static void propagate_labels(ref Intarray image) { Floatarray dist = new Floatarray(); Narray<Point> source = new Narray<Point>(); dist.Copy(image); BrushFire.brushfire_2(ref dist, ref source, 1000000); for (int i = 0; i < dist.Length1d(); i++) { Point p = source.At1d(i); if (image.At1d(i) == 0) image.Put1d(i, image[p.X, p.Y]); } }
public static void fix_diacritics(Intarray segmentation) { Narray <Rect> bboxes = new Narray <Rect>(); ImgLabels.bounding_boxes(ref bboxes, segmentation); if (bboxes.Length() < 1) { return; } Intarray assignments = new Intarray(bboxes.Length()); for (int i = 0; i < assignments.Length(); i++) { assignments[i] = i; } for (int j = 0; j < bboxes.Length(); j++) { float dist = 1e38f; int closest = -1; for (int i = 0; i < bboxes.Length(); i++) { // j should overlap i in the x direction if (bboxes.At1d(j).x1 < bboxes.At1d(i).x0) { continue; } if (bboxes.At1d(j).x0 > bboxes.At1d(i).x1) { continue; } // j should be above i if (!(bboxes.At1d(j).y0 >= bboxes.At1d(i).y1)) { continue; } #if false // j should be smaller than i if (!(bboxes.At1d(j).area() < bboxes.At1d(i).area())) { continue; } #endif float d = Math.Abs((bboxes[j].x0 + bboxes[j].x1) / 2 - (bboxes[i].x0 + bboxes[i].x1) / 2); if (d >= dist) { continue; } dist = d; closest = i; } if (closest < 0) { continue; } assignments[j] = closest; } for (int i = 0; i < segmentation.Length(); i++) { segmentation.Put1d(i, assignments[segmentation.At1d(i)]); } ImgLabels.renumber_labels(segmentation, 1); }