mirror of https://github.com/davisking/dlib.git
Added rect_filter and find_optimal_rect_filter() to python API.
This commit is contained in:
parent
0bdc9ce5b4
commit
49ec319ce4
|
@ -6,6 +6,7 @@
|
|||
#include <pybind11/stl_bind.h>
|
||||
#include "indexing.h"
|
||||
#include "opaque_types.h"
|
||||
#include <dlib/filtering.h>
|
||||
|
||||
using namespace dlib;
|
||||
using namespace std;
|
||||
|
@ -60,14 +61,32 @@ string print_rectangle_str(const rect_type& r)
|
|||
return sout.str();
|
||||
}
|
||||
|
||||
template <typename rect_type>
|
||||
string print_rectangle_repr(const rect_type& r)
|
||||
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;
|
||||
|
@ -100,6 +119,7 @@ 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)
|
||||
|
@ -115,7 +135,7 @@ void bind_rectangles(py::module& m)
|
|||
.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<type>)
|
||||
.def("__repr__", &::print_rectangle_repr)
|
||||
.def("__add__", &::add_point_to_rect)
|
||||
.def("__add__", &::add_rect_to_rect)
|
||||
.def("__iadd__", &::iadd_point_to_rect)
|
||||
|
@ -143,12 +163,89 @@ void bind_rectangles(py::module& m)
|
|||
.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<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.")
|
||||
|
|
Loading…
Reference in New Issue