public override double Process(Segmentation s1, Segmentation s2) { if (s1 == null || s2 == null) return 0; if (s1 == s2) return 1; double result = 0; //En cls van a estar los subconjuntos comunes en las dos particiones concatenados los nombres de los clusters por un &, ademas se guarda la cantidad de elementos del subconjunto. Dictionary<string, long> cls = new Dictionary<string, long>(); for (int i = 0; i < s1.Labels.Length; i++) { if (cls.ContainsKey(s1.Labels[i] + "&" + s2.Labels[i])) cls[s1.Labels[i] + "&" + s2.Labels[i]] += 1; else cls.Add(s1.Labels[i] + "&" + s2.Labels[i], 1); } string[] aux; //Tamanno de los cluster que contienen al subconjunto en P1 y P2 respectivamente. int c1 = 0, c2 = 0; //Calcular para cada subconjunto el valor de similaridad asociado. foreach (string str in cls.Keys) { aux = str.Split('&'); c1 = s1.Clusters[int.Parse(aux[0])].Count; c2 = s2.Clusters[int.Parse(aux[1])].Count; result += similarity(cls[str], c1, c2); } return result / Math.Sqrt(ComputeNorm(s1) * ComputeNorm(s2)); }
private double ComputeNorm(Segmentation s) { double norm = 0; foreach (int str in s.Clusters.Keys) norm += similarity(s.Clusters[str].Count, s.Clusters[str].Count, s.Clusters[str].Count); return norm; }
//Aqui estoy asumiendo q ya la segmentacion inicial tiene k clusters, con k el valor q quiero q tengan todas. public Segmentation GetNeighborKFIJO(SuperPixelGraph spg) { int[] newLabels = new int[Labels.Length]; for (int i = 0; i < Labels.Length; i++) newLabels[i] = Labels[i]; Random r = new Random(); //posicion del objeto q voy a cambiar de region int pos = 0; do { pos = r.Next(0, Labels.Length); } while (this.Clusters[Labels[pos]].Count <= 1); //numero de la nueva region a seleccionar entre las posibles segun el grafo de la imagen int reg = r.Next(0, spg.AdjList[pos].Count); //este es el superpixel con el q me voy a pegar en el mismo cluster. int sp = spg.AdjList[pos][reg]; //Esta es la etiqueta del cluster al q voy a ser asignado. int newL = Labels[sp]; //Tiene el problema de q si es la misma etiqueta...estoy generando la misma segmentacion de nuevo!! newLabels[pos] = newL; Segmentation result = new Segmentation(newLabels); return result; }
public Segmentation GetNeighbor(SuperPixelGraph spg) { int[] newLabels = new int[Labels.Length]; for (int i = 0; i < Labels.Length; i++) newLabels[i] = Labels[i]; Random r = new Random(); //posicion del objeto q voy a cambiar de region int pos = r.Next(0, Labels.Length-1); //le meti el -1..analizar //numero de la nueva region a seleccionar entre las posibles segun el grafo de la imagen int reg = r.Next(0, spg.AdjList[pos].Count - 1); //le meti el -1..analizar //este es el superpixel con el q me voy a pegar en el mismo cluster. int sp = spg.AdjList[pos][reg]; //Esta es la etiqueta del cluster al q voy a ser asignado. int newL = Labels[sp]; //Si la nueva posicion es la misma, cojo esta posibilidad para poner el elemento en un nuevo cluster donde esta el solo. if (newLabels[pos] == newL) newLabels[pos] = this.maxLabel + 1; else newLabels[pos] = newL; Segmentation result = new Segmentation(newLabels); return result; }
private double MI(Segmentation s1, Segmentation s2) { double mi = 0; double aux = 0; Dictionary<string, long> cls = new Dictionary<string, long>(); for (int i = 0; i < s1.Labels.Length; i++) { if (cls.ContainsKey(s1.Labels[i] + "&" + s2.Labels[i])) cls[s1.Labels[i] + "&" + s2.Labels[i]] += 1; else cls.Add(s1.Labels[i] + "&" + s2.Labels[i], 1); } //foreach (int cluster in cls.Values) //{ // aux = (((double)cluster) / ((double)s1.Labels.Length)); // if (aux != 0) // mi += aux * Math.Log(aux, 2); //} foreach (int cS1 in s1.Clusters.Keys) { foreach (int cS2 in s2.Clusters.Keys) { if (cls.ContainsKey(cS1.ToString() + "&" + cS2.ToString())) { aux = (((double)cls[cS1.ToString() + "&" + cS2.ToString()]) / ((double)s1.Labels.Length)); if (aux != 0) mi += aux * Math.Log((aux * s1.Labels.Length * s1.Labels.Length) / ((double)(s1.Clusters[cS1].Count) * ((double)s2.Clusters[cS2].Count)), 2); } } } return mi; }
private double Entropy(Segmentation s) { double entropy = 0; double aux = 0; foreach (int i in s.Clusters.Keys) { aux = (((double)s.Clusters[i].Count) / ((double)s.Labels.Length)); entropy += aux * Math.Log(aux, 2); } return -1 * entropy; }
//Esto convierte el objeto segmentacion en la real segmantacion haciendo el proceso contrario al calculo de los superpixels. //El nuevo objeto segmentacion es mucho mas grande....la cardinalidad es la cantidad de pixels y no la cantidad de superpixels. private Segmentation GetSegmentationResult(Segmentation best) { int[] result = new int[this.prob.SuperPixelMatrix.Length]; for (int i = 0; i < this.prob.SuperPixelMatrix.GetLength(0); i++) { for (int j = 0; j < this.prob.SuperPixelMatrix.GetLength(1); j++) { int sp = this.prob.SuperPixelMatrix[i, j]; result[i * this.prob.SuperPixelMatrix.GetLength(1) + j] = best.Labels[sp]; } } return new Segmentation(result); }
public abstract double Process(Segmentation s1, Segmentation s2);
//Evaluo la segmentacion con las medidas RandIndex, VI and NMI y dejo los resultados en el prob. Evaluo contra el mejor ground-truth y el promedio contra todos. private void EvaluateMatrixSegmentation(Segmentation segm) { RandIndexSegSim rand = new RandIndexSegSim(); NMISegSim nmi = new NMISegSim(); VISegSim vi = new VISegSim(); //Calcular el rand double min = double.MaxValue; double ave = 0; double aux = 0; for (int i = 0; i < this.prob.GroundTruths.Count; i++) { aux = 1 - rand.Process(segm, this.prob.GroundTruths[i]); if (aux < min) min = aux; ave += aux; } ave = ave / this.prob.GroundTruths.Count; this.prob.Best_RandEvaluation = min; this.prob.Ave_RandEvaluation = ave; //Calcular NMI min = double.MaxValue; ave = 0; aux = 0; for (int i = 0; i < this.prob.GroundTruths.Count; i++) { aux = 1 - nmi.Process(segm, this.prob.GroundTruths[i]); if (aux < min) min = aux; ave += aux; } ave = ave / this.prob.GroundTruths.Count; this.prob.Best_NMIEvaluation = min; this.prob.Ave_NMIEvaluation = ave; //Calcular VI min = double.MaxValue; ave = 0; aux = 0; for (int i = 0; i < this.prob.GroundTruths.Count; i++) { aux = vi.Process(segm, this.prob.GroundTruths[i]); if (aux < min) min = aux; ave += aux; } ave = ave / this.prob.GroundTruths.Count; this.prob.Best_VIEvaluation = min; this.prob.Ave_VIEvaluation = ave; }
//Devuelve la matriz del tamanno de la imagen final con los valores de los pixeles. private Bitmap GetFinalSegImage(Segmentation segm) { int[,] result = new int[this.prob.Image.Height, this.prob.Image.Width]; for (int i = 0; i < result.GetLength(0); i++) { for (int j = 0; j < result.GetLength(1); j++) { result[i, j] = segm.Labels[i * result.GetLength(1) + j]; } } Bitmap image = new Bitmap(this.prob.Image.Width, this.prob.Image.Height, this.prob.Image.PixelFormat); BitmapData data = image.LockBits(new Rectangle(0, 0, image.Width, image.Height), ImageLockMode.ReadWrite, image.PixelFormat); unsafe { byte* imgPtr = (byte*)(data.Scan0); for (int i = 0; i < data.Height; i++) { for (int j = 0; j < data.Width; j++) { imgPtr[0] = colors[Math.Min(67, result[i, j])].R; imgPtr[1] = colors[Math.Min(67, result[i, j])].G; imgPtr[2] = colors[Math.Min(67, result[i, j])].B; imgPtr += 3; } imgPtr += data.Stride - data.Width * 3; } image.UnlockBits(data); } return image; }
private double DistConsensus(double[] normWeights, Segmentation seg) { //Sumo 1 del primer termino y 1 del tercero..solo falta restar el 2do termino de la ecuacion (10) en el paper PR. double result = 2; for (int i = 0; i < prob.Segmentations.Count; i++) { result -= 2 * normWeights[i] * rand.Process(seg, prob.Segmentations[i]); } return result; }
//Rand es (n00 + n11) / (n(n-1)/2), pero n00+n01+n10+n11 = n(n-1)/2. Por tanto n00+n11 = n(n-1)/2 - ((n11+n10) + (n11+n01) -2*n11). //Hay una forma muy facil de calcular (n11+n10) + (n11+n01) y n11 se calcula en O(n). public override double Process(Segmentation s1, Segmentation s2) { double rand = 0; double t = 0; double n11_n01 = 0, n11_n10 = 0, n11=0; foreach (List<int> cluster in s1.Clusters.Values) { t = cluster.Count; n11_n10 += t * (t-1) / 2; } foreach (List<int> cluster in s2.Clusters.Values) { t = cluster.Count; n11_n01 += t * (t - 1) / 2; } Dictionary<string, int> cls = new Dictionary<string, int>(); for (int i = 0; i < s1.Labels.Length; i++) { if (cls.ContainsKey(s1.Labels[i] + "&" + s2.Labels[i])) cls[s1.Labels[i] + "&" + s2.Labels[i]] += 1; else cls.Add(s1.Labels[i] + "&" + s2.Labels[i], 1); } foreach (int cluster in cls.Values) if (cluster >= 2) { t = cluster; n11 += t * (t - 1) / 2; } t = s1.Labels.Length; double pc = t * (t - 1) / 2; rand = ((double)(pc - n11_n10 - n11_n01 + 2*n11)) / ((double)pc); return rand; }
//Devuelve una nueva segmentacion que se forma al unir "clusCount" pares de clusters en la segmentacion actual. public Segmentation Join(int clusCount, SuperPixelGraph spg) { int[] newLabels = new int[Labels.Length]; for (int i = 0; i < Labels.Length; i++) newLabels[i] = Labels[i]; Random r = new Random(); for (int i = 0; i < clusCount; i++) { int pos = r.Next(0, Labels.Length); int reg = r.Next(0, spg.AdjList[pos].Count); int sp = spg.AdjList[pos][reg]; int newL = newLabels[sp]; int value = newLabels[pos]; for (int j = 0; j < newLabels.Length; j++) { if (newLabels[j] == value) newLabels[j] = newL; } } Segmentation result = new Segmentation(newLabels); return result; }
private Segmentation SimulatedAnnealing(double[] normWeights, Segmentation s0, int maxIter) { Segmentation current = s0; Segmentation next = s0; Segmentation best = s0; double e0 = DistConsensus(normWeights, s0); double eCurrent = e0; double eNext = e0; double eBest = e0; int r = 0; double temp = 0.0001428; Random random = new Random(); //int[] l0 = new int[s0.Labels.Length]; //int[] l1 = new int[s0.Labels.Length]; //for (int i = 0; i < l0.Length; i++) // l0[i] = i; //Segmentation seg0 = new Segmentation(l0); //Segmentation seg1 = new Segmentation(l1); //double au0 = DistConsensus(normWeights, seg0); //double au1 = DistConsensus(normWeights, seg1); while (r < maxIter) { next = current.GetNeighbor(prob.SPGraph); eNext = DistConsensus(normWeights, next); if (eNext < eBest) { best = next; eBest = eNext; } if (Math.Exp(-1 * (eNext - eBest) / temp) > random.NextDouble()) { current = next; eCurrent = eNext; } if (r > (maxIter * 4) / 5 && r < (maxIter * 9) / 10) temp = temp * 1.002; r++; } this.prob.DistToConsensus = eBest; return best; }
//Devuelve una nueva segmentacion que se forma al separar "clusCount" clusters (en dos nuevos clusters) en la segmentacion actual. public Segmentation Split(int clusCount, SuperPixelGraph spg) { int[] newLabels = new int[Labels.Length]; for (int i = 0; i < Labels.Length; i++) newLabels[i] = Labels[i]; Random r = new Random(); int last = this.maxLabel; for (int i = 0; i < clusCount; i++) { int pos = r.Next(0, Labels.Length); newLabels[pos] = last + 1; last++; } Segmentation result = new Segmentation(newLabels); return result; }
public override double Process(Segmentation s1, Segmentation s2) { return Entropy(s1) + Entropy(s2) - 2 * MI(s1, s2); }
public override double Process(Segmentation s1, Segmentation s2) { return(Entropy(s1) + Entropy(s2) - 2 * MI(s1, s2)); }
public override double Process(Segmentation s1, Segmentation s2) { double ents = Entropy(s1) * Entropy(s2); if (ents != 0) return MI(s1, s2) / Math.Sqrt(ents); else return 1; }