private void button4_Click(object sender, EventArgs e) { Form1.sourceImages.Add(joined); map1.matched = true; map2.matched = true; List <ColorfulContourMap> cmap = ColorfulContourMap.getAllContourMap(joined, Form1.sourceImages.Count - 1); Form1.contourMaps.AddRange(cmap); Close(); }
private void button4_Click(object sender, EventArgs e) { if (Form1.sourceImages.Count != 0) { DisplayBestMatch bestMatchView = new DisplayBestMatch(); QueueView qv = new QueueView(); // extract the contour maps, send the result into queueview int index = 0; foreach (Image <Bgr, byte> image in Form1.sourceImages) { List <ColorfulContourMap> cmap; if (blackSelect.Checked == true) { cmap = ColorfulContourMap.getAllContourMap(image, index, 0); } else { cmap = ColorfulContourMap.getAllContourMap(image, index, 1); } Form1.contourMaps.AddRange(cmap); index++; } if (blackSelect.Checked) { Form1.BKG_WHITE = true; } else { Form1.BKG_WHITE = false; } Hide(); bestMatchView.Show(); qv.Show(); } else { MessageBox.Show("Please input at least one image."); } }
// algorithm plot: // 1. Try edge match // Find max confidence // Try put them together // 2. Try color match // Find max confidence // Try put them together // 3. If still fail, that is from other page // 4. If success, find the best tweak // 5. Join the images according to the final parameters // the return value is how many pages should be in the original images private int bestMatchTwo() { int pageCount = 0; double maxConfidence = 0.0; ColorfulContourMap map1 = new ColorfulContourMap(); ColorfulContourMap map2 = new ColorfulContourMap(); double overlap = 0.0; bool matched = false; // Double-thresholding algorithm (Worked for 5-piece precisely torned paper): // search for all unmatched pairs, calculate the confidence level ( fixed the problem with different results caused by different ordering ) // reject all matches that has confidence less than 80 ( eliminate some of the false positives) // calculate the intersection for each matching pair // the pair with the lowest intersection is the best // if the intersection of the lowest pair is still greater than 5000, there are no match for the given fragments List <MatchMetricData> matchMetricData = new List <MatchMetricData>(); // search for all unmatched pairs, calculate the confidence level // if the max confidence level is 0, that means the remaining pieces cannot be matched by turning angle // for this case, use the color matching algorithm // get the potential matching edges foreach (ColorfulContourMap cmap in Form1.contourMaps) { if (cmap.matched == false) { foreach (ColorfulContourMap cmap2 in Form1.contourMaps) { if (cmap2.matched == false && cmap != cmap2) { Match match = DNAUtil.partialMatch(cmap.extractDNA(), cmap2.extractDNA()); double confidence = match.confidence; matchMetricData.Add(new MatchMetricData { map1 = cmap, map2 = cmap2, confident = confidence, dna1 = cmap.extractDNA(), dna2 = cmap2.extractDNA(), match = match }); if (confidence > maxConfidence) { maxConfidence = confidence; map1 = cmap; map2 = cmap2; } } } } } // if there are no pieces eligible for edge matching, the metric data should have all elements with confidence level 0 // at this time, calculate the metrics for color matching // Double-thresholding algorithm works for color matching too if (matchMetricData.Count == 0 || matchMetricData.OrderBy(o => o.confident).Last().confident == 0) { foreach (ColorfulContourMap cmap in Form1.contourMaps) { if (cmap.matched == false) { foreach (ColorfulContourMap cmap2 in Form1.contourMaps) { if (cmap2.matched == false && cmap != cmap2) { Match match = DNAUtil.partialColorMatch(cmap.extractDNA(), cmap2.extractDNA()); double confidence = match.confidence; matchMetricData.Add(new MatchMetricData { map1 = cmap, map2 = cmap2, confident = confidence, dna1 = cmap.extractDNA(), dna2 = cmap2.extractDNA(), match = match }); if (confidence > maxConfidence) { maxConfidence = confidence; map1 = cmap; map2 = cmap2; } } } } } } // if there are still no matches, the process is done // It will consider the rest of the pieces from another page // 1st funnel: select the most potential matching edges matchMetricData = matchMetricData.Where(o => o.confident > Constants.MIN_CONFIDENCE).OrderBy(o => o.confident).Reverse().ToList(); Console.WriteLine(maxConfidence); Console.WriteLine(map1.imageIndex); Console.WriteLine(map2.imageIndex); // calculate the intersection for each matching pair List <MatchMetricData> data2 = new List <MatchMetricData>(); foreach (MatchMetricData m in matchMetricData) { Image <Bgr, byte> pic1 = Form1.sourceImages[m.map1.imageIndex].Clone(); Image <Bgr, byte> pic2 = Form1.sourceImages[m.map2.imageIndex].Clone(); Point centroid1 = new Point(); Point centroid2 = new Point(); double angle = 0.0; Match edgeMatch = m.match; Transformation.transformation(m.dna1, m.dna2, ref edgeMatch, ref centroid1, ref centroid2, ref angle); angle = angle * 180 / Math.PI; angle = -angle; Console.WriteLine(centroid1.ToString()); Console.WriteLine(centroid2.ToString()); Console.WriteLine(angle); Image <Bgr, byte> mask1 = pic1.Clone(); Image <Bgr, byte> mask2 = pic2.Clone(); Image <Bgr, byte> joined = pic1.Clone(); Image <Bgr, byte> joined_mask = joined.Clone(); ReturnColorImg result = Transformation.transformColor(pic1, mask1, pic2, mask2, joined, joined_mask, centroid1, centroid2, -angle + 180, new Point(0, 0), new Point(0, 0), Form1.BKG_WHITE); data2.Add(new MatchMetricData { map1 = m.map1, map2 = m.map2, overlap = result.overlap, dna1 = m.dna1, dna2 = m.dna2, match = m.match, confident = m.confident }); } if (data2.Count == 0) { MessageBox.Show("No match found"); return(1); // add 1 to full image found count } // the pair with highest confidence with a valid intersection is the best // 2nd funnel: select only the matches that can actually match the picture together MatchMetricData MinOverlap = data2.OrderBy(o => o.overlap).First(); if (MinOverlap.overlap < Constants.THRESHOLD) { Console.WriteLine("Map1 " + MinOverlap.map1.imageIndex); Console.WriteLine("Map2 " + MinOverlap.map2.imageIndex); Console.WriteLine("Overlap " + MinOverlap.overlap); // correct until this point // add the resulting image into the queue Image <Bgr, byte> pic1 = Form1.sourceImages[MinOverlap.map1.imageIndex].Clone(); Image <Bgr, byte> pic2 = Form1.sourceImages[MinOverlap.map2.imageIndex].Clone(); Point centroid1 = new Point(); Point centroid2 = new Point(); double angle = 0.0; Match edgeMatch = MinOverlap.match; Transformation.transformation(MinOverlap.dna1, MinOverlap.dna2, ref edgeMatch, ref centroid1, ref centroid2, ref angle); // correct until this point angle = angle * 180 / Math.PI; angle = -angle; Image <Bgr, byte> mask1 = pic1.Clone(); Image <Bgr, byte> mask2 = pic2.Clone(); Image <Bgr, byte> joined = pic1.Clone(); Image <Bgr, byte> joined_mask = joined.Clone(); // tweak ReturnColorImg bestResult = new ReturnColorImg(); double minOverlap = 999999; Console.WriteLine(centroid1.ToString()); Console.WriteLine(centroid2.ToString()); // correct until this point // The tweaking is messing up with the result, I will just ignore this for a moment // the tweaking now works for 1-button matching // but the algorithm runs extremely slow ( still way faster than gluing the pieces :) for (int i = -2; i < 3; i++) { for (int j = -2; j < 3; j++) { ReturnColorImg result = Transformation.transformColor(pic1, mask1, pic2, mask2, joined, joined_mask, centroid1, centroid2, -angle + 180, new Point(0, 0), new Point(i, j), Form1.BKG_WHITE); if (result.overlap < minOverlap && result.success) // if the overlap is 0, that means the transformation is failed { bestResult = result; minOverlap = result.overlap; } //DisplayImage dip = new DisplayImage(result.img, new Point(0,0), new Point(i, j), (int)result.overlap); //dip.Show(); } } Form1.sourceImages.Add(bestResult.img); MinOverlap.map1.matched = true; // correct MinOverlap.map2.matched = true; // correct List <ColorfulContourMap> cmap = ColorfulContourMap.getAllContourMap(bestResult.img, Form1.sourceImages.Count - 1); Form1.contourMaps.AddRange(cmap); this.overlap += bestResult.overlap; // correct refresh(); MessageBox.Show("Best Match Found."); return(0); } else { Console.WriteLine("Failed"); return(1); } }