1 // This file is part of OpenCV project.
2 // It is subject to the license terms in the LICENSE file found in the top-level directory
3 // of this distribution and at http://opencv.org/license.html.
5 // Copyright (C) 2018-2019 Intel Corporation
8 #include "test_precomp.hpp"
11 #include <ade/util/iota_range.hpp>
19 G_TYPED_KERNEL(GInvalidResize, <GMat(GMat,Size,double,double,int)>, "org.opencv.test.invalid_resize")
21 static GMatDesc outMeta(GMatDesc in, Size, double, double, int) { return in; }
24 GAPI_OCV_KERNEL(GOCVInvalidResize, GInvalidResize)
26 static void run(const cv::Mat& in, cv::Size sz, double fx, double fy, int interp, cv::Mat &out)
28 cv::resize(in, out, sz, fx, fy, interp);
32 G_TYPED_KERNEL(GReallocatingCopy, <GMat(GMat)>, "org.opencv.test.reallocating_copy")
34 static GMatDesc outMeta(GMatDesc in) { return in; }
37 GAPI_OCV_KERNEL(GOCVReallocatingCopy, GReallocatingCopy)
39 static void run(const cv::Mat& in, cv::Mat &out)
46 TEST(GAPI_Pipeline, OverloadUnary_MatMat)
49 cv::GComputation comp(in, cv::gapi::bitwise_not(in));
51 cv::Mat in_mat = cv::Mat::eye(32, 32, CV_8UC1);
52 cv::Mat ref_mat = ~in_mat;
55 comp.apply(in_mat, out_mat);
56 EXPECT_EQ(0, cv::countNonZero(out_mat != ref_mat));
59 auto cc = comp.compile(cv::descr_of(in_mat));
61 EXPECT_EQ(0, cv::countNonZero(out_mat != ref_mat));
64 TEST(GAPI_Pipeline, OverloadUnary_MatScalar)
67 cv::GComputation comp(in, cv::gapi::sum(in));
69 cv::Mat in_mat = cv::Mat::eye(32, 32, CV_8UC1);
70 cv::Scalar ref_scl = cv::sum(in_mat);
73 comp.apply(in_mat, out_scl);
74 EXPECT_EQ(out_scl, ref_scl);
76 out_scl = cv::Scalar();
77 auto cc = comp.compile(cv::descr_of(in_mat));
79 EXPECT_EQ(out_scl, ref_scl);
82 TEST(GAPI_Pipeline, OverloadBinary_Mat)
85 cv::GComputation comp(a, b, cv::gapi::add(a, b));
87 cv::Mat in_mat = cv::Mat::eye(32, 32, CV_8UC1);
88 cv::Mat ref_mat = (in_mat+in_mat);
91 comp.apply(in_mat, in_mat, out_mat);
92 EXPECT_EQ(0, cv::countNonZero(out_mat != ref_mat));
95 auto cc = comp.compile(cv::descr_of(in_mat), cv::descr_of(in_mat));
96 cc(in_mat, in_mat, out_mat);
97 EXPECT_EQ(0, cv::countNonZero(out_mat != ref_mat));
100 TEST(GAPI_Pipeline, OverloadBinary_Scalar)
103 cv::GComputation comp(a, b, cv::gapi::sum(a + b));
105 cv::Mat in_mat = cv::Mat::eye(32, 32, CV_8UC1);
106 cv::Scalar ref_scl = cv::sum(in_mat+in_mat);
109 comp.apply(in_mat, in_mat, out_scl);
110 EXPECT_EQ(out_scl, ref_scl);
112 out_scl = cv::Scalar();
113 auto cc = comp.compile(cv::descr_of(in_mat), cv::descr_of(in_mat));
114 cc(in_mat, in_mat, out_scl);
115 EXPECT_EQ(out_scl, ref_scl);
118 TEST(GAPI_Pipeline, Sharpen)
120 const cv::Size sz_in (1280, 720);
121 const cv::Size sz_out( 640, 480);
122 cv::Mat in_mat (sz_in, CV_8UC3);
123 in_mat = cv::Scalar(128, 33, 53);
125 cv::Mat out_mat(sz_out, CV_8UC3);
127 cv::Mat out_mat_ocv(sz_out, CV_8UC3);
129 float sharpen_coeffs[] = {
134 cv::Mat sharpen_kernel(3, 3, CV_32F, sharpen_coeffs);
136 // G-API code //////////////////////////////////////////////////////////////
139 auto vga = cv::gapi::resize(in, sz_out);
140 auto yuv = cv::gapi::RGB2YUV(vga);
141 auto yuv_p = cv::gapi::split3(yuv);
142 auto y_sharp = cv::gapi::filter2D(std::get<0>(yuv_p), -1, sharpen_kernel);
143 auto yuv_new = cv::gapi::merge3(y_sharp, std::get<1>(yuv_p), std::get<2>(yuv_p));
144 auto out = cv::gapi::YUV2RGB(yuv_new);
146 cv::GComputation c(cv::GIn(in), cv::GOut(y_sharp, out));
147 c.apply(cv::gin(in_mat), cv::gout(out_mat_y, out_mat));
149 // OpenCV code /////////////////////////////////////////////////////////////
152 cv::resize(in_mat, smaller, sz_out);
155 cv::cvtColor(smaller, yuv_mat, cv::COLOR_RGB2YUV);
156 std::vector<cv::Mat> yuv_planar(3);
157 cv::split(yuv_mat, yuv_planar);
158 cv::filter2D(yuv_planar[0], yuv_planar[0], -1, sharpen_kernel);
159 cv::merge(yuv_planar, yuv_mat);
160 cv::cvtColor(yuv_mat, out_mat_ocv, cv::COLOR_YUV2RGB);
163 // Comparison //////////////////////////////////////////////////////////////
165 cv::Mat diff = out_mat_ocv != out_mat;
166 std::vector<cv::Mat> diffBGR(3);
167 cv::split(diff, diffBGR);
168 EXPECT_EQ(0, cv::countNonZero(diffBGR[0]));
169 EXPECT_EQ(0, cv::countNonZero(diffBGR[1]));
170 EXPECT_EQ(0, cv::countNonZero(diffBGR[2]));
173 // Metadata check /////////////////////////////////////////////////////////
175 auto cc = c.compile(cv::descr_of(in_mat));
176 auto metas = cc.outMetas();
177 ASSERT_EQ(2u, metas.size());
179 auto out_y_meta = cv::util::get<cv::GMatDesc>(metas[0]);
180 auto out_meta = cv::util::get<cv::GMatDesc>(metas[1]);
183 EXPECT_EQ(CV_8U, out_y_meta.depth);
184 EXPECT_EQ(1, out_y_meta.chan);
185 EXPECT_EQ(640, out_y_meta.size.width);
186 EXPECT_EQ(480, out_y_meta.size.height);
189 EXPECT_EQ(CV_8U, out_meta.depth);
190 EXPECT_EQ(3, out_meta.chan);
191 EXPECT_EQ(640, out_meta.size.width);
192 EXPECT_EQ(480, out_meta.size.height);
196 TEST(GAPI_Pipeline, CustomRGB2YUV)
198 const cv::Size sz(1280, 720);
202 // std::vector<cv::Mat> out_mats_cv(3, cv::Mat(sz, CV_8U))
204 // creates a vector of 3 elements pointing to the same Mat!
205 // FIXME: Make a G-API check for that
207 std::vector<cv::Mat> in_mats(INS);
208 for (auto i : ade::util::iota(INS))
210 in_mats[i].create(sz, CV_8U);
211 cv::randu(in_mats[i], cv::Scalar::all(0), cv::Scalar::all(255));
215 std::vector<cv::Mat> out_mats_cv(OUTS);
216 std::vector<cv::Mat> out_mats_gapi(OUTS);
217 for (auto i : ade::util::iota(OUTS))
219 out_mats_cv [i].create(sz, CV_8U);
220 out_mats_gapi[i].create(sz, CV_8U);
223 // G-API code //////////////////////////////////////////////////////////////
226 cv::GMat y = 0.299f*r + 0.587f*g + 0.114f*b;
227 cv::GMat u = 0.492f*(b - y);
228 cv::GMat v = 0.877f*(r - y);
230 cv::GComputation customCvt({r, g, b}, {y, u, v});
231 customCvt.apply(in_mats, out_mats_gapi);
234 // OpenCV code /////////////////////////////////////////////////////////////
236 cv::Mat r = in_mats[0], g = in_mats[1], b = in_mats[2];
237 cv::Mat y = 0.299f*r + 0.587f*g + 0.114f*b;
238 cv::Mat u = 0.492f*(b - y);
239 cv::Mat v = 0.877f*(r - y);
246 // Comparison //////////////////////////////////////////////////////////////
248 const auto diff = [](cv::Mat m1, cv::Mat m2, int t) {
249 return cv::abs(m1-m2) > t;
252 // FIXME: Not bit-accurate even now!
254 diff_y = diff(out_mats_cv[0], out_mats_gapi[0], 2),
255 diff_u = diff(out_mats_cv[1], out_mats_gapi[1], 2),
256 diff_v = diff(out_mats_cv[2], out_mats_gapi[2], 2);
258 EXPECT_EQ(0, cv::countNonZero(diff_y));
259 EXPECT_EQ(0, cv::countNonZero(diff_u));
260 EXPECT_EQ(0, cv::countNonZero(diff_v));
264 TEST(GAPI_Pipeline, PipelineWithInvalidKernel)
267 cv::Mat in_mat(500, 500, CV_8UC1), out_mat;
268 out = GInvalidResize::on(in, cv::Size(300, 300), 0.0, 0.0, cv::INTER_LINEAR);
270 const auto pkg = cv::gapi::kernels<GOCVInvalidResize>();
271 cv::GComputation comp(cv::GIn(in), cv::GOut(out));
273 EXPECT_THROW(comp.apply(in_mat, out_mat, cv::compile_args(pkg)), std::logic_error);
276 TEST(GAPI_Pipeline, InvalidOutputComputation)
278 cv::GMat in1, out1, out2, out3;
280 std::tie(out1, out2, out2) = cv::gapi::split3(in1);
281 cv::GComputation c({in1}, {out1, out2, out3});
283 cv::Mat out_mat1, out_mat2, out_mat3, out_mat4;
284 std::vector<cv::Mat> u_outs = {out_mat1, out_mat2, out_mat3, out_mat4};
285 std::vector<cv::Mat> u_ins = {in_mat};
287 EXPECT_THROW(c.apply(u_ins, u_outs), std::logic_error);
290 TEST(GAPI_Pipeline, PipelineAllocatingKernel)
293 cv::Mat in_mat(500, 500, CV_8UC1), out_mat;
294 out = GReallocatingCopy::on(in);
296 const auto pkg = cv::gapi::kernels<GOCVReallocatingCopy>();
297 cv::GComputation comp(cv::GIn(in), cv::GOut(out));
299 EXPECT_THROW(comp.apply(in_mat, out_mat, cv::compile_args(pkg)), std::logic_error);
301 } // namespace opencv_test