Commit a8d73744 authored by Davis King's avatar Davis King

Added point_transform_projective and find_projective_transform()

parent 6e2a867a
This diff is collapsed.
......@@ -81,6 +81,78 @@ namespace dlib
all possible solutions).
!*/
// ----------------------------------------------------------------------------------------
class point_transform_projective
{
/*!
WHAT THIS OBJECT REPRESENTS
This is an object that takes 2D points or vectors and
applies a projective transformation to them.
!*/
public:
point_transform_projective (
const matrix<double,3,3>& m
);
/*!
ensures
- #get_m() == m
!*/
point_transform_projective (
const point_transform_affine& tran
);
/*!
ensures
- This object will perform exactly the same transformation as the given
affine transform.
!*/
const dlib::vector<double,2> operator() (
const dlib::vector<double,2>& p
) const;
/*!
ensures
- Applies the projective transformation defined by this object's constructor
to p and returns the result. To define this precisely:
- let p_h == the point p in homogeneous coordinates. That is:
- p_h.x() == p.x()
- p_h.y() == p.y()
- p_h.z() == 1
- let x == get_m()*p_h
- Then this function returns the value x/x.z()
!*/
const matrix<double,3,3>& get_m(
) const;
/*!
ensures
- returns the transformation matrix used by this object.
!*/
};
// ----------------------------------------------------------------------------------------
point_transform_projective find_projective_transform (
const std::vector<dlib::vector<double,2> >& from_points,
const std::vector<dlib::vector<double,2> >& to_points
);
/*!
requires
- from_points.size() == to_points.size()
- from_points.size() >= 4
ensures
- returns a point_transform_projective object, T, such that for all valid i:
length(T(from_points[i]) - to_points[i])
is minimized as often as possible. That is, this function finds the projective
transform that maps points in from_points to points in to_points. If no
projective transform exists which performs this mapping exactly then the one
which minimizes the mean squared error is selected.
!*/
// ----------------------------------------------------------------------------------------
class point_transform
......
......@@ -647,6 +647,65 @@ namespace
}
// ----------------------------------------------------------------------------------------
double projective_transform_pass_rate(const double error_rate)
{
print_spinner();
dlog << LINFO << "projective_transform_pass_rate, error_rate: "<< error_rate;
dlib::rand rnd;
running_stats<double> pass_rate;
for (int rounds = 0; rounds < 1000; ++rounds)
{
running_stats<double> rs, rs_true;
matrix<double> H = 2*(randm(3,3,rnd)-0.5);
H(0,2) = rnd.get_random_gaussian()*10;
H(1,2) = rnd.get_random_gaussian()*10;
H(2,0) = rnd.get_random_double()*2.1;
H(2,1) = rnd.get_random_double()*2.1;
H(2,2) = 1 + rnd.get_random_gaussian()*3.1;
point_transform_projective tran(H);
const int num = rnd.get_random_32bit_number()%8 + 4;
std::vector<dlib::vector<double,2> > from_points, to_points;
for (int i = 0; i < num; ++i)
{
dlib::vector<double,2> p = randm(2,1,rnd)*1000;
from_points.push_back(p);
to_points.push_back(tran(p) + (randm(2,1,rnd)-0.5)*error_rate);
}
point_transform_projective tran2 = find_projective_transform(from_points, to_points);
for (unsigned long i = 0; i < from_points.size(); ++i)
{
const double err = length_squared(tran2(from_points[i]) - to_points[i]);
rs.add(err);
const double err_true = length_squared(tran(from_points[i]) - to_points[i]);
rs_true.add(err_true);
}
if ( rs.mean() < 0.01)
{
pass_rate.add(1);
}
else
{
dlog << LINFO << " errors: mean/max: " << rs.mean() << " " << rs.max();
pass_rate.add(0);
}
}
dlog << LINFO << " pass_rate.mean(): "<< pass_rate.mean();
return pass_rate.mean();
}
// ----------------------------------------------------------------------------------------
class geometry_tester : public tester
......@@ -664,6 +723,8 @@ namespace
geometry_test();
test_border_enumerator();
test_find_affine_transform();
DLIB_TEST(projective_transform_pass_rate(0.1) > 0.99);
DLIB_TEST(projective_transform_pass_rate(0.0) == 1);
}
} a;
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment