Merge pull request #9034 from sovrasov:mats_from_initializer_list

Add constructors taking initializer_list for some of OpenCV data types (#9034)

* Add a constructor taking initializer_list for Matx

* Add a constructor taking initializer list for Mat and Mat_

* Add one more method to initialize Mat to the corresponding tutorial

* Add a note how to initialize Matx

* CV_CXX_11->CV_CXX11
pull/8511/head^2
Vladislav Sovrasov 8 years ago committed by Alexander Alekhin
parent 11626fe32c
commit e5fbb4f5d2
  1. 4
      doc/tutorials/core/mat_the_basic_image_container/mat_the_basic_image_container.markdown
  2. 12
      modules/core/include/opencv2/core/cvdef.h
  3. 10
      modules/core/include/opencv2/core/mat.hpp
  4. 19
      modules/core/include/opencv2/core/mat.inl.hpp
  5. 46
      modules/core/include/opencv2/core/matx.hpp
  6. 4
      modules/core/include/opencv2/core/utility.hpp
  7. 28
      modules/core/test/test_mat.cpp
  8. 2
      samples/cpp/tutorial_code/core/how_to_use_OpenCV_parallel_for_/how_to_use_OpenCV_parallel_for_.cpp
  9. 8
      samples/cpp/tutorial_code/core/mat_the_basic_image_container/mat_the_basic_image_container.cpp

@ -192,10 +192,12 @@ object in multiple ways:
![](images/MatBasicContainerOut3.png) ![](images/MatBasicContainerOut3.png)
- For small matrices you may use comma separated initializers: - For small matrices you may use comma separated initializers or initializer lists (C++11 support is required in the last case):
@snippet mat_the_basic_image_container.cpp comma @snippet mat_the_basic_image_container.cpp comma
@snippet mat_the_basic_image_container.cpp list
![](images/MatBasicContainerOut6.png) ![](images/MatBasicContainerOut6.png)
- Create a new header for an existing *Mat* object and @ref cv::Mat::clone or @ref cv::Mat::copyTo it. - Create a new header for an existing *Mat* object and @ref cv::Mat::clone or @ref cv::Mat::copyTo it.

@ -357,13 +357,13 @@ Cv64suf;
/****************************************************************************************\ /****************************************************************************************\
* C++ 11 * * C++ 11 *
\****************************************************************************************/ \****************************************************************************************/
#ifndef CV_CXX_11 #ifndef CV_CXX11
# if __cplusplus >= 201103L || defined(_MSC_VER) && _MSC_VER >= 1600 # if __cplusplus >= 201103L || (defined(_MSC_VER) && _MSC_VER >= 1600)
# define CV_CXX_11 1 # define CV_CXX11 1
# endif # endif
#else #else
# if CV_CXX_11 == 0 # if CV_CXX11 == 0
# undef CV_CXX_11 # undef CV_CXX11
# endif # endif
#endif #endif
@ -373,7 +373,7 @@ Cv64suf;
\****************************************************************************************/ \****************************************************************************************/
#ifndef CV_CXX_MOVE_SEMANTICS #ifndef CV_CXX_MOVE_SEMANTICS
# if __cplusplus >= 201103L || defined(__GXX_EXPERIMENTAL_CXX0X__) || defined(_MSC_VER) && _MSC_VER >= 1600 # if __cplusplus >= 201103L || defined(__GXX_EXPERIMENTAL_CXX0X__) || (defined(_MSC_VER) && _MSC_VER >= 1600)
# define CV_CXX_MOVE_SEMANTICS 1 # define CV_CXX_MOVE_SEMANTICS 1
# elif defined(__clang) # elif defined(__clang)
# if __has_feature(cxx_rvalue_references) # if __has_feature(cxx_rvalue_references)

@ -981,6 +981,12 @@ public:
*/ */
template<typename _Tp> explicit Mat(const std::vector<_Tp>& vec, bool copyData=false); template<typename _Tp> explicit Mat(const std::vector<_Tp>& vec, bool copyData=false);
#ifdef CV_CXX11
/** @overload
*/
template<typename _Tp> explicit Mat(const std::initializer_list<_Tp> list);
#endif
#ifdef CV_CXX_STD_ARRAY #ifdef CV_CXX_STD_ARRAY
/** @overload /** @overload
*/ */
@ -2170,6 +2176,10 @@ public:
explicit Mat_(const Point3_<typename DataType<_Tp>::channel_type>& pt, bool copyData=true); explicit Mat_(const Point3_<typename DataType<_Tp>::channel_type>& pt, bool copyData=true);
explicit Mat_(const MatCommaInitializer_<_Tp>& commaInitializer); explicit Mat_(const MatCommaInitializer_<_Tp>& commaInitializer);
#ifdef CV_CXX11
Mat_(std::initializer_list<_Tp> values);
#endif
#ifdef CV_CXX_STD_ARRAY #ifdef CV_CXX_STD_ARRAY
template <std::size_t _Nm> explicit Mat_(const std::array<_Tp, _Nm>& arr, bool copyData=false); template <std::size_t _Nm> explicit Mat_(const std::array<_Tp, _Nm>& arr, bool copyData=false);
#endif #endif

@ -570,6 +570,18 @@ Mat::Mat(const std::vector<_Tp>& vec, bool copyData)
Mat((int)vec.size(), 1, DataType<_Tp>::type, (uchar*)&vec[0]).copyTo(*this); Mat((int)vec.size(), 1, DataType<_Tp>::type, (uchar*)&vec[0]).copyTo(*this);
} }
#ifdef CV_CXX11
template<typename _Tp> 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()),
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);
}
#endif
#ifdef CV_CXX_STD_ARRAY #ifdef CV_CXX_STD_ARRAY
template<typename _Tp, std::size_t _Nm> inline template<typename _Tp, std::size_t _Nm> inline
Mat::Mat(const std::array<_Tp, _Nm>& arr, bool copyData) Mat::Mat(const std::array<_Tp, _Nm>& arr, bool copyData)
@ -1573,6 +1585,13 @@ Mat_<_Tp>::Mat_(const std::vector<_Tp>& vec, bool copyData)
: Mat(vec, copyData) : Mat(vec, copyData)
{} {}
#ifdef CV_CXX11
template<typename _Tp> inline
Mat_<_Tp>::Mat_(std::initializer_list<_Tp> list)
: Mat(list)
{}
#endif
#ifdef CV_CXX_STD_ARRAY #ifdef CV_CXX_STD_ARRAY
template<typename _Tp> template<std::size_t _Nm> inline template<typename _Tp> template<std::size_t _Nm> inline
Mat_<_Tp>::Mat_(const std::array<_Tp, _Nm>& arr, bool copyData) Mat_<_Tp>::Mat_(const std::array<_Tp, _Nm>& arr, bool copyData)

@ -53,6 +53,10 @@
#include "opencv2/core/traits.hpp" #include "opencv2/core/traits.hpp"
#include "opencv2/core/saturate.hpp" #include "opencv2/core/saturate.hpp"
#ifdef CV_CXX11
#include <initializer_list>
#endif
namespace cv namespace cv
{ {
@ -77,12 +81,21 @@ If you need a more flexible type, use Mat . The elements of the matrix M are acc
M(i,j) notation. Most of the common matrix operations (see also @ref MatrixExpressions ) are M(i,j) notation. Most of the common matrix operations (see also @ref MatrixExpressions ) are
available. To do an operation on Matx that is not implemented, you can easily convert the matrix to available. To do an operation on Matx that is not implemented, you can easily convert the matrix to
Mat and backwards: Mat and backwards:
@code @code{.cpp}
Matx33f m(1, 2, 3, Matx33f m(1, 2, 3,
4, 5, 6, 4, 5, 6,
7, 8, 9); 7, 8, 9);
cout << sum(Mat(m*m.t())) << endl; cout << sum(Mat(m*m.t())) << endl;
@endcode @endcode
Except of the plain constructor which takes a list of elements, Matx can be initialized from a C-array:
@code{.cpp}
float values[] = { 1, 2, 3};
Matx31f m(values);
@endcode
In case if C++11 features are avaliable, std::initializer_list can be also used to initizlize Matx:
@code{.cpp}
Matx31f m = { 1, 2, 3};
@endcode
*/ */
template<typename _Tp, int m, int n> class Matx template<typename _Tp, int m, int n> class Matx
{ {
@ -125,6 +138,10 @@ public:
_Tp v12, _Tp v13, _Tp v14, _Tp v15); //!< 1x16, 4x4 or 16x1 matrix _Tp v12, _Tp v13, _Tp v14, _Tp v15); //!< 1x16, 4x4 or 16x1 matrix
explicit Matx(const _Tp* vals); //!< initialize from a plain array explicit Matx(const _Tp* vals); //!< initialize from a plain array
#ifdef CV_CXX11
Matx(std::initializer_list<_Tp>); //!< initialize from an initializer list
#endif
static Matx all(_Tp alpha); static Matx all(_Tp alpha);
static Matx zeros(); static Matx zeros();
static Matx ones(); static Matx ones();
@ -327,6 +344,10 @@ public:
Vec(_Tp v0, _Tp v1, _Tp v2, _Tp v3, _Tp v4, _Tp v5, _Tp v6, _Tp v7, _Tp v8, _Tp v9, _Tp v10, _Tp v11, _Tp v12, _Tp v13); //!< 14-element vector constructor Vec(_Tp v0, _Tp v1, _Tp v2, _Tp v3, _Tp v4, _Tp v5, _Tp v6, _Tp v7, _Tp v8, _Tp v9, _Tp v10, _Tp v11, _Tp v12, _Tp v13); //!< 14-element vector constructor
explicit Vec(const _Tp* values); explicit Vec(const _Tp* values);
#ifdef CV_CXX11
Vec(std::initializer_list<_Tp>);
#endif
Vec(const Vec<_Tp, cn>& v); Vec(const Vec<_Tp, cn>& v);
static Vec all(_Tp alpha); static Vec all(_Tp alpha);
@ -616,6 +637,19 @@ Matx<_Tp, m, n>::Matx(const _Tp* values)
for( int i = 0; i < channels; i++ ) val[i] = values[i]; for( int i = 0; i < channels; i++ ) val[i] = values[i];
} }
#ifdef CV_CXX11
template<typename _Tp, int m, int n> inline
Matx<_Tp, m, n>::Matx(std::initializer_list<_Tp> list)
{
CV_DbgAssert(list.size() == channels);
int i = 0;
for(const auto& elem : list)
{
val[i++] = elem;
}
}
#endif
template<typename _Tp, int m, int n> inline template<typename _Tp, int m, int n> inline
Matx<_Tp, m, n> Matx<_Tp, m, n>::all(_Tp alpha) Matx<_Tp, m, n> Matx<_Tp, m, n>::all(_Tp alpha)
{ {
@ -957,6 +991,12 @@ template<typename _Tp, int cn> inline
Vec<_Tp, cn>::Vec(const _Tp* values) Vec<_Tp, cn>::Vec(const _Tp* values)
: Matx<_Tp, cn, 1>(values) {} : Matx<_Tp, cn, 1>(values) {}
#ifdef CV_CXX11
template<typename _Tp, int cn> inline
Vec<_Tp, cn>::Vec(std::initializer_list<_Tp> list)
: Matx<_Tp, cn, 1>(list) {}
#endif
template<typename _Tp, int cn> inline template<typename _Tp, int cn> inline
Vec<_Tp, cn>::Vec(const Vec<_Tp, cn>& m) Vec<_Tp, cn>::Vec(const Vec<_Tp, cn>& m)
: Matx<_Tp, cn, 1>(m.val) {} : Matx<_Tp, cn, 1>(m.val) {}
@ -1081,7 +1121,7 @@ Vec<_Tp, cn> normalize(const Vec<_Tp, cn>& v)
//////////////////////////////// matx comma initializer ////////////////////////////////// //////////////////////////////// vec comma initializer //////////////////////////////////
template<typename _Tp, typename _T2, int cn> static inline template<typename _Tp, typename _T2, int cn> static inline

@ -56,7 +56,7 @@
#include "opencv2/core.hpp" #include "opencv2/core.hpp"
#include <ostream> #include <ostream>
#ifdef CV_CXX_11 #ifdef CV_CXX11
#include <functional> #include <functional>
#endif #endif
@ -482,7 +482,7 @@ public:
*/ */
CV_EXPORTS void parallel_for_(const Range& range, const ParallelLoopBody& body, double nstripes=-1.); CV_EXPORTS void parallel_for_(const Range& range, const ParallelLoopBody& body, double nstripes=-1.);
#ifdef CV_CXX_11 #ifdef CV_CXX11
class ParallelLoopBodyLambdaWrapper : public ParallelLoopBody class ParallelLoopBodyLambdaWrapper : public ParallelLoopBody
{ {
private: private:

@ -1398,6 +1398,15 @@ TEST(Core_Matx, fromMat_)
ASSERT_EQ( cvtest::norm(a, b, NORM_INF), 0.); ASSERT_EQ( cvtest::norm(a, b, NORM_INF), 0.);
} }
#ifdef CV_CXX11
TEST(Core_Matx, from_initializer_list)
{
Mat_<double> a = (Mat_<double>(2,2) << 10, 11, 12, 13);
Matx22d b = {10, 11, 12, 13};
ASSERT_EQ( cvtest::norm(a, b, NORM_INF), 0.);
}
#endif
TEST(Core_InputArray, empty) TEST(Core_InputArray, empty)
{ {
vector<vector<Point> > data; vector<vector<Point> > data;
@ -1735,7 +1744,7 @@ TEST(Mat, regression_8680)
ASSERT_EQ(mat.channels(), 2); ASSERT_EQ(mat.channels(), 2);
} }
#ifdef CV_CXX_11 #ifdef CV_CXX11
TEST(Mat_, range_based_for) TEST(Mat_, range_based_for)
{ {
@ -1751,4 +1760,21 @@ TEST(Mat_, range_based_for)
ASSERT_DOUBLE_EQ(norm(img, ref), 0.); ASSERT_DOUBLE_EQ(norm(img, ref), 0.);
} }
TEST(Mat, from_initializer_list)
{
Mat A({1.f, 2.f, 3.f});
Mat_<float> B(3, 1); B << 1, 2, 3;
ASSERT_EQ(A.type(), CV_32F);
ASSERT_DOUBLE_EQ(norm(A, B, NORM_INF), 0.);
}
TEST(Mat_, from_initializer_list)
{
Mat_<float> A = {1, 2, 3};
Mat_<float> B(3, 1); B << 1, 2, 3;
ASSERT_DOUBLE_EQ(norm(A, B, NORM_INF), 0.);
}
#endif #endif

@ -102,7 +102,7 @@ int main()
double t1 = (double) getTickCount(); double t1 = (double) getTickCount();
#ifdef CV_CXX_11 #ifdef CV_CXX11
//! [mandelbrot-parallel-call-cxx11] //! [mandelbrot-parallel-call-cxx11]
parallel_for_(Range(0, mandelbrotImg.rows*mandelbrotImg.cols), [&](const Range& range){ parallel_for_(Range(0, mandelbrotImg.rows*mandelbrotImg.cols), [&](const Range& range){

@ -58,7 +58,13 @@ int main(int,char**)
Mat C = (Mat_<double>(3,3) << 0, -1, 0, -1, 5, -1, 0, -1, 0); Mat C = (Mat_<double>(3,3) << 0, -1, 0, -1, 5, -1, 0, -1, 0);
cout << "C = " << endl << " " << C << endl << endl; cout << "C = " << endl << " " << C << endl << endl;
//! [comma] //! [comma]
// do the same with initializer_list
#ifdef CV_CXX11
//! [list]
C = (Mat_<double>({0, -1, 0, -1, 5, -1, 0, -1, 0})).reshape(3);
cout << "C = " << endl << " " << C << endl << endl;
//! [list]
#endif
//! [clone] //! [clone]
Mat RowClone = C.row(1).clone(); Mat RowClone = C.row(1).clone();
cout << "RowClone = " << endl << " " << RowClone << endl << endl; cout << "RowClone = " << endl << " " << RowClone << endl << endl;

Loading…
Cancel
Save