Master commit of OpenFace.

This commit is contained in:
unknown
2016-04-28 15:40:36 -04:00
parent 5346d303ab
commit 57e58a6949
4406 changed files with 1441342 additions and 0 deletions

View File

@@ -0,0 +1,186 @@
// Copyright (C) 2011 Davis E. King (davis@dlib.net)
// License: Boost Software License See LICENSE.txt for the full license.
#ifndef DLIB_BORDER_EnUMERATOR_H_
#define DLIB_BORDER_EnUMERATOR_H_
#include "border_enumerator_abstract.h"
#include "rectangle.h"
namespace dlib
{
// ----------------------------------------------------------------------------------------
class border_enumerator
{
public:
border_enumerator(
)
{
reset();
}
border_enumerator(
const rectangle& rect_,
unsigned long border_size
) :
rect(rect_),
inner_rect(shrink_rect(rect_, border_size))
{
reset();
}
border_enumerator(
const rectangle& rect_,
const rectangle& non_border_region
) :
rect(rect_),
inner_rect(non_border_region.intersect(rect))
{
reset();
}
void reset (
)
{
// make the four rectangles that surround inner_rect and intersect them
// with rect.
bleft = rect.intersect(rectangle(std::numeric_limits<long>::min(),
std::numeric_limits<long>::min(),
inner_rect.left()-1,
std::numeric_limits<long>::max()));
bright = rect.intersect(rectangle(inner_rect.right()+1,
std::numeric_limits<long>::min(),
std::numeric_limits<long>::max(),
std::numeric_limits<long>::max()));
btop = rect.intersect(rectangle(inner_rect.left(),
std::numeric_limits<long>::min(),
inner_rect.right(),
inner_rect.top()-1));
bbottom = rect.intersect(rectangle(inner_rect.left(),
inner_rect.bottom()+1,
inner_rect.right(),
std::numeric_limits<long>::max()));
p = bleft.tl_corner();
p.x() -= 1;
mode = atleft;
}
bool at_start (
) const
{
point temp = bleft.tl_corner();
temp.x() -=1;
return temp == p;
}
bool current_element_valid(
) const
{
return rect.contains(p);
}
bool move_next()
{
if (mode == atleft)
{
if (advance_point(bleft, p))
return true;
mode = attop;
p = btop.tl_corner();
p.x() -= 1;
}
if (mode == attop)
{
if (advance_point(btop, p))
return true;
mode = atright;
p = bright.tl_corner();
p.x() -= 1;
}
if (mode == atright)
{
if (advance_point(bright, p))
return true;
mode = atbottom;
p = bbottom.tl_corner();
p.x() -= 1;
}
if (advance_point(bbottom, p))
return true;
// put p outside rect since there are no more points to enumerate
p = rect.br_corner();
p.x() += 1;
return false;
}
unsigned long size (
) const
{
return rect.area() - inner_rect.area();
}
const point& element (
) const
{
// make sure requires clause is not broken
DLIB_ASSERT(current_element_valid(),
"\t point border_enumerator::element()"
<< "\n\t This function can't be called unless the element is valid."
<< "\n\t this: " << this
);
return p;
}
private:
bool advance_point (
const rectangle& r,
point& p
) const
{
p.x() += 1;
if (p.x() > r.right())
{
p.x() = r.left();
p.y() += 1;
}
return r.contains(p);
}
point p;
rectangle rect;
rectangle inner_rect; // the non-border regions of rect
enum emode
{
atleft,
atright,
atbottom,
attop
};
emode mode;
rectangle btop, bleft, bright, bbottom;
};
// ----------------------------------------------------------------------------------------
}
#endif // DLIB_BORDER_EnUMERATOR_H_

View File

@@ -0,0 +1,126 @@
// Copyright (C) 2011 Davis E. King (davis@dlib.net)
// License: Boost Software License See LICENSE.txt for the full license.
#undef DLIB_BORDER_EnUMERATOR_ABSTRACT_H_
#ifdef DLIB_BORDER_EnUMERATOR_ABSTRACT_H_
#include "rectangle_abstract.h"
namespace dlib
{
// ----------------------------------------------------------------------------------------
class border_enumerator
{
/*!
POINTERS AND REFERENCES TO INTERNAL DATA
All operations on this object other than calling element() invalidate
pointers and references to internal data.
WHAT THIS OBJECT REPRESENTS
This object is an enumerator over the border points of a rectangle.
!*/
public:
border_enumerator(
);
/*!
ensures
- #move_next() == false
(i.e. this object is "empty" and won't enumerate anything)
- current_element_valid() == false
- at_start() == true
- size() == 0
!*/
border_enumerator(
const rectangle& rect,
unsigned long border_size
);
/*!
ensures
- This object will enumerate over the border points which are inside rect
but within border_size of the edge. For example, if border_size == 1
then it enumerates over the single point wide strip of points all around
the interior edge of rect.
- current_element_valid() == false
- at_start() == true
- size() == rect.area() - shrink_rect(rect,border_size).area()
(i.e. the number of points in the border area of rect)
!*/
border_enumerator(
const rectangle& rect,
const rectangle& non_border_region
);
/*!
ensures
- This object will enumerate over all points which are in rect but
not in non_border_region.
- current_element_valid() == false
- at_start() == true
- size() == rect.area() - rect.intersect(non_border_region).area()
!*/
bool at_start (
) const;
/*!
ensures
- returns true if *this represents one position before the first point
(this would also make the current element invalid) else returns false
!*/
void reset (
);
/*!
ensures
- #current_element_valid() == false
- #at_start() == true
!*/
bool current_element_valid(
) const;
/*!
ensures
- returns true if we are currently at a valid element else
returns false
!*/
bool move_next(
);
/*!
ensures
- moves to the next element. i.e. #element() will now
return the next border point.
- the return value will be equal to #current_element_valid()
- #at_start() == false
- returns true if there is another element
- returns false if there are no more elements in the container
!*/
unsigned long size (
) const;
/*!
ensures
- returns the number of border points
!*/
const point& element (
) const;
/*!
requires
- current_element_valid() == true
ensures
- returns the current border point
!*/
};
// ----------------------------------------------------------------------------------------
}
#endif // DLIB_BORDER_EnUMERATOR_ABSTRACT_H_

View File

@@ -0,0 +1,615 @@
// Copyright (C) 2003 Davis E. King (davis@dlib.net)
// License: Boost Software License See LICENSE.txt for the full license.
#ifndef DLIB_POINT_TrANSFORMS_H_
#define DLIB_POINT_TrANSFORMS_H_
#include "point_transforms_abstract.h"
#include "../algs.h"
#include "vector.h"
#include "../matrix.h"
#include "../matrix/matrix_la.h"
#include "../optimization/optimization.h"
#include <vector>
namespace dlib
{
// ----------------------------------------------------------------------------------------
class point_rotator
{
public:
point_rotator (
)
{
sin_angle = 0;
cos_angle = 1;
}
point_rotator (
const double& angle
)
{
sin_angle = std::sin(angle);
cos_angle = std::cos(angle);
}
template <typename T>
const dlib::vector<T,2> operator() (
const dlib::vector<T,2>& p
) const
{
double x = cos_angle*p.x() - sin_angle*p.y();
double y = sin_angle*p.x() + cos_angle*p.y();
return dlib::vector<double,2>(x,y);
}
const matrix<double,2,2> get_m(
) const
{
matrix<double,2,2> temp;
temp = cos_angle, -sin_angle,
sin_angle, cos_angle;
return temp;
}
inline friend void serialize (const point_rotator& item, std::ostream& out)
{
serialize(item.sin_angle, out);
serialize(item.cos_angle, out);
}
inline friend void deserialize (point_rotator& item, std::istream& in)
{
deserialize(item.sin_angle, in);
deserialize(item.cos_angle, in);
}
private:
double sin_angle;
double cos_angle;
};
// ----------------------------------------------------------------------------------------
class point_transform
{
public:
point_transform (
)
{
sin_angle = 0;
cos_angle = 1;
translate.x() = 0;
translate.y() = 0;
}
point_transform (
const double& angle,
const dlib::vector<double,2>& translate_
)
{
sin_angle = std::sin(angle);
cos_angle = std::cos(angle);
translate = translate_;
}
template <typename T>
const dlib::vector<T,2> operator() (
const dlib::vector<T,2>& p
) const
{
double x = cos_angle*p.x() - sin_angle*p.y();
double y = sin_angle*p.x() + cos_angle*p.y();
return dlib::vector<double,2>(x,y) + translate;
}
const matrix<double,2,2> get_m(
) const
{
matrix<double,2,2> temp;
temp = cos_angle, -sin_angle,
sin_angle, cos_angle;
return temp;
}
const dlib::vector<double,2> get_b(
) const { return translate; }
inline friend void serialize (const point_transform& item, std::ostream& out)
{
serialize(item.sin_angle, out);
serialize(item.cos_angle, out);
serialize(item.translate, out);
}
inline friend void deserialize (point_transform& item, std::istream& in)
{
deserialize(item.sin_angle, in);
deserialize(item.cos_angle, in);
deserialize(item.translate, in);
}
private:
double sin_angle;
double cos_angle;
dlib::vector<double,2> translate;
};
// ----------------------------------------------------------------------------------------
class point_transform_affine
{
public:
point_transform_affine (
)
{
m = identity_matrix<double>(2);
b.x() = 0;
b.y() = 0;
}
point_transform_affine (
const matrix<double,2,2>& m_,
const dlib::vector<double,2>& b_
) :m(m_), b(b_)
{
}
const dlib::vector<double,2> operator() (
const dlib::vector<double,2>& p
) const
{
return m*p + b;
}
const matrix<double,2,2>& get_m(
) const { return m; }
const dlib::vector<double,2>& get_b(
) const { return b; }
inline friend void serialize (const point_transform_affine& item, std::ostream& out)
{
serialize(item.m, out);
serialize(item.b, out);
}
inline friend void deserialize (point_transform_affine& item, std::istream& in)
{
deserialize(item.m, in);
deserialize(item.b, in);
}
private:
matrix<double,2,2> m;
dlib::vector<double,2> b;
};
// ----------------------------------------------------------------------------------------
inline point_transform_affine inv (
const point_transform_affine& trans
)
{
matrix<double,2,2> im = inv(trans.get_m());
return point_transform_affine(im, -im*trans.get_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>
point_transform_affine find_similarity_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() >= 2,
"\t point_transform_affine find_similarity_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()
);
// We use the formulas from the paper: Least-squares estimation of transformation
// parameters between two point patterns by Umeyama. They are equations 34 through
// 42.
dlib::vector<double,2> mean_from, mean_to;
double sigma_from = 0, sigma_to = 0;
matrix<double,2,2> cov;
cov = 0;
for (unsigned long i = 0; i < from_points.size(); ++i)
{
mean_from += from_points[i];
mean_to += to_points[i];
}
mean_from /= from_points.size();
mean_to /= from_points.size();
for (unsigned long i = 0; i < from_points.size(); ++i)
{
sigma_from += length_squared(from_points[i] - mean_from);
sigma_to += length_squared(to_points[i] - mean_to);
cov += (to_points[i] - mean_to)*trans(from_points[i] - mean_from);
}
sigma_from /= from_points.size();
sigma_to /= from_points.size();
cov /= from_points.size();
matrix<double,2,2> u, v, s, d;
svd(cov, u,d,v);
s = identity_matrix(cov);
if (det(cov) < 0)
{
if (d(1,1) < d(0,0))
s(1,1) = -1;
else
s(0,0) = -1;
}
matrix<double,2,2> r = u*s*trans(v);
double c = 1;
if (sigma_from != 0)
c = 1.0/sigma_from * trace(d*s);
vector<double,2> t = mean_to - c*r*mean_from;
return point_transform_affine(c*r, t);
}
// ----------------------------------------------------------------------------------------
class point_transform_projective
{
public:
point_transform_projective (
)
{
m = identity_matrix<double>(3);
}
point_transform_projective (
const matrix<double,3,3>& m_
) :m(m_)
{
}
point_transform_projective (
const point_transform_affine& tran
)
{
set_subm(m, 0,0, 2,2) = tran.get_m();
set_subm(m, 0,2, 2,1) = tran.get_b();
m(2,0) = 0;
m(2,1) = 0;
m(2,2) = 1;
}
const dlib::vector<double,2> operator() (
const dlib::vector<double,2>& p
) const
{
dlib::vector<double,3> temp(p);
temp.z() = 1;
temp = m*temp;
if (temp.z() != 0)
temp = temp/temp.z();
return temp;
}
const matrix<double,3,3>& get_m(
) const { return m; }
inline friend void serialize (const point_transform_projective& item, std::ostream& out)
{
serialize(item.m, out);
}
inline friend void deserialize (point_transform_projective& item, std::istream& in)
{
deserialize(item.m, in);
}
private:
matrix<double,3,3> m;
};
// ----------------------------------------------------------------------------------------
inline point_transform_projective inv (
const point_transform_projective& trans
)
{
return point_transform_projective(inv(trans.get_m()));
}
// ----------------------------------------------------------------------------------------
namespace impl_proj
{
inline point_transform_projective find_projective_transform_basic (
const std::vector<dlib::vector<double,2> >& from_points,
const std::vector<dlib::vector<double,2> >& to_points
)
/*!
ensures
- Uses the system of equations approach to finding a projective transform.
This is "Method 3" from Estimating Projective Transformation Matrix by
Zhengyou Zhang.
- It should be emphasized that the find_projective_transform_basic()
routine, which uses the most popular method for finding projective
transformations, doesn't really work well when the minimum error solution
doesn't have zero error. In this case, it can deviate by a large amount
from the proper minimum mean squared error transformation. Therefore,
our overall strategy will be to use the solution from
find_projective_transform_basic() as a starting point for a BFGS based
non-linear optimizer which will optimize the correct mean squared error
criterion.
!*/
{
// make sure requires clause is not broken
DLIB_ASSERT(from_points.size() == to_points.size() &&
from_points.size() >= 4,
"\t point_transform_projective find_projective_transform_basic(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,9,9> accum, u, v;
matrix<double,9,1> w;
matrix<double,2,9> B;
accum = 0;
B = 0;
for (unsigned long i = 0; i < from_points.size(); ++i)
{
dlib::vector<double,3> f = from_points[i];
f.z() = 1;
dlib::vector<double,3> t = to_points[i];
t.z() = 1;
set_subm(B,0,0,1,3) = t.y()*trans(f);
set_subm(B,1,0,1,3) = trans(f);
set_subm(B,0,3,1,3) = -t.x()*trans(f);
set_subm(B,1,6,1,3) = -t.x()*trans(f);
accum += trans(B)*B;
}
svd2(true, false, accum, u, w, v);
long j = index_of_min(w);
return point_transform_projective(reshape(colm(u,j),3,3));
}
// ----------------------------------------------------------------------------------------
struct obj
{
/*!
WHAT THIS OBJECT REPRESENTS
This is the objective function we really want to minimize when looking
for a transformation matrix. That is, we would like the transformed
points to be as close as possible to their "to" points. Here,
closeness is measured using Euclidean distance.
!*/
obj(
const std::vector<dlib::vector<double,2> >& from_points_,
const std::vector<dlib::vector<double,2> >& to_points_
) :
from_points(from_points_) ,
to_points(to_points_)
{}
const std::vector<dlib::vector<double,2> >& from_points;
const std::vector<dlib::vector<double,2> >& to_points;
double operator() (
const matrix<double,9,1>& p
) const
{
point_transform_projective tran(reshape(p,3,3));
double sum = 0;
for (unsigned long i = 0; i < from_points.size(); ++i)
{
sum += length_squared(tran(from_points[i]) - to_points[i]);
}
return sum;
}
};
struct obj_der
{
/*!
WHAT THIS OBJECT REPRESENTS
This is the derivative of obj.
!*/
obj_der(
const std::vector<dlib::vector<double,2> >& from_points_,
const std::vector<dlib::vector<double,2> >& to_points_
) :
from_points(from_points_) ,
to_points(to_points_)
{}
const std::vector<dlib::vector<double,2> >& from_points;
const std::vector<dlib::vector<double,2> >& to_points;
matrix<double,9,1> operator() (
const matrix<double,9,1>& p
) const
{
const matrix<double,3,3> H = reshape(p,3,3);
matrix<double,3,3> grad;
grad = 0;
for (unsigned long i = 0; i < from_points.size(); ++i)
{
dlib::vector<double,3> from, to;
from = from_points[i];
from.z() = 1;
to = to_points[i];
to.z() = 1;
matrix<double,3,1> w = H*from;
const double scale = (w(2) != 0) ? (1.0/w(2)) : (1);
w *= scale;
matrix<double,3,1> residual = (w-to)*2*scale;
grad(0,0) += from.x()*residual(0);
grad(0,1) += from.y()*residual(0);
grad(0,2) += residual(0);
grad(1,0) += from.x()*residual(1);
grad(1,1) += from.y()*residual(1);
grad(1,2) += residual(1);
grad(2,0) += -(from.x()*w(0)*residual(0) + from.x()*w(1)*residual(1));
grad(2,1) += -(from.y()*w(0)*residual(0) + from.y()*w(1)*residual(1));
grad(2,2) += -( w(0)*residual(0) + w(1)*residual(1));
}
return reshape_to_column_vector(grad);
}
};
}
// ----------------------------------------------------------------------------------------
inline point_transform_projective find_projective_transform (
const std::vector<dlib::vector<double,2> >& from_points,
const std::vector<dlib::vector<double,2> >& to_points
)
{
using namespace impl_proj;
// make sure requires clause is not broken
DLIB_ASSERT(from_points.size() == to_points.size() &&
from_points.size() >= 4,
"\t point_transform_projective find_projective_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()
);
// Find a candidate projective transformation. Also, find the best affine
// transform and then compare it with the projective transform estimated using the
// direct SVD method. Use whichever one works better as the starting point for a
// BFGS based optimizer. If the best solution has large mean squared error and is
// also close to affine then find_projective_transform_basic() might give a very
// bad initial guess. So also checking for a good affine transformation can
// produce a much better final result in many cases.
point_transform_projective tran1 = find_projective_transform_basic(from_points, to_points);
point_transform_affine tran2 = find_affine_transform(from_points, to_points);
// check which is best
double error1 = 0;
double error2 = 0;
for (unsigned long i = 0; i < from_points.size(); ++i)
{
error1 += length_squared(tran1(from_points[i])-to_points[i]);
error2 += length_squared(tran2(from_points[i])-to_points[i]);
}
matrix<double,9,1> params;
// Pick the minimum error solution among the two so far.
if (error1 < error2)
params = reshape_to_column_vector(tran1.get_m());
else
params = reshape_to_column_vector(point_transform_projective(tran2).get_m());
// Now refine the transformation matrix so that we can be sure we have
// at least a local minimizer.
obj o(from_points, to_points);
obj_der der(from_points, to_points);
find_min(bfgs_search_strategy(),
objective_delta_stop_strategy(1e-6,100),
o,
der,
params,
0);
return point_transform_projective(reshape(params,3,3));
}
// ----------------------------------------------------------------------------------------
template <typename T>
const dlib::vector<T,2> rotate_point (
const dlib::vector<T,2>& center,
const dlib::vector<T,2>& p,
double angle
)
{
point_rotator rot(angle);
return rot(p-center)+center;
}
// ----------------------------------------------------------------------------------------
inline matrix<double,2,2> rotation_matrix (
double angle
)
{
const double ca = std::cos(angle);
const double sa = std::sin(angle);
matrix<double,2,2> m;
m = ca, -sa,
sa, ca;
return m;
}
// ----------------------------------------------------------------------------------------
}
#endif // DLIB_POINT_TrANSFORMS_H_

View File

@@ -0,0 +1,393 @@
// Copyright (C) 2003 Davis E. King (davis@dlib.net)
// License: Boost Software License See LICENSE.txt for the full license.
#undef DLIB_POINT_TrANSFORMS_ABSTRACT_Hh_
#ifdef DLIB_POINT_TrANSFORMS_ABSTRACT_Hh_
#include "../matrix/matrix_abstract.h"
#include "vector_abstract.h"
#include <vector>
namespace dlib
{
// ----------------------------------------------------------------------------------------
class point_transform_affine
{
/*!
WHAT THIS OBJECT REPRESENTS
This is an object that takes 2D points or vectors and
applies an affine transformation to them.
!*/
public:
point_transform_affine (
);
/*!
ensures
- This object will perform the identity transform. That is, given a point
as input it will return the same point as output.
!*/
point_transform_affine (
const matrix<double,2,2>& m,
const dlib::vector<double,2>& b
);
/*!
ensures
- #get_m() == m
- #get_b() == b
- When (*this)(p) is invoked it will return a point P such that:
- P == m*p + b
!*/
const dlib::vector<double,2> operator() (
const dlib::vector<double,2>& p
) const;
/*!
ensures
- applies the affine transformation defined by this object's constructor
to p and returns the result.
!*/
const matrix<double,2,2>& get_m(
) const;
/*!
ensures
- returns the transformation matrix used by this object.
!*/
const dlib::vector<double,2>& get_b(
) const;
/*!
ensures
- returns the offset vector used by this object.
!*/
};
void serialize (const point_transform_affine& item, std::ostream& out);
void deserialize (point_transform_affine& item, std::istream& in);
/*!
provides serialization support
!*/
// ----------------------------------------------------------------------------------------
point_transform_affine inv (
const point_transform_affine& trans
);
/*!
ensures
- If trans is an invertible transformation then this function returns a new
transformation that is the inverse of trans.
!*/
// ----------------------------------------------------------------------------------------
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).
!*/
// ----------------------------------------------------------------------------------------
template <typename T>
point_transform_affine find_similarity_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() >= 2
ensures
- This function is just like find_affine_transform() except it finds the best
similarity transform instead of a full affine transform. This means that it
optimizes over only the space of rotations, scale changes, and translations.
So for example, if you mapped the 3 vertices of a triangle through a
similarity transform then the output would still be the same triangle.
However, the triangle itself may be larger or smaller, rotated, or at a
different location in the coordinate system. This is not the case for a
general affine transform which can stretch points in ways that cause, for
example, an equilateral triangle to turn into an isosceles triangle.
!*/
// ----------------------------------------------------------------------------------------
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 (
);
/*!
ensures
- This object will perform the identity transform. That is, given a point
as input it will return the same point as output.
!*/
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.
!*/
};
void serialize (const point_transform_projective& item, std::ostream& out);
void deserialize (point_transform_projective& item, std::istream& in);
/*!
provides serialization support
!*/
// ----------------------------------------------------------------------------------------
point_transform_projective inv (
const point_transform_projective& trans
);
/*!
ensures
- If trans is an invertible transformation then this function returns a new
transformation that is the inverse of trans.
!*/
// ----------------------------------------------------------------------------------------
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
{
/*!
WHAT THIS OBJECT REPRESENTS
This is an object that takes 2D points or vectors and
rotates them around the origin by a given angle and then
translates them.
!*/
public:
point_transform (
);
/*!
ensures
- This object will perform the identity transform. That is, given a point
as input it will return the same point as output.
!*/
point_transform (
const double& angle,
const dlib::vector<double,2>& translate
)
/*!
ensures
- When (*this)(p) is invoked it will return a point P such that:
- P is the point p rotated counter-clockwise around the origin
angle radians and then shifted by having translate added to it.
(Note that this is counter clockwise with respect to the normal
coordinate system with positive y going up and positive x going
to the right)
!*/
template <typename T>
const dlib::vector<T,2> operator() (
const dlib::vector<T,2>& p
) const;
/*!
ensures
- rotates p, then translates it and returns the result. The output
of this function is therefore equal to get_m()*p + get_b().
!*/
const matrix<double,2,2> get_m(
) const;
/*!
ensures
- returns the transformation matrix used by this object.
!*/
const dlib::vector<double,2> get_b(
) const;
/*!
ensures
- returns the offset vector used by this object.
!*/
};
void serialize (const point_transform& item, std::ostream& out);
void deserialize (point_transform& item, std::istream& in);
/*!
provides serialization support
!*/
// ----------------------------------------------------------------------------------------
class point_rotator
{
/*!
WHAT THIS OBJECT REPRESENTS
This is an object that takes 2D points or vectors and
rotates them around the origin by a given angle.
!*/
public:
point_rotator (
);
/*!
ensures
- This object will perform the identity transform. That is, given a point
as input it will return the same point as output.
!*/
point_rotator (
const double& angle
);
/*!
ensures
- When (*this)(p) is invoked it will return a point P such that:
- P is the point p rotated counter-clockwise around the origin
angle radians.
(Note that this is counter clockwise with respect to the normal
coordinate system with positive y going up and positive x going
to the right)
!*/
template <typename T>
const dlib::vector<T,2> operator() (
const dlib::vector<T,2>& p
) const;
/*!
ensures
- rotates p and returns the result. The output of this function is
therefore equal to get_m()*p.
!*/
const matrix<double,2,2> get_m(
) const;
/*!
ensures
- returns the transformation matrix used by this object.
!*/
};
void serialize (const point_rotator& item, std::ostream& out);
void deserialize (point_rotator& item, std::istream& in);
/*!
provides serialization support
!*/
// ----------------------------------------------------------------------------------------
template <typename T>
const dlib::vector<T,2> rotate_point (
const dlib::vector<T,2> center,
const dlib::vector<T,2> p,
double angle
);
/*!
ensures
- returns a point P such that:
- P is the point p rotated counter-clockwise around the given
center point by angle radians.
(Note that this is counter clockwise with respect to the normal
coordinate system with positive y going up and positive x going
to the right)
!*/
// ----------------------------------------------------------------------------------------
matrix<double,2,2> rotation_matrix (
double angle
);
/*!
ensures
- returns a rotation matrix which rotates points around the origin in a
counter-clockwise direction by angle radians.
(Note that this is counter clockwise with respect to the normal
coordinate system with positive y going up and positive x going
to the right)
Or in other words, this function returns a matrix M such that, given a
point P, M*P gives a point which is P rotated by angle radians around
the origin in a counter-clockwise direction.
!*/
// ----------------------------------------------------------------------------------------
}
#endif // DLIB_POINT_TrANSFORMS_ABSTRACT_Hh_

View File

@@ -0,0 +1,701 @@
// Copyright (C) 2005 Davis E. King (davis@dlib.net)
// License: Boost Software License See LICENSE.txt for the full license.
#ifndef DLIB_RECTANGLe_
#define DLIB_RECTANGLe_
#include "rectangle_abstract.h"
#include "../algs.h"
#include <algorithm>
#include <iostream>
#include "../serialize.h"
#include "vector.h"
#include "../image_processing/generic_image.h"
namespace dlib
{
// ----------------------------------------------------------------------------------------
class rectangle
{
/*!
INITIAL VALUE
The initial value of this object is defined by its constructor.
CONVENTION
left() == l
top() == t
right() == r
bottom() == b
!*/
public:
rectangle (
long l_,
long t_,
long r_,
long b_
) :
l(l_),
t(t_),
r(r_),
b(b_)
{}
rectangle (
unsigned long w,
unsigned long h
) :
l(0),
t(0),
r(static_cast<long>(w)-1),
b(static_cast<long>(h)-1)
{
DLIB_ASSERT((w > 0 && h > 0) || (w == 0 && h == 0),
"\trectangle(width,height)"
<< "\n\twidth and height must be > 0 or both == 0"
<< "\n\twidth: " << w
<< "\n\theight: " << h
<< "\n\tthis: " << this
);
}
rectangle (
const point& p
) :
l(p.x()),
t(p.y()),
r(p.x()),
b(p.y())
{
}
rectangle (
const point& p1,
const point& p2
)
{
*this = rectangle(p1) + rectangle(p2);
}
template <typename T>
rectangle (
const vector<T,2>& p1,
const vector<T,2>& p2
)
{
*this = rectangle(p1) + rectangle(p2);
}
rectangle (
) :
l(0),
t(0),
r(-1),
b(-1)
{}
long top (
) const { return t; }
long& top (
) { return t; }
void set_top (
long top_
) { t = top_; }
long left (
) const { return l; }
long& left (
) { return l; }
void set_left (
long left_
) { l = left_; }
long right (
) const { return r; }
long& right (
) { return r; }
void set_right (
long right_
) { r = right_; }
long bottom (
) const { return b; }
long& bottom (
) { return b; }
void set_bottom (
long bottom_
) { b = bottom_; }
const point tl_corner (
) const { return point(left(), top()); }
const point bl_corner (
) const { return point(left(), bottom()); }
const point tr_corner (
) const { return point(right(), top()); }
const point br_corner (
) const { return point(right(), bottom()); }
unsigned long width (
) const
{
if (is_empty())
return 0;
else
return r - l + 1;
}
unsigned long height (
) const
{
if (is_empty())
return 0;
else
return b - t + 1;
}
unsigned long area (
) const
{
return width()*height();
}
bool is_empty (
) const { return (t > b || l > r); }
rectangle operator + (
const rectangle& rhs
) const
{
if (rhs.is_empty())
return *this;
else if (is_empty())
return rhs;
return rectangle (
std::min(l,rhs.l),
std::min(t,rhs.t),
std::max(r,rhs.r),
std::max(b,rhs.b)
);
}
rectangle intersect (
const rectangle& rhs
) const
{
return rectangle (
std::max(l,rhs.l),
std::max(t,rhs.t),
std::min(r,rhs.r),
std::min(b,rhs.b)
);
}
bool contains (
const point& p
) const
{
if (p.x() < l || p.x() > r || p.y() < t || p.y() > b)
return false;
return true;
}
bool contains (
long x,
long y
) const
{
if (x < l || x > r || y < t || y > b)
return false;
return true;
}
bool contains (
const rectangle& rect
) const
{
return (rect + *this == *this);
}
rectangle& operator+= (
const point& p
)
{
*this = *this + rectangle(p);
return *this;
}
rectangle& operator+= (
const rectangle& rect
)
{
*this = *this + rect;
return *this;
}
bool operator== (
const rectangle& rect
) const
{
return (l == rect.l) && (t == rect.t) && (r == rect.r) && (b == rect.b);
}
bool operator!= (
const rectangle& rect
) const
{
return !(*this == rect);
}
private:
long l;
long t;
long r;
long b;
};
// ----------------------------------------------------------------------------------------
inline void serialize (
const rectangle& item,
std::ostream& out
)
{
try
{
serialize(item.left(),out);
serialize(item.top(),out);
serialize(item.right(),out);
serialize(item.bottom(),out);
}
catch (serialization_error& e)
{
throw serialization_error(e.info + "\n while serializing an object of type rectangle");
}
}
inline void deserialize (
rectangle& item,
std::istream& in
)
{
try
{
deserialize(item.left(),in);
deserialize(item.top(),in);
deserialize(item.right(),in);
deserialize(item.bottom(),in);
}
catch (serialization_error& e)
{
throw serialization_error(e.info + "\n while deserializing an object of type rectangle");
}
}
inline std::ostream& operator<< (
std::ostream& out,
const rectangle& item
)
{
out << "[(" << item.left() << ", " << item.top() << ") (" << item.right() << ", " << item.bottom() << ")]";
return out;
}
inline std::istream& operator>>(
std::istream& in,
rectangle& item
)
{
// ignore any whitespace
while (in.peek() == ' ' || in.peek() == '\t' || in.peek() == '\r' || in.peek() == '\n')
in.get();
// now eat the leading '[' character
if (in.get() != '[')
{
in.setstate(in.rdstate() | std::ios::failbit);
return in;
}
point p1, p2;
in >> p1;
in >> p2;
item = rectangle(p1) + rectangle(p2);
// ignore any whitespace
while (in.peek() == ' ' || in.peek() == '\t' || in.peek() == '\r' || in.peek() == '\n')
in.get();
// now eat the trailing ']' character
if (in.get() != ']')
{
in.setstate(in.rdstate() | std::ios::failbit);
}
return in;
}
// ----------------------------------------------------------------------------------------
inline const rectangle centered_rect (
long x,
long y,
unsigned long width,
unsigned long height
)
{
rectangle result;
result.set_left ( x - static_cast<long>(width) / 2 );
result.set_top ( y - static_cast<long>(height) / 2 );
result.set_right ( result.left() + width - 1 );
result.set_bottom ( result.top() + height - 1 );
return result;
}
// ----------------------------------------------------------------------------------------
inline rectangle intersect (
const rectangle& a,
const rectangle& b
) { return a.intersect(b); }
// ----------------------------------------------------------------------------------------
inline unsigned long area (
const rectangle& a
) { return a.area(); }
// ----------------------------------------------------------------------------------------
inline point center (
const dlib::rectangle& rect
)
{
point temp(rect.left() + rect.right() + 1,
rect.top() + rect.bottom() + 1);
if (temp.x() < 0)
temp.x() -= 1;
if (temp.y() < 0)
temp.y() -= 1;
return temp/2;
}
// ----------------------------------------------------------------------------------------
inline dlib::vector<double,2> dcenter (
const dlib::rectangle& rect
)
{
dlib::vector<double,2> temp(rect.left() + rect.right(),
rect.top() + rect.bottom());
return temp/2.0;
}
// ----------------------------------------------------------------------------------------
inline long distance_to_rect_edge (
const rectangle& rect,
const point& p
)
{
using std::max;
using std::min;
using std::abs;
const long dist_x = min(abs(p.x()-rect.left()), abs(p.x()-rect.right()));
const long dist_y = min(abs(p.y()-rect.top()), abs(p.y()-rect.bottom()));
if (rect.contains(p))
return min(dist_x,dist_y);
else if (rect.left() <= p.x() && p.x() <= rect.right())
return dist_y;
else if (rect.top() <= p.y() && p.y() <= rect.bottom())
return dist_x;
else
return dist_x + dist_y;
}
// ----------------------------------------------------------------------------------------
inline const point nearest_point (
const rectangle& rect,
const point& p
)
{
point temp(p);
if (temp.x() < rect.left())
temp.x() = rect.left();
else if (temp.x() > rect.right())
temp.x() = rect.right();
if (temp.y() < rect.top())
temp.y() = rect.top();
else if (temp.y() > rect.bottom())
temp.y() = rect.bottom();
return temp;
}
// ----------------------------------------------------------------------------------------
inline const rectangle centered_rect (
const point& p,
unsigned long width,
unsigned long height
)
{
return centered_rect(p.x(),p.y(),width,height);
}
// ----------------------------------------------------------------------------------------
inline const rectangle centered_rect (
const rectangle& rect,
unsigned long width,
unsigned long height
)
{
return centered_rect((rect.left()+rect.right())/2, (rect.top()+rect.bottom())/2, width, height);
}
// ----------------------------------------------------------------------------------------
inline const rectangle shrink_rect (
const rectangle& rect,
long num
)
{
return rectangle(rect.left()+num, rect.top()+num, rect.right()-num, rect.bottom()-num);
}
// ----------------------------------------------------------------------------------------
inline const rectangle grow_rect (
const rectangle& rect,
long num
)
{
return shrink_rect(rect, -num);
}
// ----------------------------------------------------------------------------------------
inline const rectangle shrink_rect (
const rectangle& rect,
long width,
long height
)
{
return rectangle(rect.left()+width, rect.top()+height, rect.right()-width, rect.bottom()-height);
}
// ----------------------------------------------------------------------------------------
inline const rectangle grow_rect (
const rectangle& rect,
long width,
long height
)
{
return shrink_rect(rect, -width, -height);
}
// ----------------------------------------------------------------------------------------
inline const rectangle translate_rect (
const rectangle& rect,
const point& p
)
{
rectangle result;
result.set_top ( rect.top() + p.y() );
result.set_bottom ( rect.bottom() + p.y() );
result.set_left ( rect.left() + p.x() );
result.set_right ( rect.right() + p.x() );
return result;
}
// ----------------------------------------------------------------------------------------
inline const rectangle translate_rect (
const rectangle& rect,
long x,
long y
)
{
rectangle result;
result.set_top ( rect.top() + y );
result.set_bottom ( rect.bottom() + y );
result.set_left ( rect.left() + x );
result.set_right ( rect.right() + x );
return result;
}
// ----------------------------------------------------------------------------------------
inline const rectangle resize_rect (
const rectangle& rect,
unsigned long width,
unsigned long height
)
{
return rectangle(rect.left(),rect.top(),
rect.left()+width-1,
rect.top()+height-1);
}
// ----------------------------------------------------------------------------------------
inline const rectangle resize_rect_width (
const rectangle& rect,
unsigned long width
)
{
return rectangle(rect.left(),rect.top(),
rect.left()+width-1,
rect.bottom());
}
// ----------------------------------------------------------------------------------------
inline const rectangle resize_rect_height (
const rectangle& rect,
unsigned long height
)
{
return rectangle(rect.left(),rect.top(),
rect.right(),
rect.top()+height-1);
}
// ----------------------------------------------------------------------------------------
inline const rectangle move_rect (
const rectangle& rect,
const point& p
)
{
return rectangle(p.x(), p.y(), p.x()+rect.width()-1, p.y()+rect.height()-1);
}
// ----------------------------------------------------------------------------------------
inline const rectangle move_rect (
const rectangle& rect,
long x,
long y
)
{
return rectangle(x, y, x+rect.width()-1, y+rect.height()-1);
}
// ----------------------------------------------------------------------------------------
inline rectangle set_aspect_ratio (
const rectangle& rect,
double ratio
)
{
DLIB_ASSERT(ratio > 0,
"\t rectangle set_aspect_ratio()"
<< "\n\t ratio: " << ratio
);
// aspect ratio is w/h
// we need to find the rectangle that is nearest to rect in area but
// with an aspect ratio of ratio.
// w/h == ratio
// w*h == rect.area()
if (ratio >= 1)
{
const long h = static_cast<long>(std::sqrt(rect.area()/ratio) + 0.5);
const long w = static_cast<long>(h*ratio + 0.5);
return centered_rect(rect, w, h);
}
else
{
const long w = static_cast<long>(std::sqrt(rect.area()*ratio) + 0.5);
const long h = static_cast<long>(w/ratio + 0.5);
return centered_rect(rect, w, h);
}
}
// ----------------------------------------------------------------------------------------
template <
typename T
>
inline const rectangle get_rect (
const T& m
)
{
return rectangle(0, 0, num_columns(m)-1, num_rows(m)-1);
}
// ----------------------------------------------------------------------------------------
inline rectangle operator+ (
const rectangle& r,
const point& p
)
{
return r + rectangle(p);
}
// ----------------------------------------------------------------------------------------
inline rectangle operator+ (
const point& p,
const rectangle& r
)
{
return r + rectangle(p);
}
// ----------------------------------------------------------------------------------------
}
namespace std
{
/*!
Define std::less<rectangle> so that you can use rectangles in the associative containers.
!*/
template<>
struct less<dlib::rectangle> : public binary_function<dlib::rectangle ,dlib::rectangle,bool>
{
inline bool operator() (const dlib::rectangle& a, const dlib::rectangle& b) const
{
if (a.left() < b.left()) return true;
else if (a.left() > b.left()) return false;
else if (a.top() < b.top()) return true;
else if (a.top() > b.top()) return false;
else if (a.right() < b.right()) return true;
else if (a.right() > b.right()) return false;
else if (a.bottom() < b.bottom()) return true;
else if (a.bottom() > b.bottom()) return false;
else return false;
}
};
}
#endif // DLIB_RECTANGLe_

View File

@@ -0,0 +1,781 @@
// Copyright (C) 2005 Davis E. King (davis@dlib.net)
// License: Boost Software License See LICENSE.txt for the full license.
#undef DLIB_RECTANGLe_ABSTRACT_
#ifdef DLIB_RECTANGLe_ABSTRACT_
#include "vector_abstract.h"
#include <iostream>
#include "../serialize.h"
namespace dlib
{
class rectangle
{
/*!
INITIAL VALUE
The initial value of this object is defined by its constructor.
WHAT THIS OBJECT REPRESENTS
This object represents a rectangular region inside a Cartesian
coordinate system. The region is the rectangle with its top
left corner at position (left(),top()) and its bottom right corner
at (right(),bottom()).
Note that the origin of the coordinate system, i.e. (0,0), is located
at the upper left corner. That is, points such as (1,1) or (3,5)
represent locations that are below and to the right of the origin.
Also note that rectangles where top() > bottom() or left() > right()
represent empty rectangles.
!*/
public:
rectangle (
const rectangle& rect
);
/*!
ensures
- #*this represents the same rectangle as rect
!*/
rectangle (
);
/*!
ensures
- #left() == 0
- #top() == 0
- #right() == -1
- #bottom() == -1
- #is_empty() == true
!*/
rectangle (
long left_,
long top_,
long right_,
long bottom_
);
/*!
ensures
- #left() == left_
- #top() == top_
- #right() == right_
- #bottom() == bottom_
!*/
rectangle (
unsigned long width_,
unsigned long height_
);
/*!
requires
- (width_ > 0 && height_ > 0) || (width_ == 0 && height_ == 0)
ensures
- #left() == 0
- #top() == 0
- #width() == width_
- #height() == height_
!*/
rectangle (
const point& p
);
/*!
ensures
- #left() == p.x()
- #top() == p.y()
- #right() == p.x()
- #bottom() == p.y()
!*/
template <typename T>
rectangle (
const vector<T,2>& p1,
const vector<T,2>& p2
);
/*!
ensures
- #*this == rectangle(p1) + rectangle(p2)
!*/
long left (
) const;
/*!
ensures
- returns the x coordinate for the left side of this rectangle
!*/
long& left (
);
/*!
ensures
- returns a non-const reference to the x coordinate for the left side
of this rectangle
!*/
void set_left (
long left_
);
/*!
ensures
- #left() == left_
!*/
long top (
) const;
/*!
ensures
- returns the y coordinate for the top of this rectangle
!*/
long& top (
);
/*!
ensures
- returns a non-const reference to the y coordinate for the
top of this rectangle
!*/
void set_top (
long top_
);
/*!
ensures
- #top() == top_
!*/
long right (
) const;
/*!
ensures
- returns the x coordinate for the right side of this rectangle
!*/
long& right (
);
/*!
ensures
- returns a non-const reference to the x coordinate for the right
side of this rectangle
!*/
void set_right (
long right_
);
/*!
ensures
- #right() == right_
!*/
long bottom (
) const;
/*!
ensures
- returns the y coordinate for the bottom of this rectangle
!*/
long& bottom (
);
/*!
ensures
- returns a non-const reference to the y coordinate for the bottom
of this rectangle
!*/
void set_bottom (
long bottom_
);
/*!
ensures
- #bottom() == bottom_
!*/
const point tl_corner (
) const;
/*!
ensures
- returns point(left(), top())
(i.e. returns the top left corner point for this rectangle)
!*/
const point bl_corner (
) const;
/*!
ensures
- returns point(left(), bottom())
(i.e. returns the bottom left corner point for this rectangle)
!*/
const point tr_corner (
) const;
/*!
ensures
- returns point(right(), top())
(i.e. returns the top right corner point for this rectangle)
!*/
const point br_corner (
) const;
/*!
ensures
- returns point(right(), bottom())
(i.e. returns the bottom right corner point for this rectangle)
!*/
bool is_empty (
) const;
/*!
ensures
- if (top() > bottom() || left() > right()) then
- returns true
- else
- returns false
!*/
unsigned long width (
) const;
/*!
ensures
- if (is_empty()) then
- returns 0
- else
- returns the width of this rectangle.
(i.e. right() - left() + 1)
!*/
unsigned long height (
) const;
/*!
ensures
- if (is_empty()) then
- returns 0
- else
- returns the height of this rectangle.
(i.e. bottom() - top() + 1)
!*/
unsigned long area (
) const;
/*!
ensures
- returns width()*height()
!*/
rectangle operator + (
const rectangle& rhs
) const;
/*!
ensures
- if (rhs.is_empty() == false && this->is_empty() == false) then
- returns the smallest rectangle that contains both *this and
rhs.
- if (rhs.is_empty() == true && this->is_empty() == false) then
- returns *this
- if (rhs.is_empty() == false && this->is_empty() == true) then
- returns rhs
- if (rhs.is_empty() == true && this->is_empty() == true) then
- returns a rectangle that has is_empty() == true
!*/
rectangle intersect (
const rectangle& rhs
) const;
/*!
ensures
- if (there is a region of intersection between *this and rhs) then
- returns a rectangle that represents the intersection of *this
and rhs.
- else
- returns a rectangle where is_empty() == true
!*/
bool contains (
long x,
long y
) const;
/*!
ensures
- if (the point (x,y) is contained in this rectangle) then
- returns true
- else
- returns false
!*/
bool contains (
const point& p
) const;
/*!
ensures
- if (the point (p.x(),p.y()) is contained in this rectangle) then
- returns true
- else
- returns false
!*/
bool contains (
const rectangle& rect
) const;
/*!
ensures
- if (rect + *this == *this) then
- returns true
(i.e. returns true if *this contains the given rectangle)
- else
- returns false
!*/
rectangle& operator= (
const rectangle& rect
);
/*!
ensures
- #*this represents the same rectangle as rect
- returns #*this
!*/
rectangle& operator+= (
const rectangle& rect
);
/*!
ensures
- #*this == *this + rect
- returns #*this
!*/
bool operator== (
const rectangle& rect
) const;
/*!
ensures
- if (top() == rect.top() && left() == rect.left() &&
right() == rect.right() && bottom() == rect.bottom()) then
- returns true
- else
- returns false
!*/
bool operator!= (
const rectangle& rect
) const;
/*!
ensures
- returns !(*this == rect)
!*/
};
// ----------------------------------------------------------------------------------------
void serialize (
const rectangle& item,
std::ostream& out
);
/*!
provides serialization support
!*/
void deserialize (
rectangle& item,
std::istream& in
);
/*!
provides deserialization support
!*/
std::ostream& operator<< (
std::ostream& out,
const rectangle& item
);
/*!
ensures
- writes item to out in the form "[(left, top) (right, bottom)]"
!*/
std::istream& operator>>(
std::istream& in,
rectangle& item
);
/*!
ensures
- reads a rectangle from the input stream in and stores it in #item.
The data in the input stream should be of the form [(left, top) (right, bottom)]
!*/
// ----------------------------------------------------------------------------------------
point center (
const dlib::rectangle& rect
);
/*!
ensures
- returns the center of the given rectangle
!*/
// ----------------------------------------------------------------------------------------
dlib::vector<double,2> dcenter (
const dlib::rectangle& rect
);
/*!
ensures
- returns the center of the given rectangle using a real valued vector.
!*/
// ----------------------------------------------------------------------------------------
inline const rectangle centered_rect (
const point& p,
unsigned long width,
unsigned long height
);
/*!
ensures
- returns a rectangle R such that:
- center(R) == p
- if (width == 0 || height == 0)
- R.width() == 0
- R.height() == 0
- else
- R.width() == width
- R.height() == height
- R.tl_corner() == point(p.x()-width/2, p.y()-height/2)
!*/
// ----------------------------------------------------------------------------------------
const rectangle centered_rect (
long x,
long y,
unsigned long width,
unsigned long height
);
/*!
ensures
- returns a rectangle R such that:
- center(R) == p
- if (width == 0 || height == 0)
- R.width() == 0
- R.height() == 0
- else
- R.width() == width
- R.height() == height
- R.tl_corner() == point(x-width/2, y-height/2)
!*/
// ----------------------------------------------------------------------------------------
inline const rectangle centered_rect (
const rectangle& rect,
unsigned long width,
unsigned long height
);
/*!
ensures
- returns centered_rect( (rect.tl_corner() + rect.br_corner())/2, width, height)
(i.e. returns a rectangle centered on rect but with the given width
and height)
!*/
// ----------------------------------------------------------------------------------------
inline rectangle set_aspect_ratio (
const rectangle& rect,
double ratio
);
/*!
requires
- ratio > 0
ensures
- This function reshapes the given rectangle so that it has the given aspect
ratio. In particular, this means we return a rectangle R such that the
following equations are as true as possible:
- R.width()/R.height() == ratio
- R.area() == rect.area()
- center(rect) == center(R)
!*/
// ----------------------------------------------------------------------------------------
inline rectangle intersect (
const rectangle& a,
const rectangle& b
);
/*!
ensures
- returns a.intersect(b)
(i.e. returns a rectangle representing the intersection of a and b)
!*/
// ----------------------------------------------------------------------------------------
inline unsigned long area (
const rectangle& a
);
/*!
ensures
- returns a.area()
!*/
// ----------------------------------------------------------------------------------------
inline const rectangle shrink_rect (
const rectangle& rect,
long num
);
/*!
ensures
- returns rectangle(rect.left()+num, rect.top()+num, rect.right()-num, rect.bottom()-num)
(i.e. shrinks the given rectangle by shrinking its border by num)
!*/
// ----------------------------------------------------------------------------------------
inline const rectangle grow_rect (
const rectangle& rect,
long num
);
/*!
ensures
- return shrink_rect(rect, -num)
(i.e. grows the given rectangle by expanding its border by num)
!*/
// ----------------------------------------------------------------------------------------
inline const rectangle shrink_rect (
const rectangle& rect,
long width,
long height
);
/*!
ensures
- returns rectangle(rect.left()+width, rect.top()+height, rect.right()-width, rect.bottom()-height)
(i.e. shrinks the given rectangle by shrinking its left and right borders by width
and its top and bottom borders by height. )
!*/
// ----------------------------------------------------------------------------------------
inline const rectangle grow_rect (
const rectangle& rect,
long width,
long height
);
/*!
ensures
- return shrink_rect(rect, -width, -height)
(i.e. grows the given rectangle by expanding its border)
!*/
// ----------------------------------------------------------------------------------------
const rectangle translate_rect (
const rectangle& rect,
const point& p
);
/*!
ensures
- returns a rectangle R such that:
- R.left() == rect.left() + p.x()
- R.right() == rect.right() + p.x()
- R.top() == rect.top() + p.y()
- R.bottom() == rect.bottom() + p.y()
!*/
// ----------------------------------------------------------------------------------------
const rectangle translate_rect (
const rectangle& rect,
long x,
long y
);
/*!
ensures
- returns a rectangle R such that:
- R.left() == rect.left() + x
- R.right() == rect.right() + x
- R.top() == rect.top() + y
- R.bottom() == rect.bottom() + y
!*/
// ----------------------------------------------------------------------------------------
const rectangle resize_rect (
const rectangle& rect,
unsigned long width,
unsigned long height
);
/*!
ensures
- returns a rectangle R such that:
- if (width == 0 || height == 0)
- R.width() == 0
- R.height() == 0
- else
- R.width() == width
- R.height() == height
- R.left() == rect.left()
- R.top() == rect.top()
!*/
// ----------------------------------------------------------------------------------------
const rectangle resize_rect_width (
const rectangle& rect,
unsigned long width
);
/*!
ensures
- returns a rectangle R such that:
- R.width() == width
- R.left() == rect.left()
- R.top() == rect.top()
- R.bottom() == rect.bottom()
!*/
// ----------------------------------------------------------------------------------------
const rectangle resize_rect_height (
const rectangle& rect,
unsigned long height
);
/*!
ensures
- returns a rectangle R such that:
- R.height() == height
- R.left() == rect.left()
- R.top() == rect.top()
- R.right() == rect.right()
!*/
// ----------------------------------------------------------------------------------------
const rectangle move_rect (
const rectangle& rect,
const point& p
);
/*!
ensures
- returns a rectangle R such that:
- R.width() == rect.width()
- R.height() == rect.height()
- R.left() == p.x()
- R.top() == p.y()
!*/
// ----------------------------------------------------------------------------------------
const rectangle move_rect (
const rectangle& rect,
long x,
long y
);
/*!
ensures
- returns a rectangle R such that:
- R.width() == rect.width()
- R.height() == rect.height()
- R.left() == x
- R.top() == y
!*/
// ----------------------------------------------------------------------------------------
inline const point nearest_point (
const rectangle& rect,
const point& p
);
/*!
ensures
- if (rect.contains(p)) then
- returns p
- else
- returns the point in rect that is closest to p
!*/
// ----------------------------------------------------------------------------------------
inline long distance_to_rect_edge (
const rectangle& rect,
const point& p
);
/*!
ensures
- returns the Manhattan distance between the edge of rect and p.
!*/
// ----------------------------------------------------------------------------------------
template <
typename T
>
const rectangle get_rect (
const T& m
);
/*!
requires
- It must be possible to determine the number of "rows" and "columns" in m.
Either by calling num_rows(m) and num_columns(m) or by calling m.nr() and
m.nc() to obtain the number of rows and columns respectively. Moreover,
these routines should return longs.
ensures
- returns rectangle(0, 0, num_columns(m)-1, num_rows(m)-1)
(i.e. assuming T represents some kind of rectangular grid, such as
the dlib::matrix or dlib::array2d objects, this function returns the
bounding rectangle for that gridded object.)
!*/
// ----------------------------------------------------------------------------------------
inline rectangle operator+ (
const rectangle& r,
const point& p
);
/*!
ensures
- returns r + rectangle(p)
(i.e. returns the rectangle that contains both r and p)
!*/
// ----------------------------------------------------------------------------------------
inline rectangle operator+ (
const point& p,
const rectangle& r
);
/*!
ensures
- returns r + rectangle(p)
(i.e. returns the rectangle that contains both r and p)
!*/
// ----------------------------------------------------------------------------------------
}
namespace std
{
/*!
Define std::less<rectangle> so that you can use rectangles in the associative containers.
!*/
template<>
struct less<dlib::rectangle> : public binary_function<dlib::rectangle,dlib::rectangle,bool>
{
inline bool operator() (const dlib::rectangle& a, const dlib::rectangle& b) const
{
if (a.left() < b.left()) return true;
else if (a.left() > b.left()) return false;
else if (a.top() < b.top()) return true;
else if (a.top() > b.top()) return false;
else if (a.right() < b.right()) return true;
else if (a.right() > b.right()) return false;
else if (a.bottom() < b.bottom()) return true;
else if (a.bottom() > b.bottom()) return false;
else return false;
}
};
}
#endif // DLIB_RECTANGLe_ABSTRACT_

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,476 @@
// Copyright (C) 2003 Davis E. King (davis@dlib.net)
// License: Boost Software License See LICENSE.txt for the full license.
#undef DLIB_VECTOR_ABSTRACT_
#ifdef DLIB_VECTOR_ABSTRACT_
#include "../serialize.h"
#include <functional>
#include <iostream>
#include "../matrix/matrix_abstract.h"
namespace dlib
{
template <
typename T,
long NR = 3
>
class vector : public matrix<T,NR,1>
{
/*!
REQUIREMENTS ON T
T should be some object that provides an interface that is
compatible with double, float, int, long and the like.
REQUIREMENTS ON NR
NR == 3 || NR == 2
INITIAL VALUE
x() == 0
y() == 0
z() == 0
WHAT THIS OBJECT REPRESENTS
This object represents a three dimensional vector. If NR == 2 then
this object is limited to representing points on the XY plane where
Z is set to 0.
Also note that this object performs the appropriate integer and
floating point conversions and promotions when vectors of mixed
type are used together. For example:
vector<int,3> vi;
vector<double,2> vd;
vd + vi == a vector<double,3> object type since that is what
is needed to contain the result of vi+vd without
any loss of information.
!*/
public:
typedef T type;
vector (
);
/*!
ensures
- #*this has been properly initialized
!*/
vector (
const T _x,
const T _y,
const T _z
);
/*!
requires
- NR == 3
ensures
- #x() == _x
- #y() == _y
- #z() == _z
!*/
vector (
const T _x,
const T _y
);
/*!
requires
- NR == 2
ensures
- #x() == _x
- #y() == _y
- #z() == 0
!*/
template <typename U, long NRv>
vector (
const vector<U,NRv>& v
);
/*!
ensures
- Initializes *this with the contents of v and does any rounding if necessary and also
takes care of converting between 2 and 3 dimensional vectors.
- if (U is a real valued type like float or double and T is an integral type like long) then
- if (NR == 3) then
- #x() == floor(v.x() + 0.5)
- #y() == floor(v.y() + 0.5)
- #z() == floor(v.z() + 0.5)
- else // NR == 2
- #x() == floor(v.x() + 0.5)
- #y() == floor(v.y() + 0.5)
- #z() == 0
- else
- if (NR == 3) then
- #x() == v.x()
- #y() == v.y()
- #z() == v.z()
- else // NR == 2
- #x() == v.x()
- #y() == v.y()
- #z() == 0
!*/
template <typename EXP>
vector (
const matrix_exp<EXP>& m
);
/*!
requires
- m.size() == NR
- m.nr() == 1 || m.nc() == 1 (i.e. m must be a row or column matrix)
ensures
- Initializes *this with the contents of m and does any rounding if necessary and also
takes care of converting between 2 and 3 dimensional vectors.
- if (m contains real valued values like float or double and T is an integral type like long) then
- #x() == floor(m(0) + 0.5)
- #y() == floor(m(1) + 0.5)
- if (NR == 3) then
- #z() == floor(m(2) + 0.5)
- else
- #z() == 0
- else
- #x() == m(0)
- #y() == m(1)
- if (NR == 3) then
- #z() == m(2)
- else
- #z() == 0
!*/
~vector (
);
/*!
ensures
- all resources associated with *this have been released
!*/
double length(
) const;
/*!
ensures
- returns the length of the vector
!*/
T& x (
);
/*!
ensures
- returns a reference to the x component of the vector
!*/
T& y (
);
/*!
ensures
- returns a reference to the y component of the vector
!*/
T& z (
);
/*!
requires
- NR == 3 (this function actually doesn't exist when NR != 3)
ensures
- returns a reference to the z component of the vector
!*/
const T& x (
) const;
/*!
ensures
- returns a const reference to the x component of the vector
!*/
const T& y (
) const;
/*!
ensures
- returns a const reference to the y component of the vector
!*/
const T& z (
) const;
/*!
ensures
- if (NR == 3) then
- returns a const reference to the z component of the vector
- else
- return 0
(there isn't really a z in this case so we just return 0)
!*/
T dot (
const vector& rhs
) const;
/*!
ensures
- returns the result of the dot product between *this and rhs
!*/
vector<T,3> cross (
const vector& rhs
) const;
/*!
ensures
- returns the result of the cross product between *this and rhs
!*/
vector<double,NR> normalize (
) const;
/*!
ensures
- returns a vector with length() == 1 and in the same direction as *this
!*/
vector operator+ (
const vector& rhs
) const;
/*!
ensures
- returns the result of adding *this to rhs
!*/
vector operator- (
const vector& rhs
) const;
/*!
ensures
- returns the result of subtracting rhs from *this
!*/
vector operator- (
) const;
/*!
ensures
- returns -1*(*this)
!*/
vector operator/ (
const T rhs
) const;
/*!
ensures
- returns the result of dividing *this by rhs
!*/
vector& operator= (
const vector& rhs
);
/*!
ensures
- #x() == rhs.x()
- #y() == rhs.y()
- #z() == rhs.z()
- returns #*this
!*/
vector& operator += (
const vector& rhs
);
/*!
ensures
- #*this == *this + rhs
- returns #*this
!*/
vector& operator -= (
const vector& rhs
);
/*!
ensures
- #*this == *this - rhs
- returns #*this
!*/
vector& operator *= (
const T rhs
);
/*!
ensures
- #*this == *this * rhs
- returns #*this
!*/
vector& operator /= (
const T rhs
);
/*!
ensures
- #*this == *this / rhs
- returns #*this
!*/
template <typename U, long NR2>
bool operator== (
const vector<U,NR2>& rhs
) const;
/*!
ensures
- if (x() == rhs.x() && y() == rhs.y() && z() == rhs.z()) then
- returns true
- else
- returns false
!*/
template <typename U, long NR2>
bool operator!= (
const vector<U,NR2>& rhs
) const;
/*!
ensures
- returns !((*this) == rhs)
!*/
void swap (
vector& item
);
/*!
ensures
- swaps *this and item
!*/
};
// ----------------------------------------------------------------------------------------
template<typename T, typename U, long NR>
vector operator* (
const vector<T,NR> & lhs,
const U rhs
);
/*!
ensures
- returns the result of multiplying the scalar rhs by lhs
!*/
template<typename T, typename U, long NR>
vector operator* (
const U lhs,
const vector<T,NR> & rhs
);
/*!
ensures
- returns the result of multiplying the scalar lhs by rhs
!*/
template<typename T, long NR>
inline void swap (
vector<T,NR> & a,
vector<T,NR> & b
) { a.swap(b); }
/*!
provides a global swap function
!*/
template<typename T, long NR>
void serialize (
const vector<T,NR>& item,
std::ostream& out
);
/*!
provides serialization support
!*/
template<typename T, long NR>
void deserialize (
vector<T,NR>& item,
std::istream& in
);
/*!
provides deserialization support
!*/
template<typename T>
std::ostream& operator<< (
std::ostream& out,
const vector<T,3>& item
);
/*!
ensures
- writes item to out in the form "(x, y, z)"
!*/
template<typename T>
std::istream& operator>>(
std::istream& in,
vector<T,3>& item
);
/*!
ensures
- reads a vector from the input stream in and stores it in #item.
The data in the input stream should be of the form (x, y, z)
!*/
template<typename T>
std::ostream& operator<< (
std::ostream& out,
const vector<T,2>& item
);
/*!
ensures
- writes item to out in the form "(x, y)"
!*/
template<typename T>
std::istream& operator>>(
std::istream& in,
vector<T,2>& item
);
/*!
ensures
- reads a vector from the input stream in and stores it in #item.
The data in the input stream should be of the form (x, y)
!*/
// ----------------------------------------------------------------------------------------
/*!A point
This is just a typedef of the vector object.
!*/
typedef vector<long,2> point;
// ----------------------------------------------------------------------------------------
}
namespace std
{
/*!
Define std::less<vector<T,3> > so that you can use vectors in the associative containers.
!*/
template<typename T>
struct less<dlib::vector<T,3> > : public binary_function<dlib::vector<T,3> ,dlib::vector<T,3> ,bool>
{
inline bool operator() (const dlib::vector<T,3> & a, const dlib::vector<T,3> & b) const
{
if (a.x() < b.x()) return true;
else if (a.x() > b.x()) return false;
else if (a.y() < b.y()) return true;
else if (a.y() > b.y()) return false;
else if (a.z() < b.z()) return true;
else if (a.z() > b.z()) return false;
else return false;
}
};
/*!
Define std::less<vector<T,2> > so that you can use vector<T,2>s in the associative containers.
!*/
template<typename T>
struct less<dlib::vector<T,2> > : public binary_function<dlib::vector<T,2> ,dlib::vector<T,2> ,bool>
{
inline bool operator() (const dlib::vector<T,2> & a, const dlib::vector<T,2> & b) const
{
if (a.x() < b.x()) return true;
else if (a.x() > b.x()) return false;
else if (a.y() < b.y()) return true;
else if (a.y() > b.y()) return false;
else return false;
}
};
}
#endif // DLIB_VECTOR_ABSTRACT_