Merge pull request !6009 from jiangzhiwen/lite/affine_uttags/v1.0.0
| @@ -516,18 +516,10 @@ void ConvertBoxes(std::vector<std::vector<float>> &boxes, const std::vector<std: | |||
| std::vector<int> ApplyNms(const std::vector<std::vector<float>> &all_boxes, std::vector<float> &all_scores, float thres, | |||
| int max_boxes) { | |||
| int boxes_num = all_boxes.size(); | |||
| std::vector<float> y1(boxes_num); | |||
| std::vector<float> x1(boxes_num); | |||
| std::vector<float> y2(boxes_num); | |||
| std::vector<float> x2(boxes_num); | |||
| std::vector<float> areas(boxes_num); | |||
| std::vector<int> order(boxes_num); | |||
| for (int i = 0; i < boxes_num; i++) { | |||
| y1[i] = all_boxes[i][0]; | |||
| x1[i] = all_boxes[i][1]; | |||
| y2[i] = all_boxes[i][2]; | |||
| x2[i] = all_boxes[i][3]; | |||
| areas[i] = (x2[i] - x1[i] + 1) * (y2[i] - y1[i] + 1); | |||
| areas[i] = (all_boxes[i][3] - all_boxes[i][1] + 1) * (all_boxes[i][2] - all_boxes[i][0] + 1); | |||
| order[i] = i; | |||
| } | |||
| @@ -543,10 +535,10 @@ std::vector<int> ApplyNms(const std::vector<std::vector<float>> &all_boxes, std: | |||
| int len = order.size() - 1; | |||
| std::vector<float> ovr(len); | |||
| for (int j = 0; j < len; j++) { | |||
| float xx1 = std::max(x1[i], x1[order[j + 1]]); | |||
| float yy1 = std::max(y1[i], y1[order[j + 1]]); | |||
| float xx2 = std::min(x2[i], x2[order[j + 1]]); | |||
| float yy2 = std::min(y2[i], y2[order[j + 1]]); | |||
| float xx1 = std::max(all_boxes[i][1], all_boxes[order[j + 1]][1]); | |||
| float yy1 = std::max(all_boxes[i][0], all_boxes[order[j + 1]][0]); | |||
| float xx2 = std::min(all_boxes[i][3], all_boxes[order[j + 1]][3]); | |||
| float yy2 = std::min(all_boxes[i][2], all_boxes[order[j + 1]][2]); | |||
| float w = std::max(0.0f, xx2 - xx1 + 1); | |||
| float h = std::max(0.0f, yy2 - yy1 + 1); | |||
| @@ -568,14 +560,15 @@ std::vector<int> ApplyNms(const std::vector<std::vector<float>> &all_boxes, std: | |||
| return keep; | |||
| } | |||
| void WarpAffine(LiteMat &src, LiteMat &out_img, double M[6], std::vector<size_t> dsize, UINT8_C3 borderValue) { | |||
| template <typename Pixel_Type> | |||
| void ImplementAffine(LiteMat &src, LiteMat &out_img, double M[6], std::vector<size_t> &dsize, Pixel_Type borderValue) { | |||
| double IM[6]; | |||
| for (int i = 0; i < 6; i++) { | |||
| IM[i] = M[i]; | |||
| } | |||
| double D = IM[0] * IM[4] - IM[1] * IM[3]; | |||
| D = D != 0 ? 1. / D : 0; | |||
| D = D != 0 ? 1.0f / D : 0; | |||
| double A11 = IM[4] * D, A22 = IM[0] * D; | |||
| IM[0] = A11; | |||
| IM[1] *= -D; | |||
| @@ -592,13 +585,22 @@ void WarpAffine(LiteMat &src, LiteMat &out_img, double M[6], std::vector<size_t> | |||
| int src_x = IM[0] * x + IM[1] * y + IM[2]; | |||
| int src_y = IM[3] * x + IM[4] * y + IM[5]; | |||
| if (src_x >= 0 && src_y >= 0 && src_x < src.width_ && src_y < src.height_) { | |||
| UINT8_C3 src_pixel = static_cast<UINT8_C3 *>(src.data_ptr_)[src_y * src.width_ + src_x]; | |||
| static_cast<UINT8_C3 *>(out_img.data_ptr_)[y * src.width_ + x] = src_pixel; | |||
| Pixel_Type src_pixel = static_cast<Pixel_Type *>(src.data_ptr_)[src_y * src.width_ + src_x]; | |||
| static_cast<Pixel_Type *>(out_img.data_ptr_)[y * src.width_ + x] = src_pixel; | |||
| } else { | |||
| static_cast<UINT8_C3 *>(out_img.data_ptr_)[y * src.width_ + x] = borderValue; | |||
| static_cast<Pixel_Type *>(out_img.data_ptr_)[y * src.width_ + x] = borderValue; | |||
| } | |||
| } | |||
| } | |||
| } | |||
| void Affine(LiteMat &src, LiteMat &out_img, double M[6], std::vector<size_t> dsize, UINT8_C1 borderValue) { | |||
| ImplementAffine(src, out_img, M, dsize, borderValue); | |||
| } | |||
| void Affine(LiteMat &src, LiteMat &out_img, double M[6], std::vector<size_t> dsize, UINT8_C3 borderValue) { | |||
| ImplementAffine(src, out_img, M, dsize, borderValue); | |||
| } | |||
| } // namespace dataset | |||
| } // namespace mindspore | |||
| @@ -20,6 +20,7 @@ | |||
| #include <math.h> | |||
| #include <vector> | |||
| #include <algorithm> | |||
| #include <iostream> | |||
| #include "lite_cv/lite_mat.h" | |||
| @@ -68,13 +69,20 @@ bool SubStractMeanNormalize(const LiteMat &src, LiteMat &dst, float *mean, float | |||
| bool Padd(const LiteMat &src, LiteMat &dst, int top, int bottom, int left, int right, PaddBorderType pad_type, | |||
| uint8_t fill_b_or_gray, uint8_t fill_g, uint8_t fill_r); | |||
| void WarpAffine(const LiteMat &src, LiteMat &out_img, double M[6], std::vector<size_t> dsize, uint8_t borderValue[3]); | |||
| /// \brief Apply affine transformation for 1 channel image | |||
| void Affine(LiteMat &src, LiteMat &out_img, double M[6], std::vector<size_t> dsize, UINT8_C1 borderValue); | |||
| /// \brief Apply affine transformation for 3 channel image | |||
| void Affine(LiteMat &src, LiteMat &out_img, double M[6], std::vector<size_t> dsize, UINT8_C3 borderValue); | |||
| /// \brief Get default anchor boxes for Faster R-CNN, SSD, YOLO etc | |||
| std::vector<std::vector<float>> GetDefaultBoxes(const BoxesConfig config); | |||
| /// \brief Convert the prediction boxes to the actual boxes of (y, x, h, w) | |||
| void ConvertBoxes(std::vector<std::vector<float>> &boxes, const std::vector<std::vector<float>> &default_boxes, | |||
| const BoxesConfig config); | |||
| /// \brief Apply Non-Maximum Suppression | |||
| std::vector<int> ApplyNms(const std::vector<std::vector<float>> &all_boxes, std::vector<float> &all_scores, float thres, | |||
| int max_boxes); | |||
| @@ -27,17 +27,20 @@ namespace dataset { | |||
| template <typename T> | |||
| struct Chn1 { | |||
| Chn1(T c1) : c1(c1) {} | |||
| T c1; | |||
| }; | |||
| template <typename T> | |||
| struct Chn2 { | |||
| Chn2(T c1, T c2) : c1(c1), c2(c2) {} | |||
| T c1; | |||
| T c2; | |||
| }; | |||
| template <typename T> | |||
| struct Chn3 { | |||
| Chn3(T c1, T c2, T c3) : c1(c1), c2(c2), c3(c3) {} | |||
| T c1; | |||
| T c2; | |||
| T c3; | |||
| @@ -45,6 +48,7 @@ struct Chn3 { | |||
| template <typename T> | |||
| struct Chn4 { | |||
| Chn4(T c1, T c2, T c3, T c4) : c1(c1), c2(c2), c3(c3), c4(c4) {} | |||
| T c1; | |||
| T c2; | |||
| T c3; | |||
| @@ -21,6 +21,8 @@ | |||
| #include <opencv2/imgproc/types_c.h> | |||
| #include "utils/log_adapter.h" | |||
| #include <fstream> | |||
| using namespace mindspore::dataset; | |||
| class MindDataImageProcess : public UT::Common { | |||
| public: | |||
| @@ -228,6 +230,7 @@ TEST_F(MindDataImageProcess, TestPadd) { | |||
| } | |||
| TEST_F(MindDataImageProcess, TestGetDefaultBoxes) { | |||
| std::string benchmark = "data/dataset/testLite/default_boxes.bin"; | |||
| BoxesConfig config; | |||
| config.img_shape = {300, 300}; | |||
| config.num_default = {3, 6, 6, 6, 6, 6}; | |||
| @@ -238,8 +241,25 @@ TEST_F(MindDataImageProcess, TestGetDefaultBoxes) { | |||
| config.steps = {16, 32, 64, 100, 150, 300}; | |||
| config.prior_scaling = {0.1, 0.2}; | |||
| int rows = 1917; | |||
| int cols = 4; | |||
| std::vector<double> benchmark_boxes(rows * cols); | |||
| std::ifstream in(benchmark, std::ios::in | std::ios::binary); | |||
| in.read(reinterpret_cast<char*>(benchmark_boxes.data()), benchmark_boxes.size() * sizeof(double)); | |||
| in.close(); | |||
| std::vector<std::vector<float>> default_boxes = GetDefaultBoxes(config); | |||
| ASSERT_TRUE(default_boxes.size() == 1917); | |||
| EXPECT_EQ(default_boxes.size(), rows); | |||
| EXPECT_EQ(default_boxes[0].size(), cols); | |||
| double distance = 0.0f; | |||
| for (int i = 0; i < rows; i++) { | |||
| for (int j = 0; j < cols; j++) { | |||
| distance += pow(default_boxes[i][j] - benchmark_boxes[i * cols + j], 2); | |||
| } | |||
| } | |||
| distance = sqrt(distance); | |||
| EXPECT_LT(distance, 1e-5); | |||
| } | |||
| TEST_F(MindDataImageProcess, TestApplyNms) { | |||
| @@ -250,3 +270,67 @@ TEST_F(MindDataImageProcess, TestApplyNms) { | |||
| ASSERT_TRUE(keep[1] == 0); | |||
| ASSERT_TRUE(keep[2] == 1); | |||
| } | |||
| TEST_F(MindDataImageProcess, TestAffine) { | |||
| // The input matrix | |||
| // 0 0 1 0 0 | |||
| // 0 0 1 0 0 | |||
| // 2 2 3 2 2 | |||
| // 0 0 1 0 0 | |||
| // 0 0 1 0 0 | |||
| size_t rows = 5; | |||
| size_t cols = 5; | |||
| LiteMat src(rows, cols); | |||
| for (size_t i = 0; i < rows; i++) { | |||
| for (size_t j = 0; j < cols; j++) { | |||
| if (i == 2 && j == 2) { | |||
| static_cast<UINT8_C1*>(src.data_ptr_)[i * cols + j] = 3; | |||
| } else if (i == 2) { | |||
| static_cast<UINT8_C1*>(src.data_ptr_)[i * cols + j] = 2; | |||
| } else if (j == 2) { | |||
| static_cast<UINT8_C1*>(src.data_ptr_)[i * cols + j] = 1; | |||
| } else { | |||
| static_cast<UINT8_C1*>(src.data_ptr_)[i * cols + j] = 0; | |||
| } | |||
| } | |||
| } | |||
| // Expect output matrix | |||
| // 0 0 2 0 0 | |||
| // 0 0 2 0 0 | |||
| // 1 1 3 1 1 | |||
| // 0 0 2 0 0 | |||
| // 0 0 2 0 0 | |||
| LiteMat expect(rows, cols); | |||
| for (size_t i = 0; i < rows; i++) { | |||
| for (size_t j = 0; j < cols; j++) { | |||
| if (i == 2 && j == 2) { | |||
| static_cast<UINT8_C1*>(expect.data_ptr_)[i * cols + j] = 3; | |||
| } else if (i == 2) { | |||
| static_cast<UINT8_C1*>(expect.data_ptr_)[i * cols + j] = 1; | |||
| } else if (j == 2) { | |||
| static_cast<UINT8_C1*>(expect.data_ptr_)[i * cols + j] = 2; | |||
| } else { | |||
| static_cast<UINT8_C1*>(expect.data_ptr_)[i * cols + j] = 0; | |||
| } | |||
| } | |||
| } | |||
| double angle = 90.0f; | |||
| cv::Point2f center(rows / 2, cols / 2); | |||
| cv::Mat rotate_matrix = cv::getRotationMatrix2D(center, angle, 1.0); | |||
| double M[6]; | |||
| for (size_t i = 0; i < 6; i++) { | |||
| M[i] = rotate_matrix.at<double>(i); | |||
| } | |||
| std::cout << std::endl; | |||
| LiteMat dst; | |||
| Affine(src, dst, M, {rows, cols}, UINT8_C1(0)); | |||
| for (size_t i = 0; i < rows; i++) { | |||
| for (size_t j = 0; j < cols; j++) { | |||
| EXPECT_EQ(static_cast<UINT8_C1*>(expect.data_ptr_)[i * cols + j].c1, | |||
| static_cast<UINT8_C1*>(dst.data_ptr_)[i * cols + j].c1); | |||
| } | |||
| } | |||
| } | |||