aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSanghoon Lee <sanghoon.lee@arm.com>2018-06-29 10:52:57 +0100
committerAnthony Barbier <anthony.barbier@arm.com>2018-11-02 16:54:10 +0000
commitdec32a9edd4b3c6dc55c60d7436e79af6be58c3d (patch)
tree0aafd0e56a4482f7a8215a1c9f9592552a27c5c4
parent149fdf3cad6b42ed302ebe2b0d614a36b9b4d81c (diff)
downloadComputeLibrary-dec32a9edd4b3c6dc55c60d7436e79af6be58c3d.tar.gz
COMPMID-566: Implement reference and CL/NEON validation for ColorConvert (part 2)
Change-Id: I4371c4b6403f55ea7d7baf39df91a45f45b21d5a Reviewed-on: https://eu-gerrit-1.euhpc.arm.com/137975 Tested-by: Jenkins <bsgcomp@arm.com> Reviewed-by: Anthony Barbier <anthony.barbier@arm.com>
-rw-r--r--tests/validation/CL/ColorConvert.cpp182
-rw-r--r--tests/validation/NEON/ColorConvert.cpp181
-rw-r--r--tests/validation/fixtures/ColorConvertFixture.h81
-rw-r--r--tests/validation/reference/ColorConvert.cpp102
-rw-r--r--tests/validation/reference/ColorConvert.h2
-rw-r--r--tests/validation/reference/ColorConvertHelper.h553
6 files changed, 1013 insertions, 88 deletions
diff --git a/tests/validation/CL/ColorConvert.cpp b/tests/validation/CL/ColorConvert.cpp
index 6d04511629..c99fa3cee1 100644
--- a/tests/validation/CL/ColorConvert.cpp
+++ b/tests/validation/CL/ColorConvert.cpp
@@ -40,6 +40,8 @@ namespace validation
{
namespace
{
+constexpr AbsoluteTolerance<uint8_t> tolerance_nv(2);
+
// Input data sets
const auto ColorConvertRGBADataset = combine(framework::dataset::make("FormatType", { Format::RGBA8888 }),
framework::dataset::make("FormatType", { Format::RGB888 }));
@@ -52,30 +54,68 @@ const auto ColorConvertYUVPlanarDataset = combine(framework::dataset::make("Form
const auto ColorConvertRGBDataset = combine(framework::dataset::make("FormatType", { Format::RGB888 }),
framework::dataset::make("FormatType", { Format::RGBA8888 }));
+const auto ColorConvertNVDataset = combine(framework::dataset::make("FormatType", { Format::RGB888, Format::RGBA8888 }),
+ framework::dataset::make("FormatType", { Format::NV12, Format::IYUV, Format::YUV444 }));
+
+const auto ColorConvertYUYVtoNVDataset = combine(framework::dataset::make("FormatType", { Format::UYVY422, Format::YUYV422 }),
+ framework::dataset::make("FormatType", { Format::NV12, Format::IYUV }));
+
+const auto ColorConvertNVtoYUVDataset = combine(framework::dataset::make("FormatType", { Format::NV12, Format::NV21 }),
+ framework::dataset::make("FormatType", { Format::IYUV, Format::YUV444 }));
+
inline void validate_configuration(const TensorShape &shape, Format src_format, Format dst_format)
{
const unsigned int src_num_planes = num_planes_from_format(src_format);
+ const unsigned int dst_num_planes = num_planes_from_format(dst_format);
- const TensorShape dst_shape = adjust_odd_shape(shape, src_format);
+ TensorShape input = adjust_odd_shape(shape, src_format);
+ input = adjust_odd_shape(input, src_format);
// Create tensors
- CLMultiImage ref_src = create_multi_image<CLMultiImage>(shape, src_format);
- CLTensor dst = create_tensor<CLTensor>(dst_shape, dst_format);
+ CLMultiImage ref_src = create_multi_image<CLMultiImage>(input, src_format);
+ CLMultiImage ref_dst = create_multi_image<CLMultiImage>(input, dst_format);
// Create and Configure function
CLColorConvert color_convert;
if(1U == src_num_planes)
{
- const CLTensor *plane_src = ref_src.cl_plane(0);
+ const CLTensor *src_plane = ref_src.cl_plane(0);
- color_convert.configure(plane_src, &dst);
- const ValidRegion dst_valid_region = shape_to_valid_region(dst_shape);
- validate(dst.info()->valid_region(), dst_valid_region);
+ if(1U == dst_num_planes)
+ {
+ CLTensor *dst_plane = ref_dst.cl_plane(0);
+ color_convert.configure(src_plane, dst_plane);
+ }
+ else
+ {
+ color_convert.configure(src_plane, &ref_dst);
+ }
}
else
{
- color_convert.configure(&ref_src, &dst);
+ if(1U == dst_num_planes)
+ {
+ CLTensor *dst_plane = ref_dst.cl_plane(0);
+ color_convert.configure(&ref_src, dst_plane);
+ }
+ else
+ {
+ color_convert.configure(&ref_src, &ref_dst);
+ }
+ }
+
+ for(unsigned int plane_idx = 0; plane_idx < src_num_planes; ++plane_idx)
+ {
+ const CLTensor *src_plane = ref_src.cl_plane(plane_idx);
+
+ ARM_COMPUTE_EXPECT(src_plane->info()->is_resizable(), framework::LogLevel::ERRORS);
+ }
+ for(unsigned int plane_idx = 0; plane_idx < dst_num_planes; ++plane_idx)
+ {
+ const CLTensor *dst_plane = ref_dst.cl_plane(plane_idx);
+
+ ARM_COMPUTE_EXPECT(dst_plane->info()->is_resizable(), framework::LogLevel::ERRORS);
}
}
} // namespace
@@ -83,6 +123,9 @@ inline void validate_configuration(const TensorShape &shape, Format src_format,
TEST_SUITE(CL)
TEST_SUITE(ColorConvert)
+template <typename T>
+using CLColorConvertFixture = ColorConvertValidationFixture<CLMultiImage, CLTensor, CLAccessor, CLColorConvert, T>;
+
TEST_SUITE(Configuration)
DATA_TEST_CASE(RGBA, framework::DatasetMode::ALL, combine(concat(datasets::Small2DShapes(), datasets::Large2DShapes()), ColorConvertRGBADataset),
shape, src_format, dst_format)
@@ -107,34 +150,63 @@ DATA_TEST_CASE(RGB, framework::DatasetMode::ALL, combine(concat(datasets::Small2
{
validate_configuration(shape, src_format, dst_format);
}
-TEST_SUITE_END()
-template <typename T>
-using CLColorConvertFixture = ColorConvertValidationFixture<CLMultiImage, CLTensor, CLAccessor, CLColorConvert, T>;
+DATA_TEST_CASE(NV, framework::DatasetMode::ALL, combine(concat(datasets::Small2DShapes(), datasets::Large2DShapes()), ColorConvertNVDataset),
+ shape, src_format, dst_format)
+{
+ validate_configuration(shape, src_format, dst_format);
+}
+
+DATA_TEST_CASE(YUVtoNV, framework::DatasetMode::ALL, combine(concat(datasets::Small2DShapes(), datasets::Large2DShapes()), ColorConvertYUYVtoNVDataset),
+ shape, src_format, dst_format)
+{
+ validate_configuration(shape, src_format, dst_format);
+}
+
+DATA_TEST_CASE(NVtoYUV, framework::DatasetMode::ALL, combine(concat(datasets::Small2DShapes(), datasets::Large2DShapes()), ColorConvertNVtoYUVDataset),
+ shape, src_format, dst_format)
+{
+ validate_configuration(shape, src_format, dst_format);
+}
+TEST_SUITE_END()
TEST_SUITE(RGBA)
FIXTURE_DATA_TEST_CASE(RunSmall, CLColorConvertFixture<uint8_t>, framework::DatasetMode::PRECOMMIT, combine(datasets::Small2DShapes(), ColorConvertRGBADataset))
{
// Validate output
- validate(CLAccessor(_target), _reference);
+ for(unsigned int plane_idx = 0; plane_idx < _dst_num_planes; ++plane_idx)
+ {
+ validate(CLAccessor(*_target.cl_plane(plane_idx)), _reference[plane_idx]);
+ }
}
FIXTURE_DATA_TEST_CASE(RunLarge, CLColorConvertFixture<uint8_t>, framework::DatasetMode::NIGHTLY, combine(datasets::Large2DShapes(), ColorConvertRGBADataset))
{
// Validate output
- validate(CLAccessor(_target), _reference);
+ for(unsigned int plane_idx = 0; plane_idx < _dst_num_planes; ++plane_idx)
+ {
+ validate(CLAccessor(*_target.cl_plane(plane_idx)), _reference[plane_idx]);
+ }
}
+
TEST_SUITE_END()
TEST_SUITE(YUV)
FIXTURE_DATA_TEST_CASE(RunSmall, CLColorConvertFixture<uint8_t>, framework::DatasetMode::PRECOMMIT, combine(datasets::Small2DShapes(), ColorConvertYUVDataset))
{
// Validate output
- validate(CLAccessor(_target), _reference);
+ for(unsigned int plane_idx = 0; plane_idx < _dst_num_planes; ++plane_idx)
+ {
+ validate(CLAccessor(*_target.cl_plane(plane_idx)), _reference[plane_idx]);
+ }
}
FIXTURE_DATA_TEST_CASE(RunLarge, CLColorConvertFixture<uint8_t>, framework::DatasetMode::NIGHTLY, combine(datasets::Large2DShapes(), ColorConvertYUVDataset))
{
- validate(CLAccessor(_target), _reference);
+ // Validate output
+ for(unsigned int plane_idx = 0; plane_idx < _dst_num_planes; ++plane_idx)
+ {
+ validate(CLAccessor(*_target.cl_plane(plane_idx)), _reference[plane_idx]);
+ }
}
TEST_SUITE_END()
@@ -142,12 +214,18 @@ TEST_SUITE(YUVPlanar)
FIXTURE_DATA_TEST_CASE(RunSmall, CLColorConvertFixture<uint8_t>, framework::DatasetMode::PRECOMMIT, combine(datasets::Small2DShapes(), ColorConvertYUVPlanarDataset))
{
// Validate output
- validate(CLAccessor(_target), _reference);
+ for(unsigned int plane_idx = 0; plane_idx < _dst_num_planes; ++plane_idx)
+ {
+ validate(CLAccessor(*_target.cl_plane(plane_idx)), _reference[plane_idx]);
+ }
}
FIXTURE_DATA_TEST_CASE(RunLarge, CLColorConvertFixture<uint8_t>, framework::DatasetMode::NIGHTLY, combine(datasets::Large2DShapes(), ColorConvertYUVPlanarDataset))
{
// Validate output
- validate(CLAccessor(_target), _reference);
+ for(unsigned int plane_idx = 0; plane_idx < _dst_num_planes; ++plane_idx)
+ {
+ validate(CLAccessor(*_target.cl_plane(plane_idx)), _reference[plane_idx]);
+ }
}
TEST_SUITE_END()
@@ -155,14 +233,80 @@ TEST_SUITE(RGB)
FIXTURE_DATA_TEST_CASE(RunSmall, CLColorConvertFixture<uint8_t>, framework::DatasetMode::PRECOMMIT, combine(datasets::Small2DShapes(), ColorConvertRGBDataset))
{
// Validate output
- validate(CLAccessor(_target), _reference);
+ for(unsigned int plane_idx = 0; plane_idx < _dst_num_planes; ++plane_idx)
+ {
+ validate(CLAccessor(*_target.cl_plane(plane_idx)), _reference[plane_idx]);
+ }
}
FIXTURE_DATA_TEST_CASE(RunLarge, CLColorConvertFixture<uint8_t>, framework::DatasetMode::NIGHTLY, combine(datasets::Large2DShapes(), ColorConvertRGBDataset))
{
// Validate output
- validate(CLAccessor(_target), _reference);
+ for(unsigned int plane_idx = 0; plane_idx < _dst_num_planes; ++plane_idx)
+ {
+ validate(CLAccessor(*_target.cl_plane(plane_idx)), _reference[plane_idx]);
+ }
+}
+TEST_SUITE_END()
+
+TEST_SUITE(NV)
+FIXTURE_DATA_TEST_CASE(RunSmall, CLColorConvertFixture<uint8_t>, framework::DatasetMode::PRECOMMIT, combine(datasets::Small2DShapes(), ColorConvertNVDataset))
+{
+ // Validate output
+ for(unsigned int plane_idx = 0; plane_idx < _dst_num_planes; ++plane_idx)
+ {
+ validate(CLAccessor(*_target.cl_plane(plane_idx)), _reference[plane_idx], tolerance_nv);
+ }
+}
+FIXTURE_DATA_TEST_CASE(RunLarge, CLColorConvertFixture<uint8_t>, framework::DatasetMode::NIGHTLY, combine(datasets::Large2DShapes(), ColorConvertNVDataset))
+{
+ // Validate output
+ for(unsigned int plane_idx = 0; plane_idx < _dst_num_planes; ++plane_idx)
+ {
+ validate(CLAccessor(*_target.cl_plane(plane_idx)), _reference[plane_idx], tolerance_nv);
+ }
+}
+TEST_SUITE_END()
+
+TEST_SUITE(YUYVtoNV)
+FIXTURE_DATA_TEST_CASE(RunSmall, CLColorConvertFixture<uint8_t>, framework::DatasetMode::PRECOMMIT, combine(datasets::Small2DShapes(), ColorConvertYUYVtoNVDataset))
+{
+ // Validate output
+ for(unsigned int plane_idx = 0; plane_idx < _dst_num_planes; ++plane_idx)
+ {
+ validate(CLAccessor(*_target.cl_plane(plane_idx)), _reference[plane_idx]);
+ }
+}
+FIXTURE_DATA_TEST_CASE(RunLarge, CLColorConvertFixture<uint8_t>, framework::DatasetMode::NIGHTLY, combine(datasets::Large2DShapes(), ColorConvertYUYVtoNVDataset))
+{
+ // Validate output
+ for(unsigned int plane_idx = 0; plane_idx < _dst_num_planes; ++plane_idx)
+ {
+ validate(CLAccessor(*_target.cl_plane(plane_idx)), _reference[plane_idx]);
+ }
+}
+
+TEST_SUITE_END()
+
+TEST_SUITE(NVtoYUV)
+FIXTURE_DATA_TEST_CASE(RunSmall, CLColorConvertFixture<uint8_t>, framework::DatasetMode::PRECOMMIT, combine(datasets::Small2DShapes(), ColorConvertNVtoYUVDataset))
+{
+ // Validate output
+ for(unsigned int plane_idx = 0; plane_idx < _dst_num_planes; ++plane_idx)
+ {
+ validate(CLAccessor(*_target.cl_plane(plane_idx)), _reference[plane_idx]);
+ }
}
+FIXTURE_DATA_TEST_CASE(RunLarge, CLColorConvertFixture<uint8_t>, framework::DatasetMode::NIGHTLY, combine(datasets::Large2DShapes(), ColorConvertNVtoYUVDataset))
+{
+ // Validate output
+ for(unsigned int plane_idx = 0; plane_idx < _dst_num_planes; ++plane_idx)
+ {
+ validate(CLAccessor(*_target.cl_plane(plane_idx)), _reference[plane_idx]);
+ }
+}
+
TEST_SUITE_END()
+
TEST_SUITE_END()
TEST_SUITE_END()
} // namespace validation
diff --git a/tests/validation/NEON/ColorConvert.cpp b/tests/validation/NEON/ColorConvert.cpp
index ab6ec5b725..ec2f1b8edc 100644
--- a/tests/validation/NEON/ColorConvert.cpp
+++ b/tests/validation/NEON/ColorConvert.cpp
@@ -40,6 +40,8 @@ namespace validation
{
namespace
{
+constexpr AbsoluteTolerance<uint8_t> tolerance_nv(2);
+
// Input data sets
const auto ColorConvertRGBADataset = combine(framework::dataset::make("FormatType", { Format::RGBA8888 }),
framework::dataset::make("FormatType", { Format::RGB888 }));
@@ -52,30 +54,68 @@ const auto ColorConvertYUVPlanarDataset = combine(framework::dataset::make("Form
const auto ColorConvertRGBDataset = combine(framework::dataset::make("FormatType", { Format::RGB888 }),
framework::dataset::make("FormatType", { Format::RGBA8888 }));
+const auto ColorConvertNVDataset = combine(framework::dataset::make("FormatType", { Format::RGB888, Format::RGBA8888 }),
+ framework::dataset::make("FormatType", { Format::NV12, Format::IYUV, Format::YUV444 }));
+
+const auto ColorConvertYUYVtoNVDataset = combine(framework::dataset::make("FormatType", { Format::UYVY422, Format::YUYV422 }),
+ framework::dataset::make("FormatType", { Format::NV12, Format::IYUV }));
+
+const auto ColorConvertNVtoYUVDataset = combine(framework::dataset::make("FormatType", { Format::NV12, Format::NV21 }),
+ framework::dataset::make("FormatType", { Format::IYUV, Format::YUV444 }));
+
inline void validate_configuration(const TensorShape &shape, Format src_format, Format dst_format)
{
const unsigned int src_num_planes = num_planes_from_format(src_format);
+ const unsigned int dst_num_planes = num_planes_from_format(dst_format);
- const TensorShape dst_shape = adjust_odd_shape(shape, src_format);
+ TensorShape input = adjust_odd_shape(shape, src_format);
+ input = adjust_odd_shape(input, dst_format);
// Create tensors
- MultiImage ref_src = create_multi_image<MultiImage>(shape, src_format);
- Tensor dst = create_tensor<Tensor>(dst_shape, dst_format);
+ MultiImage ref_src = create_multi_image<MultiImage>(input, src_format);
+ MultiImage ref_dst = create_multi_image<MultiImage>(input, dst_format);
// Create and Configure function
NEColorConvert color_convert;
if(1U == src_num_planes)
{
- const Tensor *plane_src = ref_src.plane(0);
+ const Tensor *src_plane = ref_src.plane(0);
- color_convert.configure(plane_src, &dst);
- const ValidRegion dst_valid_region = shape_to_valid_region(dst_shape);
- validate(dst.info()->valid_region(), dst_valid_region);
+ if(1U == dst_num_planes)
+ {
+ Tensor *dst_plane = ref_dst.plane(0);
+ color_convert.configure(src_plane, dst_plane);
+ }
+ else
+ {
+ color_convert.configure(src_plane, &ref_dst);
+ }
}
else
{
- color_convert.configure(&ref_src, &dst);
+ if(1U == dst_num_planes)
+ {
+ Tensor *dst_plane = ref_dst.plane(0);
+ color_convert.configure(&ref_src, dst_plane);
+ }
+ else
+ {
+ color_convert.configure(&ref_src, &ref_dst);
+ }
+ }
+
+ for(unsigned int plane_idx = 0; plane_idx < src_num_planes; ++plane_idx)
+ {
+ const Tensor *src_plane = ref_src.plane(plane_idx);
+
+ ARM_COMPUTE_EXPECT(src_plane->info()->is_resizable(), framework::LogLevel::ERRORS);
+ }
+ for(unsigned int plane_idx = 0; plane_idx < dst_num_planes; ++plane_idx)
+ {
+ const Tensor *dst_plane = ref_dst.plane(plane_idx);
+
+ ARM_COMPUTE_EXPECT(dst_plane->info()->is_resizable(), framework::LogLevel::ERRORS);
}
}
} // namespace
@@ -83,6 +123,9 @@ inline void validate_configuration(const TensorShape &shape, Format src_format,
TEST_SUITE(NEON)
TEST_SUITE(ColorConvert)
+template <typename T>
+using NEColorConvertFixture = ColorConvertValidationFixture<MultiImage, Tensor, Accessor, NEColorConvert, T>;
+
TEST_SUITE(Configuration)
DATA_TEST_CASE(RGBA, framework::DatasetMode::ALL, combine(concat(datasets::Small2DShapes(), datasets::Large2DShapes()), ColorConvertRGBADataset),
shape, src_format, dst_format)
@@ -107,35 +150,62 @@ DATA_TEST_CASE(RGB, framework::DatasetMode::ALL, combine(concat(datasets::Small2
{
validate_configuration(shape, src_format, dst_format);
}
-TEST_SUITE_END()
-template <typename T>
-using NEColorConvertFixture = ColorConvertValidationFixture<MultiImage, Tensor, Accessor, NEColorConvert, T>;
+DATA_TEST_CASE(NV, framework::DatasetMode::ALL, combine(concat(datasets::Small2DShapes(), datasets::Large2DShapes()), ColorConvertNVDataset),
+ shape, src_format, dst_format)
+{
+ validate_configuration(shape, src_format, dst_format);
+}
+
+DATA_TEST_CASE(YUVtoNV, framework::DatasetMode::ALL, combine(concat(datasets::Small2DShapes(), datasets::Large2DShapes()), ColorConvertYUYVtoNVDataset),
+ shape, src_format, dst_format)
+{
+ validate_configuration(shape, src_format, dst_format);
+}
+
+DATA_TEST_CASE(NVtoYUV, framework::DatasetMode::ALL, combine(concat(datasets::Small2DShapes(), datasets::Large2DShapes()), ColorConvertNVtoYUVDataset),
+ shape, src_format, dst_format)
+{
+ validate_configuration(shape, src_format, dst_format);
+}
+TEST_SUITE_END()
TEST_SUITE(RGBA)
FIXTURE_DATA_TEST_CASE(RunSmall, NEColorConvertFixture<uint8_t>, framework::DatasetMode::PRECOMMIT, combine(datasets::Small2DShapes(), ColorConvertRGBADataset))
{
// Validate output
- validate(Accessor(_target), _reference);
+ for(unsigned int plane_idx = 0; plane_idx < _dst_num_planes; ++plane_idx)
+ {
+ validate(Accessor(*_target.plane(plane_idx)), _reference[plane_idx]);
+ }
}
+
FIXTURE_DATA_TEST_CASE(RunLarge, NEColorConvertFixture<uint8_t>, framework::DatasetMode::NIGHTLY, combine(datasets::Large2DShapes(), ColorConvertRGBADataset))
{
// Validate output
- validate(Accessor(_target), _reference);
+ for(unsigned int plane_idx = 0; plane_idx < _dst_num_planes; ++plane_idx)
+ {
+ validate(Accessor(*_target.plane(plane_idx)), _reference[plane_idx]);
+ }
}
-
TEST_SUITE_END()
TEST_SUITE(YUV)
FIXTURE_DATA_TEST_CASE(RunSmall, NEColorConvertFixture<uint8_t>, framework::DatasetMode::PRECOMMIT, combine(datasets::Small2DShapes(), ColorConvertYUVDataset))
{
// Validate output
- validate(Accessor(_target), _reference);
+ for(unsigned int plane_idx = 0; plane_idx < _dst_num_planes; ++plane_idx)
+ {
+ validate(Accessor(*_target.plane(plane_idx)), _reference[plane_idx]);
+ }
}
FIXTURE_DATA_TEST_CASE(RunLarge, NEColorConvertFixture<uint8_t>, framework::DatasetMode::NIGHTLY, combine(datasets::Large2DShapes(), ColorConvertYUVDataset))
{
// Validate output
- validate(Accessor(_target), _reference);
+ for(unsigned int plane_idx = 0; plane_idx < _dst_num_planes; ++plane_idx)
+ {
+ validate(Accessor(*_target.plane(plane_idx)), _reference[plane_idx]);
+ }
}
TEST_SUITE_END()
@@ -144,12 +214,18 @@ TEST_SUITE(YUVPlanar)
FIXTURE_DATA_TEST_CASE(RunSmall, NEColorConvertFixture<uint8_t>, framework::DatasetMode::PRECOMMIT, combine(datasets::Small2DShapes(), ColorConvertYUVPlanarDataset))
{
// Validate output
- validate(Accessor(_target), _reference);
+ for(unsigned int plane_idx = 0; plane_idx < _dst_num_planes; ++plane_idx)
+ {
+ validate(Accessor(*_target.plane(plane_idx)), _reference[plane_idx]);
+ }
}
FIXTURE_DATA_TEST_CASE(RunLarge, NEColorConvertFixture<uint8_t>, framework::DatasetMode::NIGHTLY, combine(datasets::Large2DShapes(), ColorConvertYUVPlanarDataset))
{
// Validate output
- validate(Accessor(_target), _reference);
+ for(unsigned int plane_idx = 0; plane_idx < _dst_num_planes; ++plane_idx)
+ {
+ validate(Accessor(*_target.plane(plane_idx)), _reference[plane_idx]);
+ }
}
TEST_SUITE_END()
@@ -157,12 +233,77 @@ TEST_SUITE(RGB)
FIXTURE_DATA_TEST_CASE(RunSmall, NEColorConvertFixture<uint8_t>, framework::DatasetMode::PRECOMMIT, combine(datasets::Small2DShapes(), ColorConvertRGBDataset))
{
// Validate output
- validate(Accessor(_target), _reference);
+ for(unsigned int plane_idx = 0; plane_idx < _dst_num_planes; ++plane_idx)
+ {
+ validate(Accessor(*_target.plane(plane_idx)), _reference[plane_idx]);
+ }
}
FIXTURE_DATA_TEST_CASE(RunLarge, NEColorConvertFixture<uint8_t>, framework::DatasetMode::NIGHTLY, combine(datasets::Large2DShapes(), ColorConvertRGBDataset))
{
// Validate output
- validate(Accessor(_target), _reference);
+ for(unsigned int plane_idx = 0; plane_idx < _dst_num_planes; ++plane_idx)
+ {
+ validate(Accessor(*_target.plane(plane_idx)), _reference[plane_idx]);
+ }
+}
+TEST_SUITE_END()
+
+TEST_SUITE(NV)
+FIXTURE_DATA_TEST_CASE(RunSmall, NEColorConvertFixture<uint8_t>, framework::DatasetMode::PRECOMMIT, combine(datasets::Small2DShapes(), ColorConvertNVDataset))
+{
+ // Validate output
+ for(unsigned int plane_idx = 0; plane_idx < _dst_num_planes; ++plane_idx)
+ {
+ validate(Accessor(*_target.plane(plane_idx)), _reference[plane_idx], tolerance_nv);
+ }
+}
+
+FIXTURE_DATA_TEST_CASE(RunLarge, NEColorConvertFixture<uint8_t>, framework::DatasetMode::NIGHTLY, combine(datasets::Large2DShapes(), ColorConvertNVDataset))
+{
+ // Validate output
+ for(unsigned int plane_idx = 0; plane_idx < _dst_num_planes; ++plane_idx)
+ {
+ validate(Accessor(*_target.plane(plane_idx)), _reference[plane_idx], tolerance_nv);
+ }
+}
+TEST_SUITE_END()
+
+TEST_SUITE(YUVtoNV)
+FIXTURE_DATA_TEST_CASE(RunSmall, NEColorConvertFixture<uint8_t>, framework::DatasetMode::PRECOMMIT, combine(datasets::Small2DShapes(), ColorConvertYUYVtoNVDataset))
+{
+ // Validate output
+ for(unsigned int plane_idx = 0; plane_idx < _dst_num_planes; ++plane_idx)
+ {
+ validate(Accessor(*_target.plane(plane_idx)), _reference[plane_idx]);
+ }
+}
+
+FIXTURE_DATA_TEST_CASE(RunLarge, NEColorConvertFixture<uint8_t>, framework::DatasetMode::NIGHTLY, combine(datasets::Large2DShapes(), ColorConvertYUYVtoNVDataset))
+{
+ // Validate output
+ for(unsigned int plane_idx = 0; plane_idx < _dst_num_planes; ++plane_idx)
+ {
+ validate(Accessor(*_target.plane(plane_idx)), _reference[plane_idx]);
+ }
+}
+TEST_SUITE_END()
+
+TEST_SUITE(NVtoYUV)
+FIXTURE_DATA_TEST_CASE(RunSmall, NEColorConvertFixture<uint8_t>, framework::DatasetMode::PRECOMMIT, combine(datasets::Small2DShapes(), ColorConvertNVtoYUVDataset))
+{
+ // Validate output
+ for(unsigned int plane_idx = 0; plane_idx < _dst_num_planes; ++plane_idx)
+ {
+ validate(Accessor(*_target.plane(plane_idx)), _reference[plane_idx]);
+ }
+}
+FIXTURE_DATA_TEST_CASE(RunLarge, NEColorConvertFixture<uint8_t>, framework::DatasetMode::NIGHTLY, combine(datasets::Large2DShapes(), ColorConvertNVtoYUVDataset))
+{
+ // Validate output
+ for(unsigned int plane_idx = 0; plane_idx < _dst_num_planes; ++plane_idx)
+ {
+ validate(Accessor(*_target.plane(plane_idx)), _reference[plane_idx]);
+ }
}
TEST_SUITE_END()
diff --git a/tests/validation/fixtures/ColorConvertFixture.h b/tests/validation/fixtures/ColorConvertFixture.h
index bd00d4f724..52a9de87b0 100644
--- a/tests/validation/fixtures/ColorConvertFixture.h
+++ b/tests/validation/fixtures/ColorConvertFixture.h
@@ -51,6 +51,7 @@ public:
void setup(TensorShape shape, Format src_format, Format dst_format)
{
shape = adjust_odd_shape(shape, src_format);
+ shape = adjust_odd_shape(shape, dst_format);
_target = compute_target(shape, src_format, dst_format);
_reference = compute_reference(shape, src_format, dst_format);
@@ -60,13 +61,11 @@ protected:
template <typename U>
void fill(U &&tensor, int i)
{
- library->fill_tensor_uniform(tensor, 1);
+ library->fill_tensor_uniform(tensor, i);
}
std::vector<SimpleTensor<T>> create_tensor_planes_reference(const TensorShape &shape, Format format)
{
- TensorShape input = adjust_odd_shape(shape, format);
-
std::vector<SimpleTensor<T>> tensor_planes;
switch(format)
@@ -76,7 +75,7 @@ protected:
case Format::YUYV422:
case Format::UYVY422:
{
- tensor_planes.emplace_back(input, format);
+ tensor_planes.emplace_back(shape, format);
break;
}
case Format::NV12:
@@ -84,7 +83,7 @@ protected:
{
const TensorShape shape_uv88 = calculate_subsampled_shape(shape, Format::UV88);
- tensor_planes.emplace_back(input, Format::U8);
+ tensor_planes.emplace_back(shape, Format::U8);
tensor_planes.emplace_back(shape_uv88, Format::UV88);
break;
}
@@ -92,16 +91,16 @@ protected:
{
const TensorShape shape_sub2 = calculate_subsampled_shape(shape, Format::IYUV);
- tensor_planes.emplace_back(input, Format::U8);
+ tensor_planes.emplace_back(shape, Format::U8);
tensor_planes.emplace_back(shape_sub2, Format::U8);
tensor_planes.emplace_back(shape_sub2, Format::U8);
break;
}
case Format::YUV444:
{
- tensor_planes.emplace_back(input, Format::U8);
- tensor_planes.emplace_back(input, Format::U8);
- tensor_planes.emplace_back(input, Format::U8);
+ tensor_planes.emplace_back(shape, Format::U8);
+ tensor_planes.emplace_back(shape, Format::U8);
+ tensor_planes.emplace_back(shape, Format::U8);
break;
}
default:
@@ -112,51 +111,76 @@ protected:
return tensor_planes;
}
- TensorType compute_target(const TensorShape &shape, Format src_format, Format dst_format)
+ MultiImageType compute_target(const TensorShape &shape, Format src_format, Format dst_format)
{
- const unsigned int num_planes = num_planes_from_format(src_format);
+ _src_num_planes = num_planes_from_format(src_format);
+ _dst_num_planes = num_planes_from_format(dst_format);
// Create tensors
MultiImageType ref_src = create_multi_image<MultiImageType>(shape, src_format);
- TensorType dst = create_tensor<TensorType>(shape, dst_format);
+ MultiImageType ref_dst = create_multi_image<MultiImageType>(shape, dst_format);
// Create and configure function
FunctionType color_convert;
- if(1U == num_planes)
+ if(1U == _src_num_planes)
{
const TensorType *plane_src = static_cast<TensorType *>(ref_src.plane(0));
- color_convert.configure(plane_src, &dst);
+
+ if(1U == _dst_num_planes)
+ {
+ TensorType *dst_plane = static_cast<TensorType *>(ref_dst.plane(0));
+ color_convert.configure(plane_src, dst_plane);
+ }
+ else
+ {
+ color_convert.configure(plane_src, &ref_dst);
+ }
}
else
{
- color_convert.configure(&ref_src, &dst);
+ if(1U == _dst_num_planes)
+ {
+ TensorType *dst_plane = static_cast<TensorType *>(ref_dst.plane(0));
+ color_convert.configure(&ref_src, dst_plane);
+ }
+ else
+ {
+ color_convert.configure(&ref_src, &ref_dst);
+ }
}
- for(unsigned int plane_idx = 0; plane_idx < num_planes; ++plane_idx)
+ for(unsigned int plane_idx = 0; plane_idx < _src_num_planes; ++plane_idx)
{
const TensorType *src_plane = static_cast<const TensorType *>(ref_src.plane(plane_idx));
ARM_COMPUTE_EXPECT(src_plane->info()->is_resizable(), framework::LogLevel::ERRORS);
}
+ for(unsigned int plane_idx = 0; plane_idx < _dst_num_planes; ++plane_idx)
+ {
+ const TensorType *dst_plane = static_cast<const TensorType *>(ref_dst.plane(plane_idx));
- ARM_COMPUTE_EXPECT(dst.info()->is_resizable(), framework::LogLevel::ERRORS);
+ ARM_COMPUTE_EXPECT(dst_plane->info()->is_resizable(), framework::LogLevel::ERRORS);
+ }
// Allocate tensors
ref_src.allocate();
- dst.allocator()->allocate();
+ ref_dst.allocate();
- for(unsigned int plane_idx = 0; plane_idx < num_planes; ++plane_idx)
+ for(unsigned int plane_idx = 0; plane_idx < _src_num_planes; ++plane_idx)
{
const TensorType *src_plane = static_cast<const TensorType *>(ref_src.plane(plane_idx));
-
ARM_COMPUTE_EXPECT(!src_plane->info()->is_resizable(), framework::LogLevel::ERRORS);
}
- ARM_COMPUTE_EXPECT(!dst.info()->is_resizable(), framework::LogLevel::ERRORS);
+ for(unsigned int plane_idx = 0; plane_idx < _dst_num_planes; ++plane_idx)
+ {
+ const TensorType *dst_plane = static_cast<const TensorType *>(ref_dst.plane(plane_idx));
+ ARM_COMPUTE_EXPECT(!dst_plane->info()->is_resizable(), framework::LogLevel::ERRORS);
+ }
// Fill tensor planes
- for(unsigned int plane_idx = 0; plane_idx < num_planes; ++plane_idx)
+ for(unsigned int plane_idx = 0; plane_idx < _src_num_planes; ++plane_idx)
{
TensorType *src_plane = static_cast<TensorType *>(ref_src.plane(plane_idx));
@@ -166,13 +190,11 @@ protected:
// Compute function
color_convert.run();
- return dst;
+ return ref_dst;
}
- SimpleTensor<T> compute_reference(const TensorShape &shape, Format src_format, Format dst_format)
+ std::vector<SimpleTensor<T>> compute_reference(const TensorShape &shape, Format src_format, Format dst_format)
{
- _num_planes = num_planes_from_format(dst_format);
-
// Create reference
std::vector<SimpleTensor<T>> ref_src = create_tensor_planes_reference(shape, src_format);
@@ -185,9 +207,10 @@ protected:
return reference::color_convert<T>(shape, ref_src, src_format, dst_format);
}
- unsigned int _num_planes{};
- TensorType _target{};
- SimpleTensor<T> _reference{};
+ unsigned int _src_num_planes{};
+ unsigned int _dst_num_planes{};
+ MultiImageType _target{};
+ std::vector<SimpleTensor<T>> _reference{};
};
} // namespace validation
} // namespace test
diff --git a/tests/validation/reference/ColorConvert.cpp b/tests/validation/reference/ColorConvert.cpp
index 6aa2ffa14c..8047b34688 100644
--- a/tests/validation/reference/ColorConvert.cpp
+++ b/tests/validation/reference/ColorConvert.cpp
@@ -35,12 +35,63 @@ namespace validation
{
namespace reference
{
+namespace
+{
template <typename T>
-SimpleTensor<uint8_t> color_convert(const TensorShape &shape, const std::vector<SimpleTensor<T>> &tensor_planes, Format src_format, Format dst_format)
+inline std::vector<SimpleTensor<T>> create_image_planes(const TensorShape &shape, Format format)
{
- // Create dst and get src tensor
- SimpleTensor<T> src = tensor_planes[0];
- SimpleTensor<T> dst(shape, dst_format);
+ TensorShape image_shape = adjust_odd_shape(shape, format);
+
+ std::vector<SimpleTensor<T>> image_planes;
+
+ switch(format)
+ {
+ case Format::RGB888:
+ case Format::RGBA8888:
+ case Format::YUYV422:
+ case Format::UYVY422:
+ {
+ image_planes.emplace_back(image_shape, format);
+ break;
+ }
+ case Format::NV12:
+ case Format::NV21:
+ {
+ TensorShape shape_uv88 = calculate_subsampled_shape(image_shape, Format::UV88);
+
+ image_planes.emplace_back(image_shape, Format::U8);
+ image_planes.emplace_back(shape_uv88, Format::UV88);
+ break;
+ }
+ case Format::IYUV:
+ {
+ TensorShape shape_sub2 = calculate_subsampled_shape(image_shape, Format::IYUV);
+
+ image_planes.emplace_back(image_shape, Format::U8);
+ image_planes.emplace_back(shape_sub2, Format::U8);
+ image_planes.emplace_back(shape_sub2, Format::U8);
+ break;
+ }
+ case Format::YUV444:
+ {
+ image_planes.emplace_back(image_shape, Format::U8);
+ image_planes.emplace_back(image_shape, Format::U8);
+ image_planes.emplace_back(image_shape, Format::U8);
+ break;
+ }
+ default:
+ ARM_COMPUTE_ERROR("Not supported");
+ break;
+ }
+
+ return image_planes;
+}
+} // namespace
+
+template <typename T>
+std::vector<SimpleTensor<T>> color_convert(const TensorShape &shape, const std::vector<SimpleTensor<T>> &tensor_planes, Format src_format, Format dst_format)
+{
+ std::vector<SimpleTensor<T>> dst = create_image_planes<T>(shape, dst_format);
switch(src_format)
{
@@ -49,7 +100,16 @@ SimpleTensor<uint8_t> color_convert(const TensorShape &shape, const std::vector<
switch(dst_format)
{
case Format::RGBA8888:
- colorconvert_helper::detail::colorconvert_rgb_to_rgbx(src, dst);
+ colorconvert_helper::detail::colorconvert_rgb_to_rgbx(tensor_planes[0], dst[0]);
+ break;
+ case Format::NV12:
+ colorconvert_helper::detail::colorconvert_rgb_to_nv12(tensor_planes[0], dst);
+ break;
+ case Format::IYUV:
+ colorconvert_helper::detail::colorconvert_rgb_to_iyuv(tensor_planes[0], dst);
+ break;
+ case Format::YUV444:
+ colorconvert_helper::detail::colorconvert_rgb_to_yuv4(tensor_planes[0], dst);
break;
default:
ARM_COMPUTE_ERROR("Not Supported");
@@ -62,7 +122,16 @@ SimpleTensor<uint8_t> color_convert(const TensorShape &shape, const std::vector<
switch(dst_format)
{
case Format::RGB888:
- colorconvert_helper::detail::colorconvert_rgbx_to_rgb(src, dst);
+ colorconvert_helper::detail::colorconvert_rgbx_to_rgb(tensor_planes[0], dst[0]);
+ break;
+ case Format::NV12:
+ colorconvert_helper::detail::colorconvert_rgb_to_nv12(tensor_planes[0], dst);
+ break;
+ case Format::IYUV:
+ colorconvert_helper::detail::colorconvert_rgb_to_iyuv(tensor_planes[0], dst);
+ break;
+ case Format::YUV444:
+ colorconvert_helper::detail::colorconvert_rgb_to_yuv4(tensor_planes[0], dst);
break;
default:
ARM_COMPUTE_ERROR("Not Supported");
@@ -77,7 +146,13 @@ SimpleTensor<uint8_t> color_convert(const TensorShape &shape, const std::vector<
{
case Format::RGB888:
case Format::RGBA8888:
- colorconvert_helper::detail::colorconvert_yuyv_to_rgb(src, src_format, dst);
+ colorconvert_helper::detail::colorconvert_yuyv_to_rgb(tensor_planes[0], src_format, dst[0]);
+ break;
+ case Format::NV12:
+ colorconvert_helper::detail::colorconvert_yuyv_to_nv12(tensor_planes[0], src_format, dst);
+ break;
+ case Format::IYUV:
+ colorconvert_helper::detail::colorconvert_yuyv_to_iyuv(tensor_planes[0], src_format, dst);
break;
default:
ARM_COMPUTE_ERROR("Not Supported");
@@ -91,7 +166,7 @@ SimpleTensor<uint8_t> color_convert(const TensorShape &shape, const std::vector<
{
case Format::RGB888:
case Format::RGBA8888:
- colorconvert_helper::detail::colorconvert_iyuv_to_rgb(shape, tensor_planes, dst);
+ colorconvert_helper::detail::colorconvert_iyuv_to_rgb(shape, tensor_planes, dst[0]);
break;
default:
ARM_COMPUTE_ERROR("Not Supported");
@@ -106,7 +181,13 @@ SimpleTensor<uint8_t> color_convert(const TensorShape &shape, const std::vector<
{
case Format::RGB888:
case Format::RGBA8888:
- colorconvert_helper::detail::colorconvert_nv12_to_rgb(shape, src_format, tensor_planes, dst);
+ colorconvert_helper::detail::colorconvert_nv12_to_rgb(shape, src_format, tensor_planes, dst[0]);
+ break;
+ case Format::IYUV:
+ colorconvert_helper::detail::colorconvert_nv_to_iyuv(tensor_planes, src_format, dst);
+ break;
+ case Format::YUV444:
+ colorconvert_helper::detail::colorconvert_nv_to_yuv4(tensor_planes, src_format, dst);
break;
default:
ARM_COMPUTE_ERROR("Not Supported");
@@ -118,11 +199,10 @@ SimpleTensor<uint8_t> color_convert(const TensorShape &shape, const std::vector<
ARM_COMPUTE_ERROR("Not supported");
break;
}
-
return dst;
}
-template SimpleTensor<uint8_t> color_convert(const TensorShape &shape, const std::vector<SimpleTensor<uint8_t>> &tensor_planes, Format src_format, Format dst_format);
+template std::vector<SimpleTensor<uint8_t>> color_convert(const TensorShape &shape, const std::vector<SimpleTensor<uint8_t>> &tensor_planes, Format src_format, Format dst_format);
} // namespace reference
} // namespace validation
} // namespace test
diff --git a/tests/validation/reference/ColorConvert.h b/tests/validation/reference/ColorConvert.h
index 2a8602e7ab..a49bbba7b9 100644
--- a/tests/validation/reference/ColorConvert.h
+++ b/tests/validation/reference/ColorConvert.h
@@ -35,7 +35,7 @@ namespace validation
namespace reference
{
template <typename T>
-SimpleTensor<uint8_t> color_convert(const TensorShape &shape, const std::vector<SimpleTensor<T>> &tensor_planes, Format src_format, Format dst_format);
+std::vector<SimpleTensor<T>> color_convert(const TensorShape &shape, const std::vector<SimpleTensor<T>> &tensor_planes, Format src_format, Format dst_format);
} // namespace reference
} // namespace validation
} // namespace test
diff --git a/tests/validation/reference/ColorConvertHelper.h b/tests/validation/reference/ColorConvertHelper.h
index b4255a0f20..ee446683d6 100644
--- a/tests/validation/reference/ColorConvertHelper.h
+++ b/tests/validation/reference/ColorConvertHelper.h
@@ -39,6 +39,87 @@ constexpr float green_coef_bt709 = -0.1873f;
constexpr float green_coef2_bt709 = -0.4681f;
constexpr float blue_coef_bt709 = 1.8556f;
+constexpr float rgb2yuv_bt709_kr = 0.2126f;
+constexpr float rgb2yuv_bt709_kb = 0.0722f;
+// K_g = 1 - K_r - K_b
+constexpr float rgb2yuv_bt709_kg = 0.7152f;
+// C_u = 1 / (2 * (1 - K_b))
+constexpr float rgb2yuv_bt709_cu = 0.5389f;
+// C_v = 1 / (2 * (1 - K_r))
+constexpr float rgb2yuv_bt709_cv = 0.6350f;
+
+template <typename T>
+inline void store_rgb_from_src(const SimpleTensor<T> src, SimpleTensor<T> &rvec, SimpleTensor<T> &gvec, SimpleTensor<T> &bvec)
+{
+ int width = src.shape().x();
+ int height = src.shape().y();
+
+ for(int y = 0; y < height; ++y)
+ {
+ for(int x = 0; x < width; ++x)
+ {
+ const Coordinates src_coord{ x, y };
+ const Coordinates vec_coord{ x, y };
+
+ const auto *src_pixel = reinterpret_cast<const T *>(src(src_coord));
+ auto *rvec_pixel = reinterpret_cast<T *>(rvec(vec_coord));
+ auto *gvec_pixel = reinterpret_cast<T *>(gvec(vec_coord));
+ auto *bvec_pixel = reinterpret_cast<T *>(bvec(vec_coord));
+
+ rvec_pixel[0] = src_pixel[0];
+ gvec_pixel[0] = src_pixel[1];
+ bvec_pixel[0] = src_pixel[2];
+ }
+ }
+}
+
+template <typename T>
+inline void rgb_to_yuv_calculation(const SimpleTensor<T> rvec, const SimpleTensor<T> gvec, const SimpleTensor<T> bvec, SimpleTensor<T> &yvec, SimpleTensor<T> &uvec_top, SimpleTensor<T> &uvec_bottom,
+ SimpleTensor<T> &vvec_top, SimpleTensor<T> &vvec_bottom)
+{
+ int width = rvec.shape().x();
+ int height = rvec.shape().y();
+
+ int uvec_coord_x = 0;
+ int uvec_coord_y = 0;
+ Coordinates uvec_coord{ uvec_coord_x, uvec_coord_y };
+
+ for(int y = 0; y < height; ++y)
+ {
+ for(int x = 0; x < width; x += 2)
+ {
+ Coordinates coord{ x, y };
+ auto *yvec_pixel = reinterpret_cast<T *>(yvec(coord));
+ auto *uvec_top_pixel = reinterpret_cast<T *>(uvec_top(uvec_coord));
+ auto *uvec_bottom_pixel = reinterpret_cast<T *>(uvec_bottom(uvec_coord));
+ auto *vvec_top_pixel = reinterpret_cast<T *>(vvec_top(uvec_coord));
+ auto *vvec_bottom_pixel = reinterpret_cast<T *>(vvec_bottom(uvec_coord));
+
+ T border_value(0);
+ int rvec_val = validation::tensor_elem_at(rvec, coord, BorderMode::CONSTANT, border_value);
+ int gvec_val = validation::tensor_elem_at(gvec, coord, BorderMode::CONSTANT, border_value);
+ int bvec_val = validation::tensor_elem_at(bvec, coord, BorderMode::CONSTANT, border_value);
+ float result = rvec_val * rgb2yuv_bt709_kr + gvec_val * rgb2yuv_bt709_kg + bvec_val * rgb2yuv_bt709_kb;
+
+ yvec_pixel[0] = result;
+ uvec_top_pixel[0] = (bvec_val - result) * rgb2yuv_bt709_cu + 128.f;
+ vvec_top_pixel[0] = (rvec_val - result) * rgb2yuv_bt709_cv + 128.f;
+
+ coord.set(0, x + 1);
+ rvec_val = validation::tensor_elem_at(rvec, coord, BorderMode::CONSTANT, border_value);
+ gvec_val = validation::tensor_elem_at(gvec, coord, BorderMode::CONSTANT, border_value);
+ bvec_val = validation::tensor_elem_at(bvec, coord, BorderMode::CONSTANT, border_value);
+ result = rvec_val * rgb2yuv_bt709_kr + gvec_val * rgb2yuv_bt709_kg + bvec_val * rgb2yuv_bt709_kb;
+
+ yvec_pixel[1] = result;
+ uvec_bottom_pixel[0] = (bvec_val - result) * rgb2yuv_bt709_cu + 128.f;
+ vvec_bottom_pixel[0] = (rvec_val - result) * rgb2yuv_bt709_cv + 128.f;
+
+ uvec_coord.set(0, ++uvec_coord_x);
+ }
+ }
+}
+
template <typename T>
inline void yuyv_to_rgb_calculation(const SimpleTensor<T> yvec, const SimpleTensor<T> vvec, const SimpleTensor<T> yyvec, const SimpleTensor<T> uvec, SimpleTensor<T> &dst)
{
@@ -59,9 +140,9 @@ inline void yuyv_to_rgb_calculation(const SimpleTensor<T> yvec, const SimpleTens
const int vvec_val = validation::tensor_elem_at(vvec, { x_coord, y }, BorderMode::CONSTANT, border_value);
const int yyvec_val = validation::tensor_elem_at(yyvec, { x_coord, y }, BorderMode::CONSTANT, border_value);
const int uvec_val = validation::tensor_elem_at(uvec, { x_coord, y }, BorderMode::CONSTANT, border_value);
- const float red = (vvec_val - 128) * red_coef_bt709;
- const float green = (uvec_val - 128) * green_coef_bt709 + (vvec_val - 128) * green_coef2_bt709;
- const float blue = (uvec_val - 128) * blue_coef_bt709;
+ const float red = (vvec_val - 128.f) * red_coef_bt709;
+ const float green = (uvec_val - 128.f) * green_coef_bt709 + (vvec_val - 128.f) * green_coef2_bt709;
+ const float blue = (uvec_val - 128.f) * blue_coef_bt709;
for(int channel_idx = 0; channel_idx < dst.num_channels(); ++channel_idx)
{
@@ -261,16 +342,17 @@ inline void colorconvert_iyuv_to_rgb(const TensorShape &shape, const std::vector
for(int x = 0; x < uvec_width; ++x)
{
const Coordinates src_coord{ x, y / 2 };
- const auto *src_pixel = reinterpret_cast<const T *>(tensor_planes[1](src_coord));
+ const auto *u_pixel = reinterpret_cast<const T *>(tensor_planes[1](src_coord));
+ const auto *v_pixel = reinterpret_cast<const T *>(tensor_planes[2](src_coord));
auto *uvec_pixel_top = reinterpret_cast<T *>(uvec(top_elem_coord));
auto *vvec_pixel_top = reinterpret_cast<T *>(vvec(top_elem_coord));
auto *uvec_pixel_bottom = reinterpret_cast<T *>(uvec(bottom_elem_coord));
auto *vvec_pixel_bottom = reinterpret_cast<T *>(vvec(bottom_elem_coord));
- uvec_pixel_top[x] = src_pixel[0];
- vvec_pixel_top[x] = src_pixel[0];
- uvec_pixel_bottom[x] = src_pixel[0];
- vvec_pixel_bottom[x] = src_pixel[0];
+ uvec_pixel_top[x] = u_pixel[0];
+ vvec_pixel_top[x] = v_pixel[0];
+ uvec_pixel_bottom[x] = u_pixel[0];
+ vvec_pixel_bottom[x] = v_pixel[0];
}
top_elem_coord.set(1, y + 2);
bottom_elem_coord.set(1, top_elem_coord.y() + 1);
@@ -335,6 +417,461 @@ inline void colorconvert_nv12_to_rgb(const TensorShape &shape, const Format form
yuyv_to_rgb_calculation(yvec, vvec, yyvec, uvec, dst);
}
+template <typename T>
+inline void colorconvert_rgb_to_nv12(const SimpleTensor<T> src, std::vector<SimpleTensor<T>> &dst)
+{
+ SimpleTensor<T> rvec(TensorShape{ dst[0].shape().x(), dst[0].shape().y() }, Format::U8);
+ SimpleTensor<T> gvec(TensorShape{ dst[0].shape().x(), dst[0].shape().y() }, Format::U8);
+ SimpleTensor<T> bvec(TensorShape{ dst[0].shape().x(), dst[0].shape().y() }, Format::U8);
+ SimpleTensor<T> yvec(TensorShape{ dst[0].shape().x(), dst[0].shape().y() }, Format::U8);
+
+ int vec_shape_x = src.shape().x() * src.shape().y();
+
+ SimpleTensor<T> uvec_top(TensorShape{ vec_shape_x, 1U }, Format::U8);
+ SimpleTensor<T> uvec_bottom(TensorShape{ vec_shape_x, 1U }, Format::U8);
+ SimpleTensor<T> vvec_top(TensorShape{ vec_shape_x, 1U }, Format::U8);
+ SimpleTensor<T> vvec_bottom(TensorShape{ vec_shape_x, 1U }, Format::U8);
+
+ store_rgb_from_src(src, rvec, gvec, bvec);
+ rgb_to_yuv_calculation(rvec, gvec, bvec, dst[0], uvec_top, uvec_bottom, vvec_top, vvec_bottom);
+
+ SimpleTensor<T> utmp(TensorShape{ src.shape().x() / 2, src.shape().y() }, Format::U8);
+ SimpleTensor<T> vtmp(TensorShape{ src.shape().x() / 2, src.shape().y() }, Format::U8);
+
+ int utmp_width = utmp.shape().x();
+ int utmp_height = utmp.shape().y();
+
+ int uvec_coord_x = 0;
+ int uvec_coord_y = 0;
+ Coordinates uvec_coord{ uvec_coord_x, uvec_coord_y };
+ for(int y = 0; y < utmp_height; y++)
+ {
+ for(int x = 0; x < utmp_width; x++)
+ {
+ Coordinates coord{ x, y };
+ auto *utmp_pixel = reinterpret_cast<T *>(utmp(coord));
+ auto *vtmp_pixel = reinterpret_cast<T *>(vtmp(coord));
+
+ T border_value(0);
+ int uvec_top_val = validation::tensor_elem_at(uvec_top, uvec_coord, BorderMode::CONSTANT, border_value);
+ int uvec_bottom_val = validation::tensor_elem_at(uvec_bottom, uvec_coord, BorderMode::CONSTANT, border_value);
+ int vvec_top_val = validation::tensor_elem_at(vvec_top, uvec_coord, BorderMode::CONSTANT, border_value);
+ int vvec_bottom_val = validation::tensor_elem_at(vvec_bottom, uvec_coord, BorderMode::CONSTANT, border_value);
+
+ utmp_pixel[0] = std::ceil(float(uvec_top_val + uvec_bottom_val) / 2);
+ vtmp_pixel[0] = std::ceil(float(vvec_top_val + vvec_bottom_val) / 2);
+
+ uvec_coord.set(0, ++uvec_coord_x);
+ }
+ }
+
+ int second_plane_x = dst[1].shape().x();
+ int second_plane_y = dst[1].shape().y();
+
+ int utmp_coord_x = 0;
+ int utmp_coord_y = 0;
+
+ for(int y = 0; y < second_plane_y; y++)
+ {
+ for(int x = 0; x < second_plane_x; x++)
+ {
+ Coordinates coord{ x, y };
+ Coordinates utmp_top_coord{ utmp_coord_x, utmp_coord_y };
+ Coordinates utmp_bottom_coord{ utmp_coord_x, utmp_coord_y + 1 };
+
+ auto *dst_pixel = reinterpret_cast<T *>(dst[1](coord));
+
+ T border_value(0);
+ int utmp_top_val = validation::tensor_elem_at(utmp, utmp_top_coord, BorderMode::CONSTANT, border_value);
+ int utmp_bottom_val = validation::tensor_elem_at(utmp, utmp_bottom_coord, BorderMode::CONSTANT, border_value);
+
+ int result = (utmp_top_val + utmp_bottom_val) / 2;
+ dst_pixel[0] = result;
+
+ int vtmp_top_val = validation::tensor_elem_at(vtmp, utmp_top_coord, BorderMode::CONSTANT, border_value);
+ int vtmp_bottom_val = validation::tensor_elem_at(vtmp, utmp_bottom_coord, BorderMode::CONSTANT, border_value);
+
+ result = (vtmp_top_val + vtmp_bottom_val) / 2;
+ dst_pixel[1] = result;
+
+ utmp_coord_x++;
+
+ if(utmp_coord_x >= utmp_width)
+ {
+ utmp_coord_x = 0;
+ utmp_coord_y += 2;
+ }
+ }
+ }
+}
+
+template <typename T>
+inline void colorconvert_rgb_to_iyuv(const SimpleTensor<T> src, std::vector<SimpleTensor<T>> &dst)
+{
+ SimpleTensor<T> rvec(TensorShape{ dst[0].shape().x(), dst[0].shape().y() }, Format::U8);
+ SimpleTensor<T> gvec(TensorShape{ dst[0].shape().x(), dst[0].shape().y() }, Format::U8);
+ SimpleTensor<T> bvec(TensorShape{ dst[0].shape().x(), dst[0].shape().y() }, Format::U8);
+ SimpleTensor<T> yvec(TensorShape{ dst[0].shape().x(), dst[0].shape().y() }, Format::U8);
+
+ int vec_shape_x = src.shape().x() * src.shape().y();
+
+ SimpleTensor<T> uvec_top(TensorShape{ vec_shape_x, 1U }, Format::U8);
+ SimpleTensor<T> uvec_bottom(TensorShape{ vec_shape_x, 1U }, Format::U8);
+ SimpleTensor<T> vvec_top(TensorShape{ vec_shape_x, 1U }, Format::U8);
+ SimpleTensor<T> vvec_bottom(TensorShape{ vec_shape_x, 1U }, Format::U8);
+
+ store_rgb_from_src(src, rvec, gvec, bvec);
+ rgb_to_yuv_calculation(rvec, gvec, bvec, dst[0], uvec_top, uvec_bottom, vvec_top, vvec_bottom);
+
+ SimpleTensor<T> utmp(TensorShape{ src.shape().x() / 2, src.shape().y() }, Format::U8);
+ SimpleTensor<T> vtmp(TensorShape{ src.shape().x() / 2, src.shape().y() }, Format::U8);
+ int utmp_width = utmp.shape().x();
+ int utmp_height = utmp.shape().y();
+
+ int uvec_coord_x = 0;
+ int uvec_coord_y = 0;
+ Coordinates uvec_coord{ uvec_coord_x, uvec_coord_y };
+ for(int y = 0; y < utmp_height; y++)
+ {
+ for(int x = 0; x < utmp_width; x++)
+ {
+ Coordinates coord{ x, y };
+ auto *utmp_pixel = reinterpret_cast<T *>(utmp(coord));
+ auto *vtmp_pixel = reinterpret_cast<T *>(vtmp(coord));
+
+ T border_value(0);
+ int uvec_top_val = validation::tensor_elem_at(uvec_top, uvec_coord, BorderMode::CONSTANT, border_value);
+ int uvec_bottom_val = validation::tensor_elem_at(uvec_bottom, uvec_coord, BorderMode::CONSTANT, border_value);
+ int vvec_top_val = validation::tensor_elem_at(vvec_top, uvec_coord, BorderMode::CONSTANT, border_value);
+ int vvec_bottom_val = validation::tensor_elem_at(vvec_bottom, uvec_coord, BorderMode::CONSTANT, border_value);
+
+ utmp_pixel[0] = std::ceil(float(uvec_top_val + uvec_bottom_val) / 2);
+ vtmp_pixel[0] = std::ceil(float(vvec_top_val + vvec_bottom_val) / 2);
+
+ uvec_coord.set(0, ++uvec_coord_x);
+ }
+ }
+
+ int second_plane_x = dst[1].shape().x();
+ int second_plane_y = dst[1].shape().y();
+
+ int utmp_coord_x = 0;
+ int utmp_coord_y = 0;
+
+ for(int y = 0; y < second_plane_y; y++)
+ {
+ for(int x = 0; x < second_plane_x; x++)
+ {
+ Coordinates coord{ x, y };
+ Coordinates utmp_top_coord{ utmp_coord_x, utmp_coord_y };
+ Coordinates utmp_bottom_coord{ utmp_coord_x, utmp_coord_y + 1 };
+
+ auto *u_pixel = reinterpret_cast<T *>(dst[1](coord));
+ auto *v_pixel = reinterpret_cast<T *>(dst[2](coord));
+
+ T border_value(0);
+ int utmp_top_val = validation::tensor_elem_at(utmp, utmp_top_coord, BorderMode::CONSTANT, border_value);
+ int utmp_bottom_val = validation::tensor_elem_at(utmp, utmp_bottom_coord, BorderMode::CONSTANT, border_value);
+
+ int result = (utmp_top_val + utmp_bottom_val) / 2;
+ u_pixel[0] = result;
+
+ int vtmp_top_val = validation::tensor_elem_at(vtmp, utmp_top_coord, BorderMode::CONSTANT, border_value);
+ int vtmp_bottom_val = validation::tensor_elem_at(vtmp, utmp_bottom_coord, BorderMode::CONSTANT, border_value);
+
+ result = (vtmp_top_val + vtmp_bottom_val) / 2;
+ v_pixel[0] = result;
+
+ utmp_coord_x++;
+
+ if(utmp_coord_x >= utmp_width)
+ {
+ utmp_coord_x = 0;
+ utmp_coord_y += 2;
+ }
+ }
+ }
+}
+
+template <typename T>
+inline void colorconvert_rgb_to_yuv4(const SimpleTensor<T> src, std::vector<SimpleTensor<T>> &dst)
+{
+ SimpleTensor<T> rvec(TensorShape{ dst[0].shape().x(), dst[0].shape().y() }, Format::U8);
+ SimpleTensor<T> gvec(TensorShape{ dst[0].shape().x(), dst[0].shape().y() }, Format::U8);
+ SimpleTensor<T> bvec(TensorShape{ dst[0].shape().x(), dst[0].shape().y() }, Format::U8);
+ SimpleTensor<T> yvec(TensorShape{ dst[0].shape().x(), dst[0].shape().y() }, Format::U8);
+
+ int vec_shape_x = src.shape().x() * src.shape().y();
+
+ SimpleTensor<T> uvec_top(TensorShape{ vec_shape_x, 1U }, Format::U8);
+ SimpleTensor<T> uvec_bottom(TensorShape{ vec_shape_x, 1U }, Format::U8);
+ SimpleTensor<T> vvec_top(TensorShape{ vec_shape_x, 1U }, Format::U8);
+ SimpleTensor<T> vvec_bottom(TensorShape{ vec_shape_x, 1U }, Format::U8);
+
+ int width = src.shape().x();
+ int height = src.shape().y();
+
+ store_rgb_from_src(src, rvec, gvec, bvec);
+
+ rgb_to_yuv_calculation(rvec, gvec, bvec, dst[0], uvec_top, uvec_bottom, vvec_top, vvec_bottom);
+
+ int uvec_coord_x = 0;
+ int uvec_coord_y = 0;
+ Coordinates uvec_coord{ uvec_coord_x, uvec_coord_y };
+ for(int y = 0; y < height; y++)
+ {
+ for(int x = 0; x < width; x += 2)
+ {
+ Coordinates coord{ x, y };
+ auto *plane_1_pixel = reinterpret_cast<T *>(dst[1](coord));
+ auto *plane_2_pixel = reinterpret_cast<T *>(dst[2](coord));
+
+ T border_value(0);
+ int uvec_top_val = validation::tensor_elem_at(uvec_top, uvec_coord, BorderMode::CONSTANT, border_value);
+ int uvec_bottom_val = validation::tensor_elem_at(uvec_bottom, uvec_coord, BorderMode::CONSTANT, border_value);
+
+ plane_1_pixel[0] = uvec_top_val;
+ plane_1_pixel[1] = uvec_bottom_val;
+
+ int vvec_top_val = validation::tensor_elem_at(vvec_top, uvec_coord, BorderMode::CONSTANT, border_value);
+ int vvec_bottom_val = validation::tensor_elem_at(vvec_bottom, uvec_coord, BorderMode::CONSTANT, border_value);
+
+ plane_2_pixel[0] = vvec_top_val;
+ plane_2_pixel[1] = vvec_bottom_val;
+
+ uvec_coord.set(0, ++uvec_coord_x);
+ }
+ }
+}
+
+template <typename T>
+inline void colorconvert_yuyv_to_nv12(const SimpleTensor<T> src, const Format format, std::vector<SimpleTensor<T>> &dst)
+{
+ SimpleTensor<T> uvvec_top(TensorShape{ dst[0].shape().x(), dst[0].shape().y() / 2 }, Format::U8);
+ SimpleTensor<T> uvvec_bottom(TensorShape{ dst[0].shape().x(), dst[0].shape().y() / 2 }, Format::U8);
+
+ const int offset = (Format::YUYV422 == format) ? 0 : 1;
+
+ int width = dst[0].shape().x();
+ int height = dst[0].shape().y();
+
+ for(int y = 0; y < height; ++y)
+ {
+ for(int x = 0; x < width; x++)
+ {
+ const Coordinates dst_coord{ x, y };
+ const Coordinates uv_coord{ x, y / 2 };
+
+ const auto *src_pixel = reinterpret_cast<const T *>(src(dst_coord));
+ auto *y_pixel = reinterpret_cast<T *>(dst[0](dst_coord));
+ auto *uvvec_top_pixel = reinterpret_cast<T *>(uvvec_top(uv_coord));
+ auto *uvvec_bottom_pixel = reinterpret_cast<T *>(uvvec_bottom(uv_coord));
+
+ y_pixel[0] = src_pixel[0 + offset];
+
+ if(y % 2 == 0)
+ {
+ uvvec_top_pixel[0] = src_pixel[1 - offset];
+ }
+ else
+ {
+ uvvec_bottom_pixel[0] = src_pixel[1 - offset];
+ }
+ }
+ }
+
+ width = dst[1].shape().x();
+ height = dst[1].shape().y();
+
+ int uv_coord_x = 0;
+ int uv_coord_y = 0;
+
+ for(int y = 0; y < height; ++y)
+ {
+ for(int x = 0; x < width; x++)
+ {
+ const Coordinates dst_coord{ x, y };
+ const Coordinates uv_coord{ uv_coord_x, uv_coord_y };
+
+ auto *uv_pixel = reinterpret_cast<T *>(dst[1](dst_coord));
+ const auto *uvvec_top_pixel = reinterpret_cast<T *>(uvvec_top(uv_coord));
+ const auto *uvvec_bottom_pixel = reinterpret_cast<T *>(uvvec_bottom(uv_coord));
+
+ uv_pixel[0] = (uvvec_top_pixel[0] + uvvec_bottom_pixel[0]) / 2;
+ uv_pixel[1] = (uvvec_top_pixel[1] + uvvec_bottom_pixel[1]) / 2;
+ uv_coord_x += 2;
+ }
+ uv_coord_x = 0;
+ uv_coord_y++;
+ }
+}
+
+template <typename T>
+inline void colorconvert_yuyv_to_iyuv(const SimpleTensor<T> src, const Format format, std::vector<SimpleTensor<T>> &dst)
+{
+ SimpleTensor<T> uvvec_top(TensorShape{ dst[0].shape().x(), dst[0].shape().y() / 2 }, Format::U8);
+ SimpleTensor<T> uvvec_bottom(TensorShape{ dst[0].shape().x(), dst[0].shape().y() / 2 }, Format::U8);
+
+ const int offset = (Format::YUYV422 == format) ? 0 : 1;
+
+ int width = dst[0].shape().x();
+ int height = dst[0].shape().y();
+
+ for(int y = 0; y < height; ++y)
+ {
+ for(int x = 0; x < width; x++)
+ {
+ const Coordinates dst_coord{ x, y };
+ const Coordinates uv_coord{ x, y / 2 };
+
+ const auto *src_pixel = reinterpret_cast<const T *>(src(dst_coord));
+ auto *y_pixel = reinterpret_cast<T *>(dst[0](dst_coord));
+ auto *uvvec_top_pixel = reinterpret_cast<T *>(uvvec_top(uv_coord));
+ auto *uvvec_bottom_pixel = reinterpret_cast<T *>(uvvec_bottom(uv_coord));
+
+ y_pixel[0] = src_pixel[0 + offset];
+
+ if(y % 2 == 0)
+ {
+ uvvec_top_pixel[0] = src_pixel[1 - offset];
+ }
+ else
+ {
+ uvvec_bottom_pixel[0] = src_pixel[1 - offset];
+ }
+ }
+ }
+
+ width = dst[1].shape().x();
+ height = dst[1].shape().y();
+
+ int uv_coord_x = 0;
+ int uv_coord_y = 0;
+
+ for(int y = 0; y < height; ++y)
+ {
+ for(int x = 0; x < width; x++)
+ {
+ const Coordinates dst_coord{ x, y };
+ const Coordinates uv_coord{ uv_coord_x, uv_coord_y };
+
+ auto *u_pixel = reinterpret_cast<T *>(dst[1](dst_coord));
+ auto *v_pixel = reinterpret_cast<T *>(dst[2](dst_coord));
+ const auto *uvvec_top_pixel = reinterpret_cast<T *>(uvvec_top(uv_coord));
+ const auto *uvvec_bottom_pixel = reinterpret_cast<T *>(uvvec_bottom(uv_coord));
+
+ u_pixel[0] = (uvvec_top_pixel[0] + uvvec_bottom_pixel[0]) / 2;
+ v_pixel[0] = (uvvec_top_pixel[1] + uvvec_bottom_pixel[1]) / 2;
+ uv_coord_x += 2;
+ }
+ uv_coord_x = 0;
+ uv_coord_y++;
+ }
+}
+
+template <typename T>
+inline void nv_to_iyuv(const SimpleTensor<T> src, const Format src_format, SimpleTensor<T> &nv1, SimpleTensor<T> &nv2)
+{
+ int width = src.shape().x();
+ int height = src.shape().y();
+
+ const int offset = (Format::NV12 == src_format) ? 1 : 0;
+
+ for(int y = 0; y < height; ++y)
+ {
+ for(int x = 0; x < width; x++)
+ {
+ const Coordinates src_coord{ x, y };
+ const auto *src_pixel = reinterpret_cast<const T *>(src(src_coord));
+ auto *u_pixel = reinterpret_cast<T *>(nv1(src_coord));
+ auto *v_pixel = reinterpret_cast<T *>(nv2(src_coord));
+
+ u_pixel[0] = src_pixel[1 - offset];
+ v_pixel[0] = src_pixel[0 + offset];
+ }
+ }
+}
+
+template <typename T>
+inline void nv_to_yuv4(const SimpleTensor<T> src, const Format src_format, SimpleTensor<T> &nv1, SimpleTensor<T> &nv2)
+{
+ int width = src.shape().x();
+ int height = src.shape().y();
+
+ const int offset = (Format::NV12 == src_format) ? 1 : 0;
+
+ for(int y = 0; y < height; ++y)
+ {
+ for(int x = 0; x < width; x++)
+ {
+ const Coordinates src_coord{ x, y };
+ Coordinates dst_coord{ x * 2, y * 2 };
+ const auto *src_pixel = reinterpret_cast<const T *>(src(src_coord));
+ auto *u_pixel = reinterpret_cast<T *>(nv1(dst_coord));
+ auto *v_pixel = reinterpret_cast<T *>(nv2(dst_coord));
+
+ u_pixel[0] = src_pixel[1 - offset];
+ u_pixel[1] = src_pixel[1 - offset];
+
+ v_pixel[0] = src_pixel[0 + offset];
+ v_pixel[1] = src_pixel[0 + offset];
+
+ dst_coord.set(1, y * 2 + 1);
+ u_pixel = reinterpret_cast<T *>(nv1(dst_coord));
+ v_pixel = reinterpret_cast<T *>(nv2(dst_coord));
+ u_pixel[0] = src_pixel[1 - offset];
+ u_pixel[1] = src_pixel[1 - offset];
+
+ v_pixel[0] = src_pixel[0 + offset];
+ v_pixel[1] = src_pixel[0 + offset];
+ }
+ }
+}
+
+template <typename T>
+inline void colorconvert_nv_to_iyuv(const std::vector<SimpleTensor<T>> src, const Format src_format, std::vector<SimpleTensor<T>> &dst)
+{
+ int width = dst[0].shape().x();
+ int height = dst[0].shape().y();
+
+ for(int y = 0; y < height; ++y)
+ {
+ for(int x = 0; x < width; ++x)
+ {
+ const Coordinates dst_coord{ x, y };
+
+ const auto *src_pixel = reinterpret_cast<const T *>(src[0](dst_coord));
+ auto *y_pixel = reinterpret_cast<T *>(dst[0](dst_coord));
+
+ y_pixel[0] = src_pixel[0];
+ }
+ }
+
+ nv_to_iyuv(src[1], src_format, dst[1], dst[2]);
+}
+
+template <typename T>
+inline void colorconvert_nv_to_yuv4(const std::vector<SimpleTensor<T>> src, const Format src_format, std::vector<SimpleTensor<T>> &dst)
+{
+ int width = dst[0].shape().x();
+ int height = dst[0].shape().y();
+
+ for(int y = 0; y < height; ++y)
+ {
+ for(int x = 0; x < width; ++x)
+ {
+ const Coordinates dst_coord{ x, y };
+
+ const auto *src_pixel = reinterpret_cast<const T *>(src[0](dst_coord));
+ auto *y_pixel = reinterpret_cast<T *>(dst[0](dst_coord));
+
+ y_pixel[0] = src_pixel[0];
+ }
+ }
+
+ nv_to_yuv4(src[1], src_format, dst[1], dst[2]);
+}
+
} // namespace detail
} // color_convert_helper
} // namespace test