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