/// <summary> /// Merge a region into the current instance /// </summary> public void Merge(ConnectedRegion region) { coordinates.AddRange(region.coordinates); validBoundingRect = false; }
/// <summary> /// Normalizes the labeled regions of the image so that only root regions exist /// </summary> private void NormalizeLabelSequence() { // Tag the root labels int rootNodeCount = 0; for (int i = 0; i < labels.Count; i++) { if (IsRootNode(i)) { labels[i].Tag = rootNodeCount++; } } // Initialize as many regions as there are root labels ConnectedRegion[] regions = new ConnectedRegion[rootNodeCount]; for (int i = 0; i < rootNodeCount; i++) { regions[i] = new ConnectedRegion(); regions[i].RegionID = i; } // Fix pathological cases where sequential region numbering is borked Dictionary<int, int> realRegions = new Dictionary<int, int>(); int currentRegion = 0; // Run through the image data and set non-root labels to their root, // and add each coordinate to the corresponding region. for (int x = 0; x < Width; x++) { for (int y = 0; y < Height; y++) { int regionID = labels[RootOf(labelData[x, y])].Tag; if (realRegions.ContainsKey(regionID)) { regionID = realRegions[regionID]; } else { regionID = realRegions[regionID] = currentRegion; currentRegion++; } regions[regionID].AddCoordinate(new Point(x, y)); labelData[x, y] = regionID; } } // Cheat: The zeroth region is the image BG itself in this application. List<ConnectedRegion> regionList = new List<ConnectedRegion>(regions); regionList.RemoveAt(0); //// Optimization: A tiny region isn't going to contain any useful information. //// Remove small regions and resequence the list. //currentRegion = 0; //List<ConnectedRegion> killList = new List<ConnectedRegion>(); //foreach (ConnectedRegion region in regionList) //{ // if (region.GetCoordinates().Count < USEFUL_REGION_THRESHOLD) // { // killList.Add(region); // } // else // { // region.RegionID = currentRegion++; // foreach (Point p in region.GetCoordinates()) // { // labelData[p.X, p.Y] = region.RegionID; // } // } //} //foreach (ConnectedRegion region in killList) //{ // regionList.Remove(region); //} Regions = new ReadOnlyCollection<ConnectedRegion>(regionList); }