Merge pull request #19752 from mpashchenkov:mp/onnx-int64-to-32

G-API: ONNX. Adding INT64-32 conversion for output.

* Added int64 to 32 conversion

* Added warning

* Added type checks for all toCV

* Added type checks for tests

* Small fixes

* Const for fixture in test

* std::tuple if retutn value for toCV

* Mistake

* Changed toCV for tests

* Added Assert

* Fix for comments

* One conversion for ONNX and IE

* Clean up

* One more fix

* Added copyFromONNX

* Removed warning

* Apply review comments
This commit is contained in:
Maxim Pashchenkov
2021-03-31 00:08:43 +03:00
committed by GitHub
parent 3f14cb073b
commit 69fc0acd1a
4 changed files with 182 additions and 51 deletions
@@ -209,6 +209,12 @@ inline cv::util::optional<T> getCompileArg(const cv::GCompileArgs &args)
void GAPI_EXPORTS createMat(const cv::GMatDesc& desc, cv::Mat& mat);
inline void convertInt64ToInt32(const int64_t* src, int* dst, size_t size)
{
std::transform(src, src + size, dst,
[](int64_t el) { return static_cast<int>(el); });
}
}} // cv::gimpl
#endif // OPENCV_GAPI_GBACKEND_HPP
+12 -4
View File
@@ -106,7 +106,7 @@ inline IE::Precision toIE(int depth) {
case CV_8U: return IE::Precision::U8;
case CV_32S: return IE::Precision::I32;
case CV_32F: return IE::Precision::FP32;
default: GAPI_Assert(false && "Unsupported data type");
default: GAPI_Assert(false && "IE. Unsupported data type");
}
return IE::Precision::UNSPECIFIED;
}
@@ -115,7 +115,8 @@ inline int toCV(IE::Precision prec) {
case IE::Precision::U8: return CV_8U;
case IE::Precision::FP32: return CV_32F;
case IE::Precision::I32: return CV_32S;
default: GAPI_Assert(false && "Unsupported data type");
case IE::Precision::I64: return CV_32S;
default: GAPI_Assert(false && "IE. Unsupported data type");
}
return -1;
}
@@ -158,7 +159,7 @@ inline IE::Blob::Ptr wrapIE(const cv::Mat &mat, cv::gapi::ie::TraitAs hint) {
HANDLE(32F, float);
HANDLE(32S, int);
#undef HANDLE
default: GAPI_Assert(false && "Unsupported data type");
default: GAPI_Assert(false && "IE. Unsupported data type");
}
return IE::Blob::Ptr{};
}
@@ -194,7 +195,14 @@ inline void copyFromIE(const IE::Blob::Ptr &blob, MatType &mat) {
HANDLE(FP32, float);
HANDLE(I32, int);
#undef HANDLE
default: GAPI_Assert(false && "Unsupported data type");
case IE::Precision::I64: {
GAPI_LOG_WARNING(NULL, "INT64 isn't supported for cv::Mat. Conversion to INT32 is used.");
cv::gimpl::convertInt64ToInt32(blob->buffer().as<int64_t*>(),
reinterpret_cast<int*>(mat.data),
mat.total());
break;
}
default: GAPI_Assert(false && "IE. Unsupported data type");
}
}
+37 -17
View File
@@ -170,7 +170,8 @@ inline int toCV(ONNXTensorElementDataType prec) {
case ONNX_TENSOR_ELEMENT_DATA_TYPE_UINT8: return CV_8U;
case ONNX_TENSOR_ELEMENT_DATA_TYPE_FLOAT: return CV_32F;
case ONNX_TENSOR_ELEMENT_DATA_TYPE_INT32: return CV_32S;
default: GAPI_Assert(false && "Unsupported data type");
case ONNX_TENSOR_ELEMENT_DATA_TYPE_INT64: return CV_32S;
default: GAPI_Assert(false && "ONNX. Unsupported data type");
}
return -1;
}
@@ -184,11 +185,30 @@ inline std::vector<int> toCV(const std::vector<int64_t> &vsz) {
return result;
}
inline cv::Mat toCV(Ort::Value &v) {
auto info = v.GetTensorTypeAndShapeInfo();
return cv::Mat(toCV(info.GetShape()),
toCV(info.GetElementType()),
reinterpret_cast<void*>(v.GetTensorMutableData<uint8_t*>()));
inline void copyFromONNX(Ort::Value &v, cv::Mat& mat) {
const auto info = v.GetTensorTypeAndShapeInfo();
const auto prec = info.GetElementType();
const auto shape = toCV(info.GetShape());
mat.create(shape, toCV(prec));
switch (prec) {
#define HANDLE(E,T) \
case E: std::copy_n(v.GetTensorMutableData<T>(), \
mat.total(), \
reinterpret_cast<T*>(mat.data)); \
break;
HANDLE(ONNX_TENSOR_ELEMENT_DATA_TYPE_UINT8, uint8_t);
HANDLE(ONNX_TENSOR_ELEMENT_DATA_TYPE_FLOAT, float);
HANDLE(ONNX_TENSOR_ELEMENT_DATA_TYPE_INT32, int);
#undef HANDLE
case ONNX_TENSOR_ELEMENT_DATA_TYPE_INT64: {
GAPI_LOG_WARNING(NULL, "INT64 isn't supported for cv::Mat. Conversion to INT32 is used.");
cv::gimpl::convertInt64ToInt32(v.GetTensorMutableData<int64_t>(),
reinterpret_cast<int*>(mat.data),
mat.total());
break;
}
default: GAPI_Assert(false && "ONNX. Unsupported data type");
}
}
inline std::vector<int64_t> toORT(const cv::MatSize &sz) {
@@ -199,12 +219,13 @@ inline void preprocess(const cv::Mat& src,
const cv::gimpl::onnx::TensorInfo& ti,
cv::Mat& dst) {
GAPI_Assert(src.depth() == CV_32F || src.depth() == CV_8U);
// CNN input type
const auto type = toCV(ti.type);
if (src.depth() == CV_32F) {
// Just pass the tensor as-is.
// No layout or dimension transformations done here!
// TODO: This needs to be aligned across all NN backends.
GAPI_Assert(toCV(ti.type) == CV_32F && "Only 32F model input is supported for 32F data");
GAPI_Assert(type == CV_32F && "Only 32F model input is supported for 32F input data");
const auto tensor_dims = toORT(src.size);
if (tensor_dims.size() == ti.dims.size()) {
for (size_t i = 0; i < ti.dims.size(); ++i) {
@@ -218,16 +239,15 @@ inline void preprocess(const cv::Mat& src,
dst = src;
} else {
// 8U input: full preprocessing path
GAPI_Assert(src.depth() == CV_8U && "Only 8U data type is supported for preproc");
GAPI_Assert(src.depth() == CV_8U && "Only 8U data type is supported for preproc");
GAPI_Assert((ti.dims.size() == 4u || ti.dims.size() == 3u)
&& "Only NCHW/NHWC/CHW/HWC layouts are supported for preproc");
const bool with_batch = ti.dims.size() == 4u ? true : false;
const int shift = with_batch ? 0 : 1;
const auto ddepth = toCV(ti.type);
GAPI_Assert((ddepth == CV_8U || ddepth == CV_32F)
&& "Only 8U and 32F model input is supported for 8U data");
GAPI_Assert((type == CV_8U || type == CV_32F)
&& "Only 8U and 32F model input is supported for 8U input data");
// Assess the expected input layout
const bool is_hwc = [&](int ch) {
@@ -261,8 +281,8 @@ inline void preprocess(const cv::Mat& src,
cv::Mat rsz, pp;
cv::resize(csc, rsz, cv::Size(new_w, new_h));
if (src.depth() == CV_8U && ddepth == CV_32F) {
rsz.convertTo(pp, ddepth, ti.normalize ? 1.f / 255 : 1.f);
if (src.depth() == CV_8U && type == CV_32F) {
rsz.convertTo(pp, type, ti.normalize ? 1.f / 255 : 1.f);
if (ti.mstd.has_value()) {
pp -= ti.mstd->mean;
pp /= ti.mstd->stdev;
@@ -273,7 +293,7 @@ inline void preprocess(const cv::Mat& src,
if (!is_hwc && new_c > 1) {
// Convert to CHW
dst.create(cv::Size(new_w, new_h * new_c), ddepth);
dst.create(cv::Size(new_w, new_h * new_c), type);
std::vector<cv::Mat> planes(new_c);
for (int ch = 0; ch < new_c; ++ch) {
planes[ch] = dst.rowRange(ch * new_h, (ch + 1) * new_h);
@@ -347,7 +367,7 @@ inline Ort::Value createTensor(const Ort::MemoryInfo& memory_info,
case ONNX_TENSOR_ELEMENT_DATA_TYPE_INT32:
return createTensor<int32_t>(memory_info, tensor_params, data);
default:
GAPI_Assert(false && "Unsupported data type");
GAPI_Assert(false && "ONNX. Unsupported data type");
}
return Ort::Value{nullptr};
}
@@ -796,7 +816,7 @@ void ONNXCompiled::Run(const std::vector<cv::Mat>& ins,
ade::util::toRange(outputs))) {
const auto &out_name = std::get<0>(iter).name;
auto &out_tensor = std::get<1>(iter);
onnx_outputs[out_name] = toCV(out_tensor);
copyFromONNX(out_tensor, onnx_outputs[out_name]);
}
// Fill in G-API outputs