//Performs MST based segmentation as described by Pedro and Hutt //k - theshold. larger values make fewer components //min-size - smallest size of a component int Segment_Image(double k, int minsize, IReadAsDoubleGrid src, IReadAsDoubleGrid dst, EdgeCostFunction f) { int width = src.Width; int height = src.Height; this.edgeCostFunction = f; ds.Clear(); clusters.Clear(); for (int i = 0; i < width; i++) setmap[i] = -1; //build the graph we are going to segment over... //this is an 8 connected graph (carindal and subcardinal 1 neighbors) int numEdges = 0; for (int y = 0; y < height; y++) { for (int x = 0; x < width; x++) { if (x < width - 1) //right neighbor graph[numEdges++] = new Edge(y * width + x, y * width + (x + 1), edgeCostFunction(src, x, y, x + 1, y)); if (y > 0) //up neighbor graph[numEdges++] = new Edge(y * width + x, (y - 1) * width + x, edgeCostFunction(src, x, y, x, y - 1)); if ((x < width - 1) && (y > 0)) //up and right neibor graph[numEdges++] = new Edge(y * width + x, (y - 1) * width + (x + 1), edgeCostFunction(src, x, y, x + 1, y - 1)); if ((x < width - 1) && (y < height - 1)) //down and right neighbor graph[numEdges++] = new Edge(y * width + x, (y + 1) * width + (x + 1), edgeCostFunction(src, x, y, x + 1, y + 1)); } } //now sort the edges graph.Sort(); //ok graph is built - do some segmentation! //initalize the tresholds to their initial values (see discussion in loop) for (int i = 0; i < width * height; i++) thresholds[i] = ThresholdFunction(k, 1); //traverse the graph in increasing edge weight order... //the goal here is to try to assemble cohesive sets using the //union. for (int i = 0; i < numEdges; i++) { //the a node is the current pixel, the b node is the neighbor int aID = ds.FindSetRoot(graph[i].aNode); int bID = ds.FindSetRoot(graph[i].bNode); //if these are two distinct clusters, can we merge them? if (aID != bID) { //merge if both the aID and bID thesholds are bigger than this current elements weight if ((graph[i].weight <= thresholds[aID]) && (graph[i].weight <= thresholds[bID])) { //join the clusters ds.Union(aID, bID); //update the theshold of the newly formed cluster aID = ds.FindSetRoot(aID); //i think this can be optimized... //normalize the added theshold weight by the size of this new bigger cluster //from the paper: this threshold function is a function of the size of the component. // this ends up making small components require stronger evidence for a boundary thresholds[aID] = graph[i].weight + ThresholdFunction(k, ds.NumElements(aID)); } } } // post process small components for (int i = 0; i < numEdges; i++) { int aID = ds.FindSetRoot(graph[i].aNode); int bID = ds.FindSetRoot(graph[i].bNode); if ((aID != bID) && ((ds.NumElements(aID) < minsize) || (ds.NumElements(bID) < minsize))) ds.Union(aID, bID); } int sets = ds.NumSets(); clusters = new List<List<int>>(sets); int mapIndex = 0; for (int y = 0; y < height; y++) { for (int x = 0; x < width; x++) { int point = y * width + x; int comp = ds.FindSetRoot(point); //try to get the setmap... //first check is this a root? if (setmap[comp] == -1) { setmap[comp] = mapIndex; clusters.Add(new List<int>(ds.NumElements(comp))); clusters[mapIndex].Add(point); mapIndex++; } else { clusters[setmap[comp]].Add(point); } } } return sets; }
//Performs MST based segmentation as described by Pedro and Hutt //k - theshold. larger values make fewer components //min-size - smallest size of a component int Segment_Image(double k, int minsize, IReadAsDoubleGrid src, IReadAsDoubleGrid dst, EdgeCostFunction f) { int width = src.Width; int height = src.Height; this.edgeCostFunction = f; ds.Clear(); clusters.Clear(); for (int i = 0; i < width; i++) { setmap[i] = -1; } //build the graph we are going to segment over... //this is an 8 connected graph (carindal and subcardinal 1 neighbors) int numEdges = 0; for (int y = 0; y < height; y++) { for (int x = 0; x < width; x++) { if (x < width - 1) //right neighbor { graph[numEdges++] = new Edge(y * width + x, y * width + (x + 1), edgeCostFunction(src, x, y, x + 1, y)); } if (y > 0) //up neighbor { graph[numEdges++] = new Edge(y * width + x, (y - 1) * width + x, edgeCostFunction(src, x, y, x, y - 1)); } if ((x < width - 1) && (y > 0)) //up and right neibor { graph[numEdges++] = new Edge(y * width + x, (y - 1) * width + (x + 1), edgeCostFunction(src, x, y, x + 1, y - 1)); } if ((x < width - 1) && (y < height - 1)) //down and right neighbor { graph[numEdges++] = new Edge(y * width + x, (y + 1) * width + (x + 1), edgeCostFunction(src, x, y, x + 1, y + 1)); } } } //now sort the edges graph.Sort(); //ok graph is built - do some segmentation! //initalize the tresholds to their initial values (see discussion in loop) for (int i = 0; i < width * height; i++) { thresholds[i] = ThresholdFunction(k, 1); } //traverse the graph in increasing edge weight order... //the goal here is to try to assemble cohesive sets using the //union. for (int i = 0; i < numEdges; i++) { //the a node is the current pixel, the b node is the neighbor int aID = ds.FindSetRoot(graph[i].aNode); int bID = ds.FindSetRoot(graph[i].bNode); //if these are two distinct clusters, can we merge them? if (aID != bID) { //merge if both the aID and bID thesholds are bigger than this current elements weight if ((graph[i].weight <= thresholds[aID]) && (graph[i].weight <= thresholds[bID])) { //join the clusters ds.Union(aID, bID); //update the theshold of the newly formed cluster aID = ds.FindSetRoot(aID); //i think this can be optimized... //normalize the added theshold weight by the size of this new bigger cluster //from the paper: this threshold function is a function of the size of the component. // this ends up making small components require stronger evidence for a boundary thresholds[aID] = graph[i].weight + ThresholdFunction(k, ds.NumElements(aID)); } } } // post process small components for (int i = 0; i < numEdges; i++) { int aID = ds.FindSetRoot(graph[i].aNode); int bID = ds.FindSetRoot(graph[i].bNode); if ((aID != bID) && ((ds.NumElements(aID) < minsize) || (ds.NumElements(bID) < minsize))) { ds.Union(aID, bID); } } int sets = ds.NumSets(); clusters = new List <List <int> >(sets); int mapIndex = 0; for (int y = 0; y < height; y++) { for (int x = 0; x < width; x++) { int point = y * width + x; int comp = ds.FindSetRoot(point); //try to get the setmap... //first check is this a root? if (setmap[comp] == -1) { setmap[comp] = mapIndex; clusters.Add(new List <int>(ds.NumElements(comp))); clusters[mapIndex].Add(point); mapIndex++; } else { clusters[setmap[comp]].Add(point); } } } return(sets); }