// Partial Match Algorithm // From Line 368-438 public static Match partialMatch(List <Phi> DNAseq1, List <Phi> DNAseq2) { bool flag = true; // ToDo: Compare the control points in contours between two parts Match segment; // create an empty match segment segment.t11 = 0; segment.t12 = 0; segment.t21 = 0; segment.t22 = 0; List <Phi> seq1, seq2; // two empty List of edge maps int best = 0, max_match; int offset = 0, length = 0; // sticking // .While comparing a pair of DNA pattern, the smaller one is reversed while the longer one is copied and placed at its tail, //such that now the angle accumulated over the string is 4π if (DNAseq1.Count > DNAseq2.Count) // if the contour in first part has more control points than the second part { seq1 = replicateDNA(DNAseq1); //replicate the larger DNA seq2 = DNAseq2.ToList(); //reverse the smaller one seq2.Reverse(); } else { flag = false; seq1 = replicateDNA(DNAseq2); // if the first one has less control point, attach all the control points of the second part seq2 = DNAseq1.ToList(); //reverse the smaller one seq2.Reverse(); } // sliding //The shorter sequence is slided through the longer one and for every shift ‘d’, the difference Δφabd = φbd – φa is stored for (int shift = 0; shift < seq1.Count - seq2.Count; shift += Constants.STEP) { List <int> diff = new List <int>(); int start = 0, end = 0; for (int i = 0; i < seq2.Count; ++i) { int difference = (int)(seq1[i + shift].theta - seq2[i].theta); diff.Add(difference); } max_match = histogram(diff, seq2, ref start, ref end, Constants.DELTA_THETA); if (best < max_match) { offset = shift; best = max_match; int t_start = start + shift; int t_end = end + shift; if (start + shift >= seq1.Count / 2) { t_start = start + shift - seq1.Count / 2; } if (end + shift >= seq1.Count / 2) { t_end = end + shift - seq1.Count / 2; } length = t_start - t_end; if (flag) { segment.t21 = seq2.Count - end - 1; segment.t22 = seq2.Count - start - 1; segment.t11 = t_start; segment.t12 = t_end; } else { segment.t11 = seq2.Count - end - 1; segment.t12 = seq2.Count - start - 1; segment.t21 = t_start; segment.t22 = t_end; } } } segment.x11 = (int)DNAseq1[segment.t11].x; segment.y11 = (int)DNAseq1[segment.t11].y; segment.x12 = (int)DNAseq1[segment.t12].x; segment.y12 = (int)DNAseq1[segment.t12].y; segment.x21 = (int)DNAseq2[segment.t21].x; segment.y21 = (int)DNAseq2[segment.t21].y; segment.x22 = (int)DNAseq2[segment.t22].x; segment.y22 = (int)DNAseq2[segment.t22].y; // consider the color feature for rejection // Step 1: extract the color on the edge into a list (done) List <Bgr> colors1 = new List <Bgr>(); List <Bgr> colors2 = new List <Bgr>(); if (segment.t12 > segment.t11) { for (int i = segment.t11; i <= segment.t12; i++) { colors1.Add(DNAseq1[i].color); } } else { for (int i = segment.t11; i <= DNAseq1.Count - 1; i++) { colors1.Add(DNAseq1[i].color); } for (int i = 0; i <= segment.t12; i++) { colors1.Add(DNAseq1[i].color); } } if (segment.t22 > segment.t21) { for (int i = segment.t21; i <= segment.t22; i++) { colors2.Add(DNAseq2[i].color); } } else { for (int i = segment.t21; i <= DNAseq2.Count - 1; i++) { colors2.Add(DNAseq2[i].color); } for (int i = 0; i <= segment.t22; i++) { colors2.Add(DNAseq2[i].color); } } // Step 2: Calculate the total color difference int totalColorDifference = 0; for (int i = 0; i < Math.Min(colors1.Count, colors2.Count); i++) { totalColorDifference += Metrics.colorDifference(colors1[i], colors2[i]); } // Step 3: if the color difference is too great, reject double avgColorDifference = totalColorDifference / (Math.Min(colors1.Count, colors2.Count)); if (avgColorDifference > Constants.EDGE_COLOR_DIFFERENCE) { segment.confidence = 0; // reject } // rejections for final inconsistent matches else if (best == 0) { segment.confidence = 0; } else if (segment.t11 > segment.t12) { segment.confidence = 0; // if the first segment run over the origin, reject the match } else if (segment.t21 > segment.t22) { segment.confidence = 0; // if the second segment run over the origin, reject the match } else { segment.confidence = Math.Sqrt((double)(length * length) / best); } return(segment); }
// Partial Match Algorithm using color feature // I used the framework for the partial matching algorithm using turning angle // but using the differences of the color on the edge public static Match partialColorMatch(List <Phi> DNAseq1, List <Phi> DNAseq2) { bool flag = true; // ToDo: Compare the control points in contours between two parts Match segment; // create an empty match segment segment.t11 = 0; segment.t12 = 0; segment.t21 = 0; segment.t22 = 0; List <Phi> seq1, seq2; // two empty List of edge maps int best = 0, max_match; int offset = 0, length = 0; if (DNAseq1.Count > DNAseq2.Count) // if the contour in first part has more control points than the second part { seq1 = replicateDNA(DNAseq1); //replicate the larger DNA seq2 = DNAseq2.ToList(); //reverse the smaller one seq2.Reverse(); } else { flag = false; seq1 = replicateDNA(DNAseq2); // if the first one has less control point, attach all the control points of the second part seq2 = DNAseq1.ToList(); //reverse the smaller one seq2.Reverse(); } List <int> zc = new List <int>(); List <int> starts = new List <int>(); int iteration = 0; for (int shift = 0; shift < seq1.Count - seq2.Count; shift += Constants.STEP) { List <int> diff = new List <int>(); bool flag1 = false; int start = 0, end = 0; // TODO: change the differences into color difference (done) List <int> zeroCounts = new List <int>(); int zeroCount = 0; List <int> starts2 = new List <int>(); // TODO: need to add a tolerance level for some random non 0 differences int tolerCount = 0; // tolerance count for random non 0s. for (int i = 0; i < seq2.Count; ++i) { int difference = Metrics.colorDifference(seq1[i + shift].color, seq2[i].color); // if difference==0, flag // if difference!=0, unflag if (difference <= 0) { // if it is in unflag state, mark the point as starting point if (!flag1) { flag1 = true; start = i; //starts.Add(start); starts2.Add(start); } // count the number of zero difference points in this section zeroCount++; tolerCount = 0; } else { if (tolerCount <= Constants.COLOR_TOLERANCE) { if (flag1) { zeroCount++; tolerCount++; } } else { if (flag1) { zeroCounts.Add(zeroCount); // add to a upper level storage zeroCount = 0; // reset the counter flag1 = false; // unflag tolerCount = 0; } } } diff.Add(difference); } if (iteration == 33) { Console.WriteLine("33"); } if (zeroCounts.Count == 0) { starts.Add(-1); } else { starts.Add(starts2[zeroCounts.IndexOf(zeroCounts.Max())]); } if (zeroCounts.Count == 0) { zc.Add(0); } else { zc.Add(zeroCounts.Max()); } // TTODO: implement a histogram algorithm for color match //max_match = colorHistogram(diff, seq2, ref start, ref end, Util.DELTA_THETA); max_match = 0; /*if (end < start) * { * Console.WriteLine("22"); * }*/ /* if (best < max_match) * { * offset = shift; * best = max_match; * int t_start = start + shift; * int t_end = end + shift; * if (start + shift >= seq1.Count / 2) * t_start = start + shift - seq1.Count / 2; * if (end + shift >= seq1.Count / 2) * t_end = end + shift - seq1.Count / 2; * length = t_start - t_end; // problematic * * * if (flag) * { * segment.t21 = seq2.Count - end - 1; * segment.t22 = seq2.Count - start - 1; * segment.t11 = t_start; * segment.t12 = t_end; * } * else * { * segment.t11 = seq2.Count - end - 1; * segment.t12 = seq2.Count - start - 1; * segment.t21 = t_start; * segment.t22 = t_end; * } * } */ iteration++; } Console.WriteLine("Max:" + zc.Max()); if (zc.Max() == 0) { goto a; } int t_shift = 0; int s_start = 0; for (int i = 0; i < zc.Count; i++) { if (zc[i] == zc.Max()) { t_shift = Constants.STEP * i; s_start = starts[i]; } } int startPos1 = t_shift + s_start; int endPos1 = startPos1 + zc.Max(); int startPos2 = s_start; int endPos2 = startPos2 + zc.Max(); length = zc.Max(); // check if the algorithm get the correct position of the matching color Console.WriteLine("Flag:" + flag); Console.WriteLine("Shiftreq:" + startPos1); Console.WriteLine("Count:" + DNAseq1.Count); Console.WriteLine("P1_start_x" + seq1[startPos1].x); Console.WriteLine("P1_start_y" + seq1[startPos1].y); Console.WriteLine("P1_end_x" + seq1[endPos1].x); Console.WriteLine("P1_end_y" + seq1[endPos1].y); Console.WriteLine("P2_start_x" + seq2[startPos2].x); Console.WriteLine("P2_start_y" + seq2[startPos2].y); Console.WriteLine("P2_end_x" + seq2[endPos2].x); Console.WriteLine("P2_end_y" + seq2[endPos2].y); // correct for all the code above // regression analysis for the relationship between seq and DNA // flag=true for 3*3 frag5 and frag6 if (flag) { for (int j = 0; j < DNAseq1.Count; j++) { if ((seq1[startPos1].x == DNAseq1[j].x) && (seq1[startPos1].y == DNAseq1[j].y)) { segment.t11 = j; //segment.x11 = (int)DNAseq1[j].x; // segment.y11 = (int)DNAseq1[j].y; segment.t12 = j + zc.Max(); if (segment.t12 >= DNAseq1.Count) { segment.t12 -= DNAseq1.Count; } //segment.x12 = (int)DNAseq1[j + zc.Max()].x; //segment.y12 = (int)DNAseq1[j + zc.Max()].y; } } for (int j = 0; j < DNAseq2.Count; j++) { if ((seq2[startPos2].x == DNAseq2[j].x) && (seq2[startPos2].y == DNAseq2[j].y)) { segment.t21 = j; //segment.x21 = (int)DNAseq2[j].x; //segment.y21 = (int)DNAseq2[j].y; segment.t22 = j - zc.Max(); if (segment.t22 < 0) { segment.t22 += DNAseq2.Count; } //segment.x22 = (int)DNAseq2[j - zc.Max()].x; //segment.y22 = (int)DNAseq2[j - zc.Max()].y; } } } else { for (int j = 0; j < DNAseq2.Count; j++) { if ((seq1[startPos1].x == DNAseq2[j].x) && (seq1[startPos1].y == DNAseq2[j].y)) { segment.t21 = j; //segment.x11 = (int)DNAseq2[j].x; //segment.y11 = (int)DNAseq2[j].y; segment.t22 = j + zc.Max(); if (segment.t22 >= DNAseq2.Count) { segment.t22 -= DNAseq2.Count; } // segment.x12 = (int)DNAseq2[j - zc.Max()].x; //segment.y12 = (int)DNAseq2[j - zc.Max()].y; } } for (int j = 0; j < DNAseq1.Count; j++) { if ((seq2[startPos2].x == DNAseq1[j].x) && (seq2[startPos2].y == DNAseq1[j].y)) { segment.t11 = j; // segment.x21 = (int)DNAseq1[j].x; // segment.y21 = (int)DNAseq1[j].y; segment.t12 = j - zc.Max(); if (segment.t12 < 0) { segment.t12 += DNAseq1.Count; } //segment.x22 = (int)DNAseq1[j + zc.Max()].x; //segment.y22 = (int)DNAseq1[j + zc.Max()].y; } } } /*int t_start = t_shift; * int t_end = t_shift; * if (t_shift >= seq1.Count / 2) * t_start = t_shift - seq1.Count / 2; * if (t_shift >= seq1.Count / 2) * t_end = t_shift - seq1.Count / 2; * length = zc.Max(); // problematic * * * /*if (flag) * { * segment.t21 = seq2.Count - -1; * segment.t22 = seq2.Count - t_start - 1; * segment.t11 = t_start; * segment.t12 = t_end; * } * else * { * segment.t11 = seq2.Count - t_end - 1; * segment.t12 = seq2.Count - t_start - 1; * segment.t21 = t_start; * segment.t22 = t_end; * }*/ // fine code below a : segment.x11 = (int)DNAseq1[segment.t11].x; segment.y11 = (int)DNAseq1[segment.t11].y; segment.x12 = (int)DNAseq1[segment.t12].x; segment.y12 = (int)DNAseq1[segment.t12].y; segment.x21 = (int)DNAseq2[segment.t21].x; segment.y21 = (int)DNAseq2[segment.t21].y; segment.x22 = (int)DNAseq2[segment.t22].x; segment.y22 = (int)DNAseq2[segment.t22].y; // correct at this point /*if (best == 0) * segment.confidence = 0; * else * segment.confidence = Math.Sqrt((double)(length * length) / best); */ segment.confidence = length; Console.WriteLine(segment.ToString()); // all the code above is the matching segment without considering edge feature // we need to consider edge feature at this point // and cull out the matching edge that does not match // consider the most simple case: straight line without rotating // then to edges with turning angles but still without rotating // then to general case // Step 1: extract the portion of DNA that forms the matching edge (done) List <Phi> edge1 = new List <Phi>(); // valid edge in image 1 List <Phi> edge2 = new List <Phi>(); // valid edge in image 2 for (int i = Math.Min(segment.t11, segment.t12); i < Math.Max(segment.t11, segment.t12); i++) { edge1.Add(DNAseq1[i]); } for (int i = Math.Min(segment.t21, segment.t22); i < Math.Max(segment.t21, segment.t22); i++) { edge2.Add(DNAseq2[i]); } if (edge1.Count == 0 || edge2.Count == 0) { goto r; // if there is no matching edge, it is not nessesary for culling } // Step 2: Analyze the edge feature // convert edge into contour Contour <Point> c1; Contour <Point> c2; List <Point> pedge1; List <Point> pedge2; c1 = new Contour <Point>(Form1.mem); foreach (Phi p in edge1) { c1.Push(new Point((int)p.x, (int)p.y)); } if (c1.Total == 0) { } // stor.Dispose(); c1 = c1.ApproxPoly(2.0, Form1.mem); pedge1 = c1.ToList(); c2 = new Contour <Point>(Form1.mem); foreach (Phi p in edge2) { c2.Push(new Point((int)p.x, (int)p.y)); } c2 = c2.ApproxPoly(2.0); pedge2 = c2.ToList(); // Step 3: Cull the edge // calculate the turning angle for each edge // if the cumulative turning angle change is greater than 90, restart // use a brute force longest straight line approach first, this solves a lot of cases int maxDistance = -99999; int pos1 = 0, pos2 = 0; for (int i = 0; i < pedge1.Count - 1; i++) { if (pedge1[i + 1].X == pedge1[i].X) { if (Math.Abs(pedge1[i + 1].Y - pedge1[i].Y) > maxDistance) { maxDistance = Math.Abs(pedge1[i + 1].Y - pedge1[i].Y); pos1 = i; } } else if (pedge1[i + 1].Y == pedge1[i].Y) { if (Math.Abs(pedge1[i + 1].X - pedge1[i].X) > maxDistance) { maxDistance = Math.Abs(pedge1[i + 1].X - pedge1[i].X); pos1 = i; } } } maxDistance = -99999; for (int i = 0; i < pedge2.Count - 1; i++) { if (pedge2[i + 1].X == pedge2[i].X) { if (Math.Abs(pedge2[i + 1].Y - pedge2[i].Y) > maxDistance) { maxDistance = Math.Abs(pedge2[i + 1].Y - pedge2[i].Y); pos2 = i; } } else if (pedge2[i + 1].Y == pedge2[i].Y) { if (Math.Abs(pedge2[i + 1].X - pedge2[i].X) > maxDistance) { maxDistance = Math.Abs(pedge2[i + 1].X - pedge2[i].X); pos2 = i; } } } // now the new matching edge is calculated, send the result to output for (int j = 0; j < DNAseq1.Count; j++) { if ((pedge1[pos1].X == DNAseq1[j].x) && (pedge1[pos1].Y == DNAseq1[j].y)) { segment.t11 = j; } } for (int j = 0; j < DNAseq2.Count; j++) { if ((pedge2[pos2].X == DNAseq2[j].x) && (pedge2[pos2].Y == DNAseq2[j].y)) { segment.t21 = j; } } for (int j = 0; j < DNAseq1.Count; j++) { if ((pedge1[pos1 + 1].X == DNAseq1[j].x) && (pedge1[pos1 + 1].Y == DNAseq1[j].y)) { segment.t12 = j; } } for (int j = 0; j < DNAseq2.Count; j++) { if ((pedge2[pos2 + 1].X == DNAseq2[j].x) && (pedge2[pos2 + 1].Y == DNAseq2[j].y)) { segment.t22 = j; } } segment.x11 = (int)DNAseq1[segment.t11].x; segment.y11 = (int)DNAseq1[segment.t11].y; segment.x12 = (int)DNAseq1[segment.t12].x; segment.y12 = (int)DNAseq1[segment.t12].y; segment.x21 = (int)DNAseq2[segment.t21].x; segment.y21 = (int)DNAseq2[segment.t21].y; segment.x22 = (int)DNAseq2[segment.t22].x; segment.y22 = (int)DNAseq2[segment.t22].y; r : return(segment); }