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