diff --git a/opensfm/features.py b/opensfm/features.py index a21ce9796..eb8ce6b0d 100644 --- a/opensfm/features.py +++ b/opensfm/features.py @@ -656,8 +656,6 @@ def extract_features( xs = points[:, 0].round().astype(int) ys = points[:, 1].round().astype(int) - xs = np.clip(xs, 0, image.shape[1] - 1) - ys = np.clip(ys, 0, image.shape[0] - 1) colors = image[ys, xs] if image.shape[2] == 1: colors = np.repeat(colors, 3).reshape((-1, 3)) diff --git a/opensfm/src/features/dspsift.h b/opensfm/src/features/dspsift.h index a987b1c23..0ba8767bf 100644 --- a/opensfm/src/features/dspsift.h +++ b/opensfm/src/features/dspsift.h @@ -6,6 +6,6 @@ namespace features { py::tuple dspsift(foundation::pyarray_f image, float peak_threshold, float edge_threshold, int target_num_features, - bool feature_root, bool domain_size_pooling, bool estimate_affine_shape); + bool feature_root, bool domain_size_pooling, bool estimate_affine_shape, int border_size); } diff --git a/opensfm/src/features/python/pybind.cc b/opensfm/src/features/python/pybind.cc index ea23ef1cf..b8ba9d8e0 100644 --- a/opensfm/src/features/python/pybind.cc +++ b/opensfm/src/features/python/pybind.cc @@ -62,7 +62,8 @@ PYBIND11_MODULE(pyfeatures, m) { py::arg("target_num_features") = 0, py::arg("feature_root") = true, py::arg("domain_size_pooling") = true, - py::arg("estimate_affine_shape") = true); + py::arg("estimate_affine_shape") = true, + py::arg("border_size") = 5); m.def("match_using_words", features::match_using_words); m.def("compute_vlad_descriptor", features::compute_vlad_descriptor, diff --git a/opensfm/src/features/src/dspsift.cc b/opensfm/src/features/src/dspsift.cc index 3df85ca37..d092a4208 100644 --- a/opensfm/src/features/src/dspsift.cc +++ b/opensfm/src/features/src/dspsift.cc @@ -8,6 +8,7 @@ Copyright (c) 2023, ETH Zurich and UNC Chapel Hill. #include #include #include +#include #include extern "C" { @@ -47,11 +48,18 @@ namespace features { py::tuple dspsift(foundation::pyarray_f image, float peak_threshold, float edge_threshold, int target_num_features, - bool feature_root, bool domain_size_pooling, bool estimate_affine_shape) { + bool feature_root, bool domain_size_pooling, bool estimate_affine_shape, int border_size) { if (!image.size()) { return py::none(); } + int width = image.shape(1); + int height = image.shape(0); + + if (border_size*2 >= width || border_size*2 >= height) { + return py::none(); + } + FeatureDescriptors descriptors; FeatureKeypoints keypoints; int keypoints_count = 0; @@ -103,7 +111,13 @@ py::tuple dspsift(foundation::pyarray_f image, float peak_threshold, } VlCovDetFeature* features = vl_covdet_get_features(covdet.get()); + + VlCovDetFeature* middle = std::partition(features, features + num_features, [border_size, width, height](const VlCovDetFeature& feature) { + return feature.frame.x >= border_size && feature.frame.x < width - border_size && + feature.frame.y >= border_size && feature.frame.y < height - border_size; + }); + num_features = middle - features; // Sort features according to detected octave and scale. std::sort(