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