You can not select more than 25 topics Topics must start with a chinese character,a letter or number, can include dashes ('-') and can be up to 35 characters long.

affine_op_test.cc 4.4 kB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113
  1. /**
  2. * Copyright 2021 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. #include "common/cvop_common.h"
  17. #include "minddata/dataset/core/cv_tensor.h"
  18. #include "minddata/dataset/kernels/image/affine_op.h"
  19. #include "minddata/dataset/kernels/image/math_utils.h"
  20. #include <opencv2/opencv.hpp>
  21. #include <opencv2/imgproc/types_c.h>
  22. #include "lite_cv/lite_mat.h"
  23. #include "lite_cv/image_process.h"
  24. using namespace mindspore::dataset;
  25. using mindspore::dataset::InterpolationMode;
  26. class MindDataTestAffineOp : public UT::CVOP::CVOpCommon {
  27. public:
  28. MindDataTestAffineOp() : CVOpCommon() {}
  29. };
  30. // Helper function, consider moving this to helper class for UT
  31. double Mse(cv::Mat img1, cv::Mat img2) {
  32. // clone to get around open cv optimization
  33. cv::Mat output1 = img1.clone();
  34. cv::Mat output2 = img2.clone();
  35. // input check
  36. if (output1.rows < 0 || output1.rows != output2.rows || output1.cols < 0 || output1.cols != output2.cols) {
  37. return 10000.0;
  38. }
  39. return cv::norm(output1, output2, cv::NORM_L1);
  40. }
  41. // helper function to generate corresponding affine matrix
  42. std::vector<double> GenerateMatrix(const std::shared_ptr<Tensor> &input, float_t degrees,
  43. const std::vector<float_t> &translation, float_t scale,
  44. const std::vector<float_t> &shear) {
  45. float_t translation_x = translation[0];
  46. float_t translation_y = translation[1];
  47. DegreesToRadians(degrees, &degrees);
  48. float_t shear_x = shear[0];
  49. float_t shear_y = shear[1];
  50. DegreesToRadians(shear_x, &shear_x);
  51. DegreesToRadians(-1 * shear_y, &shear_y);
  52. float_t cx = ((input->shape()[1] - 1) / 2.0);
  53. float_t cy = ((input->shape()[0] - 1) / 2.0);
  54. // Calculate RSS
  55. std::vector<double> matrix{
  56. static_cast<double>(scale * cos(degrees + shear_y) / cos(shear_y)),
  57. static_cast<double>(scale * (-1 * cos(degrees + shear_y) * tan(shear_x) / cos(shear_y) - sin(degrees))),
  58. 0,
  59. static_cast<double>(scale * sin(degrees + shear_y) / cos(shear_y)),
  60. static_cast<double>(scale * (-1 * sin(degrees + shear_y) * tan(shear_x) / cos(shear_y) + cos(degrees))),
  61. 0};
  62. // Compute T * C * RSS * C^-1
  63. matrix[2] = (1 - matrix[0]) * cx - matrix[1] * cy + translation_x;
  64. matrix[5] = (1 - matrix[4]) * cy - matrix[3] * cx + translation_y;
  65. return matrix;
  66. }
  67. TEST_F(MindDataTestAffineOp, TestAffineLite) {
  68. MS_LOG(INFO) << "Doing MindDataTestAffine-TestAffineLite.";
  69. // create input tensor and
  70. float degree = 0.0;
  71. std::vector<float> translation = {0.0, 0.0};
  72. float scale = 0.0;
  73. std::vector<float> shear = {0.0, 0.0};
  74. // Create affine object with default values
  75. std::shared_ptr<AffineOp> op(new AffineOp(degree, translation, scale, shear, InterpolationMode::kLinear));
  76. // output tensor
  77. std::shared_ptr<Tensor> output_tensor;
  78. // output
  79. LiteMat dst;
  80. LiteMat lite_mat_rgb(input_tensor_->shape()[1], input_tensor_->shape()[0], input_tensor_->shape()[2],
  81. const_cast<void *>(reinterpret_cast<const void *>(input_tensor_->GetBuffer())),
  82. LDataType::UINT8);
  83. std::vector<double> matrix = GenerateMatrix(input_tensor_, degree, translation, scale, shear);
  84. int height = lite_mat_rgb.height_;
  85. int width = lite_mat_rgb.width_;
  86. std::vector<size_t> dsize;
  87. dsize.push_back(width);
  88. dsize.push_back(height);
  89. double M[6] = {};
  90. for (int i = 0; i < matrix.size(); i++) {
  91. M[i] = static_cast<double>(matrix[i]);
  92. }
  93. EXPECT_TRUE(Affine(lite_mat_rgb, dst, M, dsize, UINT8_C3(0, 0, 0)));
  94. Status s = op->Compute(input_tensor_, &output_tensor);
  95. EXPECT_TRUE(s.IsOk());
  96. // output tensor is a cv tenosr, we can compare mat values
  97. cv::Mat lite_cv_out(dst.height_, dst.width_, CV_8UC3, dst.data_ptr_);
  98. double mse = Mse(lite_cv_out, CVTensor(output_tensor).mat());
  99. MS_LOG(INFO) << "mse: " << std::to_string(mse) << std::endl;
  100. EXPECT_LT(mse, 1); // predetermined magic number
  101. }