diff --git a/doc/Doxyfile.in b/doc/Doxyfile.in
index dd8d325c4d..1db5427338 100644
--- a/doc/Doxyfile.in
+++ b/doc/Doxyfile.in
@@ -107,7 +107,7 @@ RECURSIVE              = YES
 EXCLUDE                =
 EXCLUDE_SYMLINKS       = NO
 EXCLUDE_PATTERNS       = *.inl.hpp *.impl.hpp *_detail.hpp */cudev/**/detail/*.hpp *.m
-EXCLUDE_SYMBOLS        = cv::DataType<*> int void
+EXCLUDE_SYMBOLS        = cv::DataType<*> cv::traits::* int void CV__*
 EXAMPLE_PATH           = @CMAKE_DOXYGEN_EXAMPLE_PATH@
 EXAMPLE_PATTERNS       = *
 EXAMPLE_RECURSIVE      = YES
diff --git a/modules/core/include/opencv2/core/cvstd.inl.hpp b/modules/core/include/opencv2/core/cvstd.inl.hpp
index fb5d8ab1bb..85230f595d 100644
--- a/modules/core/include/opencv2/core/cvstd.inl.hpp
+++ b/modules/core/include/opencv2/core/cvstd.inl.hpp
@@ -233,7 +233,7 @@ template<typename _Tp, int n> static inline
 std::ostream& operator << (std::ostream& out, const Vec<_Tp, n>& vec)
 {
     out << "[";
-    if(Vec<_Tp, n>::depth < CV_32F)
+    if (cv::traits::Depth<_Tp>::value <= CV_32S)
     {
         for (int i = 0; i < n - 1; ++i) {
             out << (int)vec[i] << ", ";
diff --git a/modules/core/include/opencv2/core/mat.hpp b/modules/core/include/opencv2/core/mat.hpp
index 990deb87de..8e35fd4dc4 100644
--- a/modules/core/include/opencv2/core/mat.hpp
+++ b/modules/core/include/opencv2/core/mat.hpp
@@ -1531,6 +1531,11 @@ public:
     */
     template<typename _Tp> void push_back(const Mat_<_Tp>& elem);
 
+    /** @overload
+    @param elem Added element(s).
+    */
+    template<typename _Tp> void push_back(const std::vector<_Tp>& elem);
+
     /** @overload
     @param m Added line(s).
     */
diff --git a/modules/core/include/opencv2/core/mat.inl.hpp b/modules/core/include/opencv2/core/mat.inl.hpp
index f1d69b4b04..934a8f07cb 100644
--- a/modules/core/include/opencv2/core/mat.inl.hpp
+++ b/modules/core/include/opencv2/core/mat.inl.hpp
@@ -82,12 +82,12 @@ inline _InputArray::_InputArray(const std::vector<UMat>& vec) { init(STD_VECTOR_
 
 template<typename _Tp> inline
 _InputArray::_InputArray(const std::vector<_Tp>& vec)
-{ init(FIXED_TYPE + STD_VECTOR + DataType<_Tp>::type + ACCESS_READ, &vec); }
+{ init(FIXED_TYPE + STD_VECTOR + traits::Type<_Tp>::value + ACCESS_READ, &vec); }
 
 #ifdef CV_CXX_STD_ARRAY
 template<typename _Tp, std::size_t _Nm> inline
 _InputArray::_InputArray(const std::array<_Tp, _Nm>& arr)
-{ init(FIXED_TYPE + FIXED_SIZE + STD_ARRAY + DataType<_Tp>::type + ACCESS_READ, arr.data(), Size(1, _Nm)); }
+{ init(FIXED_TYPE + FIXED_SIZE + STD_ARRAY + traits::Type<_Tp>::value + ACCESS_READ, arr.data(), Size(1, _Nm)); }
 
 template<std::size_t _Nm> inline
 _InputArray::_InputArray(const std::array<Mat, _Nm>& arr)
@@ -96,11 +96,11 @@ _InputArray::_InputArray(const std::array<Mat, _Nm>& arr)
 
 inline
 _InputArray::_InputArray(const std::vector<bool>& vec)
-{ init(FIXED_TYPE + STD_BOOL_VECTOR + DataType<bool>::type + ACCESS_READ, &vec); }
+{ init(FIXED_TYPE + STD_BOOL_VECTOR + traits::Type<bool>::value + ACCESS_READ, &vec); }
 
 template<typename _Tp> inline
 _InputArray::_InputArray(const std::vector<std::vector<_Tp> >& vec)
-{ init(FIXED_TYPE + STD_VECTOR_VECTOR + DataType<_Tp>::type + ACCESS_READ, &vec); }
+{ init(FIXED_TYPE + STD_VECTOR_VECTOR + traits::Type<_Tp>::value + ACCESS_READ, &vec); }
 
 inline
 _InputArray::_InputArray(const std::vector<std::vector<bool> >&)
@@ -108,19 +108,19 @@ _InputArray::_InputArray(const std::vector<std::vector<bool> >&)
 
 template<typename _Tp> inline
 _InputArray::_InputArray(const std::vector<Mat_<_Tp> >& vec)
-{ init(FIXED_TYPE + STD_VECTOR_MAT + DataType<_Tp>::type + ACCESS_READ, &vec); }
+{ init(FIXED_TYPE + STD_VECTOR_MAT + traits::Type<_Tp>::value + ACCESS_READ, &vec); }
 
 template<typename _Tp, int m, int n> inline
 _InputArray::_InputArray(const Matx<_Tp, m, n>& mtx)
-{ init(FIXED_TYPE + FIXED_SIZE + MATX + DataType<_Tp>::type + ACCESS_READ, &mtx, Size(n, m)); }
+{ init(FIXED_TYPE + FIXED_SIZE + MATX + traits::Type<_Tp>::value + ACCESS_READ, &mtx, Size(n, m)); }
 
 template<typename _Tp> inline
 _InputArray::_InputArray(const _Tp* vec, int n)
-{ init(FIXED_TYPE + FIXED_SIZE + MATX + DataType<_Tp>::type + ACCESS_READ, vec, Size(n, 1)); }
+{ init(FIXED_TYPE + FIXED_SIZE + MATX + traits::Type<_Tp>::value + ACCESS_READ, vec, Size(n, 1)); }
 
 template<typename _Tp> inline
 _InputArray::_InputArray(const Mat_<_Tp>& m)
-{ init(FIXED_TYPE + MAT + DataType<_Tp>::type + ACCESS_READ, &m); }
+{ init(FIXED_TYPE + MAT + traits::Type<_Tp>::value + ACCESS_READ, &m); }
 
 inline _InputArray::_InputArray(const double& val)
 { init(FIXED_TYPE + FIXED_SIZE + MATX + CV_64F + ACCESS_READ, &val, Size(1,1)); }
@@ -170,12 +170,12 @@ inline _OutputArray::_OutputArray(std::vector<UMat>& vec) { init(STD_VECTOR_UMAT
 
 template<typename _Tp> inline
 _OutputArray::_OutputArray(std::vector<_Tp>& vec)
-{ init(FIXED_TYPE + STD_VECTOR + DataType<_Tp>::type + ACCESS_WRITE, &vec); }
+{ init(FIXED_TYPE + STD_VECTOR + traits::Type<_Tp>::value + ACCESS_WRITE, &vec); }
 
 #ifdef CV_CXX_STD_ARRAY
 template<typename _Tp, std::size_t _Nm> inline
 _OutputArray::_OutputArray(std::array<_Tp, _Nm>& arr)
-{ init(FIXED_TYPE + FIXED_SIZE + STD_ARRAY + DataType<_Tp>::type + ACCESS_WRITE, arr.data(), Size(1, _Nm)); }
+{ init(FIXED_TYPE + FIXED_SIZE + STD_ARRAY + traits::Type<_Tp>::value + ACCESS_WRITE, arr.data(), Size(1, _Nm)); }
 
 template<std::size_t _Nm> inline
 _OutputArray::_OutputArray(std::array<Mat, _Nm>& arr)
@@ -188,7 +188,7 @@ _OutputArray::_OutputArray(std::vector<bool>&)
 
 template<typename _Tp> inline
 _OutputArray::_OutputArray(std::vector<std::vector<_Tp> >& vec)
-{ init(FIXED_TYPE + STD_VECTOR_VECTOR + DataType<_Tp>::type + ACCESS_WRITE, &vec); }
+{ init(FIXED_TYPE + STD_VECTOR_VECTOR + traits::Type<_Tp>::value + ACCESS_WRITE, &vec); }
 
 inline
 _OutputArray::_OutputArray(std::vector<std::vector<bool> >&)
@@ -196,28 +196,28 @@ _OutputArray::_OutputArray(std::vector<std::vector<bool> >&)
 
 template<typename _Tp> inline
 _OutputArray::_OutputArray(std::vector<Mat_<_Tp> >& vec)
-{ init(FIXED_TYPE + STD_VECTOR_MAT + DataType<_Tp>::type + ACCESS_WRITE, &vec); }
+{ init(FIXED_TYPE + STD_VECTOR_MAT + traits::Type<_Tp>::value + ACCESS_WRITE, &vec); }
 
 template<typename _Tp> inline
 _OutputArray::_OutputArray(Mat_<_Tp>& m)
-{ init(FIXED_TYPE + MAT + DataType<_Tp>::type + ACCESS_WRITE, &m); }
+{ init(FIXED_TYPE + MAT + traits::Type<_Tp>::value + ACCESS_WRITE, &m); }
 
 template<typename _Tp, int m, int n> inline
 _OutputArray::_OutputArray(Matx<_Tp, m, n>& mtx)
-{ init(FIXED_TYPE + FIXED_SIZE + MATX + DataType<_Tp>::type + ACCESS_WRITE, &mtx, Size(n, m)); }
+{ init(FIXED_TYPE + FIXED_SIZE + MATX + traits::Type<_Tp>::value + ACCESS_WRITE, &mtx, Size(n, m)); }
 
 template<typename _Tp> inline
 _OutputArray::_OutputArray(_Tp* vec, int n)
-{ init(FIXED_TYPE + FIXED_SIZE + MATX + DataType<_Tp>::type + ACCESS_WRITE, vec, Size(n, 1)); }
+{ init(FIXED_TYPE + FIXED_SIZE + MATX + traits::Type<_Tp>::value + ACCESS_WRITE, vec, Size(n, 1)); }
 
 template<typename _Tp> inline
 _OutputArray::_OutputArray(const std::vector<_Tp>& vec)
-{ init(FIXED_TYPE + FIXED_SIZE + STD_VECTOR + DataType<_Tp>::type + ACCESS_WRITE, &vec); }
+{ init(FIXED_TYPE + FIXED_SIZE + STD_VECTOR + traits::Type<_Tp>::value + ACCESS_WRITE, &vec); }
 
 #ifdef CV_CXX_STD_ARRAY
 template<typename _Tp, std::size_t _Nm> inline
 _OutputArray::_OutputArray(const std::array<_Tp, _Nm>& arr)
-{ init(FIXED_TYPE + FIXED_SIZE + STD_ARRAY + DataType<_Tp>::type + ACCESS_WRITE, arr.data(), Size(1, _Nm)); }
+{ init(FIXED_TYPE + FIXED_SIZE + STD_ARRAY + traits::Type<_Tp>::value + ACCESS_WRITE, arr.data(), Size(1, _Nm)); }
 
 template<std::size_t _Nm> inline
 _OutputArray::_OutputArray(const std::array<Mat, _Nm>& arr)
@@ -226,23 +226,23 @@ _OutputArray::_OutputArray(const std::array<Mat, _Nm>& arr)
 
 template<typename _Tp> inline
 _OutputArray::_OutputArray(const std::vector<std::vector<_Tp> >& vec)
-{ init(FIXED_TYPE + FIXED_SIZE + STD_VECTOR_VECTOR + DataType<_Tp>::type + ACCESS_WRITE, &vec); }
+{ init(FIXED_TYPE + FIXED_SIZE + STD_VECTOR_VECTOR + traits::Type<_Tp>::value + ACCESS_WRITE, &vec); }
 
 template<typename _Tp> inline
 _OutputArray::_OutputArray(const std::vector<Mat_<_Tp> >& vec)
-{ init(FIXED_TYPE + FIXED_SIZE + STD_VECTOR_MAT + DataType<_Tp>::type + ACCESS_WRITE, &vec); }
+{ init(FIXED_TYPE + FIXED_SIZE + STD_VECTOR_MAT + traits::Type<_Tp>::value + ACCESS_WRITE, &vec); }
 
 template<typename _Tp> inline
 _OutputArray::_OutputArray(const Mat_<_Tp>& m)
-{ init(FIXED_TYPE + FIXED_SIZE + MAT + DataType<_Tp>::type + ACCESS_WRITE, &m); }
+{ init(FIXED_TYPE + FIXED_SIZE + MAT + traits::Type<_Tp>::value + ACCESS_WRITE, &m); }
 
 template<typename _Tp, int m, int n> inline
 _OutputArray::_OutputArray(const Matx<_Tp, m, n>& mtx)
-{ init(FIXED_TYPE + FIXED_SIZE + MATX + DataType<_Tp>::type + ACCESS_WRITE, &mtx, Size(n, m)); }
+{ init(FIXED_TYPE + FIXED_SIZE + MATX + traits::Type<_Tp>::value + ACCESS_WRITE, &mtx, Size(n, m)); }
 
 template<typename _Tp> inline
 _OutputArray::_OutputArray(const _Tp* vec, int n)
-{ init(FIXED_TYPE + FIXED_SIZE + MATX + DataType<_Tp>::type + ACCESS_WRITE, vec, Size(n, 1)); }
+{ init(FIXED_TYPE + FIXED_SIZE + MATX + traits::Type<_Tp>::value + ACCESS_WRITE, vec, Size(n, 1)); }
 
 inline _OutputArray::_OutputArray(cuda::GpuMat& d_mat)
 { init(CUDA_GPU_MAT + ACCESS_WRITE, &d_mat); }
@@ -289,12 +289,12 @@ inline _InputOutputArray::_InputOutputArray(std::vector<UMat>& vec) { init(STD_V
 
 template<typename _Tp> inline
 _InputOutputArray::_InputOutputArray(std::vector<_Tp>& vec)
-{ init(FIXED_TYPE + STD_VECTOR + DataType<_Tp>::type + ACCESS_RW, &vec); }
+{ init(FIXED_TYPE + STD_VECTOR + traits::Type<_Tp>::value + ACCESS_RW, &vec); }
 
 #ifdef CV_CXX_STD_ARRAY
 template<typename _Tp, std::size_t _Nm> inline
 _InputOutputArray::_InputOutputArray(std::array<_Tp, _Nm>& arr)
-{ init(FIXED_TYPE + FIXED_SIZE + STD_ARRAY + DataType<_Tp>::type + ACCESS_RW, arr.data(), Size(1, _Nm)); }
+{ init(FIXED_TYPE + FIXED_SIZE + STD_ARRAY + traits::Type<_Tp>::value + ACCESS_RW, arr.data(), Size(1, _Nm)); }
 
 template<std::size_t _Nm> inline
 _InputOutputArray::_InputOutputArray(std::array<Mat, _Nm>& arr)
@@ -306,32 +306,32 @@ inline _InputOutputArray::_InputOutputArray(std::vector<bool>&)
 
 template<typename _Tp> inline
 _InputOutputArray::_InputOutputArray(std::vector<std::vector<_Tp> >& vec)
-{ init(FIXED_TYPE + STD_VECTOR_VECTOR + DataType<_Tp>::type + ACCESS_RW, &vec); }
+{ init(FIXED_TYPE + STD_VECTOR_VECTOR + traits::Type<_Tp>::value + ACCESS_RW, &vec); }
 
 template<typename _Tp> inline
 _InputOutputArray::_InputOutputArray(std::vector<Mat_<_Tp> >& vec)
-{ init(FIXED_TYPE + STD_VECTOR_MAT + DataType<_Tp>::type + ACCESS_RW, &vec); }
+{ init(FIXED_TYPE + STD_VECTOR_MAT + traits::Type<_Tp>::value + ACCESS_RW, &vec); }
 
 template<typename _Tp> inline
 _InputOutputArray::_InputOutputArray(Mat_<_Tp>& m)
-{ init(FIXED_TYPE + MAT + DataType<_Tp>::type + ACCESS_RW, &m); }
+{ init(FIXED_TYPE + MAT + traits::Type<_Tp>::value + ACCESS_RW, &m); }
 
 template<typename _Tp, int m, int n> inline
 _InputOutputArray::_InputOutputArray(Matx<_Tp, m, n>& mtx)
-{ init(FIXED_TYPE + FIXED_SIZE + MATX + DataType<_Tp>::type + ACCESS_RW, &mtx, Size(n, m)); }
+{ init(FIXED_TYPE + FIXED_SIZE + MATX + traits::Type<_Tp>::value + ACCESS_RW, &mtx, Size(n, m)); }
 
 template<typename _Tp> inline
 _InputOutputArray::_InputOutputArray(_Tp* vec, int n)
-{ init(FIXED_TYPE + FIXED_SIZE + MATX + DataType<_Tp>::type + ACCESS_RW, vec, Size(n, 1)); }
+{ init(FIXED_TYPE + FIXED_SIZE + MATX + traits::Type<_Tp>::value + ACCESS_RW, vec, Size(n, 1)); }
 
 template<typename _Tp> inline
 _InputOutputArray::_InputOutputArray(const std::vector<_Tp>& vec)
-{ init(FIXED_TYPE + FIXED_SIZE + STD_VECTOR + DataType<_Tp>::type + ACCESS_RW, &vec); }
+{ init(FIXED_TYPE + FIXED_SIZE + STD_VECTOR + traits::Type<_Tp>::value + ACCESS_RW, &vec); }
 
 #ifdef CV_CXX_STD_ARRAY
 template<typename _Tp, std::size_t _Nm> inline
 _InputOutputArray::_InputOutputArray(const std::array<_Tp, _Nm>& arr)
-{ init(FIXED_TYPE + FIXED_SIZE + STD_ARRAY + DataType<_Tp>::type + ACCESS_RW, arr.data(), Size(1, _Nm)); }
+{ init(FIXED_TYPE + FIXED_SIZE + STD_ARRAY + traits::Type<_Tp>::value + ACCESS_RW, arr.data(), Size(1, _Nm)); }
 
 template<std::size_t _Nm> inline
 _InputOutputArray::_InputOutputArray(const std::array<Mat, _Nm>& arr)
@@ -340,23 +340,23 @@ _InputOutputArray::_InputOutputArray(const std::array<Mat, _Nm>& arr)
 
 template<typename _Tp> inline
 _InputOutputArray::_InputOutputArray(const std::vector<std::vector<_Tp> >& vec)
-{ init(FIXED_TYPE + FIXED_SIZE + STD_VECTOR_VECTOR + DataType<_Tp>::type + ACCESS_RW, &vec); }
+{ init(FIXED_TYPE + FIXED_SIZE + STD_VECTOR_VECTOR + traits::Type<_Tp>::value + ACCESS_RW, &vec); }
 
 template<typename _Tp> inline
 _InputOutputArray::_InputOutputArray(const std::vector<Mat_<_Tp> >& vec)
-{ init(FIXED_TYPE + FIXED_SIZE + STD_VECTOR_MAT + DataType<_Tp>::type + ACCESS_RW, &vec); }
+{ init(FIXED_TYPE + FIXED_SIZE + STD_VECTOR_MAT + traits::Type<_Tp>::value + ACCESS_RW, &vec); }
 
 template<typename _Tp> inline
 _InputOutputArray::_InputOutputArray(const Mat_<_Tp>& m)
-{ init(FIXED_TYPE + FIXED_SIZE + MAT + DataType<_Tp>::type + ACCESS_RW, &m); }
+{ init(FIXED_TYPE + FIXED_SIZE + MAT + traits::Type<_Tp>::value + ACCESS_RW, &m); }
 
 template<typename _Tp, int m, int n> inline
 _InputOutputArray::_InputOutputArray(const Matx<_Tp, m, n>& mtx)
-{ init(FIXED_TYPE + FIXED_SIZE + MATX + DataType<_Tp>::type + ACCESS_RW, &mtx, Size(n, m)); }
+{ init(FIXED_TYPE + FIXED_SIZE + MATX + traits::Type<_Tp>::value + ACCESS_RW, &mtx, Size(n, m)); }
 
 template<typename _Tp> inline
 _InputOutputArray::_InputOutputArray(const _Tp* vec, int n)
-{ init(FIXED_TYPE + FIXED_SIZE + MATX + DataType<_Tp>::type + ACCESS_RW, vec, Size(n, 1)); }
+{ init(FIXED_TYPE + FIXED_SIZE + MATX + traits::Type<_Tp>::value + ACCESS_RW, vec, Size(n, 1)); }
 
 inline _InputOutputArray::_InputOutputArray(cuda::GpuMat& d_mat)
 { init(CUDA_GPU_MAT + ACCESS_RW, &d_mat); }
@@ -559,7 +559,7 @@ Mat::Mat(Size _sz, int _type, void* _data, size_t _step)
 
 template<typename _Tp> inline
 Mat::Mat(const std::vector<_Tp>& vec, bool copyData)
-    : flags(MAGIC_VAL | DataType<_Tp>::type | CV_MAT_CONT_FLAG), dims(2), rows((int)vec.size()),
+    : flags(MAGIC_VAL | traits::Type<_Tp>::value | CV_MAT_CONT_FLAG), dims(2), rows((int)vec.size()),
       cols(1), data(0), datastart(0), dataend(0), datalimit(0), allocator(0), u(0), size(&rows), step(0)
 {
     if(vec.empty())
@@ -571,25 +571,25 @@ Mat::Mat(const std::vector<_Tp>& vec, bool copyData)
         datalimit = dataend = datastart + rows * step[0];
     }
     else
-        Mat((int)vec.size(), 1, DataType<_Tp>::type, (uchar*)&vec[0]).copyTo(*this);
+        Mat((int)vec.size(), 1, traits::Type<_Tp>::value, (uchar*)&vec[0]).copyTo(*this);
 }
 
 #ifdef CV_CXX11
 template<typename _Tp, typename> inline
 Mat::Mat(const std::initializer_list<_Tp> list)
-    : flags(MAGIC_VAL | DataType<_Tp>::type | CV_MAT_CONT_FLAG), dims(2), rows((int)list.size()),
+    : flags(MAGIC_VAL | traits::Type<_Tp>::value | CV_MAT_CONT_FLAG), dims(2), rows((int)list.size()),
       cols(1), data(0), datastart(0), dataend(0), datalimit(0), allocator(0), u(0), size(&rows), step(0)
 {
     if(list.size() == 0)
         return;
-    Mat((int)list.size(), 1, DataType<_Tp>::type, (uchar*)list.begin()).copyTo(*this);
+    Mat((int)list.size(), 1, traits::Type<_Tp>::value, (uchar*)list.begin()).copyTo(*this);
 }
 #endif
 
 #ifdef CV_CXX_STD_ARRAY
 template<typename _Tp, std::size_t _Nm> inline
 Mat::Mat(const std::array<_Tp, _Nm>& arr, bool copyData)
-    : flags(MAGIC_VAL | DataType<_Tp>::type | CV_MAT_CONT_FLAG), dims(2), rows((int)arr.size()),
+    : flags(MAGIC_VAL | traits::Type<_Tp>::value | CV_MAT_CONT_FLAG), dims(2), rows((int)arr.size()),
       cols(1), data(0), datastart(0), dataend(0), datalimit(0), allocator(0), u(0), size(&rows), step(0)
 {
     if(arr.empty())
@@ -601,13 +601,13 @@ Mat::Mat(const std::array<_Tp, _Nm>& arr, bool copyData)
         datalimit = dataend = datastart + rows * step[0];
     }
     else
-        Mat((int)arr.size(), 1, DataType<_Tp>::type, (uchar*)arr.data()).copyTo(*this);
+        Mat((int)arr.size(), 1, traits::Type<_Tp>::value, (uchar*)arr.data()).copyTo(*this);
 }
 #endif
 
 template<typename _Tp, int n> inline
 Mat::Mat(const Vec<_Tp, n>& vec, bool copyData)
-    : flags(MAGIC_VAL | DataType<_Tp>::type | CV_MAT_CONT_FLAG), dims(2), rows(n), cols(1), data(0),
+    : flags(MAGIC_VAL | traits::Type<_Tp>::value | CV_MAT_CONT_FLAG), dims(2), rows(n), cols(1), data(0),
       datastart(0), dataend(0), datalimit(0), allocator(0), u(0), size(&rows), step(0)
 {
     if( !copyData )
@@ -617,13 +617,13 @@ Mat::Mat(const Vec<_Tp, n>& vec, bool copyData)
         datalimit = dataend = datastart + rows * step[0];
     }
     else
-        Mat(n, 1, DataType<_Tp>::type, (void*)vec.val).copyTo(*this);
+        Mat(n, 1, traits::Type<_Tp>::value, (void*)vec.val).copyTo(*this);
 }
 
 
 template<typename _Tp, int m, int n> inline
 Mat::Mat(const Matx<_Tp,m,n>& M, bool copyData)
-    : flags(MAGIC_VAL | DataType<_Tp>::type | CV_MAT_CONT_FLAG), dims(2), rows(m), cols(n), data(0),
+    : flags(MAGIC_VAL | traits::Type<_Tp>::value | CV_MAT_CONT_FLAG), dims(2), rows(m), cols(n), data(0),
       datastart(0), dataend(0), datalimit(0), allocator(0), u(0), size(&rows), step(0)
 {
     if( !copyData )
@@ -634,12 +634,12 @@ Mat::Mat(const Matx<_Tp,m,n>& M, bool copyData)
         datalimit = dataend = datastart + rows * step[0];
     }
     else
-        Mat(m, n, DataType<_Tp>::type, (uchar*)M.val).copyTo(*this);
+        Mat(m, n, traits::Type<_Tp>::value, (uchar*)M.val).copyTo(*this);
 }
 
 template<typename _Tp> inline
 Mat::Mat(const Point_<_Tp>& pt, bool copyData)
-    : flags(MAGIC_VAL | DataType<_Tp>::type | CV_MAT_CONT_FLAG), dims(2), rows(2), cols(1), data(0),
+    : flags(MAGIC_VAL | traits::Type<_Tp>::value | CV_MAT_CONT_FLAG), dims(2), rows(2), cols(1), data(0),
       datastart(0), dataend(0), datalimit(0), allocator(0), u(0), size(&rows), step(0)
 {
     if( !copyData )
@@ -650,7 +650,7 @@ Mat::Mat(const Point_<_Tp>& pt, bool copyData)
     }
     else
     {
-        create(2, 1, DataType<_Tp>::type);
+        create(2, 1, traits::Type<_Tp>::value);
         ((_Tp*)data)[0] = pt.x;
         ((_Tp*)data)[1] = pt.y;
     }
@@ -658,7 +658,7 @@ Mat::Mat(const Point_<_Tp>& pt, bool copyData)
 
 template<typename _Tp> inline
 Mat::Mat(const Point3_<_Tp>& pt, bool copyData)
-    : flags(MAGIC_VAL | DataType<_Tp>::type | CV_MAT_CONT_FLAG), dims(2), rows(3), cols(1), data(0),
+    : flags(MAGIC_VAL | traits::Type<_Tp>::value | CV_MAT_CONT_FLAG), dims(2), rows(3), cols(1), data(0),
       datastart(0), dataend(0), datalimit(0), allocator(0), u(0), size(&rows), step(0)
 {
     if( !copyData )
@@ -669,7 +669,7 @@ Mat::Mat(const Point3_<_Tp>& pt, bool copyData)
     }
     else
     {
-        create(3, 1, DataType<_Tp>::type);
+        create(3, 1, traits::Type<_Tp>::value);
         ((_Tp*)data)[0] = pt.x;
         ((_Tp*)data)[1] = pt.y;
         ((_Tp*)data)[2] = pt.z;
@@ -678,7 +678,7 @@ Mat::Mat(const Point3_<_Tp>& pt, bool copyData)
 
 template<typename _Tp> inline
 Mat::Mat(const MatCommaInitializer_<_Tp>& commaInitializer)
-    : flags(MAGIC_VAL | DataType<_Tp>::type | CV_MAT_CONT_FLAG), dims(0), rows(0), cols(0), data(0),
+    : flags(MAGIC_VAL | traits::Type<_Tp>::value | CV_MAT_CONT_FLAG), dims(0), rows(0), cols(0), data(0),
       datastart(0), dataend(0), allocator(0), u(0), size(&rows)
 {
     *this = commaInitializer.operator Mat_<_Tp>();
@@ -1065,7 +1065,7 @@ _Tp& Mat::at(int i0, int i1)
     CV_DbgAssert(data);
     CV_DbgAssert((unsigned)i0 < (unsigned)size.p[0]);
     CV_DbgAssert((unsigned)(i1 * DataType<_Tp>::channels) < (unsigned)(size.p[1] * channels()));
-    CV_DbgAssert(CV_ELEM_SIZE1(DataType<_Tp>::depth) == elemSize1());
+    CV_DbgAssert(CV_ELEM_SIZE1(traits::Depth<_Tp>::value) == elemSize1());
     return ((_Tp*)(data + step.p[0] * i0))[i1];
 }
 
@@ -1076,7 +1076,7 @@ const _Tp& Mat::at(int i0, int i1) const
     CV_DbgAssert(data);
     CV_DbgAssert((unsigned)i0 < (unsigned)size.p[0]);
     CV_DbgAssert((unsigned)(i1 * DataType<_Tp>::channels) < (unsigned)(size.p[1] * channels()));
-    CV_DbgAssert(CV_ELEM_SIZE1(DataType<_Tp>::depth) == elemSize1());
+    CV_DbgAssert(CV_ELEM_SIZE1(traits::Depth<_Tp>::value) == elemSize1());
     return ((const _Tp*)(data + step.p[0] * i0))[i1];
 }
 
@@ -1087,7 +1087,7 @@ _Tp& Mat::at(Point pt)
     CV_DbgAssert(data);
     CV_DbgAssert((unsigned)pt.y < (unsigned)size.p[0]);
     CV_DbgAssert((unsigned)(pt.x * DataType<_Tp>::channels) < (unsigned)(size.p[1] * channels()));
-    CV_DbgAssert(CV_ELEM_SIZE1(DataType<_Tp>::depth) == elemSize1());
+    CV_DbgAssert(CV_ELEM_SIZE1(traits::Depth<_Tp>::value) == elemSize1());
     return ((_Tp*)(data + step.p[0] * pt.y))[pt.x];
 }
 
@@ -1098,7 +1098,7 @@ const _Tp& Mat::at(Point pt) const
     CV_DbgAssert(data);
     CV_DbgAssert((unsigned)pt.y < (unsigned)size.p[0]);
     CV_DbgAssert((unsigned)(pt.x * DataType<_Tp>::channels) < (unsigned)(size.p[1] * channels()));
-    CV_DbgAssert(CV_ELEM_SIZE1(DataType<_Tp>::depth) == elemSize1());
+    CV_DbgAssert(CV_ELEM_SIZE1(traits::Depth<_Tp>::value) == elemSize1());
     return ((const _Tp*)(data + step.p[0] * pt.y))[pt.x];
 }
 
@@ -1108,7 +1108,7 @@ _Tp& Mat::at(int i0)
     CV_DbgAssert(dims <= 2);
     CV_DbgAssert(data);
     CV_DbgAssert((unsigned)i0 < (unsigned)(size.p[0] * size.p[1]));
-    CV_DbgAssert(elemSize() == CV_ELEM_SIZE(DataType<_Tp>::type));
+    CV_DbgAssert(elemSize() == CV_ELEM_SIZE(traits::Type<_Tp>::value));
     if( isContinuous() || size.p[0] == 1 )
         return ((_Tp*)data)[i0];
     if( size.p[1] == 1 )
@@ -1123,7 +1123,7 @@ const _Tp& Mat::at(int i0) const
     CV_DbgAssert(dims <= 2);
     CV_DbgAssert(data);
     CV_DbgAssert((unsigned)i0 < (unsigned)(size.p[0] * size.p[1]));
-    CV_DbgAssert(elemSize() == CV_ELEM_SIZE(DataType<_Tp>::type));
+    CV_DbgAssert(elemSize() == CV_ELEM_SIZE(traits::Type<_Tp>::value));
     if( isContinuous() || size.p[0] == 1 )
         return ((const _Tp*)data)[i0];
     if( size.p[1] == 1 )
@@ -1135,42 +1135,42 @@ const _Tp& Mat::at(int i0) const
 template<typename _Tp> inline
 _Tp& Mat::at(int i0, int i1, int i2)
 {
-    CV_DbgAssert( elemSize() == CV_ELEM_SIZE(DataType<_Tp>::type) );
+    CV_DbgAssert( elemSize() == CV_ELEM_SIZE(traits::Type<_Tp>::value) );
     return *(_Tp*)ptr(i0, i1, i2);
 }
 
 template<typename _Tp> inline
 const _Tp& Mat::at(int i0, int i1, int i2) const
 {
-    CV_DbgAssert( elemSize() == CV_ELEM_SIZE(DataType<_Tp>::type) );
+    CV_DbgAssert( elemSize() == CV_ELEM_SIZE(traits::Type<_Tp>::value) );
     return *(const _Tp*)ptr(i0, i1, i2);
 }
 
 template<typename _Tp> inline
 _Tp& Mat::at(const int* idx)
 {
-    CV_DbgAssert( elemSize() == CV_ELEM_SIZE(DataType<_Tp>::type) );
+    CV_DbgAssert( elemSize() == CV_ELEM_SIZE(traits::Type<_Tp>::value) );
     return *(_Tp*)ptr(idx);
 }
 
 template<typename _Tp> inline
 const _Tp& Mat::at(const int* idx) const
 {
-    CV_DbgAssert( elemSize() == CV_ELEM_SIZE(DataType<_Tp>::type) );
+    CV_DbgAssert( elemSize() == CV_ELEM_SIZE(traits::Type<_Tp>::value) );
     return *(const _Tp*)ptr(idx);
 }
 
 template<typename _Tp, int n> inline
 _Tp& Mat::at(const Vec<int, n>& idx)
 {
-    CV_DbgAssert( elemSize() == CV_ELEM_SIZE(DataType<_Tp>::type) );
+    CV_DbgAssert( elemSize() == CV_ELEM_SIZE(traits::Type<_Tp>::value) );
     return *(_Tp*)ptr(idx.val);
 }
 
 template<typename _Tp, int n> inline
 const _Tp& Mat::at(const Vec<int, n>& idx) const
 {
-    CV_DbgAssert( elemSize() == CV_ELEM_SIZE(DataType<_Tp>::type) );
+    CV_DbgAssert( elemSize() == CV_ELEM_SIZE(traits::Type<_Tp>::value) );
     return *(const _Tp*)ptr(idx.val);
 }
 
@@ -1241,10 +1241,10 @@ Mat::operator Vec<_Tp, n>() const
     CV_Assert( data && dims <= 2 && (rows == 1 || cols == 1) &&
                rows + cols - 1 == n && channels() == 1 );
 
-    if( isContinuous() && type() == DataType<_Tp>::type )
+    if( isContinuous() && type() == traits::Type<_Tp>::value )
         return Vec<_Tp, n>((_Tp*)data);
     Vec<_Tp, n> v;
-    Mat tmp(rows, cols, DataType<_Tp>::type, v.val);
+    Mat tmp(rows, cols, traits::Type<_Tp>::value, v.val);
     convertTo(tmp, tmp.type());
     return v;
 }
@@ -1254,10 +1254,10 @@ Mat::operator Matx<_Tp, m, n>() const
 {
     CV_Assert( data && dims <= 2 && rows == m && cols == n && channels() == 1 );
 
-    if( isContinuous() && type() == DataType<_Tp>::type )
+    if( isContinuous() && type() == traits::Type<_Tp>::value )
         return Matx<_Tp, m, n>((_Tp*)data);
     Matx<_Tp, m, n> mtx;
-    Mat tmp(rows, cols, DataType<_Tp>::type, mtx.val);
+    Mat tmp(rows, cols, traits::Type<_Tp>::value, mtx.val);
     convertTo(tmp, tmp.type());
     return mtx;
 }
@@ -1267,10 +1267,10 @@ void Mat::push_back(const _Tp& elem)
 {
     if( !data )
     {
-        *this = Mat(1, 1, DataType<_Tp>::type, (void*)&elem).clone();
+        *this = Mat(1, 1, traits::Type<_Tp>::value, (void*)&elem).clone();
         return;
     }
-    CV_Assert(DataType<_Tp>::type == type() && cols == 1
+    CV_Assert(traits::Type<_Tp>::value == type() && cols == 1
               /* && dims == 2 (cols == 1 implies dims == 2) */);
     const uchar* tmp = dataend + step[0];
     if( !isSubmatrix() && isContinuous() && tmp <= datalimit )
@@ -1294,6 +1294,13 @@ void Mat::push_back(const MatExpr& expr)
     push_back(static_cast<Mat>(expr));
 }
 
+
+template<typename _Tp> inline
+void Mat::push_back(const std::vector<_Tp>& v)
+{
+    push_back(Mat(v));
+}
+
 #ifdef CV_CXX_MOVE_SEMANTICS
 
 inline
@@ -1462,47 +1469,47 @@ template<typename _Tp> inline
 Mat_<_Tp>::Mat_()
     : Mat()
 {
-    flags = (flags & ~CV_MAT_TYPE_MASK) | DataType<_Tp>::type;
+    flags = (flags & ~CV_MAT_TYPE_MASK) | traits::Type<_Tp>::value;
 }
 
 template<typename _Tp> inline
 Mat_<_Tp>::Mat_(int _rows, int _cols)
-    : Mat(_rows, _cols, DataType<_Tp>::type)
+    : Mat(_rows, _cols, traits::Type<_Tp>::value)
 {
 }
 
 template<typename _Tp> inline
 Mat_<_Tp>::Mat_(int _rows, int _cols, const _Tp& value)
-    : Mat(_rows, _cols, DataType<_Tp>::type)
+    : Mat(_rows, _cols, traits::Type<_Tp>::value)
 {
     *this = value;
 }
 
 template<typename _Tp> inline
 Mat_<_Tp>::Mat_(Size _sz)
-    : Mat(_sz.height, _sz.width, DataType<_Tp>::type)
+    : Mat(_sz.height, _sz.width, traits::Type<_Tp>::value)
 {}
 
 template<typename _Tp> inline
 Mat_<_Tp>::Mat_(Size _sz, const _Tp& value)
-    : Mat(_sz.height, _sz.width, DataType<_Tp>::type)
+    : Mat(_sz.height, _sz.width, traits::Type<_Tp>::value)
 {
     *this = value;
 }
 
 template<typename _Tp> inline
 Mat_<_Tp>::Mat_(int _dims, const int* _sz)
-    : Mat(_dims, _sz, DataType<_Tp>::type)
+    : Mat(_dims, _sz, traits::Type<_Tp>::value)
 {}
 
 template<typename _Tp> inline
 Mat_<_Tp>::Mat_(int _dims, const int* _sz, const _Tp& _s)
-    : Mat(_dims, _sz, DataType<_Tp>::type, Scalar(_s))
+    : Mat(_dims, _sz, traits::Type<_Tp>::value, Scalar(_s))
 {}
 
 template<typename _Tp> inline
 Mat_<_Tp>::Mat_(int _dims, const int* _sz, _Tp* _data, const size_t* _steps)
-    : Mat(_dims, _sz, DataType<_Tp>::type, _data, _steps)
+    : Mat(_dims, _sz, traits::Type<_Tp>::value, _data, _steps)
 {}
 
 template<typename _Tp> inline
@@ -1519,7 +1526,7 @@ template<typename _Tp> inline
 Mat_<_Tp>::Mat_(const Mat& m)
     : Mat()
 {
-    flags = (flags & ~CV_MAT_TYPE_MASK) | DataType<_Tp>::type;
+    flags = (flags & ~CV_MAT_TYPE_MASK) | traits::Type<_Tp>::value;
     *this = m;
 }
 
@@ -1530,7 +1537,7 @@ Mat_<_Tp>::Mat_(const Mat_& m)
 
 template<typename _Tp> inline
 Mat_<_Tp>::Mat_(int _rows, int _cols, _Tp* _data, size_t steps)
-    : Mat(_rows, _cols, DataType<_Tp>::type, _data, steps)
+    : Mat(_rows, _cols, traits::Type<_Tp>::value, _data, steps)
 {}
 
 template<typename _Tp> inline
@@ -1545,7 +1552,7 @@ Mat_<_Tp>::Mat_(const Mat_& m, const Rect& roi)
 
 template<typename _Tp> template<int n> inline
 Mat_<_Tp>::Mat_(const Vec<typename DataType<_Tp>::channel_type, n>& vec, bool copyData)
-    : Mat(n / DataType<_Tp>::channels, 1, DataType<_Tp>::type, (void*)&vec)
+    : Mat(n / DataType<_Tp>::channels, 1, traits::Type<_Tp>::value, (void*)&vec)
 {
     CV_Assert(n%DataType<_Tp>::channels == 0);
     if( copyData )
@@ -1554,7 +1561,7 @@ Mat_<_Tp>::Mat_(const Vec<typename DataType<_Tp>::channel_type, n>& vec, bool co
 
 template<typename _Tp> template<int m, int n> inline
 Mat_<_Tp>::Mat_(const Matx<typename DataType<_Tp>::channel_type, m, n>& M, bool copyData)
-    : Mat(m, n / DataType<_Tp>::channels, DataType<_Tp>::type, (void*)&M)
+    : Mat(m, n / DataType<_Tp>::channels, traits::Type<_Tp>::value, (void*)&M)
 {
     CV_Assert(n % DataType<_Tp>::channels == 0);
     if( copyData )
@@ -1563,7 +1570,7 @@ Mat_<_Tp>::Mat_(const Matx<typename DataType<_Tp>::channel_type, m, n>& M, bool
 
 template<typename _Tp> inline
 Mat_<_Tp>::Mat_(const Point_<typename DataType<_Tp>::channel_type>& pt, bool copyData)
-    : Mat(2 / DataType<_Tp>::channels, 1, DataType<_Tp>::type, (void*)&pt)
+    : Mat(2 / DataType<_Tp>::channels, 1, traits::Type<_Tp>::value, (void*)&pt)
 {
     CV_Assert(2 % DataType<_Tp>::channels == 0);
     if( copyData )
@@ -1572,7 +1579,7 @@ Mat_<_Tp>::Mat_(const Point_<typename DataType<_Tp>::channel_type>& pt, bool cop
 
 template<typename _Tp> inline
 Mat_<_Tp>::Mat_(const Point3_<typename DataType<_Tp>::channel_type>& pt, bool copyData)
-    : Mat(3 / DataType<_Tp>::channels, 1, DataType<_Tp>::type, (void*)&pt)
+    : Mat(3 / DataType<_Tp>::channels, 1, traits::Type<_Tp>::value, (void*)&pt)
 {
     CV_Assert(3 % DataType<_Tp>::channels == 0);
     if( copyData )
@@ -1606,12 +1613,12 @@ Mat_<_Tp>::Mat_(const std::array<_Tp, _Nm>& arr, bool copyData)
 template<typename _Tp> inline
 Mat_<_Tp>& Mat_<_Tp>::operator = (const Mat& m)
 {
-    if( DataType<_Tp>::type == m.type() )
+    if( traits::Type<_Tp>::value == m.type() )
     {
         Mat::operator = (m);
         return *this;
     }
-    if( DataType<_Tp>::depth == m.depth() )
+    if( traits::Depth<_Tp>::value == m.depth() )
     {
         return (*this = m.reshape(DataType<_Tp>::channels, m.dims, 0));
     }
@@ -1638,19 +1645,19 @@ Mat_<_Tp>& Mat_<_Tp>::operator = (const _Tp& s)
 template<typename _Tp> inline
 void Mat_<_Tp>::create(int _rows, int _cols)
 {
-    Mat::create(_rows, _cols, DataType<_Tp>::type);
+    Mat::create(_rows, _cols, traits::Type<_Tp>::value);
 }
 
 template<typename _Tp> inline
 void Mat_<_Tp>::create(Size _sz)
 {
-    Mat::create(_sz, DataType<_Tp>::type);
+    Mat::create(_sz, traits::Type<_Tp>::value);
 }
 
 template<typename _Tp> inline
 void Mat_<_Tp>::create(int _dims, const int* _sz)
 {
-    Mat::create(_dims, _sz, DataType<_Tp>::type);
+    Mat::create(_dims, _sz, traits::Type<_Tp>::value);
 }
 
 template<typename _Tp> inline
@@ -1715,15 +1722,15 @@ size_t Mat_<_Tp>::elemSize1() const
 template<typename _Tp> inline
 int Mat_<_Tp>::type() const
 {
-    CV_DbgAssert( Mat::type() == DataType<_Tp>::type );
-    return DataType<_Tp>::type;
+    CV_DbgAssert( Mat::type() == traits::Type<_Tp>::value );
+    return traits::Type<_Tp>::value;
 }
 
 template<typename _Tp> inline
 int Mat_<_Tp>::depth() const
 {
-    CV_DbgAssert( Mat::depth() == DataType<_Tp>::depth );
-    return DataType<_Tp>::depth;
+    CV_DbgAssert( Mat::depth() == traits::Depth<_Tp>::value );
+    return traits::Depth<_Tp>::value;
 }
 
 template<typename _Tp> inline
@@ -1796,7 +1803,7 @@ _Tp& Mat_<_Tp>::operator ()(int i0, int i1)
     CV_DbgAssert(data);
     CV_DbgAssert((unsigned)i0 < (unsigned)size.p[0]);
     CV_DbgAssert((unsigned)i1 < (unsigned)size.p[1]);
-    CV_DbgAssert(type() == DataType<_Tp>::type);
+    CV_DbgAssert(type() == traits::Type<_Tp>::value);
     return ((_Tp*)(data + step.p[0] * i0))[i1];
 }
 
@@ -1807,7 +1814,7 @@ const _Tp& Mat_<_Tp>::operator ()(int i0, int i1) const
     CV_DbgAssert(data);
     CV_DbgAssert((unsigned)i0 < (unsigned)size.p[0]);
     CV_DbgAssert((unsigned)i1 < (unsigned)size.p[1]);
-    CV_DbgAssert(type() == DataType<_Tp>::type);
+    CV_DbgAssert(type() == traits::Type<_Tp>::value);
     return ((const _Tp*)(data + step.p[0] * i0))[i1];
 }
 
@@ -1818,7 +1825,7 @@ _Tp& Mat_<_Tp>::operator ()(Point pt)
     CV_DbgAssert(data);
     CV_DbgAssert((unsigned)pt.y < (unsigned)size.p[0]);
     CV_DbgAssert((unsigned)pt.x < (unsigned)size.p[1]);
-    CV_DbgAssert(type() == DataType<_Tp>::type);
+    CV_DbgAssert(type() == traits::Type<_Tp>::value);
     return ((_Tp*)(data + step.p[0] * pt.y))[pt.x];
 }
 
@@ -1829,7 +1836,7 @@ const _Tp& Mat_<_Tp>::operator ()(Point pt) const
     CV_DbgAssert(data);
     CV_DbgAssert((unsigned)pt.y < (unsigned)size.p[0]);
     CV_DbgAssert((unsigned)pt.x < (unsigned)size.p[1]);
-    CV_DbgAssert(type() == DataType<_Tp>::type);
+    CV_DbgAssert(type() == traits::Type<_Tp>::value);
     return ((const _Tp*)(data + step.p[0] * pt.y))[pt.x];
 }
 
@@ -1980,19 +1987,19 @@ template<typename _Tp> inline
 Mat_<_Tp>::Mat_(Mat&& m)
     : Mat()
 {
-    flags = (flags & ~CV_MAT_TYPE_MASK) | DataType<_Tp>::type;
+    flags = (flags & ~CV_MAT_TYPE_MASK) | traits::Type<_Tp>::value;
     *this = m;
 }
 
 template<typename _Tp> inline
 Mat_<_Tp>& Mat_<_Tp>::operator = (Mat&& m)
 {
-    if( DataType<_Tp>::type == m.type() )
+    if( traits::Type<_Tp>::value == m.type() )
     {
         Mat::operator = ((Mat&&)m);
         return *this;
     }
-    if( DataType<_Tp>::depth == m.depth() )
+    if( traits::Depth<_Tp>::value == m.depth() )
     {
         Mat::operator = ((Mat&&)m.reshape(DataType<_Tp>::channels, m.dims, 0));
         return *this;
@@ -2006,7 +2013,7 @@ template<typename _Tp> inline
 Mat_<_Tp>::Mat_(MatExpr&& e)
     : Mat()
 {
-    flags = (flags & ~CV_MAT_TYPE_MASK) | DataType<_Tp>::type;
+    flags = (flags & ~CV_MAT_TYPE_MASK) | traits::Type<_Tp>::value;
     *this = Mat(e);
 }
 
@@ -2343,21 +2350,21 @@ SparseMatConstIterator_<_Tp> SparseMat::end() const
 template<typename _Tp> inline
 SparseMat_<_Tp>::SparseMat_()
 {
-    flags = MAGIC_VAL | DataType<_Tp>::type;
+    flags = MAGIC_VAL | traits::Type<_Tp>::value;
 }
 
 template<typename _Tp> inline
 SparseMat_<_Tp>::SparseMat_(int _dims, const int* _sizes)
-    : SparseMat(_dims, _sizes, DataType<_Tp>::type)
+    : SparseMat(_dims, _sizes, traits::Type<_Tp>::value)
 {}
 
 template<typename _Tp> inline
 SparseMat_<_Tp>::SparseMat_(const SparseMat& m)
 {
-    if( m.type() == DataType<_Tp>::type )
+    if( m.type() == traits::Type<_Tp>::value )
         *this = (const SparseMat_<_Tp>&)m;
     else
-        m.convertTo(*this, DataType<_Tp>::type);
+        m.convertTo(*this, traits::Type<_Tp>::value);
 }
 
 template<typename _Tp> inline
@@ -2392,9 +2399,9 @@ SparseMat_<_Tp>& SparseMat_<_Tp>::operator = (const SparseMat_<_Tp>& m)
 template<typename _Tp> inline
 SparseMat_<_Tp>& SparseMat_<_Tp>::operator = (const SparseMat& m)
 {
-    if( m.type() == DataType<_Tp>::type )
+    if( m.type() == traits::Type<_Tp>::value )
         return (*this = (const SparseMat_<_Tp>&)m);
-    m.convertTo(*this, DataType<_Tp>::type);
+    m.convertTo(*this, traits::Type<_Tp>::value);
     return *this;
 }
 
@@ -2415,19 +2422,19 @@ SparseMat_<_Tp> SparseMat_<_Tp>::clone() const
 template<typename _Tp> inline
 void SparseMat_<_Tp>::create(int _dims, const int* _sizes)
 {
-    SparseMat::create(_dims, _sizes, DataType<_Tp>::type);
+    SparseMat::create(_dims, _sizes, traits::Type<_Tp>::value);
 }
 
 template<typename _Tp> inline
 int SparseMat_<_Tp>::type() const
 {
-    return DataType<_Tp>::type;
+    return traits::Type<_Tp>::value;
 }
 
 template<typename _Tp> inline
 int SparseMat_<_Tp>::depth() const
 {
-    return DataType<_Tp>::depth;
+    return traits::Depth<_Tp>::value;
 }
 
 template<typename _Tp> inline
@@ -3128,7 +3135,7 @@ template<typename _Tp> inline
 SparseMatConstIterator_<_Tp>::SparseMatConstIterator_(const SparseMat* _m)
     : SparseMatConstIterator(_m)
 {
-    CV_Assert( _m->type() == DataType<_Tp>::type );
+    CV_Assert( _m->type() == traits::Type<_Tp>::value );
 }
 
 template<typename _Tp> inline
@@ -3264,50 +3271,50 @@ Mat& Mat::operator = (const MatExpr& e)
 template<typename _Tp> inline
 Mat_<_Tp>::Mat_(const MatExpr& e)
 {
-    e.op->assign(e, *this, DataType<_Tp>::type);
+    e.op->assign(e, *this, traits::Type<_Tp>::value);
 }
 
 template<typename _Tp> inline
 Mat_<_Tp>& Mat_<_Tp>::operator = (const MatExpr& e)
 {
-    e.op->assign(e, *this, DataType<_Tp>::type);
+    e.op->assign(e, *this, traits::Type<_Tp>::value);
     return *this;
 }
 
 template<typename _Tp> inline
 MatExpr Mat_<_Tp>::zeros(int rows, int cols)
 {
-    return Mat::zeros(rows, cols, DataType<_Tp>::type);
+    return Mat::zeros(rows, cols, traits::Type<_Tp>::value);
 }
 
 template<typename _Tp> inline
 MatExpr Mat_<_Tp>::zeros(Size sz)
 {
-    return Mat::zeros(sz, DataType<_Tp>::type);
+    return Mat::zeros(sz, traits::Type<_Tp>::value);
 }
 
 template<typename _Tp> inline
 MatExpr Mat_<_Tp>::ones(int rows, int cols)
 {
-    return Mat::ones(rows, cols, DataType<_Tp>::type);
+    return Mat::ones(rows, cols, traits::Type<_Tp>::value);
 }
 
 template<typename _Tp> inline
 MatExpr Mat_<_Tp>::ones(Size sz)
 {
-    return Mat::ones(sz, DataType<_Tp>::type);
+    return Mat::ones(sz, traits::Type<_Tp>::value);
 }
 
 template<typename _Tp> inline
 MatExpr Mat_<_Tp>::eye(int rows, int cols)
 {
-    return Mat::eye(rows, cols, DataType<_Tp>::type);
+    return Mat::eye(rows, cols, traits::Type<_Tp>::value);
 }
 
 template<typename _Tp> inline
 MatExpr Mat_<_Tp>::eye(Size sz)
 {
-    return Mat::eye(sz, DataType<_Tp>::type);
+    return Mat::eye(sz, traits::Type<_Tp>::value);
 }
 
 inline
@@ -3333,7 +3340,7 @@ template<typename _Tp> inline
 MatExpr::operator Mat_<_Tp>() const
 {
     Mat_<_Tp> m;
-    op->assign(*this, m, DataType<_Tp>::type);
+    op->assign(*this, m, traits::Type<_Tp>::value);
     return m;
 }
 
@@ -3566,7 +3573,7 @@ UMat::UMat(const UMat& m)
 
 template<typename _Tp> inline
 UMat::UMat(const std::vector<_Tp>& vec, bool copyData)
-: flags(MAGIC_VAL | DataType<_Tp>::type | CV_MAT_CONT_FLAG), dims(2), rows((int)vec.size()),
+: flags(MAGIC_VAL | traits::Type<_Tp>::value | CV_MAT_CONT_FLAG), dims(2), rows((int)vec.size()),
 cols(1), allocator(0), usageFlags(USAGE_DEFAULT), u(0), offset(0), size(&rows)
 {
     if(vec.empty())
@@ -3577,7 +3584,7 @@ cols(1), allocator(0), usageFlags(USAGE_DEFAULT), u(0), offset(0), size(&rows)
         CV_Error(Error::StsNotImplemented, "");
     }
     else
-        Mat((int)vec.size(), 1, DataType<_Tp>::type, (uchar*)&vec[0]).copyTo(*this);
+        Mat((int)vec.size(), 1, traits::Type<_Tp>::value, (uchar*)&vec[0]).copyTo(*this);
 }
 
 inline
diff --git a/modules/core/include/opencv2/core/matx.hpp b/modules/core/include/opencv2/core/matx.hpp
index 6469962c63..1d1ab4a43c 100644
--- a/modules/core/include/opencv2/core/matx.hpp
+++ b/modules/core/include/opencv2/core/matx.hpp
@@ -100,11 +100,14 @@ In case if C++11 features are avaliable, std::initializer_list can be also used
 template<typename _Tp, int m, int n> class Matx
 {
 public:
-    enum { depth    = DataType<_Tp>::depth,
+    enum {
            rows     = m,
            cols     = n,
            channels = rows*cols,
+#ifdef OPENCV_TRAITS_ENABLE_DEPRECATED
+           depth    = traits::Type<_Tp>::value,
            type     = CV_MAKETYPE(depth, channels),
+#endif
            shortdim = (m < n ? m : n)
          };
 
@@ -259,13 +262,23 @@ public:
     typedef value_type                                    vec_type;
 
     enum { generic_type = 0,
-           depth        = DataType<channel_type>::depth,
            channels     = m * n,
-           fmt          = DataType<channel_type>::fmt + ((channels - 1) << 8),
-           type         = CV_MAKETYPE(depth, channels)
+           fmt          = traits::SafeFmt<channel_type>::fmt + ((channels - 1) << 8)
+#ifdef OPENCV_TRAITS_ENABLE_DEPRECATED
+           ,depth        = DataType<channel_type>::depth
+           ,type         = CV_MAKETYPE(depth, channels)
+#endif
          };
 };
 
+namespace traits {
+template<typename _Tp, int m, int n>
+struct Depth< Matx<_Tp, m, n> > { enum { value = Depth<_Tp>::value }; };
+template<typename _Tp, int m, int n>
+struct Type< Matx<_Tp, m, n> > { enum { value = CV_MAKETYPE(Depth<_Tp>::value, n*m) }; };
+} // namespace
+
+
 /** @brief  Comma-separated Matrix Initializer
 */
 template<typename _Tp, int m, int n> class MatxCommaInitializer
@@ -323,9 +336,13 @@ template<typename _Tp, int cn> class Vec : public Matx<_Tp, cn, 1>
 {
 public:
     typedef _Tp value_type;
-    enum { depth    = Matx<_Tp, cn, 1>::depth,
+    enum {
            channels = cn,
-           type     = CV_MAKETYPE(depth, channels)
+#ifdef OPENCV_TRAITS_ENABLE_DEPRECATED
+           depth    = Matx<_Tp, cn, 1>::depth,
+           type     = CV_MAKETYPE(depth, channels),
+#endif
+           _dummy_enum_finalizer = 0
          };
 
     //! default constructor
@@ -422,13 +439,24 @@ public:
     typedef value_type                                 vec_type;
 
     enum { generic_type = 0,
-           depth        = DataType<channel_type>::depth,
            channels     = cn,
            fmt          = DataType<channel_type>::fmt + ((channels - 1) << 8),
-           type         = CV_MAKETYPE(depth, channels)
+#ifdef OPENCV_TRAITS_ENABLE_DEPRECATED
+           depth        = DataType<channel_type>::depth,
+           type         = CV_MAKETYPE(depth, channels),
+#endif
+           _dummy_enum_finalizer = 0
          };
 };
 
+namespace traits {
+template<typename _Tp, int cn>
+struct Depth< Vec<_Tp, cn> > { enum { value = Depth<_Tp>::value }; };
+template<typename _Tp, int cn>
+struct Type< Vec<_Tp, cn> > { enum { value = CV_MAKETYPE(Depth<_Tp>::value, cn) }; };
+} // namespace
+
+
 /** @brief  Comma-separated Vec Initializer
 */
 template<typename _Tp, int m> class VecCommaInitializer : public MatxCommaInitializer<_Tp, m, 1>
diff --git a/modules/core/include/opencv2/core/persistence.hpp b/modules/core/include/opencv2/core/persistence.hpp
index 65d6a69b1f..e0a6efa465 100644
--- a/modules/core/include/opencv2/core/persistence.hpp
+++ b/modules/core/include/opencv2/core/persistence.hpp
@@ -815,7 +815,7 @@ namespace internal
         VecWriterProxy( FileStorage* _fs ) : fs(_fs) {}
         void operator()(const std::vector<_Tp>& vec) const
         {
-            int _fmt = DataType<_Tp>::fmt;
+            int _fmt = traits::SafeFmt<_Tp>::fmt;
             char fmt[] = { (char)((_fmt >> 8) + '1'), (char)_fmt, '\0' };
             fs->writeRaw(fmt, !vec.empty() ? (uchar*)&vec[0] : 0, vec.size() * sizeof(_Tp));
         }
@@ -846,7 +846,7 @@ namespace internal
         {
             size_t remaining = it->remaining;
             size_t cn = DataType<_Tp>::channels;
-            int _fmt = DataType<_Tp>::fmt;
+            int _fmt = traits::SafeFmt<_Tp>::fmt;
             char fmt[] = { (char)((_fmt >> 8)+'1'), (char)_fmt, '\0' };
             size_t remaining1 = remaining / cn;
             count = count < remaining1 ? count : remaining1;
@@ -999,7 +999,7 @@ void write( FileStorage& fs, const std::vector<DMatch>& vec )
 template<typename _Tp> static inline
 void write( FileStorage& fs, const std::vector<_Tp>& vec )
 {
-    cv::internal::VecWriterProxy<_Tp, DataType<_Tp>::fmt != 0> w(&fs);
+    cv::internal::VecWriterProxy<_Tp, traits::SafeFmt<_Tp>::fmt != 0> w(&fs);
     w(vec);
 }
 
@@ -1076,7 +1076,7 @@ void write(FileStorage& fs, const String& name, const DMatch& r )
 template<typename _Tp> static inline
 void write( FileStorage& fs, const String& name, const std::vector<_Tp>& vec )
 {
-    cv::internal::WriteStructContext ws(fs, name, FileNode::SEQ+(DataType<_Tp>::fmt != 0 ? FileNode::FLOW : 0));
+    cv::internal::WriteStructContext ws(fs, name, FileNode::SEQ+(traits::SafeFmt<_Tp>::fmt != 0 ? FileNode::FLOW : 0));
     write(fs, vec);
 }
 
@@ -1086,7 +1086,7 @@ void write( FileStorage& fs, const String& name, const std::vector< std::vector<
     cv::internal::WriteStructContext ws(fs, name, FileNode::SEQ);
     for(size_t i = 0; i < vec.size(); i++)
     {
-        cv::internal::WriteStructContext ws_(fs, name, FileNode::SEQ+(DataType<_Tp>::fmt != 0 ? FileNode::FLOW : 0));
+        cv::internal::WriteStructContext ws_(fs, name, FileNode::SEQ+(traits::SafeFmt<_Tp>::fmt != 0 ? FileNode::FLOW : 0));
         write(fs, vec[i]);
     }
 }
@@ -1139,7 +1139,7 @@ void read(const FileNode& node, short& value, short default_value)
 template<typename _Tp> static inline
 void read( FileNodeIterator& it, std::vector<_Tp>& vec, size_t maxCount = (size_t)INT_MAX )
 {
-    cv::internal::VecReaderProxy<_Tp, DataType<_Tp>::fmt != 0> r(&it);
+    cv::internal::VecReaderProxy<_Tp, traits::SafeFmt<_Tp>::fmt != 0> r(&it);
     r(vec, maxCount);
 }
 
@@ -1228,7 +1228,7 @@ FileNodeIterator& operator >> (FileNodeIterator& it, _Tp& value)
 template<typename _Tp> static inline
 FileNodeIterator& operator >> (FileNodeIterator& it, std::vector<_Tp>& vec)
 {
-    cv::internal::VecReaderProxy<_Tp, DataType<_Tp>::fmt != 0> r(&it);
+    cv::internal::VecReaderProxy<_Tp, traits::SafeFmt<_Tp>::fmt != 0> r(&it);
     r(vec, (size_t)INT_MAX);
     return it;
 }
diff --git a/modules/core/include/opencv2/core/traits.hpp b/modules/core/include/opencv2/core/traits.hpp
index f83b05f06d..6cb10f44cf 100644
--- a/modules/core/include/opencv2/core/traits.hpp
+++ b/modules/core/include/opencv2/core/traits.hpp
@@ -49,11 +49,15 @@
 namespace cv
 {
 
+//#define OPENCV_TRAITS_ENABLE_DEPRECATED
+
 //! @addtogroup core_basic
 //! @{
 
 /** @brief Template "trait" class for OpenCV primitive data types.
 
+@note Deprecated. This is replaced by "single purpose" traits: traits::Type and traits::Depth
+
 A primitive OpenCV data type is one of unsigned char, bool, signed char, unsigned short, signed
 short, int, float, double, or a tuple of values of one of these types, where all the values in the
 tuple have the same type. Any primitive type from the list can be defined by an identifier in the
@@ -102,10 +106,13 @@ So, such traits are used to tell OpenCV which data type you are working with, ev
 not native to OpenCV. For example, the matrix B initialization above is compiled because OpenCV
 defines the proper specialized template class DataType\<complex\<_Tp\> \> . This mechanism is also
 useful (and used in OpenCV this way) for generic algorithms implementations.
+
+@note Default values were dropped to stop confusing developers about using of unsupported types (see #7599)
 */
 template<typename _Tp> class DataType
 {
 public:
+#ifdef OPENCV_TRAITS_ENABLE_DEPRECATED
     typedef _Tp         value_type;
     typedef value_type  work_type;
     typedef value_type  channel_type;
@@ -116,6 +123,7 @@ public:
            fmt          = 0,
            type = CV_MAKETYPE(depth, channels)
          };
+#endif
 };
 
 template<> class DataType<bool>
@@ -270,11 +278,14 @@ public:
 };
 
 
+#ifdef OPENCV_TRAITS_ENABLE_DEPRECATED
 
 template<int _depth> class TypeDepth
 {
+#ifdef OPENCV_TRAITS_ENABLE_LEGACY_DEFAULTS
     enum { depth = CV_USRTYPE1 };
     typedef void value_type;
+#endif
 };
 
 template<> class TypeDepth<CV_8U>
@@ -319,8 +330,68 @@ template<> class TypeDepth<CV_64F>
     typedef double value_type;
 };
 
+#endif
+
 //! @}
 
+namespace traits {
+
+namespace internal {
+#define CV_CREATE_MEMBER_CHECK(X) \
+template<typename T> class CheckMember_##X { \
+    struct Fallback { int X; }; \
+    struct Derived : T, Fallback { }; \
+    template<typename U, U> struct Check; \
+    typedef char CV_NO[1]; \
+    typedef char CV_YES[2]; \
+    template<typename U> static CV_NO & func(Check<int Fallback::*, &U::X> *); \
+    template<typename U> static CV_YES & func(...); \
+public: \
+    typedef CheckMember_##X type; \
+    enum { value = sizeof(func<Derived>(0)) == sizeof(CV_YES) }; \
+};
+
+CV_CREATE_MEMBER_CHECK(fmt)
+CV_CREATE_MEMBER_CHECK(type)
+
+} // namespace internal
+
+
+template<typename T>
+struct Depth
+{ enum { value = DataType<T>::depth }; };
+
+template<typename T>
+struct Type
+{ enum { value = DataType<T>::type }; };
+
+/** Similar to traits::Type<T> but has value = -1 in case of unknown type (instead of compiler error) */
+template<typename T, bool available = internal::CheckMember_type< DataType<T> >::value >
+struct SafeType {};
+
+template<typename T>
+struct SafeType<T, false>
+{ enum { value = -1 }; };
+
+template<typename T>
+struct SafeType<T, true>
+{ enum { value = Type<T>::value }; };
+
+
+template<typename T, bool available = internal::CheckMember_fmt< DataType<T> >::value >
+struct SafeFmt {};
+
+template<typename T>
+struct SafeFmt<T, false>
+{ enum { fmt = 0 }; };
+
+template<typename T>
+struct SafeFmt<T, true>
+{ enum { fmt = DataType<T>::fmt }; };
+
+
+} // namespace
+
 } // cv
 
 #endif // OPENCV_CORE_TRAITS_HPP
diff --git a/modules/core/test/test_operations.cpp b/modules/core/test/test_operations.cpp
index aea5d5daee..c72cc5eb6a 100644
--- a/modules/core/test/test_operations.cpp
+++ b/modules/core/test/test_operations.cpp
@@ -105,7 +105,7 @@ CV_OperationsTest::~CV_OperationsTest() {}
 template<typename _Tp> void CV_OperationsTest::TestType(Size sz, _Tp value)
 {
     cv::Mat_<_Tp> m(sz);
-    CV_Assert(m.cols == sz.width && m.rows == sz.height && m.depth() == DataType<_Tp>::depth &&
+    CV_Assert(m.cols == sz.width && m.rows == sz.height && m.depth() == cv::traits::Depth<_Tp>::value &&
               m.channels() == DataType<_Tp>::channels &&
               m.elemSize() == sizeof(_Tp) && m.step == m.elemSize()*m.cols);
     for( int y = 0; y < sz.height; y++ )
diff --git a/modules/python/src2/cv2.cpp b/modules/python/src2/cv2.cpp
index be8965c6e0..b24ba5110a 100644
--- a/modules/python/src2/cv2.cpp
+++ b/modules/python/src2/cv2.cpp
@@ -1076,7 +1076,7 @@ template<typename _Tp> struct pyopencvVecConverter
         int i, j, n = (int)PySequence_Fast_GET_SIZE(seq);
         value.resize(n);
 
-        int type = DataType<_Tp>::type;
+        int type = traits::Type<_Tp>::value;
         int depth = CV_MAT_DEPTH(type), channels = CV_MAT_CN(type);
         PyObject** items = PySequence_Fast_ITEMS(seq);
 
@@ -1159,7 +1159,9 @@ template<typename _Tp> struct pyopencvVecConverter
     {
         if(value.empty())
             return PyTuple_New(0);
-        Mat src((int)value.size(), DataType<_Tp>::channels, DataType<_Tp>::depth, (uchar*)&value[0]);
+        int type = traits::Type<_Tp>::value;
+        int depth = CV_MAT_DEPTH(type), channels = CV_MAT_CN(type);
+        Mat src((int)value.size(), channels, depth, (uchar*)&value[0]);
         return pyopencv_from(src);
     }
 };