diff --git a/modules/gapi/include/opencv2/gapi/gcomputation.hpp b/modules/gapi/include/opencv2/gapi/gcomputation.hpp index 439b349d89..9a6febc118 100644 --- a/modules/gapi/include/opencv2/gapi/gcomputation.hpp +++ b/modules/gapi/include/opencv2/gapi/gcomputation.hpp @@ -315,7 +315,7 @@ public: * inputs/outputs which were used to define this GComputation. */ void apply(const std::vector& ins, // Compatibility overload - const std::vector& outs, + std::vector& outs, GCompileArgs &&args = {}); #endif // !defined(GAPI_STANDALONE) // Various versions of compile(): ////////////////////////////////////////// diff --git a/modules/gapi/src/api/gcomputation.cpp b/modules/gapi/src/api/gcomputation.cpp index ab761edf9e..1b19a3e2f2 100644 --- a/modules/gapi/src/api/gcomputation.cpp +++ b/modules/gapi/src/api/gcomputation.cpp @@ -159,16 +159,14 @@ void cv::GComputation::apply(cv::Mat in1, cv::Mat in2, cv::Scalar &out, GCompile } void cv::GComputation::apply(const std::vector &ins, - const std::vector &outs, + std::vector &outs, GCompileArgs &&args) { GRunArgs call_ins; GRunArgsP call_outs; - // Make a temporary copy of vector outs - cv::Mats are copies anyway - auto tmp = outs; - for (const cv::Mat &m : ins) { call_ins.emplace_back(m); } - for ( cv::Mat &m : tmp) { call_outs.emplace_back(&m); } + for (const cv::Mat &m : ins) { call_ins.emplace_back(m); } + for ( cv::Mat &m : outs) { call_outs.emplace_back(&m); } apply(std::move(call_ins), std::move(call_outs), std::move(args)); } diff --git a/modules/gapi/test/gapi_gcomputation_tests.cpp b/modules/gapi/test/gapi_gcomputation_tests.cpp index 070cea6927..c00b30660c 100644 --- a/modules/gapi/test/gapi_gcomputation_tests.cpp +++ b/modules/gapi/test/gapi_gcomputation_tests.cpp @@ -7,6 +7,7 @@ #include "test_precomp.hpp" #include "opencv2/gapi/cpu/gcpukernel.hpp" +#include namespace opencv_test { @@ -51,6 +52,41 @@ namespace opencv_test { } }; + + struct GComputationVectorMatsAsOutput: public ::testing::Test + { + cv::Mat in_mat; + cv::GComputation m_c; + std::vector ref_mats; + + GComputationVectorMatsAsOutput() : in_mat(300, 300, CV_8UC3), + m_c([&](){ + cv::GMat in; + cv::GMat out[3]; + std::tie(out[0], out[1], out[2]) = cv::gapi::split3(in); + return cv::GComputation({in}, {out[0], out[1], out[2]}); + }) + { + cv::randu(in_mat, cv::Scalar::all(0), cv::Scalar::all(255)); + cv::split(in_mat, ref_mats); + } + + void run(std::vector& out_mats) + { + m_c.apply({in_mat}, out_mats); + } + + void check(const std::vector& out_mats) + { + for (const auto& it : ade::util::zip(ref_mats, out_mats)) + { + const auto& ref_mat = std::get<0>(it); + const auto& out_mat = std::get<1>(it); + + EXPECT_EQ(0, cv::countNonZero(ref_mat != out_mat)); + } + } + }; } TEST_F(GComputationApplyTest, ThrowDontPassCustomKernel) @@ -65,4 +101,37 @@ namespace opencv_test ASSERT_NO_THROW(m_c.apply(in_mat, out_mat, cv::compile_args(pkg))); } + TEST_F(GComputationVectorMatsAsOutput, OutputAllocated) + { + std::vector out_mats(3); + for (auto& out_mat : out_mats) + { + out_mat.create(in_mat.size(), CV_8UC1); + } + + run(out_mats); + check(out_mats); + } + + TEST_F(GComputationVectorMatsAsOutput, OutputNotAllocated) + { + std::vector out_mats(3); + + run(out_mats); + check(out_mats); + } + + TEST_F(GComputationVectorMatsAsOutput, OutputAllocatedWithInvalidMeta) + { + std::vector out_mats(3); + + for (auto& out_mat : out_mats) + { + out_mat.create(in_mat.size() / 2, CV_8UC1); + } + + run(out_mats); + check(out_mats); + } + } // namespace opencv_test