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