/// <summary> /// Matches the provided template pyramid against the linearized memory maps pyramid. /// </summary> /// <param name="linPyr">Linearized memory pyramid.</param> /// <param name="templPyr">Template pyramid.</param> /// <param name="minMatchingPercentage">Minimum matching percentage [0..100].</param> /// <returns>List of found matches.</returns> public static List <Match> MatchTemplate(this LinearizedMapPyramid linPyr, ITemplatePyramid templPyr, int minMatchingPercentage = 85) { if (linPyr.PyramidalMaps.Length != templPyr.Templates.Length) { throw new Exception("Number of pyramids in linear pyramid must match the number of templates in template pyramid!" + "\n" + "Check if the number of neighborhood per level is the same as the number of features per level for template!"); } List <Match>[] pyrMatches = new List <Match> [linPyr.PyramidalMaps.Length]; //match at the lowest level int lowestLevelIdx = linPyr.PyramidalMaps.Length - 1; var searchArea = new Rectangle(new Point(), linPyr.PyramidalMaps[lowestLevelIdx].ImageSize); //search whole image pyrMatches[lowestLevelIdx] = matchTemplate(linPyr.PyramidalMaps[lowestLevelIdx], templPyr.Templates[lowestLevelIdx], searchArea, minMatchingPercentage, true); //refine matches for (int pyrLevel = (lowestLevelIdx - 1); pyrLevel >= 0; pyrLevel--) { LinearizedMaps maps = linPyr.PyramidalMaps[pyrLevel]; ITemplate template = templPyr.Templates[pyrLevel]; Size imageValidSize = maps.ImageValidSize; pyrMatches[pyrLevel] = new List <Match>(); int previousNeigborhood = linPyr.PyramidalMaps[pyrLevel + 1].NeigborhoodSize; for (int candidateIdx = 0; candidateIdx < pyrMatches[pyrLevel + 1].Count; candidateIdx++) //for every candidate of previous pyramid level... { //translate match to lower pyrmaid level Match canidate = pyrMatches[pyrLevel + 1][candidateIdx]; canidate.X = canidate.X * 2 + 1; canidate.Y = canidate.Y * 2 + 1; canidate.Template = template; //translate search area to lower pyramid level searchArea = new Rectangle //in originalImageSize coordinate system { X = System.Math.Max(0, canidate.X - previousNeigborhood), Y = System.Math.Max(0, canidate.Y - previousNeigborhood), Width = previousNeigborhood * 2, Height = previousNeigborhood * 2 }; searchArea = searchArea.Intersect(imageValidSize); var foundCandidates = matchTemplate(linPyr.PyramidalMaps[pyrLevel], template, searchArea, minMatchingPercentage, pyrLevel != 0 /*filter partial object for all levels except for the original one*/); pyrMatches[pyrLevel].AddRange(foundCandidates); } } return(pyrMatches[0]); //matches of the highest pyr level }
/// <summary> /// Matches the provided template pyramid against the linearized memory maps pyramid. /// </summary> /// <param name="linPyr">Linearized memory pyramid.</param> /// <param name="templPyr">Template pyramid.</param> /// <param name="minMatchingPercentage">Minimum matching percentage [0..100].</param> /// <returns>List of found matches.</returns> public static List<Match> MatchTemplate(this LinearizedMapPyramid linPyr, ITemplatePyramid templPyr, int minMatchingPercentage = 85) { if (linPyr.PyramidalMaps.Length != templPyr.Templates.Length) throw new Exception("Number of pyramids in linear pyramid must match the number of templates in template pyramid!" + "\n" + "Check if the number of neighborhood per level is the same as the number of features per level for template!"); List<Match>[] pyrMatches = new List<Match>[linPyr.PyramidalMaps.Length]; //match at the lowest level int lowestLevelIdx = linPyr.PyramidalMaps.Length - 1; var searchArea = new Rectangle(new Point(), linPyr.PyramidalMaps[lowestLevelIdx].ImageSize); //search whole image pyrMatches[lowestLevelIdx] = matchTemplate(linPyr.PyramidalMaps[lowestLevelIdx], templPyr.Templates[lowestLevelIdx], searchArea, minMatchingPercentage, true); //refine matches for (int pyrLevel = (lowestLevelIdx - 1); pyrLevel >= 0; pyrLevel--) { LinearizedMaps maps = linPyr.PyramidalMaps[pyrLevel]; ITemplate template = templPyr.Templates[pyrLevel]; Size imageValidSize = maps.ImageValidSize; pyrMatches[pyrLevel] = new List<Match>(); int previousNeigborhood = linPyr.PyramidalMaps[pyrLevel + 1].NeigborhoodSize; for (int candidateIdx = 0; candidateIdx < pyrMatches[pyrLevel+1].Count; candidateIdx++) //for every candidate of previous pyramid level... { //translate match to lower pyrmaid level Match canidate = pyrMatches[pyrLevel + 1][candidateIdx]; canidate.X = canidate.X * 2 + 1; canidate.Y = canidate.Y * 2 + 1; canidate.Template = template; //translate search area to lower pyramid level searchArea = new Rectangle //in originalImageSize coordinate system { X = System.Math.Max(0, canidate.X - previousNeigborhood), Y = System.Math.Max(0, canidate.Y - previousNeigborhood), Width = previousNeigborhood * 2, Height = previousNeigborhood * 2 }; searchArea = searchArea.Intersect(imageValidSize); var foundCandidates = matchTemplate(linPyr.PyramidalMaps[pyrLevel], template, searchArea, minMatchingPercentage, pyrLevel != 0 /*filter partial object for all levels except for the original one*/); pyrMatches[pyrLevel].AddRange(foundCandidates); } } return pyrMatches[0]; //matches of the highest pyr level }