1 /** 2 * Copyright 2020 Huawei Technologies Co., Ltd 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 #ifndef MINI_MAT_H_ 18 #define MINI_MAT_H_ 19 20 #include <string> 21 #include <memory> 22 23 #include "include/api/types.h" 24 25 namespace mindspore { 26 namespace dataset { 27 constexpr int kAlign = 16; 28 constexpr size_t kMaxDims = 3; 29 30 template <typename T> 31 struct Chn1 { Chn1Chn132 Chn1(T c1) : c1(c1) {} 33 T c1; 34 }; 35 36 template <typename T> 37 struct Chn2 { Chn2Chn238 Chn2(T c1, T c2) : c1(c1), c2(c2) {} 39 T c1; 40 T c2; 41 }; 42 43 template <typename T> 44 struct Chn3 { Chn3Chn345 Chn3(T c1, T c2, T c3) : c1(c1), c2(c2), c3(c3) {} 46 T c1; 47 T c2; 48 T c3; 49 }; 50 51 template <typename T> 52 struct Chn4 { Chn4Chn453 Chn4(T c1, T c2, T c3, T c4) : c1(c1), c2(c2), c3(c3), c4(c4) {} 54 T c1; 55 T c2; 56 T c3; 57 T c4; 58 }; 59 60 /// \brief Struct representing the location of pixel. 61 /// \note Location usually starts from the left top of image. 62 /// \par Example 63 /// \code 64 /// // Define a point p points to the pixel at (X=10,Y=5). 65 /// Point p = Point(10, 5); 66 /// \endcode 67 struct Point { 68 float x; ///< X location of pixel. 69 float y; ///< Y location of pixel. 70 PointPoint71 Point() : x(0), y(0) {} ///< Constructor. PointPoint72 Point(float _x, float _y) : x(_x), y(_y) {} ///< Constructor. 73 }; 74 75 typedef struct imageToolsImage { 76 int w; 77 int h; 78 int stride; 79 int dataType; 80 void *image_buff; 81 } imageToolsImage_t; 82 83 using BOOL_C1 = Chn1<bool>; 84 using BOOL_C2 = Chn2<bool>; 85 using BOOL_C3 = Chn3<bool>; 86 using BOOL_C4 = Chn4<bool>; 87 88 using UINT8_C1 = Chn1<uint8_t>; 89 using UINT8_C2 = Chn2<uint8_t>; 90 using UINT8_C3 = Chn3<uint8_t>; 91 using UINT8_C4 = Chn4<uint8_t>; 92 93 using INT8_C1 = Chn1<int8_t>; 94 using INT8_C2 = Chn2<int8_t>; 95 using INT8_C3 = Chn3<int8_t>; 96 using INT8_C4 = Chn4<int8_t>; 97 98 using UINT16_C1 = Chn1<uint16_t>; 99 using UINT16_C2 = Chn2<uint16_t>; 100 using UINT16_C3 = Chn3<uint16_t>; 101 using UINT16_C4 = Chn4<uint16_t>; 102 103 using INT16_C1 = Chn1<int16_t>; 104 using INT16_C2 = Chn2<int16_t>; 105 using INT16_C3 = Chn3<int16_t>; 106 using INT16_C4 = Chn4<int16_t>; 107 108 using UINT32_C1 = Chn1<uint32_t>; 109 using UINT32_C2 = Chn2<uint32_t>; 110 using UINT32_C3 = Chn3<uint32_t>; 111 using UINT32_C4 = Chn4<uint32_t>; 112 113 using INT32_C1 = Chn1<int32_t>; 114 using INT32_C2 = Chn2<int32_t>; 115 using INT32_C3 = Chn3<int32_t>; 116 using INT32_C4 = Chn4<int32_t>; 117 118 using UINT64_C1 = Chn1<uint64_t>; 119 using UINT64_C2 = Chn2<uint64_t>; 120 using UINT64_C3 = Chn3<uint64_t>; 121 using UINT64_C4 = Chn4<uint64_t>; 122 123 using INT64_C1 = Chn1<int64_t>; 124 using INT64_C2 = Chn2<int64_t>; 125 using INT64_C3 = Chn3<int64_t>; 126 using INT64_C4 = Chn4<int64_t>; 127 128 using FLOAT32_C1 = Chn1<float>; 129 using FLOAT32_C2 = Chn2<float>; 130 using FLOAT32_C3 = Chn3<float>; 131 using FLOAT32_C4 = Chn4<float>; 132 133 using FLOAT64_C1 = Chn1<double>; 134 using FLOAT64_C2 = Chn2<double>; 135 using FLOAT64_C3 = Chn3<double>; 136 using FLOAT64_C4 = Chn4<double>; 137 138 enum LPixelType { 139 BGR = 0, /**< Pixel in BGR type. */ 140 RGB = 1, /**< Pixel in RGB type. */ 141 RGBA = 2, /**< Pixel in RGBA type. */ 142 RGBA2GRAY = 3, /**< Convert image from RGBA to GRAY. */ 143 RGBA2BGR = 4, /**< Convert image from RGBA to BGR. */ 144 RGBA2RGB = 5, /**< Convert image from RGBA to RGB. */ 145 NV212BGR = 6, /**< Convert image from NV21 to BGR. */ 146 NV122BGR = 7, /**< Convert image from NV12 to BGR. */ 147 }; 148 149 enum WARP_BORDER_MODE { WARP_BORDER_MODE_CONSTANT }; 150 151 /// \brief Class representing the data type. 152 /// \note Supported data type list: 153 /// - LDataType::BOOL 154 /// - LDataType::INT8 155 /// - LDataType::UINT8 156 /// - LDataType::INT16 157 /// - LDataType::INT32 158 /// - LDataType::UINT32 159 /// - LDataType::INT64 160 /// - LDataType::UINT64 161 /// - LDataType::FLOAT16 162 /// - LDataType::FLOAT32 163 /// - LDataType::FLOAT64 164 /// - LDataType::DOUBLE 165 class DATASET_API LDataType { 166 public: 167 enum Type : uint8_t { 168 UNKNOWN = 0, /**< Unknown data type. */ 169 BOOL, /**< BOOL data type. */ 170 INT8, /**< INT8 data type. */ 171 UINT8, /**< UINT8 data type. */ 172 INT16, /**< INT16 data type. */ 173 UINT16, /**< UINT16 data type. */ 174 INT32, /**< INT32 data type. */ 175 UINT32, /**< UINT32 data type. */ 176 INT64, /**< INT64 data type. */ 177 UINT64, /**< UINT64 data type. */ 178 FLOAT16, /**< FLOAT16 data type. */ 179 FLOAT32, /**< FLOAT32 data type. */ 180 FLOAT64, /**< FLOAT64 data type. */ 181 DOUBLE, /**< DOUBLE data type. */ 182 NUM_OF_TYPES /**< number of types. */ 183 }; 184 185 /// \brief Constructor. LDataType()186 LDataType() : type_(UNKNOWN) {} 187 LDataType(Type d)188 LDataType(Type d) : type_(d) {} 189 190 /// \brief Destructor. 191 ~LDataType() = default; 192 Value()193 inline Type Value() const { return type_; } 194 195 inline bool operator==(const LDataType &ps) const { return this->type_ == ps.type_; } 196 197 inline bool operator!=(const LDataType &ps) const { return this->type_ != ps.type_; } 198 199 /// \brief Function to return the length of data type. 200 /// \return Memory length of data type. SizeInBytes()201 uint8_t SizeInBytes() const { 202 if (type_ < LDataType::NUM_OF_TYPES) { 203 return SIZE_IN_BYTES[type_]; 204 } else { 205 return 0; 206 } 207 } 208 209 public: 210 static inline const uint8_t SIZE_IN_BYTES[] = { 211 0, /**< Unknown size. */ 212 1, /**< Size of BOOL. */ 213 1, /**< Size of INT8. */ 214 1, /**< Size of UINT8. */ 215 2, /**< Size of INT16. */ 216 2, /**< Size of UINT16. */ 217 4, /**< Size of INT32. */ 218 4, /**< Size of UINT32. */ 219 8, /**< Size of INT64. */ 220 8, /**< Size of UINT64. */ 221 2, /**< Size of FLOAT16. */ 222 4, /**< Size of FLOAT32. */ 223 8, /**< Size of FLOAT64. */ 224 8, /**< Size of DOUBLE. */ 225 }; 226 227 Type type_; 228 }; 229 230 /// \brief Basic class storing the image data. 231 class DATASET_API LiteMat { 232 public: 233 /// \brief Constructor. 234 LiteMat(); 235 236 /// \brief Function to create an LiteMat object. 237 /// \param[in] width The width of the input object. 238 /// \param[in] data_type The data type of the input object. 239 explicit LiteMat(int width, LDataType data_type = LDataType::UINT8); 240 241 /// \brief Function to create an LiteMat object. 242 /// \param[in] width The width of the input object. 243 /// \param[in] height The height of the input object. 244 /// \param[in] data_type The data type of the input object. 245 LiteMat(int width, int height, LDataType data_type = LDataType::UINT8); 246 247 /// \brief Function to create an LiteMat object. 248 /// \param[in] width The width of the input object. 249 /// \param[in] height The height of the input object. 250 /// \param[in] p_data The pointer data of the input object. 251 /// \param[in] data_type The data type of the input object. 252 LiteMat(int width, int height, void *p_data, LDataType data_type = LDataType::UINT8); 253 254 /// \brief Function to create an LiteMat object. 255 /// \param[in] width The width of the input object. 256 /// \param[in] height The height of the input object. 257 /// \param[in] channel The channel of the input object. 258 /// \param[in] data_type The data type of the input object. 259 LiteMat(int width, int height, int channel, LDataType data_type = LDataType::UINT8); 260 261 /// \brief Function to create an LiteMat object. 262 /// \param[in] width The width of the input object. 263 /// \param[in] height The height of the input object. 264 /// \param[in] channel The channel of the input object. 265 /// \param[in] p_data The pointer data of the input object. 266 /// \param[in] data_type The data type of the input object. 267 LiteMat(int width, int height, int channel, void *p_data, LDataType data_type = LDataType::UINT8); 268 269 /// \brief Destructor. 270 ~LiteMat(); 271 272 LiteMat(const LiteMat &m); 273 274 /// \brief Perform Init operation on given LiteMat 275 /// \param[in] width Set width for given LiteMat. 276 /// \param[in] data_type Set data type for given LiteMat. 277 void Init(int width, LDataType data_type = LDataType::UINT8); 278 279 /// \brief Perform Init operation on given LiteMat 280 /// \param[in] width Set width for given LiteMat. 281 /// \param[in] height Set height for given LiteMat. 282 /// \param[in] data_type Set data type for given LiteMat. 283 void Init(int width, int height, LDataType data_type = LDataType::UINT8); 284 285 /// \brief Perform Init operation on given LiteMat 286 /// \param[in] width Set width for given LiteMat. 287 /// \param[in] height Set height for given LiteMat. 288 /// \param[in] p_data Set pointer data for given LiteMat. 289 /// \param[in] data_type Set data type for given LiteMat. 290 void Init(int width, int height, void *p_data, LDataType data_type = LDataType::UINT8); 291 292 /// \brief Perform Init operation on given LiteMat 293 /// \param[in] width Set width for given LiteMat. 294 /// \param[in] height Set height for given LiteMat. 295 /// \param[in] channel Set channel for given LiteMat. 296 /// \param[in] data_type Set data type for given LiteMat. 297 /// \param[in] align_memory Whether malloc align memory or not, default is true, 298 /// which is better for doing acceleration. 299 void Init(int width, int height, int channel, const LDataType &data_type = LDataType::UINT8, 300 bool align_memory = true); 301 302 /// \brief Perform Init operation on given LiteMat 303 /// \param[in] width Set width for given LiteMat. 304 /// \param[in] height Set height for given LiteMat. 305 /// \param[in] channel Set channel for given LiteMat. 306 /// \param[in] p_data Set pointer data for given LiteMat. 307 /// \param[in] data_type Set data type for given LiteMat. 308 void Init(int width, int height, int channel, void *p_data, LDataType data_type = LDataType::UINT8); 309 310 bool GetROI(int x, int y, int w, int h, LiteMat &dst); // NOLINT 311 312 bool IsEmpty() const; 313 314 void Release(); 315 316 LiteMat &operator=(const LiteMat &m); 317 318 template <typename T> 319 operator T *() { 320 return reinterpret_cast<T *>(data_ptr_); 321 } 322 323 template <typename T> 324 operator const T *() const { 325 return reinterpret_cast<const T *>(data_ptr_); 326 } 327 328 template <typename T> ptr(int w)329 inline T *ptr(int w) const { 330 if (w >= height_) { 331 return nullptr; 332 } 333 if (IsEmpty()) { 334 return nullptr; 335 } 336 return reinterpret_cast<T *>(reinterpret_cast<unsigned char *>(data_ptr_) + steps_[0] * w); 337 } 338 339 private: 340 /// \brief Apply for memory alignment 341 /// \param[in] size The size of the requested memory alignment. 342 void *AlignMalloc(unsigned int size); 343 344 /// \brief Free memory 345 /// \param[in] ptr Pointer to free memory. 346 void AlignFree(void *ptr); 347 348 /// \brief Initialize the element size of different types of data. 349 /// \param[in] data_type Type of data. 350 void InitElemSize(LDataType data_type); 351 352 /// \brief Add value of reference count. 353 /// \param[in] p The point of references count. 354 /// \param[in] value The value of new added references. 355 /// \return return reference count. 356 static int addRef(int *p, int value); 357 358 /// \brief Set the step size of the pixels in the Litemat array. 359 /// \param[in] c0 The number used to set teh value of step[0]. 360 /// \param[in] c1 The number used to set teh value of step[1]. 361 /// \param[in] c2 The number used to set teh value of step[2]. 362 void setSteps(size_t c0, size_t c1, size_t c2); 363 364 bool CheckLiteMat() const; 365 366 public: 367 void *data_ptr_ = nullptr; 368 int elem_size_; 369 int width_; 370 int height_; 371 int channel_; 372 int c_step_; 373 int dims_; 374 size_t size_; 375 LDataType data_type_; 376 int *ref_count_; 377 size_t steps_[kMaxDims]{}; 378 bool release_flag_; 379 }; 380 381 /// \brief Given image A and image B and calculate the difference of them (A - B). 382 /// This is an element by element operation by subtracting corresponding elements of inputs. 383 /// \param[in] src_a Input image data. 384 /// \param[in] src_b Input image data. 385 /// \param[in] dst The difference of input images. 386 /// \par Example 387 /// \code 388 /// std::vector<uint8_t> mat1 = {3, 3, 3, 3}; 389 /// LiteMat lite_mat_src; 390 /// lite_mat_src.Init(2, 2, 1, mat1.data(), LDataType::UINT8); 391 /// 392 /// std::vector<uint8_t> mat2 = {2, 2, 2, 2}; 393 /// LiteMat lite_mat_src2; 394 /// lite_mat_src2.Init(2, 2, 1, mat2.data(), LDataType::UINT8); 395 /// 396 /// /* Calculate the difference of images */ 397 /// LiteMat diff; 398 /// Subtract(lite_mat_src, lite_mat_src2, &diff); 399 /// for (int i = 0; i < diff.height_; i++) { 400 /// for (int j = 0; j < diff.width_; j++) { 401 /// std::cout << std::to_string(diff.ptr<uint8_t>(i)[j]) << ", "; 402 /// } 403 /// std::cout << std::endl; 404 /// } 405 /// \endcode 406 /// \return Return true if transform successfully. 407 bool DATASET_API Subtract(const LiteMat &src_a, const LiteMat &src_b, LiteMat *dst); 408 409 /// \brief Given image A and image B and calculate the division of them (A / B). 410 /// This is an element by element operation. 411 /// \param[in] src_a Input image data. 412 /// \param[in] src_b Input image data. 413 /// \param[in] dst The division of input images. 414 /// \par Example 415 /// \code 416 /// std::vector<uint8_t> mat1 = {8, 8, 8, 8}; 417 /// LiteMat lite_mat_src; 418 /// lite_mat_src.Init(2, 2, 1, mat1.data(), LDataType::UINT8); 419 /// 420 /// std::vector<uint8_t> mat2 = {2, 2, 2, 2}; 421 /// LiteMat lite_mat_src2; 422 /// lite_mat_src2.Init(2, 2, 1, mat2.data(), LDataType::UINT8); 423 /// 424 /// /* Calculate the division of images */ 425 /// LiteMat div; 426 /// Divide(lite_mat_src, lite_mat_src2, &div); 427 /// for (int i = 0; i < div.height_; i++) { 428 /// for (int j = 0; j < div.width_; j++) { 429 /// std::cout << std::to_string(div.ptr<uint8_t>(i)[j]) << ", "; 430 /// } 431 /// std::cout << std::endl; 432 /// } 433 /// \endcode 434 /// \return Return true if transform successfully. 435 bool DATASET_API Divide(const LiteMat &src_a, const LiteMat &src_b, LiteMat *dst); 436 437 /// \brief Given image A and image B and calculate the product of them (A * B). 438 /// This is an element by element operation by multiplying corresponding elements of inputs. 439 /// \param[in] src_a Input image data. 440 /// \param[in] src_b Input image data. 441 /// \param[in] dst The product of input images. 442 /// \par Example 443 /// \code 444 /// std::vector<uint8_t> mat1 = {4, 4, 4, 4}; 445 /// LiteMat lite_mat_src; 446 /// lite_mat_src.Init(2, 2, 1, mat1.data(), LDataType::UINT8); 447 /// 448 /// std::vector<uint8_t> mat2 = {2, 2, 2, 2}; 449 /// LiteMat lite_mat_src2; 450 /// lite_mat_src2.Init(2, 2, 1, mat2.data(), LDataType::UINT8); 451 /// 452 /// /* Calculate the product of images */ 453 /// LiteMat mut; 454 /// Multiply(lite_mat_src, lite_mat_src2, &mut); 455 /// for (int i = 0; i < mut.height_; i++) { 456 /// for (int j = 0; j < mut.width_; j++) { 457 /// std::cout << std::to_string(mut.ptr<uint8_t>(i)[j]) << ", "; 458 /// } 459 /// std::cout << std::endl; 460 /// } 461 /// \endcode 462 /// \return Return true if transform successfully. 463 bool DATASET_API Multiply(const LiteMat &src_a, const LiteMat &src_b, LiteMat *dst); 464 465 #define RETURN_FALSE_IF_LITEMAT_EMPTY(_m) \ 466 do { \ 467 if ((_m).IsEmpty()) { \ 468 return false; \ 469 } \ 470 } while (false) 471 472 #define RETURN_IF_LITEMAT_EMPTY(_m) \ 473 do { \ 474 if ((_m).IsEmpty()) { \ 475 return; \ 476 } \ 477 } while (false) 478 479 } // namespace dataset 480 } // namespace mindspore 481 #endif // MINI_MAT_H_ 482