1 /*M///////////////////////////////////////////////////////////////////////////////////////
2 //
3 //  IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING.
4 //
5 //  By downloading, copying, installing or using the software you agree to this license.
6 //  If you do not agree to this license, do not download, install,
7 //  copy or use the software.
8 //
9 //
10 //                          License Agreement
11 //                For Open Source Computer Vision Library
12 //
13 // Copyright (C) 2000-2008, Intel Corporation, all rights reserved.
14 // Copyright (C) 2009, Willow Garage Inc., all rights reserved.
15 // Copyright (C) 2013, OpenCV Foundation, all rights reserved.
16 // Third party copyrights are property of their respective owners.
17 //
18 // Redistribution and use in source and binary forms, with or without modification,
19 // are permitted provided that the following conditions are met:
20 //
21 //   * Redistribution's of source code must retain the above copyright notice,
22 //     this list of conditions and the following disclaimer.
23 //
24 //   * Redistribution's in binary form must reproduce the above copyright notice,
25 //     this list of conditions and the following disclaimer in the documentation
26 //     and/or other materials provided with the distribution.
27 //
28 //   * The name of the copyright holders may not be used to endorse or promote products
29 //     derived from this software without specific prior written permission.
30 //
31 // This software is provided by the copyright holders and contributors "as is" and
32 // any express or implied warranties, including, but not limited to, the implied
33 // warranties of merchantability and fitness for a particular purpose are disclaimed.
34 // In no event shall the Intel Corporation or contributors be liable for any direct,
35 // indirect, incidental, special, exemplary, or consequential damages
36 // (including, but not limited to, procurement of substitute goods or services;
37 // loss of use, data, or profits; or business interruption) however caused
38 // and on any theory of liability, whether in contract, strict liability,
39 // or tort (including negligence or otherwise) arising in any way out of
40 // the use of this software, even if advised of the possibility of such damage.
41 //
42 //M*/
43 
44 
45 #ifndef OPENCV_CORE_EIGEN_HPP
46 #define OPENCV_CORE_EIGEN_HPP
47 
48 #ifndef EIGEN_WORLD_VERSION
49 #error "Wrong usage of OpenCV's Eigen utility header. Include Eigen's headers first. See https://github.com/opencv/opencv/issues/17366"
50 #endif
51 
52 #include "opencv2/core.hpp"
53 
54 #if defined _MSC_VER && _MSC_VER >= 1200
55 #define NOMINMAX // fix https://github.com/opencv/opencv/issues/17548
56 #pragma warning( disable: 4714 ) //__forceinline is not inlined
57 #pragma warning( disable: 4127 ) //conditional expression is constant
58 #pragma warning( disable: 4244 ) //conversion from '__int64' to 'int', possible loss of data
59 #endif
60 
61 #if !defined(OPENCV_DISABLE_EIGEN_TENSOR_SUPPORT)
62 #if EIGEN_WORLD_VERSION == 3 && EIGEN_MAJOR_VERSION >= 3 \
63     && defined(CV_CXX11) && defined(CV_CXX_STD_ARRAY)
64 #include <unsupported/Eigen/CXX11/Tensor>
65 #define OPENCV_EIGEN_TENSOR_SUPPORT 1
66 #endif  // EIGEN_WORLD_VERSION == 3 && EIGEN_MAJOR_VERSION >= 3
67 #endif  // !defined(OPENCV_DISABLE_EIGEN_TENSOR_SUPPORT)
68 
69 namespace cv
70 {
71 
72 /** @addtogroup core_eigen
73 These functions are provided for OpenCV-Eigen interoperability. They convert `Mat`
74 objects to corresponding `Eigen::Matrix` objects and vice-versa. Consult the [Eigen
75 documentation](https://eigen.tuxfamily.org/dox/group__TutorialMatrixClass.html) for
76 information about the `Matrix` template type.
77 
78 @note Using these functions requires the `Eigen/Dense` or similar header to be
79 included before this header.
80 */
81 //! @{
82 
83 #if defined(OPENCV_EIGEN_TENSOR_SUPPORT) || defined(CV_DOXYGEN)
84 /** @brief Converts an Eigen::Tensor to a cv::Mat.
85 
86 The method converts an Eigen::Tensor with shape (H x W x C) to a cv::Mat where:
87  H = number of rows
88  W = number of columns
89  C = number of channels
90 
91 Usage:
92 \code
93 Eigen::Tensor<float, 3, Eigen::RowMajor> a_tensor(...);
94 // populate tensor with values
95 Mat a_mat;
96 eigen2cv(a_tensor, a_mat);
97 \endcode
98 */
99 template <typename _Tp, int _layout> static inline
eigen2cv(const Eigen::Tensor<_Tp,3,_layout> & src,OutputArray dst)100 void eigen2cv( const Eigen::Tensor<_Tp, 3, _layout> &src, OutputArray dst )
101 {
102     if( !(_layout & Eigen::RowMajorBit) )
103     {
104         const std::array<int, 3> shuffle{2, 1, 0};
105         Eigen::Tensor<_Tp, 3, !_layout> row_major_tensor = src.swap_layout().shuffle(shuffle);
106         Mat _src(src.dimension(0), src.dimension(1), CV_MAKETYPE(DataType<_Tp>::type, src.dimension(2)), row_major_tensor.data());
107         _src.copyTo(dst);
108     }
109     else
110     {
111         Mat _src(src.dimension(0), src.dimension(1), CV_MAKETYPE(DataType<_Tp>::type, src.dimension(2)), (void *)src.data());
112         _src.copyTo(dst);
113     }
114 }
115 
116 /** @brief Converts a cv::Mat to an Eigen::Tensor.
117 
118 The method converts a cv::Mat to an Eigen Tensor with shape (H x W x C) where:
119  H = number of rows
120  W = number of columns
121  C = number of channels
122 
123 Usage:
124 \code
125 Mat a_mat(...);
126 // populate Mat with values
127 Eigen::Tensor<float, 3, Eigen::RowMajor> a_tensor(...);
128 cv2eigen(a_mat, a_tensor);
129 \endcode
130 */
131 template <typename _Tp, int _layout> static inline
cv2eigen(const Mat & src,Eigen::Tensor<_Tp,3,_layout> & dst)132 void cv2eigen( const Mat &src, Eigen::Tensor<_Tp, 3, _layout> &dst )
133 {
134     if( !(_layout & Eigen::RowMajorBit) )
135     {
136         Eigen::Tensor<_Tp, 3, !_layout> row_major_tensor(src.rows, src.cols, src.channels());
137         Mat _dst(src.rows, src.cols, CV_MAKETYPE(DataType<_Tp>::type, src.channels()), row_major_tensor.data());
138         if (src.type() == _dst.type())
139             src.copyTo(_dst);
140         else
141             src.convertTo(_dst, _dst.type());
142         const std::array<int, 3> shuffle{2, 1, 0};
143         dst = row_major_tensor.swap_layout().shuffle(shuffle);
144     }
145     else
146     {
147         dst.resize(src.rows, src.cols, src.channels());
148         Mat _dst(src.rows, src.cols, CV_MAKETYPE(DataType<_Tp>::type, src.channels()), dst.data());
149         if (src.type() == _dst.type())
150             src.copyTo(_dst);
151         else
152             src.convertTo(_dst, _dst.type());
153     }
154 }
155 
156 /** @brief Maps cv::Mat data to an Eigen::TensorMap.
157 
158 The method wraps an existing Mat data array with an Eigen TensorMap of shape (H x W x C) where:
159  H = number of rows
160  W = number of columns
161  C = number of channels
162 
163 Explicit instantiation of the return type is required.
164 
165 @note Caller should be aware of the lifetime of the cv::Mat instance and take appropriate safety measures.
166 The cv::Mat instance will retain ownership of the data and the Eigen::TensorMap will lose access when the cv::Mat data is deallocated.
167 
168 The example below initializes a cv::Mat and produces an Eigen::TensorMap:
169 \code
170 float arr[] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11};
171 Mat a_mat(2, 2, CV_32FC3, arr);
172 Eigen::TensorMap<Eigen::Tensor<float, 3, Eigen::RowMajor>> a_tensormap = cv2eigen_tensormap<float>(a_mat);
173 \endcode
174 */
175 template <typename _Tp> static inline
cv2eigen_tensormap(InputArray src)176 Eigen::TensorMap<Eigen::Tensor<_Tp, 3, Eigen::RowMajor>> cv2eigen_tensormap(InputArray src)
177 {
178     Mat mat = src.getMat();
179     CV_CheckTypeEQ(mat.type(), CV_MAKETYPE(traits::Type<_Tp>::value, mat.channels()), "");
180     return Eigen::TensorMap<Eigen::Tensor<_Tp, 3, Eigen::RowMajor>>((_Tp *)mat.data, mat.rows, mat.cols, mat.channels());
181 }
182 #endif // OPENCV_EIGEN_TENSOR_SUPPORT
183 
184 template<typename _Tp, int _rows, int _cols, int _options, int _maxRows, int _maxCols> static inline
eigen2cv(const Eigen::Matrix<_Tp,_rows,_cols,_options,_maxRows,_maxCols> & src,OutputArray dst)185 void eigen2cv( const Eigen::Matrix<_Tp, _rows, _cols, _options, _maxRows, _maxCols>& src, OutputArray dst )
186 {
187     if( !(src.Flags & Eigen::RowMajorBit) )
188     {
189         Mat _src(src.cols(), src.rows(), traits::Type<_Tp>::value,
190               (void*)src.data(), src.outerStride()*sizeof(_Tp));
191         transpose(_src, dst);
192     }
193     else
194     {
195         Mat _src(src.rows(), src.cols(), traits::Type<_Tp>::value,
196                  (void*)src.data(), src.outerStride()*sizeof(_Tp));
197         _src.copyTo(dst);
198     }
199 }
200 
201 // Matx case
202 template<typename _Tp, int _rows, int _cols, int _options, int _maxRows, int _maxCols> static inline
eigen2cv(const Eigen::Matrix<_Tp,_rows,_cols,_options,_maxRows,_maxCols> & src,Matx<_Tp,_rows,_cols> & dst)203 void eigen2cv( const Eigen::Matrix<_Tp, _rows, _cols, _options, _maxRows, _maxCols>& src,
204                Matx<_Tp, _rows, _cols>& dst )
205 {
206     if( !(src.Flags & Eigen::RowMajorBit) )
207     {
208         dst = Matx<_Tp, _cols, _rows>(static_cast<const _Tp*>(src.data())).t();
209     }
210     else
211     {
212         dst = Matx<_Tp, _rows, _cols>(static_cast<const _Tp*>(src.data()));
213     }
214 }
215 
216 template<typename _Tp, int _rows, int _cols, int _options, int _maxRows, int _maxCols> static inline
cv2eigen(const Mat & src,Eigen::Matrix<_Tp,_rows,_cols,_options,_maxRows,_maxCols> & dst)217 void cv2eigen( const Mat& src,
218                Eigen::Matrix<_Tp, _rows, _cols, _options, _maxRows, _maxCols>& dst )
219 {
220     CV_DbgAssert(src.rows == _rows && src.cols == _cols);
221     if( !(dst.Flags & Eigen::RowMajorBit) )
222     {
223         const Mat _dst(src.cols, src.rows, traits::Type<_Tp>::value,
224                  dst.data(), (size_t)(dst.outerStride()*sizeof(_Tp)));
225         if( src.type() == _dst.type() )
226             transpose(src, _dst);
227         else if( src.cols == src.rows )
228         {
229             src.convertTo(_dst, _dst.type());
230             transpose(_dst, _dst);
231         }
232         else
233             Mat(src.t()).convertTo(_dst, _dst.type());
234     }
235     else
236     {
237         const Mat _dst(src.rows, src.cols, traits::Type<_Tp>::value,
238                  dst.data(), (size_t)(dst.outerStride()*sizeof(_Tp)));
239         src.convertTo(_dst, _dst.type());
240     }
241 }
242 
243 // Matx case
244 template<typename _Tp, int _rows, int _cols, int _options, int _maxRows, int _maxCols> static inline
cv2eigen(const Matx<_Tp,_rows,_cols> & src,Eigen::Matrix<_Tp,_rows,_cols,_options,_maxRows,_maxCols> & dst)245 void cv2eigen( const Matx<_Tp, _rows, _cols>& src,
246                Eigen::Matrix<_Tp, _rows, _cols, _options, _maxRows, _maxCols>& dst )
247 {
248     if( !(dst.Flags & Eigen::RowMajorBit) )
249     {
250         const Mat _dst(_cols, _rows, traits::Type<_Tp>::value,
251                  dst.data(), (size_t)(dst.outerStride()*sizeof(_Tp)));
252         transpose(src, _dst);
253     }
254     else
255     {
256         const Mat _dst(_rows, _cols, traits::Type<_Tp>::value,
257                  dst.data(), (size_t)(dst.outerStride()*sizeof(_Tp)));
258         Mat(src).copyTo(_dst);
259     }
260 }
261 
262 template<typename _Tp>  static inline
cv2eigen(const Mat & src,Eigen::Matrix<_Tp,Eigen::Dynamic,Eigen::Dynamic> & dst)263 void cv2eigen( const Mat& src,
264                Eigen::Matrix<_Tp, Eigen::Dynamic, Eigen::Dynamic>& dst )
265 {
266     dst.resize(src.rows, src.cols);
267     if( !(dst.Flags & Eigen::RowMajorBit) )
268     {
269         const Mat _dst(src.cols, src.rows, traits::Type<_Tp>::value,
270              dst.data(), (size_t)(dst.outerStride()*sizeof(_Tp)));
271         if( src.type() == _dst.type() )
272             transpose(src, _dst);
273         else if( src.cols == src.rows )
274         {
275             src.convertTo(_dst, _dst.type());
276             transpose(_dst, _dst);
277         }
278         else
279             Mat(src.t()).convertTo(_dst, _dst.type());
280     }
281     else
282     {
283         const Mat _dst(src.rows, src.cols, traits::Type<_Tp>::value,
284                  dst.data(), (size_t)(dst.outerStride()*sizeof(_Tp)));
285         src.convertTo(_dst, _dst.type());
286     }
287 }
288 
289 // Matx case
290 template<typename _Tp, int _rows, int _cols> static inline
cv2eigen(const Matx<_Tp,_rows,_cols> & src,Eigen::Matrix<_Tp,Eigen::Dynamic,Eigen::Dynamic> & dst)291 void cv2eigen( const Matx<_Tp, _rows, _cols>& src,
292                Eigen::Matrix<_Tp, Eigen::Dynamic, Eigen::Dynamic>& dst )
293 {
294     dst.resize(_rows, _cols);
295     if( !(dst.Flags & Eigen::RowMajorBit) )
296     {
297         const Mat _dst(_cols, _rows, traits::Type<_Tp>::value,
298              dst.data(), (size_t)(dst.outerStride()*sizeof(_Tp)));
299         transpose(src, _dst);
300     }
301     else
302     {
303         const Mat _dst(_rows, _cols, traits::Type<_Tp>::value,
304                  dst.data(), (size_t)(dst.outerStride()*sizeof(_Tp)));
305         Mat(src).copyTo(_dst);
306     }
307 }
308 
309 template<typename _Tp> static inline
cv2eigen(const Mat & src,Eigen::Matrix<_Tp,Eigen::Dynamic,1> & dst)310 void cv2eigen( const Mat& src,
311                Eigen::Matrix<_Tp, Eigen::Dynamic, 1>& dst )
312 {
313     CV_Assert(src.cols == 1);
314     dst.resize(src.rows);
315 
316     if( !(dst.Flags & Eigen::RowMajorBit) )
317     {
318         const Mat _dst(src.cols, src.rows, traits::Type<_Tp>::value,
319                  dst.data(), (size_t)(dst.outerStride()*sizeof(_Tp)));
320         if( src.type() == _dst.type() )
321             transpose(src, _dst);
322         else
323             Mat(src.t()).convertTo(_dst, _dst.type());
324     }
325     else
326     {
327         const Mat _dst(src.rows, src.cols, traits::Type<_Tp>::value,
328                  dst.data(), (size_t)(dst.outerStride()*sizeof(_Tp)));
329         src.convertTo(_dst, _dst.type());
330     }
331 }
332 
333 // Matx case
334 template<typename _Tp, int _rows> static inline
cv2eigen(const Matx<_Tp,_rows,1> & src,Eigen::Matrix<_Tp,Eigen::Dynamic,1> & dst)335 void cv2eigen( const Matx<_Tp, _rows, 1>& src,
336                Eigen::Matrix<_Tp, Eigen::Dynamic, 1>& dst )
337 {
338     dst.resize(_rows);
339 
340     if( !(dst.Flags & Eigen::RowMajorBit) )
341     {
342         const Mat _dst(1, _rows, traits::Type<_Tp>::value,
343                  dst.data(), (size_t)(dst.outerStride()*sizeof(_Tp)));
344         transpose(src, _dst);
345     }
346     else
347     {
348         const Mat _dst(_rows, 1, traits::Type<_Tp>::value,
349                  dst.data(), (size_t)(dst.outerStride()*sizeof(_Tp)));
350         src.copyTo(_dst);
351     }
352 }
353 
354 
355 template<typename _Tp> static inline
cv2eigen(const Mat & src,Eigen::Matrix<_Tp,1,Eigen::Dynamic> & dst)356 void cv2eigen( const Mat& src,
357                Eigen::Matrix<_Tp, 1, Eigen::Dynamic>& dst )
358 {
359     CV_Assert(src.rows == 1);
360     dst.resize(src.cols);
361     if( !(dst.Flags & Eigen::RowMajorBit) )
362     {
363         const Mat _dst(src.cols, src.rows, traits::Type<_Tp>::value,
364                  dst.data(), (size_t)(dst.outerStride()*sizeof(_Tp)));
365         if( src.type() == _dst.type() )
366             transpose(src, _dst);
367         else
368             Mat(src.t()).convertTo(_dst, _dst.type());
369     }
370     else
371     {
372         const Mat _dst(src.rows, src.cols, traits::Type<_Tp>::value,
373                  dst.data(), (size_t)(dst.outerStride()*sizeof(_Tp)));
374         src.convertTo(_dst, _dst.type());
375     }
376 }
377 
378 //Matx
379 template<typename _Tp, int _cols> static inline
cv2eigen(const Matx<_Tp,1,_cols> & src,Eigen::Matrix<_Tp,1,Eigen::Dynamic> & dst)380 void cv2eigen( const Matx<_Tp, 1, _cols>& src,
381                Eigen::Matrix<_Tp, 1, Eigen::Dynamic>& dst )
382 {
383     dst.resize(_cols);
384     if( !(dst.Flags & Eigen::RowMajorBit) )
385     {
386         const Mat _dst(_cols, 1, traits::Type<_Tp>::value,
387                  dst.data(), (size_t)(dst.outerStride()*sizeof(_Tp)));
388         transpose(src, _dst);
389     }
390     else
391     {
392         const Mat _dst(1, _cols, traits::Type<_Tp>::value,
393                  dst.data(), (size_t)(dst.outerStride()*sizeof(_Tp)));
394         Mat(src).copyTo(_dst);
395     }
396 }
397 
398 //! @}
399 
400 } // cv
401 
402 #endif
403