mirror of
https://github.com/opencv/opencv.git
synced 2025-07-24 14:06:27 +08:00
Added reshape() functionality to CPU backend
This commit is contained in:
parent
a332509e02
commit
ecb30409f6
@ -2,7 +2,7 @@
|
||||
// It is subject to the license terms in the LICENSE file found in the top-level directory
|
||||
// of this distribution and at http://opencv.org/license.html.
|
||||
//
|
||||
// Copyright (C) 2018-2021 Intel Corporation
|
||||
// Copyright (C) 2018-2022 Intel Corporation
|
||||
|
||||
|
||||
#include "precomp.hpp"
|
||||
@ -88,7 +88,7 @@ cv::gimpl::GCPUExecutable::GCPUExecutable(const ade::Graph &g,
|
||||
{
|
||||
case NodeType::OP:
|
||||
{
|
||||
m_script.push_back({nh, GModel::collectOutputMeta(m_gm, nh)});
|
||||
m_opNodes.push_back(nh);
|
||||
|
||||
// If kernel is stateful then prepare storage for its state.
|
||||
GCPUKernel k = gcm.metadata(nh).get<CPUUnit>().k;
|
||||
@ -107,19 +107,12 @@ cv::gimpl::GCPUExecutable::GCPUExecutable(const ade::Graph &g,
|
||||
auto rc = RcDesc{desc.rc, desc.shape, desc.ctor};
|
||||
magazine::bindInArg(m_res, rc, m_gm.metadata(nh).get<ConstValue>().arg);
|
||||
}
|
||||
//preallocate internal Mats in advance
|
||||
if (desc.storage == Data::Storage::INTERNAL && desc.shape == GShape::GMAT)
|
||||
{
|
||||
const auto mat_desc = util::get<cv::GMatDesc>(desc.meta);
|
||||
auto& mat = m_res.slot<cv::Mat>()[desc.rc];
|
||||
createMat(mat_desc, mat);
|
||||
}
|
||||
break;
|
||||
}
|
||||
default: util::throw_error(std::logic_error("Unsupported NodeType type"));
|
||||
}
|
||||
}
|
||||
|
||||
makeReshape();
|
||||
// For each stateful kernel call 'setup' user callback to initialize state.
|
||||
setupKernelStates();
|
||||
}
|
||||
@ -176,8 +169,38 @@ void cv::gimpl::GCPUExecutable::setupKernelStates()
|
||||
}
|
||||
}
|
||||
|
||||
void cv::gimpl::GCPUExecutable::makeReshape() {
|
||||
// Prepare the execution script
|
||||
m_script.clear();
|
||||
for (auto &nh : m_opNodes) {
|
||||
m_script.push_back({nh, GModel::collectOutputMeta(m_gm, nh)});
|
||||
}
|
||||
|
||||
// Preallocate internal mats
|
||||
for (auto& nh : m_dataNodes) {
|
||||
const auto& desc = m_gm.metadata(nh).get<Data>();
|
||||
if (desc.storage == Data::Storage::INTERNAL && desc.shape == GShape::GMAT) {
|
||||
const auto mat_desc = util::get<cv::GMatDesc>(desc.meta);
|
||||
auto& mat = m_res.slot<cv::Mat>()[desc.rc];
|
||||
createMat(mat_desc, mat);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void cv::gimpl::GCPUExecutable::reshape(ade::Graph&, const GCompileArgs& args) {
|
||||
m_compileArgs = args;
|
||||
makeReshape();
|
||||
// Signal to reset stateful kernels` state.
|
||||
// There can be no handleNewStream() call to set this flag
|
||||
// if user didn't call GCompiled`s prepareForNewStream()
|
||||
m_newStreamStarted = true;
|
||||
}
|
||||
|
||||
void cv::gimpl::GCPUExecutable::handleNewStream()
|
||||
{
|
||||
// Signal to reset stateful kernels` state.
|
||||
// No need to call reshape() here since it'll
|
||||
// be called automatically if input meta was changed
|
||||
m_newStreamStarted = true;
|
||||
}
|
||||
|
||||
|
@ -2,7 +2,7 @@
|
||||
// It is subject to the license terms in the LICENSE file found in the top-level directory
|
||||
// of this distribution and at http://opencv.org/license.html.
|
||||
//
|
||||
// Copyright (C) 2018-2020 Intel Corporation
|
||||
// Copyright (C) 2018-2022 Intel Corporation
|
||||
|
||||
|
||||
#ifndef OPENCV_GAPI_GCPUBACKEND_HPP
|
||||
@ -33,7 +33,7 @@ class GCPUExecutable final: public GIslandExecutable
|
||||
{
|
||||
const ade::Graph &m_g;
|
||||
GModel::ConstGraph m_gm;
|
||||
const cv::GCompileArgs m_compileArgs;
|
||||
cv::GCompileArgs m_compileArgs;
|
||||
|
||||
struct OperationInfo
|
||||
{
|
||||
@ -51,6 +51,7 @@ class GCPUExecutable final: public GIslandExecutable
|
||||
|
||||
// List of all resources in graph (both internal and external)
|
||||
std::vector<ade::NodeHandle> m_dataNodes;
|
||||
std::vector<ade::NodeHandle> m_opNodes;
|
||||
|
||||
// Actual data of all resources in graph (both internal and external)
|
||||
Mag m_res;
|
||||
@ -61,19 +62,15 @@ class GCPUExecutable final: public GIslandExecutable
|
||||
GArg packArg(const GArg &arg);
|
||||
void setupKernelStates();
|
||||
|
||||
void makeReshape();
|
||||
|
||||
public:
|
||||
GCPUExecutable(const ade::Graph &graph,
|
||||
const cv::GCompileArgs &compileArgs,
|
||||
const std::vector<ade::NodeHandle> &nodes);
|
||||
|
||||
virtual inline bool canReshape() const override { return false; }
|
||||
virtual inline void reshape(ade::Graph&, const GCompileArgs&) override
|
||||
{
|
||||
// FIXME: CPU plugin is in fact reshapeable (as it was initially,
|
||||
// even before outMeta() has been introduced), so this limitation
|
||||
// should be dropped.
|
||||
util::throw_error(std::logic_error("GCPUExecutable::reshape() should never be called"));
|
||||
}
|
||||
virtual inline bool canReshape() const override { return true; }
|
||||
virtual void reshape(ade::Graph&, const GCompileArgs&) override;
|
||||
|
||||
virtual void handleNewStream() override;
|
||||
|
||||
|
@ -2,7 +2,7 @@
|
||||
// It is subject to the license terms in the LICENSE file found in the top-level directory
|
||||
// of this distribution and at http://opencv.org/license.html.
|
||||
//
|
||||
// Copyright (C) 2018-2020 Intel Corporation
|
||||
// Copyright (C) 2018-2022 Intel Corporation
|
||||
|
||||
|
||||
#include "precomp.hpp"
|
||||
@ -954,7 +954,7 @@ namespace
|
||||
GFluidModel fg(graph);
|
||||
for (const auto& node : g.nodes())
|
||||
{
|
||||
if (g.metadata(node).get<NodeType>().t == NodeType::DATA)
|
||||
if (fg.metadata(node).contains<FluidData>())
|
||||
{
|
||||
auto& fd = fg.metadata(node).get<FluidData>();
|
||||
fd.latency = 0;
|
||||
|
@ -2,7 +2,7 @@
|
||||
// It is subject to the license terms in the LICENSE file found in the top-level directory
|
||||
// of this distribution and at http://opencv.org/license.html.
|
||||
//
|
||||
// Copyright (C) 2020 Intel Corporation
|
||||
// Copyright (C) 2020-2022 Intel Corporation
|
||||
|
||||
#include "gapi_ocv_stateful_kernel_test_utils.hpp"
|
||||
#include <opencv2/gapi/cpu/core.hpp>
|
||||
@ -342,7 +342,79 @@ TEST(StatefulKernel, StateIsInitViaCompArgsInStreaming)
|
||||
// Allowing 5% difference of all pixels between G-API and reference OpenCV results
|
||||
testBackSubInStreaming(gapiBackSub, 5);
|
||||
}
|
||||
|
||||
TEST(StatefulKernel, StateIsChangedViaCompArgsOnReshape)
|
||||
{
|
||||
cv::GMat in;
|
||||
cv::GComputation comp(in, GBackSub::on(in));
|
||||
|
||||
const auto pkg = cv::gapi::kernels<GOCVBackSub>();
|
||||
|
||||
// OpenCV reference substractor
|
||||
auto pOCVBackSubKNN = createBackgroundSubtractorKNN();
|
||||
auto pOCVBackSubMOG2 = createBackgroundSubtractorMOG2();
|
||||
|
||||
const auto run = [&](const std::string& videoPath, const std::string& method) {
|
||||
auto path = findDataFile(videoPath);
|
||||
cv::gapi::wip::IStreamSource::Ptr source;
|
||||
try {
|
||||
source = gapi::wip::make_src<cv::gapi::wip::GCaptureSource>(path);
|
||||
} catch(...) {
|
||||
throw SkipTestException("Video file can not be opened");
|
||||
}
|
||||
cv::Mat inMat, gapiForeground, ocvForeground;
|
||||
|
||||
for (int i = 0; i < 10; i++) {
|
||||
cv::gapi::wip::Data inData;
|
||||
source->pull(inData);
|
||||
inMat = cv::util::get<cv::Mat>(inData);
|
||||
comp.apply(inMat, gapiForeground,
|
||||
cv::compile_args(pkg, BackSubStateParams{method}));
|
||||
|
||||
if (method == "knn") {
|
||||
pOCVBackSubKNN->apply(inMat, ocvForeground, -1);
|
||||
// Allowing 1% difference among all pixels
|
||||
compareBackSubResults(gapiForeground, ocvForeground, 1);
|
||||
} else if (method == "mog2") {
|
||||
pOCVBackSubMOG2->apply(inMat, ocvForeground, -1);
|
||||
compareBackSubResults(gapiForeground, ocvForeground, 5);
|
||||
} else {
|
||||
CV_Assert(false && "Unknown BackSub method");
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
run("cv/video/768x576.avi", "knn");
|
||||
run("cv/video/1920x1080.avi", "mog2");
|
||||
}
|
||||
#endif
|
||||
|
||||
TEST(StatefulKernel, StateIsAutoResetOnReshape)
|
||||
{
|
||||
cv::GMat in;
|
||||
cv::GOpaque<bool> up_to_date = GIsStateUpToDate::on(in);
|
||||
cv::GOpaque<int> calls_count = GCountCalls::on(in);
|
||||
cv::GComputation comp(cv::GIn(in), cv::GOut(up_to_date, calls_count));
|
||||
|
||||
auto run = [&comp](const cv::Mat& in_mat) {
|
||||
const auto pkg = cv::gapi::kernels<GOCVIsStateUpToDate, GOCVCountCalls>();
|
||||
bool stateIsUpToDate = false;
|
||||
int callsCount = 0;
|
||||
for (int i = 0; i < 3; i++) {
|
||||
comp.apply(cv::gin(in_mat), cv::gout(stateIsUpToDate, callsCount),
|
||||
cv::compile_args(pkg));
|
||||
EXPECT_TRUE(stateIsUpToDate);
|
||||
EXPECT_EQ(i+1, callsCount);
|
||||
}
|
||||
};
|
||||
|
||||
cv::Mat in_mat1(32, 32, CV_8UC1);
|
||||
run(in_mat1);
|
||||
|
||||
cv::Mat in_mat2(16, 16, CV_8UC1);
|
||||
run(in_mat2);
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------------------------------------------------
|
||||
|
||||
|
||||
|
@ -2,12 +2,14 @@
|
||||
// It is subject to the license terms in the LICENSE file found in the top-level directory
|
||||
// of this distribution and at http://opencv.org/license.html.
|
||||
//
|
||||
// Copyright (C) 2018 Intel Corporation
|
||||
// Copyright (C) 2018-2022 Intel Corporation
|
||||
|
||||
|
||||
#include "../test_precomp.hpp"
|
||||
#include "../gapi_mock_kernels.hpp"
|
||||
|
||||
#include <opencv2/gapi/core.hpp>
|
||||
|
||||
namespace opencv_test
|
||||
{
|
||||
|
||||
@ -294,6 +296,28 @@ TEST_F(GExecutorReshapeTest, ReshapeCallAllocate)
|
||||
EXPECT_EQ(1, island1.getReshapeCounter());
|
||||
}
|
||||
|
||||
TEST_F(GExecutorReshapeTest, CPUBackendIsReshapable)
|
||||
{
|
||||
comp = cv::GComputation([](){
|
||||
cv::GMat in;
|
||||
cv::GMat foo = I::Foo::on(in);
|
||||
cv::GMat out = cv::gapi::bitwise_not(cv::gapi::bitwise_not(in));
|
||||
return cv::GComputation(cv::GIn(in), cv::GOut(foo, out));
|
||||
});
|
||||
// NB: Initial state
|
||||
EXPECT_EQ(0, island1.getReshapeCounter());
|
||||
|
||||
// NB: First compilation.
|
||||
cv::Mat out_mat2;
|
||||
comp.apply(cv::gin(in_mat1), cv::gout(out_mat, out_mat2), cv::compile_args(pkg));
|
||||
EXPECT_EQ(0, island1.getReshapeCounter());
|
||||
|
||||
// NB: The entire graph is reshapable, so it won't be recompiled, but reshaped.
|
||||
comp.apply(cv::gin(in_mat2), cv::gout(out_mat, out_mat2), cv::compile_args(pkg));
|
||||
EXPECT_EQ(1, island1.getReshapeCounter());
|
||||
EXPECT_EQ(0, cvtest::norm(out_mat2, in_mat2, NORM_INF));
|
||||
}
|
||||
|
||||
// FIXME: Add explicit tests on GMat/GScalar/GArray<T> being connectors
|
||||
// between executed islands
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user