Added unit tests and fixed a few issues.

This commit is contained in:
Davis King 2011-10-10 21:07:57 -04:00
parent 4b6f44b866
commit b9ce6dd0a7
2 changed files with 178 additions and 87 deletions

View File

@ -15,12 +15,22 @@ namespace dlib
template <typename M1, typename M2, bool flip_m2 = false>
struct op_conv
{
op_conv( const M1& m1_, const M2& m2_) : m1(m1_),m2(m2_)
op_conv( const M1& m1_, const M2& m2_) :
m1(m1_),
m2(m2_),
nr_(m1.nr()+m2.nr()-1),
nc_(m1.nc()+m2.nc()-1)
{
if (nr_ < 0 || m1.size() == 0 || m2.size() == 0)
nr_ = 0;
if (nc_ < 0 || m1.size() == 0 || m2.size() == 0)
nc_ = 0;
}
const M1& m1;
const M2& m2;
long nr_;
long nc_;
const static long cost = (M1::cost+M2::cost)*10;
const static long NR = (M1::NR*M2::NR==0) ? (0) : (M1::NR+M2::NR-1);
@ -54,8 +64,8 @@ namespace dlib
return temp;
}
long nr () const { return m1.nr()+m2.nr()-1; }
long nc () const { return m1.nc()+m2.nc()-1; }
long nr () const { return nr_; }
long nc () const { return nc_; }
template <typename U> bool aliases ( const matrix_exp<U>& item) const { return m1.aliases(item) || m2.aliases(item); }
template <typename U> bool destructively_aliases ( const matrix_exp<U>& item) const { return m1.aliases(item) || m2.aliases(item); }
@ -70,17 +80,6 @@ namespace dlib
const matrix_exp<M1>& m1,
const matrix_exp<M2>& m2
)
/*!
requires
- m1 and m2 both contain elements of the same type
ensures
- returns a matrix R such that:
- R is the convolution of m1 with m2. In particular, this function is
equivalent to performing the following in matlab: R = conv2(m1,m2).
- R::type == the same type that was in m1 and m2.
- R.nr() == m1.nr()+m2.nr()-1
- R.nc() == m1.nc()+m2.nc()-1
!*/
{
COMPILE_TIME_ASSERT((is_same_type<typename M1::type,typename M2::type>::value == true));
@ -96,17 +95,6 @@ namespace dlib
const matrix_exp<M1>& m1,
const matrix_exp<M2>& m2
)
/*!
requires
- m1 and m2 both contain elements of the same type
ensures
- returns a matrix R such that:
- R is the cross-correlation of m1 with m2. In particular, this
function returns conv(m1,flip(m2)).
- R::type == the same type that was in m1 and m2.
- R.nr() == m1.nr()+m2.nr()-1
- R.nc() == m1.nc()+m2.nc()-1
!*/
{
COMPILE_TIME_ASSERT((is_same_type<typename M1::type,typename M2::type>::value == true));
@ -120,12 +108,18 @@ namespace dlib
template <typename M1, typename M2, bool flip_m2 = false>
struct op_conv_same
{
op_conv_same( const M1& m1_, const M2& m2_) : m1(m1_),m2(m2_)
op_conv_same( const M1& m1_, const M2& m2_) : m1(m1_),m2(m2_),nr_(m1.nr()),nc_(m1.nc())
{
if (m1.size() == 0 || m2.size() == 0)
nr_ = 0;
if (m1.size() == 0 || m2.size() == 0)
nc_ = 0;
}
const M1& m1;
const M2& m2;
long nr_;
long nc_;
const static long cost = (M1::cost+M2::cost)*10;
const static long NR = M1::NR;
@ -162,8 +156,8 @@ namespace dlib
return temp;
}
long nr () const { return m1.nr(); }
long nc () const { return m1.nc(); }
long nr () const { return nr_; }
long nc () const { return nc_; }
template <typename U> bool aliases ( const matrix_exp<U>& item) const { return m1.aliases(item) || m2.aliases(item); }
template <typename U> bool destructively_aliases ( const matrix_exp<U>& item) const { return m1.aliases(item) || m2.aliases(item); }
@ -178,20 +172,6 @@ namespace dlib
const matrix_exp<M1>& m1,
const matrix_exp<M2>& m2
)
/*!
requires
- m1 and m2 both contain elements of the same type
ensures
- returns a matrix R such that:
- R is the convolution of m1 with m2. In particular, this function is
equivalent to performing the following in matlab: R = conv2(m1,m2,'same').
In particular, this means the result will have the same dimensions as m1 and will
contain the central part of the full convolution. This means conv_same(m1,m2) is
equivalent to subm(conv(m1,m2), m2.nr()/2, m2.nc()/2, m1.nr(), m1.nc()).
- R::type == the same type that was in m1 and m2.
- R.nr() == m1.nr()
- R.nc() == m1.nc()
!*/
{
COMPILE_TIME_ASSERT((is_same_type<typename M1::type,typename M2::type>::value == true));
@ -207,17 +187,6 @@ namespace dlib
const matrix_exp<M1>& m1,
const matrix_exp<M2>& m2
)
/*!
requires
- m1 and m2 both contain elements of the same type
ensures
- returns a matrix R such that:
- R is the cross-correlation of m1 with m2. In particular, this
function returns conv_same(m1,flip(m2)).
- R::type == the same type that was in m1 and m2.
- R.nr() == m1.nr()
- R.nc() == m1.nc()
!*/
{
COMPILE_TIME_ASSERT((is_same_type<typename M1::type,typename M2::type>::value == true));
@ -236,9 +205,9 @@ namespace dlib
nr_(m1.nr()-m2.nr()+1),
nc_(m1.nc()-m2.nc()+1)
{
if (nr_ < 0)
if (nr_ < 0 || nc_ <= 0 || m1.size() == 0 || m2.size() == 0)
nr_ = 0;
if (nc_ < 0)
if (nc_ < 0 || nr_ <= 0 || m1.size() == 0 || m2.size() == 0)
nc_ = 0;
}
@ -298,23 +267,6 @@ namespace dlib
const matrix_exp<M1>& m1,
const matrix_exp<M2>& m2
)
/*!
requires
- m1 and m2 both contain elements of the same type
ensures
- returns a matrix R such that:
- R is the convolution of m1 with m2. In particular, this function is
equivalent to performing the following in matlab: R = conv2(m1,m2,'valid').
In particular, this means only elements of the convolution which don't require
zero padding are included in the result.
- R::type == the same type that was in m1 and m2.
- if (m1 has larger dimensions than m2) then
- R.nr() == m1.nr()-m2.nr()+1
- R.nc() == m1.nc()-m2.nc()+1
- else
- R.nr() == 0
- R.nc() == 0
!*/
{
COMPILE_TIME_ASSERT((is_same_type<typename M1::type,typename M2::type>::value == true));
@ -330,21 +282,6 @@ namespace dlib
const matrix_exp<M1>& m1,
const matrix_exp<M2>& m2
)
/*!
requires
- m1 and m2 both contain elements of the same type
ensures
- returns a matrix R such that:
- R is the cross-correlation of m1 with m2. In particular, this
function returns conv_valid(m1,flip(m2)).
- R::type == the same type that was in m1 and m2.
- if (m1 has larger dimensions than m2) then
- R.nr() == m1.nr()-m2.nr()+1
- R.nc() == m1.nc()-m2.nc()+1
- else
- R.nr() == 0
- R.nc() == 0
!*/
{
COMPILE_TIME_ASSERT((is_same_type<typename M1::type,typename M2::type>::value == true));

View File

@ -611,6 +611,157 @@ namespace
template <
long D1,
long D2,
long D3,
long D4
>
void test_conv()
{
dlog << LINFO << D1 << " " << D2 << " " << D3 << " " << D4;
matrix<int,D1,D1> a(1,1);
matrix<int,D2,D2> b(2,2);
matrix<int,D3,D3> c(3,3);
matrix<int,D4,D1> d(4,1);
a = 4;
b = 1,2,
3,4;
c = 1,2,3,
4,5,6,
7,8,9;
d = 1,
2,
3,
4;
matrix<int> temp(4,4), temp2;
temp = 1, 4, 7, 6,
7, 23, 33, 24,
19, 53, 63, 42,
21, 52, 59, 36;
DLIB_TEST(conv(b,c) == temp);
DLIB_TEST(conv(c,b) == temp);
DLIB_TEST(xcorr(c,flip(b)) == temp);
temp.set_size(2,2);
temp = 23, 33,
53, 63;
DLIB_TEST(conv_same(b,c) == temp);
DLIB_TEST(xcorr_same(b,flip(c)) == temp);
temp2.set_size(2,2);
temp2 = 63, 53,
33, 23;
DLIB_TEST(flip(temp) == temp2);
DLIB_TEST(flip(temp) == fliplr(flipud(temp)));
DLIB_TEST(conv_valid(b,c).nr() == 0);
DLIB_TEST(conv_valid(b,c).nc() == 0);
DLIB_TEST(conv_valid(c,b) == temp);
DLIB_TEST(xcorr_valid(c,flip(b)) == temp);
temp.set_size(1,1);
temp = 16;
DLIB_TEST(conv(a,a) == temp);
DLIB_TEST(conv_same(a,a) == temp);
DLIB_TEST(conv_valid(a,a) == temp);
DLIB_TEST(xcorr(a,a) == temp);
DLIB_TEST(xcorr_same(a,a) == temp);
DLIB_TEST(xcorr_valid(a,a) == temp);
temp.set_size(0,0);
DLIB_TEST(conv(temp,temp).nr() == 0);
DLIB_TEST(conv(temp,temp).nc() == 0);
DLIB_TEST(conv_same(temp,temp).nr() == 0);
DLIB_TEST(conv_same(temp,temp).nc() == 0);
DLIB_TEST_MSG(conv_valid(temp,temp).nr() == 0, conv_valid(temp,temp).nr());
DLIB_TEST(conv_valid(temp,temp).nc() == 0);
DLIB_TEST(conv(c,temp).nr() == 0);
DLIB_TEST(conv(c,temp).nc() == 0);
DLIB_TEST(conv_same(c,temp).nr() == 0);
DLIB_TEST(conv_same(c,temp).nc() == 0);
DLIB_TEST(conv_valid(c,temp).nr() == 0);
DLIB_TEST(conv_valid(c,temp).nc() == 0);
DLIB_TEST(conv(temp,c).nr() == 0);
DLIB_TEST(conv(temp,c).nc() == 0);
DLIB_TEST(conv_same(temp,c).nr() == 0);
DLIB_TEST(conv_same(temp,c).nc() == 0);
DLIB_TEST(conv_valid(temp,c).nr() == 0);
DLIB_TEST(conv_valid(temp,c).nc() == 0);
temp.set_size(5,2);
temp = 1, 2,
5, 8,
9, 14,
13, 20,
12, 16;
DLIB_TEST(conv(b,d) == temp);
DLIB_TEST(xcorr(b,flip(d)) == temp);
temp.set_size(2,2);
temp = 9, 14,
13, 20;
DLIB_TEST(conv_same(b,d) == temp);
DLIB_TEST(xcorr_same(b,flip(d)) == temp);
DLIB_TEST(conv_valid(b,d).nr() == 0);
DLIB_TEST(xcorr_valid(b,flip(d)).nr() == 0);
DLIB_TEST_MSG(conv_valid(b,d).nc() == 0, conv_valid(b,d).nc());
DLIB_TEST(xcorr_valid(b,flip(d)).nc() == 0);
temp.set_size(5,5);
temp = 1, 4, 10, 12, 9,
8, 26, 56, 54, 36,
30, 84, 165, 144, 90,
56, 134, 236, 186, 108,
49, 112, 190, 144, 81;
DLIB_TEST(conv(c,c) == temp);
DLIB_TEST(xcorr(c,flip(c)) == temp);
matrix<int> temp3 = c;
temp3 = conv(temp3,c);
DLIB_TEST(temp3 == temp);
temp3 = c;
temp3 = conv(c,temp3);
DLIB_TEST(temp3 == temp);
temp.set_size(3,3);
temp = 26, 56, 54,
84, 165, 144,
134, 236, 186;
DLIB_TEST(conv_same(c,c) == temp);
DLIB_TEST(xcorr_same(c,flip(c)) == temp);
temp3 = c;
temp3 = conv_same(c,temp3);
DLIB_TEST(temp3 == temp);
temp3 = c;
temp3 = conv_same(temp3,c);
DLIB_TEST(temp3 == temp);
temp.set_size(1,1);
temp = 165;
DLIB_TEST(conv_valid(c,c) == temp);
DLIB_TEST(xcorr_valid(c,flip(c)) == temp);
temp3 = c;
temp3 = conv_valid(c,temp3);
DLIB_TEST(temp3 == temp);
temp3 = c;
temp3 = conv_valid(temp3,c);
DLIB_TEST(temp3 == temp);
}
class matrix_tester : public tester
@ -625,6 +776,9 @@ namespace
void perform_test (
)
{
test_conv<0,0,0,0>();
test_conv<1,2,3,4>();
test_stuff();
for (int i = 0; i < 10; ++i)
matrix_test();