diff options
Diffstat (limited to 'ml/dlib/tools/python/src/rectangles.cpp')
-rw-r--r-- | ml/dlib/tools/python/src/rectangles.cpp | 268 |
1 files changed, 268 insertions, 0 deletions
diff --git a/ml/dlib/tools/python/src/rectangles.cpp b/ml/dlib/tools/python/src/rectangles.cpp new file mode 100644 index 000000000..d06ec591b --- /dev/null +++ b/ml/dlib/tools/python/src/rectangles.cpp @@ -0,0 +1,268 @@ +// Copyright (C) 2015 Davis E. King (davis@dlib.net) +// License: Boost Software License See LICENSE.txt for the full license. + +#include <dlib/python.h> +#include <dlib/geometry.h> +#include <pybind11/stl_bind.h> +#include "indexing.h" +#include "opaque_types.h" +#include <dlib/filtering.h> + +using namespace dlib; +using namespace std; + +namespace py = pybind11; + + +// ---------------------------------------------------------------------------------------- + +long left(const rectangle& r) { return r.left(); } +long top(const rectangle& r) { return r.top(); } +long right(const rectangle& r) { return r.right(); } +long bottom(const rectangle& r) { return r.bottom(); } +long width(const rectangle& r) { return r.width(); } +long height(const rectangle& r) { return r.height(); } +unsigned long area(const rectangle& r) { return r.area(); } + +double dleft(const drectangle& r) { return r.left(); } +double dtop(const drectangle& r) { return r.top(); } +double dright(const drectangle& r) { return r.right(); } +double dbottom(const drectangle& r) { return r.bottom(); } +double dwidth(const drectangle& r) { return r.width(); } +double dheight(const drectangle& r) { return r.height(); } +double darea(const drectangle& r) { return r.area(); } + +template <typename rect_type> +bool is_empty(const rect_type& r) { return r.is_empty(); } + +template <typename rect_type> +point center(const rect_type& r) { return center(r); } + +template <typename rect_type> +point dcenter(const rect_type& r) { return dcenter(r); } + +template <typename rect_type> +bool contains(const rect_type& r, const point& p) { return r.contains(p); } + +template <typename rect_type> +bool contains_xy(const rect_type& r, const long x, const long y) { return r.contains(point(x, y)); } + +template <typename rect_type> +bool contains_rec(const rect_type& r, const rect_type& r2) { return r.contains(r2); } + +template <typename rect_type> +rect_type intersect(const rect_type& r, const rect_type& r2) { return r.intersect(r2); } + +template <typename rect_type> +string print_rectangle_str(const rect_type& r) +{ + std::ostringstream sout; + sout << r; + return sout.str(); +} + +string print_rectangle_repr(const rectangle& r) +{ + std::ostringstream sout; + sout << "rectangle(" << r.left() << "," << r.top() << "," << r.right() << "," << r.bottom() << ")"; + return sout.str(); +} + +string print_drectangle_repr(const drectangle& r) +{ + std::ostringstream sout; + sout << "drectangle(" << r.left() << "," << r.top() << "," << r.right() << "," << r.bottom() << ")"; + return sout.str(); +} + +string print_rect_filter(const rect_filter& r) +{ + std::ostringstream sout; + sout << "rect_filter("; + sout << "measurement_noise="<<r.get_left().get_measurement_noise(); + sout << ", typical_acceleration="<<r.get_left().get_typical_acceleration(); + sout << ", max_measurement_deviation="<<r.get_left().get_max_measurement_deviation(); + sout << ")"; + return sout.str(); +} + + +rectangle add_point_to_rect(const rectangle& r, const point& p) +{ + return r + p; +} + +rectangle add_rect_to_rect(const rectangle& r, const rectangle& p) +{ + return r + p; +} + +rectangle& iadd_point_to_rect(rectangle& r, const point& p) +{ + r += p; + return r; +} + +rectangle& iadd_rect_to_rect(rectangle& r, const rectangle& p) +{ + r += p; + return r; +} + + + +// ---------------------------------------------------------------------------------------- + +void bind_rectangles(py::module& m) +{ + { + typedef rectangle type; + py::class_<type>(m, "rectangle", "This object represents a rectangular area of an image.") + .def(py::init<long,long,long,long>(), py::arg("left"),py::arg("top"),py::arg("right"),py::arg("bottom")) + .def(py::init()) + .def("area", &::area) + .def("left", &::left) + .def("top", &::top) + .def("right", &::right) + .def("bottom", &::bottom) + .def("width", &::width) + .def("height", &::height) + .def("is_empty", &::is_empty<type>) + .def("center", &::center<type>) + .def("dcenter", &::dcenter<type>) + .def("contains", &::contains<type>, py::arg("point")) + .def("contains", &::contains_xy<type>, py::arg("x"), py::arg("y")) + .def("contains", &::contains_rec<type>, py::arg("rectangle")) + .def("intersect", &::intersect<type>, py::arg("rectangle")) + .def("__str__", &::print_rectangle_str<type>) + .def("__repr__", &::print_rectangle_repr) + .def("__add__", &::add_point_to_rect) + .def("__add__", &::add_rect_to_rect) + .def("__iadd__", &::iadd_point_to_rect) + .def("__iadd__", &::iadd_rect_to_rect) + .def(py::self == py::self) + .def(py::self != py::self) + .def(py::pickle(&getstate<type>, &setstate<type>)); + } + { + typedef drectangle type; + py::class_<type>(m, "drectangle", "This object represents a rectangular area of an image with floating point coordinates.") + .def(py::init<double,double,double,double>(), py::arg("left"), py::arg("top"), py::arg("right"), py::arg("bottom")) + .def("area", &::darea) + .def("left", &::dleft) + .def("top", &::dtop) + .def("right", &::dright) + .def("bottom", &::dbottom) + .def("width", &::dwidth) + .def("height", &::dheight) + .def("is_empty", &::is_empty<type>) + .def("center", &::center<type>) + .def("dcenter", &::dcenter<type>) + .def("contains", &::contains<type>, py::arg("point")) + .def("contains", &::contains_xy<type>, py::arg("x"), py::arg("y")) + .def("contains", &::contains_rec<type>, py::arg("rectangle")) + .def("intersect", &::intersect<type>, py::arg("rectangle")) + .def("__str__", &::print_rectangle_str<type>) + .def("__repr__", &::print_drectangle_repr) + .def(py::self == py::self) + .def(py::self != py::self) + .def(py::pickle(&getstate<type>, &setstate<type>)); + } + + { + typedef rect_filter type; + py::class_<type>(m, "rect_filter", + R"asdf( + This object is a simple tool for filtering a rectangle that + measures the location of a moving object that has some non-trivial + momentum. Importantly, the measurements are noisy and the object can + experience sudden unpredictable accelerations. To accomplish this + filtering we use a simple Kalman filter with a state transition model of: + + position_{i+1} = position_{i} + velocity_{i} + velocity_{i+1} = velocity_{i} + some_unpredictable_acceleration + + and a measurement model of: + + measured_position_{i} = position_{i} + measurement_noise + + Where some_unpredictable_acceleration and measurement_noise are 0 mean Gaussian + noise sources with standard deviations of typical_acceleration and + measurement_noise respectively. + + To allow for really sudden and large but infrequent accelerations, at each + step we check if the current measured position deviates from the predicted + filtered position by more than max_measurement_deviation*measurement_noise + and if so we adjust the filter's state to keep it within these bounds. + This allows the moving object to undergo large unmodeled accelerations, far + in excess of what would be suggested by typical_acceleration, without + then experiencing a long lag time where the Kalman filter has to "catches + up" to the new position. )asdf" + ) + .def(py::init<double,double,double>(), py::arg("measurement_noise"), py::arg("typical_acceleration"), py::arg("max_measurement_deviation")) + .def("measurement_noise", [](const rect_filter& a){return a.get_left().get_measurement_noise();}) + .def("typical_acceleration", [](const rect_filter& a){return a.get_left().get_typical_acceleration();}) + .def("max_measurement_deviation", [](const rect_filter& a){return a.get_left().get_max_measurement_deviation();}) + .def("__call__", [](rect_filter& f, const dlib::rectangle& r){return rectangle(f(r)); }, py::arg("rect")) + .def("__repr__", print_rect_filter) + .def(py::pickle(&getstate<type>, &setstate<type>)); + } + + m.def("find_optimal_rect_filter", + [](const std::vector<rectangle>& rects, const double smoothness ) { return find_optimal_rect_filter(rects, smoothness); }, + py::arg("rects"), + py::arg("smoothness")=1, +"requires \n\ + - rects.size() > 4 \n\ + - smoothness >= 0 \n\ +ensures \n\ + - This function finds the \"optimal\" settings of a rect_filter based on recorded \n\ + measurement data stored in rects. Here we assume that rects is a complete \n\ + track history of some object's measured positions. Essentially, what we do \n\ + is find the rect_filter that minimizes the following objective function: \n\ + sum of abs(predicted_location[i] - measured_location[i]) + smoothness*abs(filtered_location[i]-filtered_location[i-1]) \n\ + Where i is a time index. \n\ + The sum runs over all the data in rects. So what we do is find the \n\ + filter settings that produce smooth filtered trajectories but also produce \n\ + filtered outputs that are as close to the measured positions as possible. \n\ + The larger the value of smoothness the less jittery the filter outputs will \n\ + be, but they might become biased or laggy if smoothness is set really high. " + /*! + requires + - rects.size() > 4 + - smoothness >= 0 + ensures + - This function finds the "optimal" settings of a rect_filter based on recorded + measurement data stored in rects. Here we assume that rects is a complete + track history of some object's measured positions. Essentially, what we do + is find the rect_filter that minimizes the following objective function: + sum of abs(predicted_location[i] - measured_location[i]) + smoothness*abs(filtered_location[i]-filtered_location[i-1]) + Where i is a time index. + The sum runs over all the data in rects. So what we do is find the + filter settings that produce smooth filtered trajectories but also produce + filtered outputs that are as close to the measured positions as possible. + The larger the value of smoothness the less jittery the filter outputs will + be, but they might become biased or laggy if smoothness is set really high. + !*/ + ); + + { + typedef std::vector<rectangle> type; + py::bind_vector<type>(m, "rectangles", "An array of rectangle objects.") + .def("clear", &type::clear) + .def("resize", resize<type>) + .def("extend", extend_vector_with_python_list<rectangle>) + .def(py::pickle(&getstate<type>, &setstate<type>)); + } + + { + typedef std::vector<std::vector<rectangle>> type; + py::bind_vector<type>(m, "rectangless", "An array of arrays of rectangle objects.") + .def("clear", &type::clear) + .def("resize", resize<type>) + .def("extend", extend_vector_with_python_list<rectangle>) + .def(py::pickle(&getstate<type>, &setstate<type>)); + } +} + +// ---------------------------------------------------------------------------------------- |