diff --git a/src/OpenCvSharp/OpenCvSharp.csproj b/src/OpenCvSharp/OpenCvSharp.csproj
index d681a8975..1dc6d2162 100644
--- a/src/OpenCvSharp/OpenCvSharp.csproj
+++ b/src/OpenCvSharp/OpenCvSharp.csproj
@@ -86,6 +86,7 @@
+
@@ -119,6 +120,7 @@
+
diff --git a/src/OpenCvSharp/PInvoke/features2d/NativeMethods_features2d_KeyPointsFilter.cs b/src/OpenCvSharp/PInvoke/features2d/NativeMethods_features2d_KeyPointsFilter.cs
new file mode 100644
index 000000000..007755a8e
--- /dev/null
+++ b/src/OpenCvSharp/PInvoke/features2d/NativeMethods_features2d_KeyPointsFilter.cs
@@ -0,0 +1,32 @@
+using System;
+using System.Runtime.InteropServices;
+
+#pragma warning disable 1591
+
+namespace OpenCvSharp
+{
+ static partial class NativeMethods
+ {
+ // ReSharper disable InconsistentNaming
+
+ [DllImport(DllExtern, CallingConvention = CallingConvention.Cdecl)]
+ public static extern void features2d_KeyPointsFilter_runByImageBorder(
+ IntPtr keypoints, Size imageSize, int borderSize);
+
+ [DllImport(DllExtern, CallingConvention = CallingConvention.Cdecl)]
+ public static extern void features2d_KeyPointsFilter_runByKeypointSize(
+ IntPtr keypoints, float minSize, float maxSize);
+
+ [DllImport(DllExtern, CallingConvention = CallingConvention.Cdecl)]
+ public static extern void features2d_KeyPointsFilter_runByPixelsMask(
+ IntPtr keypoints, IntPtr mask);
+
+ [DllImport(DllExtern, CallingConvention = CallingConvention.Cdecl)]
+ public static extern void features2d_KeyPointsFilter_removeDuplicated(
+ IntPtr keypoints);
+
+ [DllImport(DllExtern, CallingConvention = CallingConvention.Cdecl)]
+ public static extern void features2d_KeyPointsFilter_retainBest(
+ IntPtr keypoints, int npoints);
+ }
+}
\ No newline at end of file
diff --git a/src/OpenCvSharp/modules/features2d/KeyPointsFilter.cs b/src/OpenCvSharp/modules/features2d/KeyPointsFilter.cs
new file mode 100644
index 000000000..70566c035
--- /dev/null
+++ b/src/OpenCvSharp/modules/features2d/KeyPointsFilter.cs
@@ -0,0 +1,113 @@
+using System;
+using System.Collections.Generic;
+
+namespace OpenCvSharp
+{
+ // ReSharper disable once InconsistentNaming
+
+ ///
+ /// A class filters a vector of keypoints.
+ ///
+ public static class KeyPointsFilter
+ {
+ ///
+ /// Remove keypoints within borderPixels of an image edge.
+ ///
+ ///
+ ///
+ ///
+ ///
+ public static KeyPoint[] RunByImageBorder(IEnumerable keypoints, Size imageSize, int borderSize)
+ {
+ if (keypoints == null)
+ throw new ArgumentNullException("keypoints");
+
+ using (var keypointsVec = new VectorOfKeyPoint(keypoints))
+ {
+ NativeMethods.features2d_KeyPointsFilter_runByImageBorder(
+ keypointsVec.CvPtr, imageSize, borderSize);
+ return keypointsVec.ToArray();
+ }
+ }
+
+ ///
+ /// Remove keypoints of sizes out of range.
+ ///
+ ///
+ ///
+ ///
+ ///
+ public static KeyPoint[] RunByKeypointSize(IEnumerable keypoints, float minSize,
+ float maxSize = Single.MaxValue)
+ {
+ if (keypoints == null)
+ throw new ArgumentNullException("keypoints");
+
+ using (var keypointsVec = new VectorOfKeyPoint(keypoints))
+ {
+ NativeMethods.features2d_KeyPointsFilter_runByKeypointSize(
+ keypointsVec.CvPtr, minSize, maxSize);
+ return keypointsVec.ToArray();
+ }
+ }
+
+ ///
+ /// Remove keypoints from some image by mask for pixels of this image.
+ ///
+ ///
+ ///
+ ///
+ public static KeyPoint[] RunByPixelsMask(IEnumerable keypoints, Mat mask)
+ {
+ if (keypoints == null)
+ throw new ArgumentNullException("keypoints");
+ if (mask == null)
+ throw new ArgumentNullException("mask");
+ mask.ThrowIfDisposed();
+
+ using (var keypointsVec = new VectorOfKeyPoint(keypoints))
+ {
+ NativeMethods.features2d_KeyPointsFilter_runByPixelsMask(
+ keypointsVec.CvPtr, mask.CvPtr);
+ GC.KeepAlive(mask);
+ return keypointsVec.ToArray();
+ }
+ }
+
+ ///
+ /// Remove duplicated keypoints.
+ ///
+ ///
+ ///
+ public static KeyPoint[] RemoveDuplicated(IEnumerable keypoints)
+ {
+ if (keypoints == null)
+ throw new ArgumentNullException("keypoints");
+
+ using (var keypointsVec = new VectorOfKeyPoint(keypoints))
+ {
+ NativeMethods.features2d_KeyPointsFilter_removeDuplicated(keypointsVec.CvPtr);
+ return keypointsVec.ToArray();
+ }
+ }
+
+ ///
+ /// Retain the specified number of the best keypoints (according to the response)
+ ///
+ ///
+ ///
+ ///
+ public static KeyPoint[] RetainBest(IEnumerable keypoints, int npoints)
+ {
+ if (keypoints == null)
+ throw new ArgumentNullException("keypoints");
+
+ using (var keypointsVec = new VectorOfKeyPoint(keypoints))
+ {
+ NativeMethods.features2d_KeyPointsFilter_retainBest(
+ keypointsVec.CvPtr, npoints);
+ return keypointsVec.ToArray();
+ }
+ }
+ }
+}
diff --git a/src/OpenCvSharpExtern/OpenCvSharpExtern.vcxproj b/src/OpenCvSharpExtern/OpenCvSharpExtern.vcxproj
index 03bd11664..05f66ca7b 100644
--- a/src/OpenCvSharpExtern/OpenCvSharpExtern.vcxproj
+++ b/src/OpenCvSharpExtern/OpenCvSharpExtern.vcxproj
@@ -363,6 +363,7 @@
+
diff --git a/src/OpenCvSharpExtern/OpenCvSharpExtern.vcxproj.filters b/src/OpenCvSharpExtern/OpenCvSharpExtern.vcxproj.filters
index 983c5bf38..7bc052b67 100644
--- a/src/OpenCvSharpExtern/OpenCvSharpExtern.vcxproj.filters
+++ b/src/OpenCvSharpExtern/OpenCvSharpExtern.vcxproj.filters
@@ -240,6 +240,9 @@
Header Files\features2d
+
+ Header Files\features2d
+
diff --git a/src/OpenCvSharpExtern/features2d_KeyPointsFilter.h b/src/OpenCvSharpExtern/features2d_KeyPointsFilter.h
new file mode 100644
index 000000000..cf3acbae4
--- /dev/null
+++ b/src/OpenCvSharpExtern/features2d_KeyPointsFilter.h
@@ -0,0 +1,36 @@
+#ifndef _CPP_FEATURES2D_KAZE_H_
+#define _CPP_FEATURES2D_KAZE_H_
+
+#include "include_opencv.h"
+
+
+CVAPI(void) features2d_KeyPointsFilter_runByImageBorder(
+ std::vector *keypoints, MyCvSize imageSize, int borderSize)
+{
+ cv::KeyPointsFilter::runByImageBorder(*keypoints, cpp(imageSize), borderSize);
+}
+
+CVAPI(void) features2d_KeyPointsFilter_runByKeypointSize(
+ std::vector *keypoints, float minSize, float maxSize)
+{
+ cv::KeyPointsFilter::runByKeypointSize(*keypoints, minSize, maxSize);
+}
+CVAPI(void) features2d_KeyPointsFilter_runByPixelsMask(
+ std::vector *keypoints, cv::Mat *mask)
+{
+ cv::KeyPointsFilter::runByPixelsMask(*keypoints, *mask);
+}
+
+CVAPI(void) features2d_KeyPointsFilter_removeDuplicated(
+ std::vector *keypoints)
+{
+ cv::KeyPointsFilter::removeDuplicated(*keypoints);
+}
+
+CVAPI(void) features2d_KeyPointsFilter_retainBest(
+ std::vector *keypoints, int npoints)
+{
+ cv::KeyPointsFilter::retainBest(*keypoints, npoints);
+}
+
+#endif
\ No newline at end of file