• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /**
2  * Copyright 2019-2023 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 "minddata/dataset/core/cv_tensor.h"
17 
18 #include "minddata/dataset/core/tensor.h"
19 #include "minddata/dataset/include/dataset/constants.h"
20 
21 namespace mindspore {
22 namespace dataset {
CVTensor(std::shared_ptr<Tensor> tensor)23 CVTensor::CVTensor(std::shared_ptr<Tensor> tensor) : Tensor(std::move(*tensor)) {
24   (void)this->MatInit(GetMutableBuffer(), shape_, type_, &mat_);
25 }
26 
CreateEmpty(const TensorShape & shape,DataType type,CVTensorPtr * out)27 Status CVTensor::CreateEmpty(const TensorShape &shape, DataType type, CVTensorPtr *out) {
28   RETURN_UNEXPECTED_IF_NULL(out);
29   *out = std::make_shared<CVTensor>(shape, type);
30   RETURN_UNEXPECTED_IF_NULL(*out);
31   int64_t byte_size = (*out)->SizeInBytes();
32   // Don't allocate if we have a tensor with no elements.
33   if (byte_size != 0) {
34     RETURN_IF_NOT_OK((*out)->AllocateBuffer(byte_size));
35   }
36 
37   return (*out)->MatInit((*out)->GetMutableBuffer(), (*out)->shape_, (*out)->type_, &(*out)->mat_);
38 }
39 
CreateFromMat(const cv::Mat & mat,const dsize_t rank,CVTensorPtr * out)40 Status CVTensor::CreateFromMat(const cv::Mat &mat, const dsize_t rank, CVTensorPtr *out) {
41   RETURN_UNEXPECTED_IF_NULL(out);
42   TensorPtr out_tensor;
43   cv::Mat mat_local = mat;
44   // if the input Mat's memory is not continuous, copy it to one block of memory
45   if (!mat.isContinuous()) {
46     mat_local = mat.clone();
47   }
48   TensorShape shape({});
49   if (mat.dims == 2 && rank == 2) {
50     shape = TensorShape({mat.rows, mat.cols});
51   } else if (mat.dims == 2 && rank == 3) {
52     shape = TensorShape({mat.rows, mat.cols, mat.channels()});
53   } else {
54     // the info of <C, H, W> tensor is: dims = 3, size = (C, H, W), channels = 1
55     RETURN_STATUS_UNEXPECTED("CreateFromMat: tensor should be in shape of <H,W,C> or <H,W>.");
56   }
57   DataType type = DataType::FromCVType(mat_local.type());
58   RETURN_IF_NOT_OK(CreateFromMemory(shape, type, mat_local.data, &out_tensor));
59   *out = AsCVTensor(out_tensor);
60   return Status::OK();
61 }
62 
IsValidImage(uchar * data,const TensorShape & shape,const DataType & type)63 std::pair<std::array<int, 2>, int> CVTensor::IsValidImage(uchar *data, const TensorShape &shape, const DataType &type) {
64   constexpr int64_t array_size = 2;
65   constexpr int64_t rank_two = 2;
66   constexpr int64_t rank_three = 3;
67   constexpr int64_t index = 2;
68   std::array<int, array_size> size = {1, 1};
69   if (shape.Rank() <= rank_two || (shape.Rank() == rank_three && shape[index] <= CV_CN_MAX)) {
70     uint16_t ch = 1;
71     if (shape.Rank() == rank_three) {
72       ch = static_cast<uint16_t>(shape[2]);
73     }
74     if (shape.Rank() > 0) {
75       size[0] = static_cast<int>(shape[0]);
76     }
77     if (shape.Rank() > 1) {
78       size[1] = static_cast<int>(shape[1]);
79     }
80     if (type.AsCVType() == kCVInvalidType) {
81       return std::make_pair(size, -1);
82     }
83     int cv_type = CV_MAKETYPE(type.AsCVType(), ch);
84     // update the n which in matrx(m*n) for bytes type
85     if (type == DataType::DE_BYTES) {
86       offset_t *offset = reinterpret_cast<offset_t *>(data);
87       size[1] = *(offset + 1) - *offset - 1;
88     }
89     return std::make_pair(size, cv_type);
90   }
91   return std::make_pair(size, -1);
92 }
93 
AsCVTensor(std::shared_ptr<Tensor> t)94 std::shared_ptr<CVTensor> CVTensor::AsCVTensor(std::shared_ptr<Tensor> t) {
95   if (t == nullptr) {
96     return nullptr;
97   }
98   std::shared_ptr<CVTensor> cv_t = std::dynamic_pointer_cast<CVTensor>(t);
99   if (cv_t != nullptr) {
100     return cv_t;
101   } else {
102     return std::make_shared<CVTensor>(t);
103   }
104 }
105 
MatInit(uchar * data,const TensorShape & shape,const DataType & type,cv::Mat * mat)106 Status CVTensor::MatInit(uchar *data, const TensorShape &shape, const DataType &type, cv::Mat *mat) {
107   RETURN_UNEXPECTED_IF_NULL(data);
108   RETURN_UNEXPECTED_IF_NULL(mat);
109   const int kShapeAsDefault = 2;
110   std::pair<std::array<int, kShapeAsDefault>, int> cv_shape_type = IsValidImage(data, shape, type);
111   if (cv_shape_type.second == -1) {
112     std::vector<dsize_t> sizes = shape.AsVector();
113     std::vector<int> sizes32(sizes.begin(), sizes.end());  // convert long to int for usage with OpenCV
114 
115     uint8_t cv_type = type.AsCVType();
116     if (cv_type == kCVInvalidType) {
117       RETURN_STATUS_UNEXPECTED("Error in creating CV mat. Invalid type.");
118     }
119     *mat = cv::Mat(static_cast<int>(shape.Rank()), &sizes32[0], cv_type, data);
120   } else {
121     if (type == DataType::DE_BYTES) {
122       *mat = cv::Mat(kShapeAsDefault, &(cv_shape_type.first[0]), cv_shape_type.second, data + kOffsetSize * 2);
123     } else {
124       *mat = cv::Mat(kShapeAsDefault, &(cv_shape_type.first[0]), cv_shape_type.second, data);
125     }
126   }
127   if (mat == nullptr) {
128     RETURN_STATUS_UNEXPECTED("Error in creating CV mat from dataset Tensor.");
129   }
130   return Status::OK();
131 }
132 
Reshape(const TensorShape & shape)133 Status CVTensor::Reshape(const TensorShape &shape) {
134   RETURN_IF_NOT_OK(Tensor::Reshape(shape));
135   RETURN_IF_NOT_OK(this->MatInit(GetMutableBuffer(), shape_, type_, &mat_));
136   return Status::OK();
137 }
138 
ExpandDim(const dsize_t & axis)139 Status CVTensor::ExpandDim(const dsize_t &axis) {
140   RETURN_IF_NOT_OK(Tensor::ExpandDim(axis));
141   RETURN_IF_NOT_OK(this->MatInit(GetMutableBuffer(), shape_, type_, &mat_));
142   return Status::OK();
143 }
144 
Squeeze()145 void CVTensor::Squeeze() {
146   Tensor::Squeeze();
147   Status rc = this->MatInit(GetMutableBuffer(), shape_, type_, &mat_);
148   if (rc.IsError()) {
149     MS_LOG(ERROR) << "Squeeze failed, error details is " << rc;
150   }
151 }
152 
MatAtIndex(const std::vector<dsize_t> & index,cv::Mat * mat)153 Status CVTensor::MatAtIndex(const std::vector<dsize_t> &index, cv::Mat *mat) {
154   RETURN_UNEXPECTED_IF_NULL(mat);
155   uchar *start = nullptr;
156   TensorShape remaining({-1});
157   RETURN_IF_NOT_OK(this->StartAddrOfIndex(index, &start, &remaining));
158   RETURN_IF_NOT_OK(this->MatInit(start, remaining, type_, mat));
159   return Status::OK();
160 }
161 }  // namespace dataset
162 }  // namespace mindspore
163