Commit 8a3ecdc7 authored by Davis King's avatar Davis King

Added the find_affine_transform() routine.

parent 9cc8e568
......@@ -5,8 +5,9 @@
#include "point_transforms_abstract.h"
#include "../algs.h"
#include "../matrix.h"
#include "vector.h"
#include "../matrix.h"
#include "../matrix/matrix_la.h"
#include <vector>
namespace dlib
......@@ -97,6 +98,40 @@ namespace dlib
dlib::vector<double,2> b;
};
// ----------------------------------------------------------------------------------------
template <typename T>
point_transform_affine find_affine_transform (
const std::vector<dlib::vector<T,2> >& from_points,
const std::vector<dlib::vector<T,2> >& to_points
)
{
// make sure requires clause is not broken
DLIB_ASSERT(from_points.size() == to_points.size() &&
from_points.size() >= 3,
"\t point_transform_affine find_affine_transform(from_points, to_points)"
<< "\n\t Invalid inputs were given to this function."
<< "\n\t from_points.size(): " << from_points.size()
<< "\n\t to_points.size(): " << to_points.size()
);
matrix<double,3,0> P(3, from_points.size());
matrix<double,2,0> Q(2, from_points.size());
for (unsigned long i = 0; i < from_points.size(); ++i)
{
P(0,i) = from_points[i].x();
P(1,i) = from_points[i].y();
P(2,i) = 1;
Q(0,i) = to_points[i].x();
Q(1,i) = to_points[i].y();
}
const matrix<double,2,3> m = Q*pinv(P);
return point_transform_affine(subm(m,0,0,2,2), colm(m,2));
}
// ----------------------------------------------------------------------------------------
template <typename T>
......
......@@ -5,6 +5,7 @@
#include "../matrix/matrix_abstract.h"
#include "vector_abstract.h"
#include <vector>
namespace dlib
{
......@@ -40,6 +41,30 @@ namespace dlib
};
// ----------------------------------------------------------------------------------------
template <typename T>
point_transform_affine find_affine_transform (
const std::vector<dlib::vector<T,2> >& from_points,
const std::vector<dlib::vector<T,2> >& to_points
);
/*!
requires
- from_points.size() == to_points.size()
- from_points.size() >= 3
ensures
- returns a point_transform_affine 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 affine
transform that maps points in from_points to points in to_points. If no
affine transform exists which performs this mapping exactly then the one
which minimizes the mean squared error is selected. Additionally, if many
equally good transformations exist, then the transformation with the smallest
squared parameters is selected (i.e. if you wrote the transformation as a
matrix then we say we select the transform with minimum Frobenius norm among
all possible solutions).
!*/
// ----------------------------------------------------------------------------------------
class point_transform
......
......@@ -616,6 +616,36 @@ namespace
}
// ----------------------------------------------------------------------------------------
void test_find_affine_transform()
{
//typedef dlib::vector<double,2> vect;
typedef point vect;
std::vector<vect> from, to;
from.push_back(vect(0,0));
to.push_back(vect(0,1));
from.push_back(vect(0,1));
to.push_back(vect(1,1));
from.push_back(vect(1,1));
to.push_back(vect(1,0));
from.push_back(vect(1,0));
to.push_back(vect(0,0));
point_transform_affine t = find_affine_transform(from,to);
for (unsigned long i = 0; i < from.size(); ++i)
{
dlog << LINFO << "affine transformation error: "<< length(t(from[i])-to[i]);
DLIB_TEST(length(t(from[i])-to[i]) < 1e-14);
}
}
// ----------------------------------------------------------------------------------------
class geometry_tester : public tester
......@@ -632,6 +662,7 @@ namespace
{
geometry_test();
test_border_enumerator();
test_find_affine_transform();
}
} 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