Merge pull request #14917 from rgarnov:gapi_planar_kernels

G-API planar kernels (#14917)

* Added resizeP with tests

* NV12 planar filters

* fix warnings in ResizeP test

* fix out mat ocv warning

* sz_on - > sz rename

* cpu tests new signature

* try to fix resizeP test

* trailing spaces remove

* doxygen doc fixed

* doxygen minor fix

* more doxygen fixes

* Doxygen corrected and extended after review.
This commit is contained in:
Ruslan Garnov 2019-07-04 18:19:09 +03:00 committed by Alexander Alekhin
parent 097d81363b
commit ad49138fae
12 changed files with 305 additions and 1 deletions

View File

@ -398,6 +398,16 @@ namespace core {
}
};
G_TYPED_KERNEL(GResizeP, <GMatP(GMatP,Size,int)>, "org.opencv.core.transform.resizeP") {
static GMatDesc outMeta(GMatDesc in, Size sz, int interp) {
GAPI_Assert(in.depth == CV_8U);
GAPI_Assert(in.chan == 3);
GAPI_Assert(in.planar);
GAPI_Assert(interp == cv::INTER_LINEAR);
return in.withSize(sz);
}
};
G_TYPED_KERNEL(GMerge3, <GMat(GMat,GMat,GMat)>, "org.opencv.core.transform.merge3") {
static GMatDesc outMeta(GMatDesc in, GMatDesc, GMatDesc) {
// Preserve depth and add channel component
@ -1342,10 +1352,28 @@ enlarge an image, it will generally look best with cv::INTER_CUBIC (slow) or cv:
\f[\texttt{(double)dsize.height/src.rows}\f]
@param interpolation interpolation method, see cv::InterpolationFlags
@sa warpAffine, warpPerspective, remap
@sa warpAffine, warpPerspective, remap, resizeP
*/
GAPI_EXPORTS GMat resize(const GMat& src, const Size& dsize, double fx = 0, double fy = 0, int interpolation = INTER_LINEAR);
/** @brief Resizes a planar image.
The function resizes the image src down to or up to the specified size.
Planar image memory layout is three planes laying in the memory contiguously,
so the image height should be plane_height*plane_number, image type is @ref CV_8UC1.
Output image size will have the size dsize, the depth of output is the same as of src.
@note Function textual ID is "org.opencv.core.transform.resizeP"
@param src input image, must be of @ref CV_8UC1 type;
@param dsize output image size;
@param interpolation interpolation method, only cv::INTER_LINEAR is supported at the moment
@sa warpAffine, warpPerspective, remap, resize
*/
GAPI_EXPORTS GMatP resizeP(const GMatP& src, const Size& dsize, int interpolation = cv::INTER_LINEAR);
/** @brief Creates one 3-channel (4-channel) matrix out of 3(4) single-channel ones.
The function merges several matrices to make a single multi-channel matrix. That is, each

View File

@ -207,6 +207,35 @@ namespace imgproc {
return in.withType(in.depth, 2);
}
};
G_TYPED_KERNEL(GNV12toRGBp, <GMatP(GMat,GMat)>, "org.opencv.colorconvert.imgproc.nv12torgbp") {
static GMatDesc outMeta(GMatDesc inY, GMatDesc inUV) {
GAPI_Assert(inY.depth == CV_8U);
GAPI_Assert(inUV.depth == CV_8U);
GAPI_Assert(inY.chan == 1);
GAPI_Assert(inY.planar == false);
GAPI_Assert(inUV.chan == 2);
GAPI_Assert(inUV.planar == false);
GAPI_Assert(inY.size.width == 2 * inUV.size.width);
GAPI_Assert(inY.size.height == 2 * inUV.size.height);
return inY.withType(CV_8U, 3).asPlanar();
}
};
G_TYPED_KERNEL(GNV12toBGRp, <GMatP(GMat,GMat)>, "org.opencv.colorconvert.imgproc.nv12tobgrp") {
static GMatDesc outMeta(GMatDesc inY, GMatDesc inUV) {
GAPI_Assert(inY.depth == CV_8U);
GAPI_Assert(inUV.depth == CV_8U);
GAPI_Assert(inY.chan == 1);
GAPI_Assert(inY.planar == false);
GAPI_Assert(inUV.chan == 2);
GAPI_Assert(inUV.planar == false);
GAPI_Assert(inY.size.width == 2 * inUV.size.width);
GAPI_Assert(inY.size.height == 2 * inUV.size.height);
return inY.withType(CV_8U, 3).asPlanar();
}
};
}
@ -847,6 +876,42 @@ Output image must be 8-bit unsigned 2-channel image @ref CV_8UC2.
*/
GAPI_EXPORTS GMat RGB2YUV422(const GMat& src);
/** @brief Converts an image from NV12 (YUV420p) color space to RGB.
The function converts an input image from NV12 color space to RGB.
The conventional ranges for Y, U, and V channel values are 0 to 255.
Output image must be 8-bit unsigned planar 3-channel image @ref CV_8UC1.
Planar image memory layout is three planes laying in the memory contiguously,
so the image height should be plane_height*plane_number,
image type is @ref CV_8UC1.
@note Function textual ID is "org.opencv.imgproc.colorconvert.nv12torgbp"
@param src_y input image: 8-bit unsigned 1-channel image @ref CV_8UC1.
@param src_uv input image: 8-bit unsigned 2-channel image @ref CV_8UC2.
@sa YUV2RGB, NV12toBGRp, NV12toRGB
*/
GAPI_EXPORTS GMatP NV12toRGBp(const GMat &src_y, const GMat &src_uv);
/** @brief Converts an image from NV12 (YUV420p) color space to BGR.
The function converts an input image from NV12 color space to BGR.
The conventional ranges for Y, U, and V channel values are 0 to 255.
Output image must be 8-bit unsigned planar 3-channel image @ref CV_8UC1.
Planar image memory layout is three planes laying in the memory contiguously,
so the image height should be plane_height*plane_number,
image type is @ref CV_8UC1.
@note Function textual ID is "org.opencv.imgproc.colorconvert.nv12torgbp"
@param src_y input image: 8-bit unsigned 1-channel image @ref CV_8UC1.
@param src_uv input image: 8-bit unsigned 2-channel image @ref CV_8UC2.
@sa YUV2RGB, NV12toRGBp, NV12toBGR
*/
GAPI_EXPORTS GMatP NV12toBGRp(const GMat &src_y, const GMat &src_uv);
//! @} gapi_colorconvert
} //namespace gapi
} //namespace cv

View File

@ -301,6 +301,11 @@ GMat resize(const GMat& src, const Size& dsize, double fx, double fy, int interp
return core::GResize::on(src, dsize, fx, fy, interpolation);
}
GMatP resizeP(const GMatP& src, const Size& dsize, int interpolation)
{
return core::GResizeP::on(src, dsize, interpolation);
}
GMat remap(const GMat& src, const Mat& map1, const Mat& map2,
int interpolation, int borderMode,
const Scalar& borderValue)

View File

@ -169,5 +169,15 @@ GMat RGB2YUV422(const GMat& src) {
return imgproc::GRGB2YUV422::on(src);
}
GMatP NV12toRGBp(const GMat &y, const GMat &uv)
{
return imgproc::GNV12toRGBp::on(y, uv);
}
GMatP NV12toBGRp(const GMat &y, const GMat &uv)
{
return imgproc::GNV12toBGRp::on(y, uv);
}
} //namespace gapi
} //namespace cv

View File

@ -461,6 +461,22 @@ GAPI_OCV_KERNEL(GCPUResize, cv::gapi::core::GResize)
}
};
GAPI_OCV_KERNEL(GCPUResizeP, cv::gapi::core::GResizeP)
{
static void run(const cv::Mat& in, cv::Size out_sz, int interp, cv::Mat& out)
{
int inH = in.rows / 3;
int inW = in.cols;
int outH = out.rows / 3;
int outW = out.cols;
for (int i = 0; i < 3; i++) {
auto in_plane = in(cv::Rect(0, i*inH, inW, inH));
auto out_plane = out(cv::Rect(0, i*outH, outW, outH));
cv::resize(in_plane, out_plane, out_sz, 0, 0, interp);
}
}
};
GAPI_OCV_KERNEL(GCPURemap, cv::gapi::core::GRemap)
{
static void run(const cv::Mat& in, const cv::Mat& x, const cv::Mat& y, int a, int b, cv::Scalar s, cv::Mat& out)
@ -589,6 +605,7 @@ cv::gapi::GKernelPackage cv::gapi::core::cpu::kernels()
, GCPUSplit3
, GCPUSplit4
, GCPUResize
, GCPUResizeP
, GCPUMerge3
, GCPUMerge4
, GCPURemap

View File

@ -309,6 +309,43 @@ GAPI_OCV_KERNEL(GCPURGB2YUV422, cv::gapi::imgproc::GRGB2YUV422)
}
};
static void toPlanar(const cv::Mat& in, cv::Mat& out)
{
GAPI_Assert(out.depth() == in.depth());
GAPI_Assert(out.channels() == 1);
GAPI_Assert(in.channels() == 3);
GAPI_Assert(out.cols == in.cols);
GAPI_Assert(out.rows == 3*in.rows);
std::vector<cv::Mat> outs(3);
for (int i = 0; i < 3; i++) {
outs[i] = out(cv::Rect(0, i*in.rows, in.cols, in.rows));
}
cv::split(in, outs);
}
GAPI_OCV_KERNEL(GCPUNV12toRGBp, cv::gapi::imgproc::GNV12toRGBp)
{
static void run(const cv::Mat& inY, const cv::Mat& inUV, cv::Mat& out)
{
cv::Mat rgb;
cv::cvtColorTwoPlane(inY, inUV, rgb, cv::COLOR_YUV2RGB_NV12);
toPlanar(rgb, out);
}
};
GAPI_OCV_KERNEL(GCPUNV12toBGRp, cv::gapi::imgproc::GNV12toBGRp)
{
static void run(const cv::Mat& inY, const cv::Mat& inUV, cv::Mat& out)
{
cv::Mat rgb;
cv::cvtColorTwoPlane(inY, inUV, rgb, cv::COLOR_YUV2BGR_NV12);
toPlanar(rgb, out);
}
};
cv::gapi::GKernelPackage cv::gapi::imgproc::cpu::kernels()
{
static auto pkg = cv::gapi::kernels
@ -339,6 +376,8 @@ cv::gapi::GKernelPackage cv::gapi::imgproc::cpu::kernels()
, GCPUBayerGR2RGB
, GCPURGB2HSV
, GCPURGB2YUV422
, GCPUNV12toRGBp
, GCPUNV12toBGRp
>();
return pkg;
}

View File

@ -145,6 +145,8 @@ GAPI_TEST_FIXTURE(Split3Test, initMatrixRandU, <>, 0)
GAPI_TEST_FIXTURE(Split4Test, initMatrixRandU, <>, 0)
GAPI_TEST_FIXTURE(ResizeTest, initNothing, FIXTURE_API(compare_f,int,cv::Size), 3,
cmpF, interp, sz_out)
GAPI_TEST_FIXTURE(ResizePTest, initNothing, FIXTURE_API(compare_f,int,cv::Size), 3,
cmpF, interp, sz_out)
GAPI_TEST_FIXTURE(ResizeTestFxFy, initNothing, FIXTURE_API(compare_f,int,double,double), 4,
cmpF, interp, fx, fy)
GAPI_TEST_FIXTURE(Merge3Test, initMatsRandU, <>, 0)

View File

@ -848,6 +848,37 @@ TEST_P(ResizeTestFxFy, AccuracyTest)
ResizeAccuracyTest(cmpF, type, interp, sz, cv::Size{0, 0}, fx, fy, getCompileArgs());
}
TEST_P(ResizePTest, AccuracyTest)
{
constexpr int planeNum = 3;
cv::Size sz_in_p {sz.width, sz.height*planeNum};
cv::Size sz_out_p{sz_out.width, sz_out.height*planeNum};
cv::Mat in_mat(sz_in_p, CV_8UC1);
cv::randn(in_mat, cv::Scalar::all(127.0f), cv::Scalar::all(40.f));
cv::Mat out_mat (sz_out_p, CV_8UC1);
cv::Mat out_mat_ocv_p(sz_out_p, CV_8UC1);
cv::GMatP in;
auto out = cv::gapi::resizeP(in, sz_out, interp);
cv::GComputation c(cv::GIn(in), cv::GOut(out));
c.compile(cv::descr_of(in_mat).asPlanar(planeNum), getCompileArgs())
(cv::gin(in_mat), cv::gout(out_mat));
for (int i = 0; i < planeNum; i++) {
const cv::Mat in_mat_roi = in_mat(cv::Rect(0, i*sz.height, sz.width, sz.height));
cv::Mat out_mat_roi = out_mat_ocv_p(cv::Rect(0, i*sz_out.height, sz_out.width, sz_out.height));
cv::resize(in_mat_roi, out_mat_roi, sz_out, 0, 0, interp);
}
// Comparison //////////////////////////////////////////////////////////////
{
EXPECT_TRUE(cmpF(out_mat, out_mat_ocv_p));
}
}
TEST_P(Merge3Test, AccuracyTest)
{
cv::Mat in_mat3(sz, type);

View File

@ -42,6 +42,8 @@ GAPI_TEST_FIXTURE(BGR2GrayTest, initMatrixRandN, FIXTURE_API(compare_f), 1, cmpF
GAPI_TEST_FIXTURE(RGB2YUVTest, initMatrixRandN, FIXTURE_API(compare_f), 1, cmpF)
GAPI_TEST_FIXTURE(YUV2RGBTest, initMatrixRandN, FIXTURE_API(compare_f), 1, cmpF)
GAPI_TEST_FIXTURE(NV12toRGBTest, initMatrixRandN, FIXTURE_API(compare_f), 1, cmpF)
GAPI_TEST_FIXTURE(NV12toBGRpTest, initMatrixRandN, FIXTURE_API(compare_f), 1, cmpF)
GAPI_TEST_FIXTURE(NV12toRGBpTest, initMatrixRandN, FIXTURE_API(compare_f), 1, cmpF)
GAPI_TEST_FIXTURE(NV12toBGRTest, initMatrixRandN, FIXTURE_API(compare_f), 1, cmpF)
GAPI_TEST_FIXTURE(RGB2LabTest, initMatrixRandN, FIXTURE_API(compare_f), 1, cmpF)
GAPI_TEST_FIXTURE(BGR2LUVTest, initMatrixRandN, FIXTURE_API(compare_f), 1, cmpF)

View File

@ -489,6 +489,80 @@ TEST_P(NV12toBGRTest, AccuracyTest)
}
}
static void toPlanar(const cv::Mat& in, cv::Mat& out)
{
GAPI_Assert(out.depth() == in.depth());
GAPI_Assert(out.channels() == 1);
GAPI_Assert(in.channels() == 3);
GAPI_Assert(out.cols == in.cols);
GAPI_Assert(out.rows == 3*in.rows);
std::vector<cv::Mat> outs(3);
for (int i = 0; i < 3; i++) {
outs[i] = out(cv::Rect(0, i*in.rows, in.cols, in.rows));
}
cv::split(in, outs);
}
TEST_P(NV12toRGBpTest, AccuracyTest)
{
cv::Size sz_p = cv::Size(sz.width, sz.height * 3);
// G-API code //////////////////////////////////////////////////////////////
cv::GMat in_y;
cv::GMat in_uv;
auto out = cv::gapi::NV12toRGBp(in_y, in_uv);
// Additional mat for uv
cv::Mat in_mat_uv(cv::Size(sz.width / 2, sz.height / 2), CV_8UC2);
cv::randn(in_mat_uv, cv::Scalar::all(127), cv::Scalar::all(40.f));
cv::GComputation c(cv::GIn(in_y, in_uv), cv::GOut(out));
cv::Mat out_mat_gapi_planar(cv::Size(sz.width, sz.height * 3), CV_8UC1);
c.apply(cv::gin(in_mat1, in_mat_uv), cv::gout(out_mat_gapi_planar), getCompileArgs());
// OpenCV code /////////////////////////////////////////////////////////////
cv::Mat out_mat_ocv_planar(cv::Size(sz.width, sz.height * 3), CV_8UC1);
{
cv::cvtColorTwoPlane(in_mat1, in_mat_uv, out_mat_ocv, cv::COLOR_YUV2RGB_NV12);
toPlanar(out_mat_ocv, out_mat_ocv_planar);
}
// Comparison //////////////////////////////////////////////////////////////
{
EXPECT_TRUE(cmpF(out_mat_gapi_planar, out_mat_ocv_planar));
EXPECT_EQ(out_mat_gapi_planar.size(), sz_p);
}
}
TEST_P(NV12toBGRpTest, AccuracyTest)
{
cv::Size sz_p = cv::Size(sz.width, sz.height * 3);
// G-API code //////////////////////////////////////////////////////////////
cv::GMat in_y;
cv::GMat in_uv;
auto out = cv::gapi::NV12toBGRp(in_y, in_uv);
// Additional mat for uv
cv::Mat in_mat_uv(cv::Size(sz.width / 2, sz.height / 2), CV_8UC2);
cv::randn(in_mat_uv, cv::Scalar::all(127), cv::Scalar::all(40.f));
cv::GComputation c(cv::GIn(in_y, in_uv), cv::GOut(out));
cv::Mat out_mat_gapi_planar(cv::Size(sz.width, sz.height * 3), CV_8UC1);
c.apply(cv::gin(in_mat1, in_mat_uv), cv::gout(out_mat_gapi_planar), getCompileArgs());
// OpenCV code /////////////////////////////////////////////////////////////
cv::Mat out_mat_ocv_planar(cv::Size(sz.width, sz.height * 3), CV_8UC1);
{
cv::cvtColorTwoPlane(in_mat1, in_mat_uv, out_mat_ocv, cv::COLOR_YUV2BGR_NV12);
toPlanar(out_mat_ocv, out_mat_ocv_planar);
}
// Comparison //////////////////////////////////////////////////////////////
{
EXPECT_TRUE(cmpF(out_mat_gapi_planar, out_mat_ocv_planar));
EXPECT_EQ(out_mat_gapi_planar.size(), sz_p);
}
}
TEST_P(RGB2LabTest, AccuracyTest)
{
// G-API code //////////////////////////////////////////////////////////////

View File

@ -338,6 +338,19 @@ INSTANTIATE_TEST_CASE_P(ResizeTestCPU, ResizeTest,
Values(cv::Size(64,64),
cv::Size(30,30))));
INSTANTIATE_TEST_CASE_P(ResizePTestCPU, ResizePTest,
Combine(Values( CV_8UC1, CV_8UC3, CV_16UC1, CV_16SC1, CV_32FC1 ),
Values(cv::Size(1280, 720),
cv::Size(640, 480),
cv::Size(128, 128)),
Values(-1),
Values(false),
Values(CORE_CPU),
Values(AbsSimilarPoints(2, 0.05).to_compare_f()),
Values(cv::INTER_LINEAR),
Values(cv::Size(64,64),
cv::Size(30,30))));
INSTANTIATE_TEST_CASE_P(ResizeTestCPU, ResizeTestFxFy,
Combine(Values( CV_8UC1, CV_8UC3, CV_16UC1, CV_16SC1, CV_32FC1 ),
Values(cv::Size(1280, 720),

View File

@ -264,6 +264,24 @@ INSTANTIATE_TEST_CASE_P(NV12toBGRTestCPU, NV12toBGRTest,
Values(IMGPROC_CPU),
Values(AbsExact().to_compare_f())));
INSTANTIATE_TEST_CASE_P(NV12toRGBpTestCPU, NV12toRGBpTest,
Combine(Values(CV_8UC1),
Values(cv::Size(1280, 720),
cv::Size(640, 480)),
Values(CV_8UC3),
Values(true),
Values(IMGPROC_CPU),
Values(AbsExact().to_compare_f())));
INSTANTIATE_TEST_CASE_P(NV12toBGRpTestCPU, NV12toBGRpTest,
Combine(Values(CV_8UC1),
Values(cv::Size(1280, 720),
cv::Size(640, 480)),
Values(CV_8UC3),
Values(true),
Values(IMGPROC_CPU),
Values(AbsExact().to_compare_f())));
INSTANTIATE_TEST_CASE_P(RGB2LabTestCPU, RGB2LabTest,
Combine(Values(CV_8UC3),
Values(cv::Size(1280, 720),