Skip to content

Commit

Permalink
[PP] Support for FP16 in Reorder cases
Browse files Browse the repository at this point in the history
 - added basic support for FP16 (plain wrapper over int16_t)
 - extended Split/Merge operations to support it
 - tests
  • Loading branch information
anton-potapov committed Mar 11, 2021
1 parent b792214 commit 4fa9012
Show file tree
Hide file tree
Showing 5 changed files with 91 additions and 18 deletions.
3 changes: 2 additions & 1 deletion inference-engine/src/preprocessing/ie_preprocess_gapi.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -81,7 +81,8 @@ inline int get_cv_depth(const TensorDesc &ie_desc) {
case Precision::U8: return CV_8U;
case Precision::FP32: return CV_32F;
case Precision::U16: return CV_16U;
case Precision::FP16: return CV_16U;
case Precision::I16: return CV_16S;
case Precision::FP16: return CV_16F;

default: THROW_IE_EXCEPTION << "Unsupported data type";
}
Expand Down
23 changes: 20 additions & 3 deletions inference-engine/src/preprocessing/ie_preprocess_gapi_kernels.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -434,6 +434,11 @@ void splitRow(const uint8_t* in, std::array<uint8_t*, chs>& outs, int length) {

namespace {

struct fp_16_t {
int16_t v;
};


template<typename type>
struct cv_type_to_depth;

Expand All @@ -443,6 +448,7 @@ template<> struct cv_type_to_depth<std::uint16_t> { enum { depth = CV_16U }; }
template<> struct cv_type_to_depth<std::int16_t> { enum { depth = CV_16S }; };
template<> struct cv_type_to_depth<std::int32_t> { enum { depth = CV_32S }; };
template<> struct cv_type_to_depth<float> { enum { depth = CV_32F }; };
template<> struct cv_type_to_depth<fp_16_t> { enum { depth = CV_16F }; };

template<typename ... types>
struct typelist {};
Expand Down Expand Up @@ -500,14 +506,20 @@ bool is_cv_type_in_list(const int type_id) {

namespace {

using merge_supported_types = typelist<uint8_t, int8_t, uint16_t, int16_t, int32_t, float>;
using merge_supported_types = typelist<uint8_t, int8_t, uint16_t, int16_t, int32_t, float, fp_16_t>;

template<int chs>
struct typed_merge_row {
using p_f = void (*)(const std::array<const uint8_t*, chs>& ins, uint8_t* out, int length);

template <typename type>
p_f operator()(type_to_type<type> ) { return mergeRow<type, chs>; }

p_f operator()(type_to_type<fp_16_t> ) {
static_assert(sizeof(fp_16_t) == sizeof(fp_16_t::v),
"fp_16_t should be a plain wrap over FP16 implementation type");
return mergeRow<decltype(fp_16_t::v), chs>;
}
};

} // namespace
Expand Down Expand Up @@ -562,15 +574,20 @@ GAPI_FLUID_KERNEL(FMerge4, Merge4, false) {


namespace {

using split_supported_types = typelist<uint8_t, int8_t, uint16_t, int16_t, int32_t, float>;
using split_supported_types = typelist<uint8_t, int8_t, uint16_t, int16_t, int32_t, float, fp_16_t>;

template<int chs>
struct typed_split_row {
using p_f = void (*)(const uint8_t* in, std::array<uint8_t*, chs>& outs, int length);

template <typename type>
p_f operator()(type_to_type<type> ) { return splitRow<type, chs>; }

p_f operator()(type_to_type<fp_16_t> ) {
static_assert(sizeof(fp_16_t) == sizeof(fp_16_t::v),
"fp_16_t should be a plain wrap over FP16 implementation type");
return splitRow<decltype(fp_16_t::v), chs>;
}
};

} // namespace
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -193,7 +193,7 @@ InferenceEngine::Blob::Ptr img2Blob(cv::Mat &img, InferenceEngine::Layout layout
const size_t height = img.size().height;
const size_t width = img.size().width;

CV_Assert(cv::DataType<data_t>::depth == img.depth());
CV_Assert(cv::DataType<data_t>::depth == img.depth() || (PRC == Precision::FP16 && img.depth() == CV_16F));

SizeVector dims = {1, channels, height, width};
Blob::Ptr resultBlob = make_shared_blob<data_t>(TensorDesc(PRC, dims, layout));;
Expand Down Expand Up @@ -237,7 +237,8 @@ void Blob2Img(const InferenceEngine::Blob::Ptr& blobP, cv::Mat& img, InferenceEn
const size_t height = img.size().height;
const size_t width = img.size().width;

CV_Assert(cv::DataType<data_t>::depth == img.depth());
//IE and OpenCV use different data types for FP16 representation, so need to check for it explicitly
CV_Assert(cv::DataType<data_t>::depth == img.depth() || ((img.depth() == CV_16F) && (PRC == Precision::FP16)));

data_t* blobData = blobP->buffer().as<data_t*>();

Expand Down Expand Up @@ -438,11 +439,20 @@ TEST_P(SplitTestGAPI, AccuracyTest)
cv::Size sz = std::get<2>(params);
double tolerance = std::get<3>(params);

int srcType = CV_MAKE_TYPE(depth, planes);
auto make_src_type = [planes](int d){
return CV_MAKE_TYPE(d, planes);
};
int srcType = make_src_type(depth);
int dstType = CV_MAKE_TYPE(depth, 1);

cv::Mat in_mat(sz, srcType);
cv::randn(in_mat, cv::Scalar::all(127), cv::Scalar::all(40.f));
bool const is_fp16 = (depth == CV_16F);
cv::Mat rnd_mat = is_fp16 ? cv::Mat(sz, make_src_type(CV_32F)) : in_mat;
cv::randn(rnd_mat, cv::Scalar::all(127), cv::Scalar::all(40.f));

if (is_fp16) {
rnd_mat.convertTo(in_mat, depth);
}

std::vector<cv::Mat> out_mats_gapi(planes, cv::Mat::zeros(sz, dstType));
std::vector<cv::Mat> out_mats_ocv (planes, cv::Mat::zeros(sz, dstType));
Expand Down Expand Up @@ -520,12 +530,21 @@ TEST_P(MergeTestGAPI, AccuracyTest)
cv::Size sz = std::get<2>(params);
double tolerance = std::get<3>(params);

int srcType = CV_MAKE_TYPE(depth, 1);
auto make_src_type = [](int d){
return CV_MAKE_TYPE(d, 1);
};
int srcType = make_src_type(depth);
int dstType = CV_MAKE_TYPE(depth, planes);

std::vector<cv::Mat> in_mats(planes, cv::Mat(sz, srcType));
for (int p = 0; p < planes; p++) {
cv::randn(in_mats[p], cv::Scalar::all(127), cv::Scalar::all(40.f));
bool const is_fp16 = (depth == CV_16F);
cv::Mat rnd_mat = is_fp16 ? cv::Mat(sz, make_src_type(CV_32F)) : in_mats[p];
cv::randn(rnd_mat, cv::Scalar::all(127), cv::Scalar::all(40.f));

if (is_fp16) {
rnd_mat.convertTo(in_mats[p], depth);
}
}

cv::Mat out_mat_ocv = cv::Mat::zeros(sz, dstType);
Expand Down Expand Up @@ -754,7 +773,8 @@ TEST_P(ColorConvertTestIE, AccuracyTest)
cv::Scalar mean = cv::Scalar::all(127);
cv::Scalar stddev = cv::Scalar::all(40.f);

cv::randn(in_mat1, mean, stddev);
if (depth != CV_16F)
cv::randn(in_mat1, mean, stddev);

cv::Mat out_mat(size, out_type);
cv::Mat out_mat_ocv(size, out_type);
Expand All @@ -771,7 +791,7 @@ TEST_P(ColorConvertTestIE, AccuracyTest)
size_t out_channels = out_mat.channels();
CV_Assert(3 == out_channels || 4 == out_channels);

CV_Assert(CV_8U == depth || CV_32F == depth);
CV_Assert(CV_8U == depth || CV_32F == depth || depth == CV_16S || depth == CV_16F);

ASSERT_TRUE(in_mat1.isContinuous() && out_mat.isContinuous());

Expand All @@ -780,8 +800,21 @@ TEST_P(ColorConvertTestIE, AccuracyTest)
InferenceEngine::SizeVector in_sv = { 1, in_channels, in_height, in_width };
InferenceEngine::SizeVector out_sv = { 1, out_channels, out_height, out_width };

auto depth_to_precision = [](int depth) -> Precision::ePrecision {
switch (depth)
{
case CV_8U: return Precision::U8;
case CV_16S: return Precision::I16;
case CV_16F: return Precision::FP16;
case CV_32F: return Precision::FP32;
default:
throw std::logic_error("Unsupported configuration");
}
return Precision::UNSPECIFIED;
};

// HWC blob: channels are interleaved
Precision precision = CV_8U == depth ? Precision::U8 : Precision::FP32;
Precision precision = depth_to_precision(depth);

Blob::Ptr in_blob, out_blob;
switch (precision)
Expand All @@ -796,6 +829,18 @@ TEST_P(ColorConvertTestIE, AccuracyTest)
out_blob = img2Blob<Precision::FP32>(out_mat, out_layout);
break;

case Precision::I16:
in_blob = img2Blob<Precision::I16>(in_mat1, in_layout);
out_blob = img2Blob<Precision::I16>(out_mat, out_layout);
break;

case Precision::FP16:
in_blob = img2Blob<Precision::FP16>(in_mat1, in_layout);
out_blob = img2Blob<Precision::FP16>(out_mat, out_layout);

break;


default:
FAIL() << "Unsupported configuration";
}
Expand All @@ -813,6 +858,8 @@ TEST_P(ColorConvertTestIE, AccuracyTest)
{
case Precision::U8: Blob2Img<Precision::U8> (out_blob, out_mat, out_layout); break;
case Precision::FP32: Blob2Img<Precision::FP32>(out_blob, out_mat, out_layout); break;
case Precision::I16: Blob2Img<Precision::I16> (out_blob, out_mat, out_layout); break;
case Precision::FP16: Blob2Img<Precision::FP16> (out_blob, out_mat, out_layout); break;
default: FAIL() << "Unsupported configuration";
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -132,7 +132,7 @@ INSTANTIATE_TEST_CASE_P(ResizeTestFluid_F32, ResizeTestGAPI,

INSTANTIATE_TEST_CASE_P(SplitTestFluid, SplitTestGAPI,
Combine(Values(2, 3, 4),
Values(CV_8U, CV_8S, CV_16U, CV_16S, CV_32F, CV_32S),
Values(CV_8U, CV_8S, CV_16U, CV_16S, CV_16F, CV_32F, CV_32S),
Values(TEST_SIZES),
Values(0)));

Expand All @@ -144,7 +144,7 @@ INSTANTIATE_TEST_CASE_P(ChanToPlaneTestFluid, ChanToPlaneTestGAPI,

INSTANTIATE_TEST_CASE_P(MergeTestFluid, MergeTestGAPI,
Combine(Values(2, 3, 4),
Values(CV_8U, CV_8S, CV_16U, CV_16S, CV_32F, CV_32S),
Values(CV_8U, CV_8S, CV_16U, CV_16S, CV_16F, CV_32F, CV_32S),
Values(TEST_SIZES),
Values(0)));

Expand Down Expand Up @@ -269,15 +269,15 @@ INSTANTIATE_TEST_CASE_P(ColorConvertYUV420Fluid, ColorConvertYUV420TestIE,
Values(0)));

INSTANTIATE_TEST_CASE_P(Reorder_HWC2CHW, ColorConvertTestIE,
Combine(Values(CV_8U, CV_32F),
Combine(Values(CV_8U, CV_32F, CV_16S, CV_16F),
Values(InferenceEngine::ColorFormat::BGR),
Values(InferenceEngine::NHWC),
Values(InferenceEngine::NCHW),
Values(TEST_SIZES),
Values(0)));

INSTANTIATE_TEST_CASE_P(Reorder_CHW2HWC, ColorConvertTestIE,
Combine(Values(CV_8U, CV_32F),
Combine(Values(CV_8U, CV_32F, CV_16S, CV_16F),
Values(InferenceEngine::ColorFormat::BGR),
Values(InferenceEngine::NCHW),
Values(InferenceEngine::NHWC),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,8 @@ typedef unsigned short ushort;
#define CV_32S 4
#define CV_32F 5
#define CV_64F 6
#define CV_USRTYPE1 7
#define CV_16F 7
#define CV_USRTYPE1 8

#define CV_MAT_DEPTH_MASK (CV_DEPTH_MAX - 1)
#define CV_MAT_DEPTH(flags) ((flags) & CV_MAT_DEPTH_MASK)
Expand Down Expand Up @@ -70,6 +71,13 @@ typedef unsigned short ushort;
#define CV_32SC4 CV_MAKETYPE(CV_32S,4)
#define CV_32SC(n) CV_MAKETYPE(CV_32S,(n))


#define CV_16FC1 CV_MAKETYPE(CV_16F,1)
#define CV_16FC2 CV_MAKETYPE(CV_16F,2)
#define CV_16FC3 CV_MAKETYPE(CV_16F,3)
#define CV_16FC4 CV_MAKETYPE(CV_16F,4)
#define CV_16FC(n) CV_MAKETYPE(CV_16F,(n))

#define CV_32FC1 CV_MAKETYPE(CV_32F,1)
#define CV_32FC2 CV_MAKETYPE(CV_32F,2)
#define CV_32FC3 CV_MAKETYPE(CV_32F,3)
Expand Down

0 comments on commit 4fa9012

Please sign in to comment.