mat.hpp 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354
  1. // This file is part of OpenCV project.
  2. // It is subject to the license terms in the LICENSE file found in the top-level directory
  3. // of this distribution and at http://opencv.org/license.html.
  4. //
  5. // Copyright (C) 2018 Intel Corporation
  6. #ifndef OPENCV_GAPI_OWN_MAT_HPP
  7. #define OPENCV_GAPI_OWN_MAT_HPP
  8. #include <opencv2/gapi/opencv_includes.hpp>
  9. #include <opencv2/gapi/own/types.hpp>
  10. #include <opencv2/gapi/own/scalar.hpp>
  11. #include <opencv2/gapi/own/saturate.hpp>
  12. #include <opencv2/gapi/own/assert.hpp>
  13. #include <memory> //std::shared_ptr
  14. #include <cstring> //std::memcpy
  15. #include <numeric> //std::accumulate
  16. #include <vector>
  17. #include <opencv2/gapi/util/throw.hpp>
  18. namespace cv { namespace gapi { namespace own {
  19. namespace detail {
  20. template <typename T, unsigned char channels>
  21. void assign_row(void* ptr, int cols, Scalar const& s)
  22. {
  23. auto p = static_cast<T*>(ptr);
  24. for (int c = 0; c < cols; c++)
  25. {
  26. for (int ch = 0; ch < channels; ch++)
  27. {
  28. p[c * channels + ch] = saturate<T>(s[ch], roundd);
  29. }
  30. }
  31. }
  32. inline size_t default_step(int type, int cols)
  33. {
  34. return CV_ELEM_SIZE(type) * cols;
  35. }
  36. //Matrix header, i.e. fields that are unique to each Mat object.
  37. //Devoted class is needed to implement custom behavior on move (erasing state of moved from object)
  38. struct MatHeader{
  39. enum { AUTO_STEP = 0};
  40. enum { TYPE_MASK = 0x00000FFF };
  41. MatHeader() = default;
  42. MatHeader(int _rows, int _cols, int type, void* _data, size_t _step)
  43. : flags((type & TYPE_MASK)), rows(_rows), cols(_cols), data((uchar*)_data), step(_step == AUTO_STEP ? detail::default_step(type, _cols) : _step)
  44. {}
  45. MatHeader(const std::vector<int> &_dims, int type, void* _data)
  46. : flags((type & TYPE_MASK)), data((uchar*)_data), step(0), dims(_dims)
  47. {}
  48. MatHeader(const MatHeader& ) = default;
  49. MatHeader(MatHeader&& src) : MatHeader(src) // reuse copy constructor here
  50. {
  51. MatHeader empty; //give it a name to call copy(not move) assignment below
  52. src = empty;
  53. }
  54. MatHeader& operator=(const MatHeader& ) = default;
  55. MatHeader& operator=(MatHeader&& src)
  56. {
  57. *this = src; //calling a copy assignment here, not move one
  58. MatHeader empty; //give it a name to call copy(not move) assignment below
  59. src = empty;
  60. return *this;
  61. }
  62. /*! includes several bit-fields:
  63. - depth
  64. - number of channels
  65. */
  66. int flags = 0;
  67. //! the number of rows and columns or (-1, -1) when the matrix has more than 2 dimensions
  68. int rows = 0, cols = 0;
  69. //! pointer to the data
  70. uchar* data = nullptr;
  71. size_t step = 0;
  72. //! dimensions (ND-case)
  73. std::vector<int> dims;
  74. };
  75. } // namespace detail
  76. //concise version of cv::Mat suitable for GAPI needs (used when no dependence on OpenCV is required)
  77. class Mat : public detail::MatHeader{
  78. public:
  79. Mat() = default;
  80. /** @overload
  81. @param _rows Number of rows in a 2D array.
  82. @param _cols Number of columns in a 2D array.
  83. @param _type Array type. Use CV_8UC1, ..., CV_64FC4 to create 1-4 channel matrices, or
  84. CV_8UC(n), ..., CV_64FC(n) to create multi-channel (up to CV_CN_MAX channels) matrices.
  85. @param _data Pointer to the user data. Matrix constructors that take data and step parameters do not
  86. allocate matrix data. Instead, they just initialize the matrix header that points to the specified
  87. data, which means that no data is copied. This operation is very efficient and can be used to
  88. process external data using OpenCV functions. The external data is not automatically deallocated, so
  89. you should take care of it.
  90. @param _step Number of bytes each matrix row occupies. The value should include the padding bytes at
  91. the end of each row, if any. If the parameter is missing (set to AUTO_STEP ), no padding is assumed
  92. and the actual step is calculated as cols*elemSize(). See Mat::elemSize.
  93. */
  94. Mat(int _rows, int _cols, int _type, void* _data, size_t _step = AUTO_STEP)
  95. : MatHeader (_rows, _cols, _type, _data, _step)
  96. {}
  97. Mat(const std::vector<int> &_dims, int _type, void* _data)
  98. : MatHeader (_dims, _type, _data)
  99. {}
  100. Mat(std::vector<int> &&_dims, int _type, void* _data)
  101. : MatHeader (std::move(_dims), _type, _data)
  102. {}
  103. Mat(Mat const& src, const Rect& roi )
  104. : Mat(src)
  105. {
  106. rows = roi.height;
  107. cols = roi.width;
  108. data = ptr(roi.y, roi.x);
  109. }
  110. Mat(Mat const& ) = default;
  111. Mat(Mat&& ) = default;
  112. Mat& operator=(Mat const& ) = default;
  113. Mat& operator=(Mat&& ) = default;
  114. /** @brief Sets all or some of the array elements to the specified value.
  115. @param s Assigned scalar converted to the actual array type.
  116. */
  117. Mat& operator = (const Scalar& s)
  118. {
  119. constexpr unsigned max_channels = 4; //Scalar can't fit more than 4
  120. using func_p_t = void (*)(void*, int, Scalar const&);
  121. using detail::assign_row;
  122. #define TABLE_ENTRY(type) {assign_row<type, 1>, assign_row<type, 2>, assign_row<type, 3>, assign_row<type, 4>}
  123. static constexpr func_p_t func_tbl[][max_channels] = {
  124. TABLE_ENTRY(uchar),
  125. TABLE_ENTRY(schar),
  126. TABLE_ENTRY(ushort),
  127. TABLE_ENTRY(short),
  128. TABLE_ENTRY(int),
  129. TABLE_ENTRY(float),
  130. TABLE_ENTRY(double)
  131. };
  132. #undef TABLE_ENTRY
  133. static_assert(CV_8U == 0 && CV_8S == 1 && CV_16U == 2 && CV_16S == 3
  134. && CV_32S == 4 && CV_32F == 5 && CV_64F == 6,
  135. "OCV type ids used as indexes to array, thus exact numbers are important!"
  136. );
  137. const auto depth = static_cast<unsigned int>(this->depth());
  138. GAPI_Assert(depth < sizeof(func_tbl)/sizeof(func_tbl[0]));
  139. if (dims.empty())
  140. {
  141. const auto channels = static_cast<unsigned int>(this->channels());
  142. GAPI_Assert(channels <= max_channels);
  143. auto* f = func_tbl[depth][channels - 1];
  144. for (int r = 0; r < rows; ++r)
  145. {
  146. (*f)(static_cast<void *>(ptr(r)), cols, s );
  147. }
  148. }
  149. else
  150. {
  151. auto* f = func_tbl[depth][0];
  152. // FIXME: better to refactor assign_row to use std::size_t by default
  153. (*f)(static_cast<void *>(data), static_cast<int>(total()), s);
  154. }
  155. return *this;
  156. }
  157. /** @brief Returns the matrix element size in bytes.
  158. The method returns the matrix element size in bytes. For example, if the matrix type is CV_16SC3 ,
  159. the method returns 3\*sizeof(short) or 6.
  160. */
  161. size_t elemSize() const
  162. {
  163. return CV_ELEM_SIZE(type());
  164. }
  165. /** @brief Returns the type of a matrix element.
  166. The method returns a matrix element type. This is an identifier compatible with the CvMat type
  167. system, like CV_16SC3 or 16-bit signed 3-channel array, and so on.
  168. */
  169. int type() const {return CV_MAT_TYPE(flags);}
  170. /** @brief Returns the depth of a matrix element.
  171. The method returns the identifier of the matrix element depth (the type of each individual channel).
  172. For example, for a 16-bit signed element array, the method returns CV_16S . A complete list of
  173. matrix types contains the following values:
  174. - CV_8U - 8-bit unsigned integers ( 0..255 )
  175. - CV_8S - 8-bit signed integers ( -128..127 )
  176. - CV_16U - 16-bit unsigned integers ( 0..65535 )
  177. - CV_16S - 16-bit signed integers ( -32768..32767 )
  178. - CV_32S - 32-bit signed integers ( -2147483648..2147483647 )
  179. - CV_32F - 32-bit floating-point numbers ( -FLT_MAX..FLT_MAX, INF, NAN )
  180. - CV_64F - 64-bit floating-point numbers ( -DBL_MAX..DBL_MAX, INF, NAN )
  181. */
  182. int depth() const {return CV_MAT_DEPTH(flags);}
  183. /** @brief Returns the number of matrix channels.
  184. The method returns the number of matrix channels.
  185. If matrix is N-dimensional, -1 is returned.
  186. */
  187. int channels() const {return dims.empty() ? CV_MAT_CN(flags) : -1;}
  188. /**
  189. @param _rows New number of rows.
  190. @param _cols New number of columns.
  191. @param _type New matrix type.
  192. */
  193. void create(int _rows, int _cols, int _type)
  194. {
  195. create(Size{_cols, _rows}, _type);
  196. }
  197. /** @overload
  198. @param _size Alternative new matrix size specification: Size(cols, rows)
  199. @param _type New matrix type.
  200. */
  201. void create(Size _size, int _type)
  202. {
  203. GAPI_Assert(_size.height >= 0 && _size.width >= 0);
  204. if (_size != Size{cols, rows} )
  205. {
  206. Mat tmp{_size.height, _size.width, _type, nullptr};
  207. tmp.memory.reset(new uchar[ tmp.step * tmp.rows], [](uchar * p){delete[] p;});
  208. tmp.data = tmp.memory.get();
  209. *this = std::move(tmp);
  210. }
  211. }
  212. void create(const std::vector<int> &_dims, int _type)
  213. {
  214. // FIXME: make a proper reallocation-on-demands
  215. // WARNING: no tensor views, so no strides
  216. Mat tmp{_dims, _type, nullptr};
  217. // FIXME: this accumulate duplicates a lot
  218. const auto sz = std::accumulate(_dims.begin(), _dims.end(), 1, std::multiplies<int>());
  219. tmp.memory.reset(new uchar[CV_ELEM_SIZE(_type)*sz], [](uchar * p){delete[] p;});
  220. tmp.data = tmp.memory.get();
  221. *this = std::move(tmp);
  222. }
  223. /** @brief Creates a full copy of the matrix and the underlying data.
  224. The method creates a full copy of the matrix. The original step[] is not taken into account.
  225. So, the copy has a continuous buffer occupying total() * elemSize() bytes.
  226. */
  227. Mat clone() const
  228. {
  229. Mat m;
  230. copyTo(m);
  231. return m;
  232. }
  233. /** @brief Copies the matrix to another one.
  234. The method copies the matrix data to another matrix. Before copying the data, the method invokes :
  235. @code
  236. m.create(this->size(), this->type());
  237. @endcode
  238. so that the destination matrix is reallocated if needed. While m.copyTo(m); works flawlessly, the
  239. function does not handle the case of a partial overlap between the source and the destination
  240. matrices.
  241. */
  242. void copyTo(Mat& dst) const
  243. {
  244. if (dims.empty())
  245. {
  246. dst.create(rows, cols, type());
  247. for (int r = 0; r < rows; ++r)
  248. {
  249. std::copy_n(ptr(r), detail::default_step(type(),cols), dst.ptr(r));
  250. }
  251. }
  252. else
  253. {
  254. dst.create(dims, depth());
  255. std::copy_n(data, total()*elemSize(), data);
  256. }
  257. }
  258. /** @brief Returns true if the array has no elements.
  259. The method returns true if Mat::total() is 0 or if Mat::data is NULL. Because of pop_back() and
  260. resize() methods `M.total() == 0` does not imply that `M.data == NULL`.
  261. */
  262. bool empty() const
  263. {
  264. return data == 0 || total() == 0;
  265. }
  266. /** @brief Returns the total number of array elements.
  267. The method returns the number of array elements (a number of pixels if the array represents an
  268. image).
  269. */
  270. size_t total() const
  271. {
  272. return dims.empty()
  273. ? (static_cast<std::size_t>(rows) * cols)
  274. : std::accumulate(dims.begin(), dims.end(), static_cast<std::size_t>(1), std::multiplies<size_t>());
  275. }
  276. /** @overload
  277. @param roi Extracted submatrix specified as a rectangle.
  278. */
  279. Mat operator()( const Rect& roi ) const
  280. {
  281. return Mat{*this, roi};
  282. }
  283. /** @brief Returns a pointer to the specified matrix row.
  284. The methods return `uchar*` or typed pointer to the specified matrix row. See the sample in
  285. Mat::isContinuous to know how to use these methods.
  286. @param row Index along the dimension 0
  287. @param col Index along the dimension 1
  288. */
  289. uchar* ptr(int row, int col = 0)
  290. {
  291. return const_cast<uchar*>(const_cast<const Mat*>(this)->ptr(row,col));
  292. }
  293. /** @overload */
  294. const uchar* ptr(int row, int col = 0) const
  295. {
  296. return data + step * row + CV_ELEM_SIZE(type()) * col;
  297. }
  298. private:
  299. //actual memory allocated for storage, or nullptr if object is non owning view to over memory
  300. std::shared_ptr<uchar> memory;
  301. };
  302. } //namespace own
  303. } //namespace gapi
  304. } //namespace cv
  305. #endif /* OPENCV_GAPI_OWN_MAT_HPP */