public DebuggerProxy(DenseHistogram v) { _v = v; }
/// <summary> /// Eliminate the matched features whose scale and rotation do not aggree with the majority's scale and rotation. /// </summary> /// <param name="rotationBins">The numbers of bins for rotation, a good value might be 20 (which means each bin covers 18 degree)</param> /// <param name="scaleIncrement">This determins the different in scale for neighbour hood bins, a good value might be 1.5 (which means matched features in bin i+1 is scaled 1.5 times larger than matched features in bin i</param> /// <param name="matchedFeatures">The matched feature that will be participated in the voting. For each matchedFeatures, only the zero indexed ModelFeature will be considered.</param> public static MatchedSURFFeature[] VoteForSizeAndOrientation(MatchedSURFFeature[] matchedFeatures, double scaleIncrement, int rotationBins) { int elementsCount = matchedFeatures.Length; float[] scales = new float[elementsCount]; float[] rotations = new float[elementsCount]; float[] flags = new float[elementsCount]; float minScale = float.MaxValue; float maxScale = float.MinValue; for (int i = 0; i < matchedFeatures.Length; i++) { float scale = (float)matchedFeatures[i].ObservedFeature.Point.size / (float)matchedFeatures[i].SimilarFeatures[0].Feature.Point.size; scale = (float)Math.Log10(scale); scales[i] = scale; if (scale < minScale) { minScale = scale; } if (scale > maxScale) { maxScale = scale; } float rotation = matchedFeatures[i].ObservedFeature.Point.dir - matchedFeatures[i].SimilarFeatures[0].Feature.Point.dir; rotations[i] = rotation < 0.0 ? rotation + 360 : rotation; } int scaleBinSize = (int)Math.Max(((maxScale - minScale) / Math.Log10(scaleIncrement)), 1); int count; using (DenseHistogram h = new DenseHistogram(new int[] { scaleBinSize, rotationBins }, new RangeF[] { new RangeF(minScale, maxScale), new RangeF(0, 360) })) { GCHandle scaleHandle = GCHandle.Alloc(scales, GCHandleType.Pinned); GCHandle rotationHandle = GCHandle.Alloc(rotations, GCHandleType.Pinned); GCHandle flagsHandle = GCHandle.Alloc(flags, GCHandleType.Pinned); using (Matrix <float> flagsMat = new Matrix <float>(1, elementsCount, flagsHandle.AddrOfPinnedObject())) using (Matrix <float> scalesMat = new Matrix <float>(1, elementsCount, scaleHandle.AddrOfPinnedObject())) using (Matrix <float> rotationsMat = new Matrix <float>(1, elementsCount, rotationHandle.AddrOfPinnedObject())) { h.Calculate(new Matrix <float>[] { scalesMat, rotationsMat }, true, null); float minVal, maxVal; int[] minLoc, maxLoc; h.MinMax(out minVal, out maxVal, out minLoc, out maxLoc); h.Threshold(maxVal * 0.5); CvInvoke.cvCalcBackProject(new IntPtr[] { scalesMat.Ptr, rotationsMat.Ptr }, flagsMat.Ptr, h.Ptr); count = CvInvoke.cvCountNonZero(flagsMat); } scaleHandle.Free(); rotationHandle.Free(); flagsHandle.Free(); MatchedSURFFeature[] matchedGoodFeatures = new MatchedSURFFeature[count]; int index = 0; for (int i = 0; i < matchedFeatures.Length; i++) { if (flags[i] != 0) { matchedGoodFeatures[index++] = matchedFeatures[i]; } } return(matchedGoodFeatures); } }