// Copyright (C) 2006 Davis E. King (davis@dlib.net) // License: Boost Software License See LICENSE.txt for the full license. #undef DLIB_MATRIx_UTILITIES_ABSTRACT_ #ifdef DLIB_MATRIx_UTILITIES_ABSTRACT_ #include "matrix_abstract.h" #include <complex> #include "../pixel.h" #include "../geometry.h" #inclue <vector> namespace dlib { // ---------------------------------------------------------------------------------------- // ---------------------------------------------------------------------------------------- // Simple matrix utilities // ---------------------------------------------------------------------------------------- // ---------------------------------------------------------------------------------------- const matrix_exp diag ( const matrix_exp& m ); /*! ensures - returns a column vector R that contains the elements from the diagonal of m in the order R(0)==m(0,0), R(1)==m(1,1), R(2)==m(2,2) and so on. !*/ template <typename EXP> struct diag_exp { /*! WHAT THIS OBJECT REPRESENTS This struct allows you to determine the type of matrix expression object returned from the diag() function. An example makes its use clear: template <typename EXP> void do_something( const matrix_exp<EXP>& mat) { // d is a matrix expression that aliases mat. typename diag_exp<EXP>::type d = diag(mat); // Print the diagonal of mat. So we see that by using // diag_exp we can save the object returned by diag() in // a local variable. cout << d << endl; // Note that you can only save the return value of diag() to // a local variable if the argument to diag() has a lifetime // beyond the diag() expression. The example shown above is // OK but the following would result in undefined behavior: typename diag_exp<EXP>::type bad = diag(mat + mat); } !*/ typedef type_of_expression_returned_by_diag type; }; // ---------------------------------------------------------------------------------------- const matrix_exp diagm ( const matrix_exp& m ); /*! requires - is_vector(m) == true (i.e. m is a row or column matrix) ensures - returns a square matrix M such that: - diag(M) == m - non diagonal elements of M are 0 !*/ // ---------------------------------------------------------------------------------------- const matrix_exp trans ( const matrix_exp& m ); /*! ensures - returns the transpose of the matrix m !*/ // ---------------------------------------------------------------------------------------- const matrix_type::type dot ( const matrix_exp& m1, const matrix_exp& m2 ); /*! requires - is_vector(m1) == true - is_vector(m2) == true - m1.size() == m2.size() ensures - returns the dot product between m1 and m2. That is, this function computes and returns the sum, for all i, of m1(i)*m2(i). !*/ // ---------------------------------------------------------------------------------------- const matrix_exp lowerm ( const matrix_exp& m ); /*! ensures - returns a matrix M such that: - M::type == the same type that was in m - M has the same dimensions as m - M is the lower triangular part of m. That is: - if (r >= c) then - M(r,c) == m(r,c) - else - M(r,c) == 0 !*/ // ---------------------------------------------------------------------------------------- const matrix_exp lowerm ( const matrix_exp& m, const matrix_exp::type scalar_value ); /*! ensures - returns a matrix M such that: - M::type == the same type that was in m - M has the same dimensions as m - M is the lower triangular part of m except that the diagonal has been set to scalar_value. That is: - if (r > c) then - M(r,c) == m(r,c) - else if (r == c) then - M(r,c) == scalar_value - else - M(r,c) == 0 !*/ // ---------------------------------------------------------------------------------------- const matrix_exp upperm ( const matrix_exp& m ); /*! ensures - returns a matrix M such that: - M::type == the same type that was in m - M has the same dimensions as m - M is the upper triangular part of m. That is: - if (r <= c) then - M(r,c) == m(r,c) - else - M(r,c) == 0 !*/ // ---------------------------------------------------------------------------------------- const matrix_exp upperm ( const matrix_exp& m, const matrix_exp::type scalar_value ); /*! ensures - returns a matrix M such that: - M::type == the same type that was in m - M has the same dimensions as m - M is the upper triangular part of m except that the diagonal has been set to scalar_value. That is: - if (r < c) then - M(r,c) == m(r,c) - else if (r == c) then - M(r,c) == scalar_value - else - M(r,c) == 0 !*/ // ---------------------------------------------------------------------------------------- const matrix_exp make_symmetric ( const matrix_exp& m ); /*! requires - m.nr() == m.nc() (i.e. m must be a square matrix) ensures - returns a matrix M such that: - M::type == the same type that was in m - M has the same dimensions as m - M is a symmetric matrix, that is, M == trans(M) and it is constructed from the lower triangular part of m. Specifically, we have: - lowerm(M) == lowerm(m) - upperm(M) == trans(lowerm(m)) !*/ // ---------------------------------------------------------------------------------------- template < typename T, long NR, long NC, T val > const matrix_exp uniform_matrix ( ); /*! requires - NR > 0 && NC > 0 ensures - returns an NR by NC matrix with elements of type T and all set to val. !*/ // ---------------------------------------------------------------------------------------- template < typename T, long NR, long NC > const matrix_exp uniform_matrix ( const T& val ); /*! requires - NR > 0 && NC > 0 ensures - returns an NR by NC matrix with elements of type T and all set to val. !*/ // ---------------------------------------------------------------------------------------- template < typename T > const matrix_exp uniform_matrix ( long nr, long nc, const T& val ); /*! requires - nr > 0 && nc > 0 ensures - returns an nr by nc matrix with elements of type T and all set to val. !*/ // ---------------------------------------------------------------------------------------- template < typename T > const matrix_exp ones_matrix ( long nr, long nc ); /*! requires - nr > 0 && nc > 0 ensures - returns uniform_matrix<T>(nr, nc, 1) !*/ // ---------------------------------------------------------------------------------------- template < typename T > const matrix_exp zeros_matrix ( long nr, long nc ); /*! requires - nr > 0 && nc > 0 ensures - returns uniform_matrix<T>(nr, nc, 0) !*/ // ---------------------------------------------------------------------------------------- template < typename T > const matrix_exp identity_matrix ( long N ); /*! requires - N > 0 ensures - returns an N by N identity matrix with elements of type T. !*/ // ---------------------------------------------------------------------------------------- template < typename T, long N > const matrix_exp identity_matrix ( ); /*! requires - N > 0 ensures - returns an N by N identity matrix with elements of type T. !*/ // ---------------------------------------------------------------------------------------- const matrix_exp linspace ( double start, double end, long num ); /*! requires - num >= 0 ensures - returns a matrix M such that: - M::type == double - is_row_vector(M) == true - M.size() == num - M == a row vector with num linearly spaced values beginning with start and stopping with end. - M(num-1) == end - if (num > 1) then - M(0) == start !*/ // ---------------------------------------------------------------------------------------- const matrix_exp logspace ( double start, double end, long num ); /*! requires - num >= 0 ensures - returns a matrix M such that: - M::type == double - is_row_vector(M) == true - M.size() == num - M == a row vector with num logarithmically spaced values beginning with 10^start and stopping with 10^end. (i.e. M == pow(10, linspace(start, end, num))) - M(num-1) == 10^end !*/ // ---------------------------------------------------------------------------------------- template < long R, long C > const matrix_exp rotate ( const matrix_exp& m ); /*! ensures - returns a matrix R such that: - R::type == the same type that was in m - R has the same dimensions as m - for all valid r and c: R( (r+R)%m.nr() , (c+C)%m.nc() ) == m(r,c) !*/ // ---------------------------------------------------------------------------------------- const matrix_exp fliplr ( const matrix_exp& m ); /*! ensures - flips the matrix m from left to right and returns the result. I.e. reverses the order of the columns. - returns a matrix M such that: - M::type == the same type that was in m - M has the same dimensions as m - for all valid r and c: M(r,c) == m(r, m.nc()-c-1) !*/ // ---------------------------------------------------------------------------------------- const matrix_exp flipud ( const matrix_exp& m ); /*! ensures - flips the matrix m from up to down and returns the result. I.e. reverses the order of the rows. - returns a matrix M such that: - M::type == the same type that was in m - M has the same dimensions as m - for all valid r and c: M(r,c) == m(m.nr()-r-1, c) !*/ // ---------------------------------------------------------------------------------------- template < typename vector_type > const matrix_exp vector_to_matrix ( const vector_type& vector ); /*! requires - vector_type is an implementation of array/array_kernel_abstract.h or std::vector or dlib::std_vector_c or dlib::matrix ensures - if (vector_type is a dlib::matrix) then - returns a reference to vector - else - returns a matrix R such that: - is_col_vector(R) == true - R.size() == vector.size() - for all valid r: R(r) == vector[r] !*/ // ---------------------------------------------------------------------------------------- template < typename array_type > const matrix_exp array_to_matrix ( const array_type& array ); /*! requires - array_type is an implementation of array2d/array2d_kernel_abstract.h or dlib::matrix ensures - if (array_type is a dlib::matrix) then - returns a reference to array - else - returns a matrix R such that: - R.nr() == array.nr() - R.nc() == array.nc() - for all valid r and c: R(r, c) == array[r][c] !*/ // ---------------------------------------------------------------------------------------- template < typename T > const matrix_exp pointer_to_matrix ( const T* ptr, long nr, long nc ); /*! requires - nr > 0 - nc > 0 - ptr == a pointer to at least nr*nc T objects ensures - returns a matrix M such that: - M.nr() == nr - m.nc() == nc - for all valid r and c: M(r,c) == ptr[r*nc + c] (i.e. the pointer is interpreted as a matrix laid out in memory in row major order) - Note that the returned matrix doesn't take "ownership" of the pointer and thus will not delete or free it. !*/ // ---------------------------------------------------------------------------------------- template < typename T > const matrix_exp pointer_to_column_vector ( const T* ptr, long nr ); /*! requires - nr > 0 - ptr == a pointer to at least nr T objects ensures - returns a matrix M such that: - M.nr() == nr - m.nc() == 1 - for all valid i: M(i) == ptr[i] - Note that the returned matrix doesn't take "ownership" of the pointer and thus will not delete or free it. !*/ // ---------------------------------------------------------------------------------------- const matrix_exp reshape ( const matrix_exp& m, long rows, long cols ); /*! requires - m.size() == rows*cols - rows > 0 - cols > 0 ensures - returns a matrix M such that: - M.nr() == rows - M.nc() == cols - M.size() == m.size() - for all valid r and c: - let IDX = r*cols + c - M(r,c) == m(IDX/m.nc(), IDX%m.nc()) - i.e. The matrix m is reshaped into a new matrix of rows by cols dimension. Additionally, the elements of m are laid into M in row major order. !*/ // ---------------------------------------------------------------------------------------- const matrix_exp reshape_to_column_vector ( const matrix_exp& m ); /*! ensures - returns a matrix M such that: - is_col_vector(M) == true - M.size() == m.size() - for all valid r and c: - m(r,c) == M(r*m.nc() + c) - i.e. The matrix m is reshaped into a column vector. Note that the elements are pulled out in row major order. !*/ // ---------------------------------------------------------------------------------------- template < long R, long C > const matrix_exp removerc ( const matrix_exp& m ); /*! requires - m.nr() > R >= 0 - m.nc() > C >= 0 ensures - returns a matrix M such that: - M.nr() == m.nr() - 1 - M.nc() == m.nc() - 1 - M == m with its R row and C column removed !*/ // ---------------------------------------------------------------------------------------- const matrix_exp removerc ( const matrix_exp& m, long R, long C ); /*! requires - m.nr() > R >= 0 - m.nc() > C >= 0 ensures - returns a matrix M such that: - M.nr() == m.nr() - 1 - M.nc() == m.nc() - 1 - M == m with its R row and C column removed !*/ // ---------------------------------------------------------------------------------------- template < long R > const matrix_exp remove_row ( const matrix_exp& m ); /*! requires - m.nr() > R >= 0 ensures - returns a matrix M such that: - M.nr() == m.nr() - 1 - M.nc() == m.nc() - M == m with its R row removed !*/ // ---------------------------------------------------------------------------------------- const matrix_exp remove_row ( const matrix_exp& m, long R ); /*! requires - m.nr() > R >= 0 ensures - returns a matrix M such that: - M.nr() == m.nr() - 1 - M.nc() == m.nc() - M == m with its R row removed !*/ // ---------------------------------------------------------------------------------------- template < long C > const matrix_exp remove_col ( const matrix_exp& m ); /*! requires - m.nc() > C >= 0 ensures - returns a matrix M such that: - M.nr() == m.nr() - M.nc() == m.nc() - 1 - M == m with its C column removed !*/ // ---------------------------------------------------------------------------------------- const matrix_exp remove_col ( const matrix_exp& m, long C ); /*! requires - m.nc() > C >= 0 ensures - returns a matrix M such that: - M.nr() == m.nr() - M.nc() == m.nc() - 1 - M == m with its C column removed !*/ // ---------------------------------------------------------------------------------------- template < typename target_type > const matrix_exp matrix_cast ( const matrix_exp& m ); /*! ensures - returns a matrix R where for all valid r and c: R(r,c) == static_cast<target_type>(m(r,c)) also, R has the same dimensions as m. !*/ // ---------------------------------------------------------------------------------------- template < typename T, long NR, long NC, typename MM, typename U > void set_all_elements ( matrix<T,NR,NC,MM>& m, U value ); /*! ensures - for all valid r and c: m(r,c) == value !*/ // ---------------------------------------------------------------------------------------- const matrix_exp::matrix_type tmp ( const matrix_exp& m ); /*! ensures - returns a temporary matrix object that is a copy of m. (This allows you to easily force a matrix_exp to fully evaluate) !*/ // ---------------------------------------------------------------------------------------- // if matrix_exp contains non-complex types (e.g. float, double) bool equal ( const matrix_exp& a, const matrix_exp& b, const matrix_exp::type epsilon = 100*std::numeric_limits<matrix_exp::type>::epsilon() ); /*! ensures - if (a and b don't have the same dimensions) then - returns false - else if (there exists an r and c such that abs(a(r,c)-b(r,c)) > epsilon) then - returns false - else - returns true !*/ // ---------------------------------------------------------------------------------------- // if matrix_exp contains std::complex types bool equal ( const matrix_exp& a, const matrix_exp& b, const matrix_exp::type::value_type epsilon = 100*std::numeric_limits<matrix_exp::type::value_type>::epsilon() ); /*! ensures - if (a and b don't have the same dimensions) then - returns false - else if (there exists an r and c such that abs(real(a(r,c)-b(r,c))) > epsilon or abs(imag(a(r,c)-b(r,c))) > epsilon) then - returns false - else - returns true !*/ // ---------------------------------------------------------------------------------------- const matrix_exp pointwise_multiply ( const matrix_exp& a, const matrix_exp& b ); /*! requires - a.nr() == b.nr() - a.nc() == b.nc() - a and b both contain the same type of element (one or both can also be of type std::complex so long as the underlying type in them is the same) ensures - returns a matrix R such that: - R::type == the same type that was in a and b. - R has the same dimensions as a and b. - for all valid r and c: R(r,c) == a(r,c) * b(r,c) !*/ const matrix_exp pointwise_multiply ( const matrix_exp& a, const matrix_exp& b, const matrix_exp& c ); /*! performs pointwise_multiply(a,pointwise_multiply(b,c)); !*/ const matrix_exp pointwise_multiply ( const matrix_exp& a, const matrix_exp& b, const matrix_exp& c, const matrix_exp& d ); /*! performs pointwise_multiply(pointwise_multiply(a,b),pointwise_multiply(c,d)); !*/ // ---------------------------------------------------------------------------------------- const matrix_exp join_rows ( const matrix_exp& a, const matrix_exp& b ); /*! requires - a.nr() == b.nr() - a and b both contain the same type of element ensures - This function joins two matrices together by concatenating their rows. - returns a matrix R such that: - R::type == the same type that was in a and b. - R.nr() == a.nr() == b.nr() - R.nc() == a.nc() + b.nc() - for all valid r and c: - if (c < a.nc()) then - R(r,c) == a(r,c) - else - R(r,c) == b(r, c-a.nc()) !*/ // ---------------------------------------------------------------------------------------- const matrix_exp join_cols ( const matrix_exp& a, const matrix_exp& b ); /*! requires - a.nc() == b.nc() - a and b both contain the same type of element ensures - This function joins two matrices together by concatenating their columns. - returns a matrix R such that: - R::type == the same type that was in a and b. - R.nr() == a.nr() + b.nr() - R.nc() == a.nc() == b.nc() - for all valid r and c: - if (r < a.nr()) then - R(r,c) == a(r,c) - else - R(r,c) == b(r-a.nr(), c) !*/ // ---------------------------------------------------------------------------------------- const matrix_exp tensor_product ( const matrix_exp& a, const matrix_exp& b ); /*! requires - a and b both contain the same type of element ensures - returns a matrix R such that: - R::type == the same type that was in a and b. - R.nr() == a.nr() * b.nr() - R.nc() == a.nc() * b.nc() - for all valid r and c: R(r,c) == a(r/b.nr(), c/b.nc()) * b(r%b.nr(), c%b.nc()) - I.e. R is the tensor product of matrix a with matrix b !*/ // ---------------------------------------------------------------------------------------- const matrix_exp cartesian_product ( const matrix_exp& A, const matrix_exp& B ); /*! requires - A and B both contain the same type of element ensures - Think of A and B as sets of column vectors. Then this function returns a matrix that contains a set of column vectors that is the Cartesian product of the sets A and B. That is, the resulting matrix contains every possible combination of vectors from both A and B. - returns a matrix R such that: - R::type == the same type that was in A and B. - R.nr() == A.nr() + B.nr() - R.nc() == A.nc() * B.nc() - Each column of R is the concatenation of a column vector from A with a column vector from B. - for all valid r and c: - if (r < A.nr()) then - R(r,c) == A(r, c/B.nc()) - else - R(r,c) == B(r-A.nr(), c%B.nc()) !*/ // ---------------------------------------------------------------------------------------- const matrix_exp scale_columns ( const matrix_exp& m, const matrix_exp& v ); /*! requires - is_vector(v) == true - v.size() == m.nc() - m and v both contain the same type of element ensures - returns a matrix R such that: - R::type == the same type that was in m and v. - R has the same dimensions as m. - for all valid r and c: R(r,c) == m(r,c) * v(c) - i.e. R is the result of multiplying each of m's columns by the corresponding scalar in v. - Note that this function is identical to the expression m*diagm(v). That is, the * operator is overloaded for this case and will invoke scale_columns() automatically as appropriate. !*/ // ---------------------------------------------------------------------------------------- const matrix_exp scale_rows ( const matrix_exp& m, const matrix_exp& v ); /*! requires - is_vector(v) == true - v.size() == m.nr() - m and v both contain the same type of element ensures - returns a matrix R such that: - R::type == the same type that was in m and v. - R has the same dimensions as m. - for all valid r and c: R(r,c) == m(r,c) * v(r) - i.e. R is the result of multiplying each of m's rows by the corresponding scalar in v. - Note that this function is identical to the expression diagm(v)*m. That is, the * operator is overloaded for this case and will invoke scale_rows() automatically as appropriate. !*/ // ---------------------------------------------------------------------------------------- template <typename T> void sort_columns ( matrix<T>& m, matrix<T>& v ); /*! requires - is_col_vector(v) == true - v.size() == m.nc() - m and v both contain the same type of element ensures - the dimensions for m and v are not changed - sorts the columns of m according to the values in v. i.e. - #v == the contents of v but in sorted order according to operator<. So smaller elements come first. - Let #v(new(i)) == v(i) (i.e. new(i) is the index element i moved to) - colm(#m,new(i)) == colm(m,i) !*/ // ---------------------------------------------------------------------------------------- template <typename T> void rsort_columns ( matrix<T>& m, matrix<T>& v ); /*! requires - is_col_vector(v) == true - v.size() == m.nc() - m and v both contain the same type of element ensures - the dimensions for m and v are not changed - sorts the columns of m according to the values in v. i.e. - #v == the contents of v but in sorted order according to operator>. So larger elements come first. - Let #v(new(i)) == v(i) (i.e. new(i) is the index element i moved to) - colm(#m,new(i)) == colm(m,i) !*/ // ---------------------------------------------------------------------------------------- const matrix_exp::type length_squared ( const matrix_exp& m ); /*! requires - is_vector(m) == true ensures - returns sum(squared(m)) (i.e. returns the square of the length of the vector m) !*/ // ---------------------------------------------------------------------------------------- const matrix_exp::type length ( const matrix_exp& m ); /*! requires - is_vector(m) == true ensures - returns sqrt(sum(squared(m))) (i.e. returns the length of the vector m) !*/ // ---------------------------------------------------------------------------------------- bool is_row_vector ( const matrix_exp& m ); /*! ensures - if (m.nr() == 1) then - return true - else - returns false !*/ bool is_col_vector ( const matrix_exp& m ); /*! ensures - if (m.nc() == 1) then - return true - else - returns false !*/ bool is_vector ( const matrix_exp& m ); /*! ensures - if (is_row_vector(m) || is_col_vector(m)) then - return true - else - returns false !*/ // ---------------------------------------------------------------------------------------- // ---------------------------------------------------------------------------------------- // Thresholding relational operators // ---------------------------------------------------------------------------------------- // ---------------------------------------------------------------------------------------- template <typename S> const matrix_exp operator< ( const matrix_exp& m, const S& s ); /*! requires - is_built_in_scalar_type<S>::value == true - is_built_in_scalar_type<matrix_exp::type>::value == true ensures - returns a matrix R such that: - R::type == the same type that was in m. - R has the same dimensions as m. - for all valid r and c: - if (m(r,c) < s) then - R(r,c) == 1 - else - R(r,c) == 0 - i.e. R is a binary matrix of all 1s or 0s. !*/ // ---------------------------------------------------------------------------------------- template <typename S> const matrix_exp operator< ( const S& s, const matrix_exp& m ); /*! requires - is_built_in_scalar_type<S>::value == true - is_built_in_scalar_type<matrix_exp::type>::value == true ensures - returns a matrix R such that: - R::type == the same type that was in m. - R has the same dimensions as m. - for all valid r and c: - if (s < m(r,c)) then - R(r,c) == 1 - else - R(r,c) == 0 - i.e. R is a binary matrix of all 1s or 0s. !*/ // ---------------------------------------------------------------------------------------- template <typename S> const matrix_exp operator<= ( const matrix_exp& m, const S& s ); /*! requires - is_built_in_scalar_type<S>::value == true - is_built_in_scalar_type<matrix_exp::type>::value == true ensures - returns a matrix R such that: - R::type == the same type that was in m. - R has the same dimensions as m. - for all valid r and c: - if (m(r,c) <= s) then - R(r,c) == 1 - else - R(r,c) == 0 - i.e. R is a binary matrix of all 1s or 0s. !*/ // ---------------------------------------------------------------------------------------- template <typename S> const matrix_exp operator<= ( const S& s, const matrix_exp& m ); /*! requires - is_built_in_scalar_type<S>::value == true - is_built_in_scalar_type<matrix_exp::type>::value == true ensures - returns a matrix R such that: - R::type == the same type that was in m. - R has the same dimensions as m. - for all valid r and c: - if (s <= m(r,c)) then - R(r,c) == 1 - else - R(r,c) == 0 - i.e. R is a binary matrix of all 1s or 0s. !*/ // ---------------------------------------------------------------------------------------- template <typename S> const matrix_exp operator> ( const matrix_exp& m, const S& s ); /*! requires - is_built_in_scalar_type<S>::value == true - is_built_in_scalar_type<matrix_exp::type>::value == true ensures - returns a matrix R such that: - R::type == the same type that was in m. - R has the same dimensions as m. - for all valid r and c: - if (m(r,c) > s) then - R(r,c) == 1 - else - R(r,c) == 0 - i.e. R is a binary matrix of all 1s or 0s. !*/ // ---------------------------------------------------------------------------------------- template <typename S> const matrix_exp operator> ( const S& s, const matrix_exp& m ); /*! requires - is_built_in_scalar_type<S>::value == true - is_built_in_scalar_type<matrix_exp::type>::value == true ensures - returns a matrix R such that: - R::type == the same type that was in m. - R has the same dimensions as m. - for all valid r and c: - if (s > m(r,c)) then - R(r,c) == 1 - else - R(r,c) == 0 - i.e. R is a binary matrix of all 1s or 0s. !*/ // ---------------------------------------------------------------------------------------- template <typename S> const matrix_exp operator>= ( const matrix_exp& m, const S& s ); /*! requires - is_built_in_scalar_type<S>::value == true - is_built_in_scalar_type<matrix_exp::type>::value == true ensures - returns a matrix R such that: - R::type == the same type that was in m. - R has the same dimensions as m. - for all valid r and c: - if (m(r,c) >= s) then - R(r,c) == 1 - else - R(r,c) == 0 - i.e. R is a binary matrix of all 1s or 0s. !*/ // ---------------------------------------------------------------------------------------- template <typename S> const matrix_exp operator>= ( const S& s, const matrix_exp& m ); /*! requires - is_built_in_scalar_type<S>::value == true - is_built_in_scalar_type<matrix_exp::type>::value == true ensures - returns a matrix R such that: - R::type == the same type that was in m. - R has the same dimensions as m. - for all valid r and c: - if (s >= m(r,c)) then - R(r,c) == 1 - else - R(r,c) == 0 - i.e. R is a binary matrix of all 1s or 0s. !*/ // ---------------------------------------------------------------------------------------- template <typename S> const matrix_exp operator== ( const matrix_exp& m, const S& s ); /*! requires - is_built_in_scalar_type<S>::value == true - is_built_in_scalar_type<matrix_exp::type>::value == true ensures - returns a matrix R such that: - R::type == the same type that was in m. - R has the same dimensions as m. - for all valid r and c: - if (m(r,c) == s) then - R(r,c) == 1 - else - R(r,c) == 0 - i.e. R is a binary matrix of all 1s or 0s. !*/ // ---------------------------------------------------------------------------------------- template <typename S> const matrix_exp operator== ( const S& s, const matrix_exp& m ); /*! requires - is_built_in_scalar_type<S>::value == true - is_built_in_scalar_type<matrix_exp::type>::value == true ensures - returns a matrix R such that: - R::type == the same type that was in m. - R has the same dimensions as m. - for all valid r and c: - if (s == m(r,c)) then - R(r,c) == 1 - else - R(r,c) == 0 - i.e. R is a binary matrix of all 1s or 0s. !*/ // ---------------------------------------------------------------------------------------- template <typename S> const matrix_exp operator!= ( const matrix_exp& m, const S& s ); /*! requires - is_built_in_scalar_type<S>::value == true - is_built_in_scalar_type<matrix_exp::type>::value == true ensures - returns a matrix R such that: - R::type == the same type that was in m. - R has the same dimensions as m. - for all valid r and c: - if (m(r,c) != s) then - R(r,c) == 1 - else - R(r,c) == 0 - i.e. R is a binary matrix of all 1s or 0s. !*/ // ---------------------------------------------------------------------------------------- template <typename S> const matrix_exp operator!= ( const S& s, const matrix_exp& m ); /*! requires - is_built_in_scalar_type<S>::value == true - is_built_in_scalar_type<matrix_exp::type>::value == true ensures - returns a matrix R such that: - R::type == the same type that was in m. - R has the same dimensions as m. - for all valid r and c: - if (s != m(r,c)) then - R(r,c) == 1 - else - R(r,c) == 0 - i.e. R is a binary matrix of all 1s or 0s. !*/ // ---------------------------------------------------------------------------------------- // ---------------------------------------------------------------------------------------- // Statistics // ---------------------------------------------------------------------------------------- // ---------------------------------------------------------------------------------------- const matrix_exp::type min ( const matrix_exp& m ); /*! requires - m.size() > 0 ensures - returns the value of the smallest element of m !*/ // ---------------------------------------------------------------------------------------- const matrix_exp::type max ( const matrix_exp& m ); /*! requires - m.size() > 0 ensures - returns the value of the biggest element of m !*/ // ---------------------------------------------------------------------------------------- void find_min_and_max ( const matrix_exp& m, matrix_exp::type& min_val, matrix_exp::type& max_val ); /*! requires - m.size() > 0 ensures - #min_val == min(m) - #max_val == max(m) - This function computes both the min and max in just one pass over the elements of the matrix m. !*/ // ---------------------------------------------------------------------------------------- long index_of_max ( const matrix_exp& m ); /*! requires - is_vector(m) == true - m.size() > 0 ensures - returns the index of the largest element in m. (i.e. m(index_of_max(m)) == max(m)) !*/ // ---------------------------------------------------------------------------------------- long index_of_min ( const matrix_exp& m ); /*! requires - is_vector(m) == true - m.size() > 0 ensures - returns the index of the smallest element in m. (i.e. m(index_of_min(m)) == min(m)) !*/ // ---------------------------------------------------------------------------------------- const matrix_exp::type sum ( const matrix_exp& m ); /*! ensures - returns the sum of all elements in m !*/ // ---------------------------------------------------------------------------------------- const matrix_exp sum_rows ( const matrix_exp& m ); /*! requires - m.size() > 0 ensures - returns a row matrix that contains the sum of all the rows in m. - returns a matrix M such that - M::type == the same type that was in m - M.nr() == 1 - M.nc() == m.nc() - for all valid i: - M(i) == sum(colm(m,i)) !*/ // ---------------------------------------------------------------------------------------- const matrix_exp sum_cols ( const matrix_exp& m ); /*! requires - m.size() > 0 ensures - returns a column matrix that contains the sum of all the columns in m. - returns a matrix M such that - M::type == the same type that was in m - M.nr() == m.nr() - M.nc() == 1 - for all valid i: - M(i) == sum(rowm(m,i)) !*/ // ---------------------------------------------------------------------------------------- const matrix_exp::type prod ( const matrix_exp& m ); /*! ensures - returns the results of multiplying all elements of m together. !*/ // ---------------------------------------------------------------------------------------- const matrix_exp::type mean ( const matrix_exp& m ); /*! ensures - returns the mean of all elements in m. (i.e. returns sum(m)/(m.nr()*m.nc())) !*/ // ---------------------------------------------------------------------------------------- const matrix_exp::type variance ( const matrix_exp& m ); /*! ensures - returns the unbiased sample variance of all elements in m (i.e. 1.0/(m.nr()*m.nc() - 1)*(sum of all pow(m(i,j) - mean(m),2))) !*/ // ---------------------------------------------------------------------------------------- const matrix covariance ( const matrix_exp& m ); /*! requires - matrix_exp::type == a dlib::matrix object - is_col_vector(m) == true - m.size() > 1 - for all valid i, j: - is_col_vector(m(i)) == true - m(i).size() > 0 - m(i).size() == m(j).size() - i.e. m contains only column vectors and all the column vectors have the same non-zero length ensures - returns the unbiased sample covariance matrix for the set of samples in m. (i.e. 1.0/(m.nr()-1)*(sum of all (m(i) - mean(m))*trans(m(i) - mean(m)))) - the returned matrix will contain elements of type matrix_exp::type::type. - the returned matrix will have m(0).nr() rows and columns. !*/ // ---------------------------------------------------------------------------------------- template <typename rand_gen> const matrix<double> randm( long nr, long nc, rand_gen& rnd ); /*! requires - nr >= 0 - nc >= 0 - rand_gen == an object that implements the rand/rand_float_abstract.h interface ensures - generates a random matrix using the given rnd random number generator - returns a matrix M such that - M::type == double - M.nr() == nr - M.nc() == nc - for all valid i, j: - M(i,j) == a random number such that 0 <= M(i,j) < 1 !*/ // ---------------------------------------------------------------------------------------- inline const matrix<double> randm( long nr, long nc ); /*! requires - nr >= 0 - nc >= 0 ensures - generates a random matrix using std::rand() - returns a matrix M such that - M::type == double - M.nr() == nr - M.nc() == nc - for all valid i, j: - M(i,j) == a random number such that 0 <= M(i,j) < 1 !*/ // ---------------------------------------------------------------------------------------- // ---------------------------------------------------------------------------------------- // Pixel and Image Utilities // ---------------------------------------------------------------------------------------- // ---------------------------------------------------------------------------------------- template < typename T, typename P > const matrix_exp pixel_to_vector ( const P& pixel ); /*! requires - pixel_traits<P> must be defined ensures - returns a matrix M such that: - M::type == T - M::NC == 1 - M::NR == pixel_traits<P>::num - if (pixel_traits<P>::grayscale) then - M(0) == pixel - if (pixel_traits<P>::rgb) then - M(0) == pixel.red - M(1) == pixel.green - M(2) == pixel.blue - if (pixel_traits<P>::hsi) then - M(0) == pixel.h - M(1) == pixel.s - M(2) == pixel.i !*/ // ---------------------------------------------------------------------------------------- template < typename P > void vector_to_pixel ( P& pixel, const matrix_exp& vector ); /*! requires - vector::NR == pixel_traits<P>::num - vector::NC == 1 (i.e. you have to use a statically dimensioned vector) ensures - if (pixel_traits<P>::grayscale) then - pixel == M(0) - if (pixel_traits<P>::rgb) then - pixel.red == M(0) - pixel.green == M(1) - pixel.blue == M(2) - if (pixel_traits<P>::hsi) then - pixel.h == M(0) - pixel.s == M(1) - pixel.i == M(2) !*/ // ---------------------------------------------------------------------------------------- template < long lower, long upper > const matrix_exp clamp ( const matrix_exp& m ); /*! ensures - returns a matrix R such that: - R::type == the same type that was in m - R has the same dimensions as m - for all valid r and c: - if (m(r,c) > upper) then - R(r,c) == upper - else if (m(r,c) < lower) then - R(r,c) == lower - else - R(r,c) == m(r,c) !*/ // ---------------------------------------------------------------------------------------- const matrix_exp clamp ( const matrix_exp& m, const matrix_exp::type& lower, const matrix_exp::type& upper ); /*! ensures - returns a matrix R such that: - R::type == the same type that was in m - R has the same dimensions as m - for all valid r and c: - if (m(r,c) > upper) then - R(r,c) == upper - else if (m(r,c) < lower) then - R(r,c) == lower - else - R(r,c) == m(r,c) !*/ // ---------------------------------------------------------------------------------------- } #endif // DLIB_MATRIx_UTILITIES_ABSTRACT_