mirror of
https://github.com/opencv/opencv.git
synced 2026-07-29 23:33:05 +04:00
gapi: Full calcOpticalFlowPyrLK implementation (2 overloads) and tests
- opencv_gapi module is linked with opencv_video module (optional dependency)
- kernels added to a new cv::gapi::video namespace and a brand new files created to provide gapi_video environment
- there are 2 different kernels as G-API should provide GMat AND GArray<GMat> implementation: cv::calcOptFlowPyrLK doesn't calculate pyramids if vector<Mat> is given so just the cast GMat -> GArray<GMat> wouldn't represent all the cv:: functionality
- tests to check both kernels (based on cv::video tests for cv::calcOpticalFlowPyrLK())
- tests for internal purposes added
- vectors<T> comparison in tests implemented
- new (and old too) common test structures refactored to avoid code copypasting
- "modules/gapi/test/common/gapi_video_tests_common.hpp" created to share some code snippets between perf and acc tests and avoid code copypasting
This commit is contained in:
@@ -784,7 +784,6 @@ TEST_P(RGB2YUV422Test, AccuracyTest)
|
||||
EXPECT_EQ(out_mat_gapi.size(), sz);
|
||||
}
|
||||
}
|
||||
|
||||
} // opencv_test
|
||||
|
||||
#endif //OPENCV_GAPI_IMGPROC_TESTS_INL_HPP
|
||||
|
||||
@@ -196,25 +196,32 @@ public:
|
||||
}
|
||||
}
|
||||
|
||||
void initMatsFromImages(int channels, const std::string& pattern, int imgNum)
|
||||
{
|
||||
initTestDataPath();
|
||||
GAPI_Assert(channels == 1 || channels == 3 || channels == 4);
|
||||
const int flags = (channels == 1) ? cv::IMREAD_GRAYSCALE : cv::IMREAD_COLOR;
|
||||
|
||||
cv::Mat m1 = cv::imread(findDataFile(cv::format(pattern.c_str(), imgNum)), flags);
|
||||
cv::Mat m2 = cv::imread(findDataFile(cv::format(pattern.c_str(), imgNum + 1)), flags);
|
||||
if (channels == 4)
|
||||
{
|
||||
cvtColor(m1, in_mat1, cv::COLOR_BGR2BGRA);
|
||||
cvtColor(m2, in_mat2, cv::COLOR_BGR2BGRA);
|
||||
}
|
||||
else
|
||||
{
|
||||
std::tie(in_mat1, in_mat2) = std::make_tuple(m1, m2);
|
||||
}
|
||||
}
|
||||
|
||||
// empty function intended to show that nothing is to be initialized via TestFunctional methods
|
||||
void initNothing(int, cv::Size, int, bool = true) {}
|
||||
};
|
||||
|
||||
template<class T>
|
||||
class TestParams: public TestFunctional, public TestWithParam<T>{};
|
||||
|
||||
template<class T>
|
||||
class TestPerfParams: public TestFunctional, public perf::TestBaseWithParam<T>{};
|
||||
|
||||
using compare_f = std::function<bool(const cv::Mat &a, const cv::Mat &b)>;
|
||||
|
||||
using compare_scalar_f = std::function<bool(const cv::Scalar &a, const cv::Scalar &b)>;
|
||||
|
||||
template<typename Elem>
|
||||
using compare_vector_f = std::function<bool(const std::vector<Elem> &a,
|
||||
const std::vector<Elem> &b)>;
|
||||
|
||||
|
||||
// FIXME: re-use MatType. current problem: "special values" interpreted incorrectly (-1 is printed
|
||||
// as 16FC512)
|
||||
struct MatType2
|
||||
@@ -368,6 +375,14 @@ struct TestWithParamsSpecific : public TestWithParamsBase<ParamsSpecific<Specifi
|
||||
// Example: FIXTURE_API(int, bool) expands to <int, bool>
|
||||
#define FIXTURE_API(...) <__VA_ARGS__>
|
||||
|
||||
|
||||
using compare_f = std::function<bool(const cv::Mat &a, const cv::Mat &b)>;
|
||||
using compare_scalar_f = std::function<bool(const cv::Scalar &a, const cv::Scalar &b)>;
|
||||
|
||||
template<typename Elem>
|
||||
using compare_vector_f = std::function<bool(const std::vector<Elem> &a,
|
||||
const std::vector<Elem> &b)>;
|
||||
|
||||
template<typename T1, typename T2>
|
||||
struct CompareF
|
||||
{
|
||||
|
||||
@@ -0,0 +1,9 @@
|
||||
// This file is part of OpenCV project.
|
||||
// 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
|
||||
|
||||
|
||||
#include "../test_precomp.hpp"
|
||||
#include "gapi_video_tests_inl.hpp"
|
||||
@@ -0,0 +1,24 @@
|
||||
// This file is part of OpenCV project.
|
||||
// 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
|
||||
|
||||
#ifndef OPENCV_GAPI_VIDEO_TESTS_HPP
|
||||
#define OPENCV_GAPI_VIDEO_TESTS_HPP
|
||||
|
||||
#include "gapi_video_tests_common.hpp"
|
||||
|
||||
namespace opencv_test
|
||||
{
|
||||
GAPI_TEST_FIXTURE_SPEC_PARAMS(OptFlowLKTest, FIXTURE_API(std::string,int,tuple<int,int>,int,
|
||||
cv::TermCriteria),
|
||||
5, fileNamePattern, channels, pointsNum, winSize, criteria)
|
||||
|
||||
GAPI_TEST_FIXTURE_SPEC_PARAMS(OptFlowLKTestForPyr, FIXTURE_API(std::string,int,tuple<int,int>,int,
|
||||
cv::TermCriteria,bool),
|
||||
6, fileNamePattern, channels, pointsNum, winSize, criteria,withDeriv)
|
||||
} // opencv_test
|
||||
|
||||
|
||||
#endif // OPENCV_GAPI_VIDEO_TESTS_HPP
|
||||
@@ -0,0 +1,249 @@
|
||||
// This file is part of OpenCV project.
|
||||
// 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
|
||||
|
||||
#ifndef OPENCV_GAPI_VIDEO_TESTS_COMMON_HPP
|
||||
#define OPENCV_GAPI_VIDEO_TESTS_COMMON_HPP
|
||||
|
||||
#include "gapi_tests_common.hpp"
|
||||
#include "../../include/opencv2/gapi/video.hpp"
|
||||
|
||||
#ifdef HAVE_OPENCV_VIDEO
|
||||
#include <opencv2/video.hpp>
|
||||
#endif // HAVE_OPENCV_VIDEO
|
||||
|
||||
|
||||
|
||||
namespace opencv_test
|
||||
{
|
||||
namespace
|
||||
{
|
||||
inline void initTrackingPointsArray(std::vector<cv::Point2f>& points, int width, int height,
|
||||
int nPointsX, int nPointsY)
|
||||
{
|
||||
if (nPointsX > width || nPointsY > height)
|
||||
{
|
||||
FAIL() << "Specified points number is too big";
|
||||
}
|
||||
|
||||
int stepX = width / nPointsX;
|
||||
int stepY = height / nPointsY;
|
||||
|
||||
|
||||
points.clear();
|
||||
GAPI_Assert((nPointsX >= 0) && (nPointsY) >= 0);
|
||||
points.reserve(static_cast<size_t>(nPointsX * nPointsY));
|
||||
|
||||
for (int x = stepX / 2; x < width; x += stepX)
|
||||
{
|
||||
for (int y = stepY / 2; y < height; y += stepY)
|
||||
{
|
||||
Point2f pt(static_cast<float>(x), static_cast<float>(y));
|
||||
points.push_back(pt);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
template<typename Type>
|
||||
struct OptFlowLKTestInput
|
||||
{
|
||||
Type& prevData;
|
||||
Type& nextData;
|
||||
std::vector<cv::Point2f>& prevPoints;
|
||||
};
|
||||
|
||||
struct OptFlowLKTestOutput
|
||||
{
|
||||
std::vector<cv::Point2f> &nextPoints;
|
||||
std::vector<uchar> &statuses;
|
||||
std::vector<float> &errors;
|
||||
};
|
||||
|
||||
struct OptFlowLKTestParams
|
||||
{
|
||||
OptFlowLKTestParams(): fileNamePattern(""), format(1), channels(0), pointsNum{0, 0},
|
||||
winSize(0), maxLevel(3), minEigThreshold(1e-4), flags(0) { }
|
||||
|
||||
OptFlowLKTestParams(const std::string& namePat, int chans,
|
||||
const std::tuple<int,int>& ptsNum, int winSz,
|
||||
const cv::TermCriteria& crit, const cv::GCompileArgs& compArgs,
|
||||
int flgs = 0, int fmt = 1, int maxLvl = 3, double minEigThresh = 1e-4):
|
||||
|
||||
fileNamePattern(namePat), format(fmt), channels(chans),
|
||||
pointsNum(ptsNum), winSize(winSz), maxLevel(maxLvl),
|
||||
criteria(crit), minEigThreshold(minEigThresh), compileArgs(compArgs),
|
||||
flags(flgs) { }
|
||||
|
||||
std::string fileNamePattern = "";
|
||||
int format = 1;
|
||||
int channels = 0;
|
||||
std::tuple<int,int> pointsNum = std::make_tuple(0, 0);
|
||||
int winSize = 0;
|
||||
int maxLevel = 3;
|
||||
cv::TermCriteria criteria;
|
||||
double minEigThreshold = 1e-4;
|
||||
cv::GCompileArgs compileArgs;
|
||||
int flags = 0;
|
||||
};
|
||||
|
||||
#ifdef HAVE_OPENCV_VIDEO
|
||||
|
||||
template<typename GType, typename Type>
|
||||
cv::GComputation runOCVnGAPIOptFlowLK(OptFlowLKTestInput<Type>& in,
|
||||
int width, int height,
|
||||
const OptFlowLKTestParams& params,
|
||||
OptFlowLKTestOutput& ocvOut,
|
||||
OptFlowLKTestOutput& gapiOut)
|
||||
{
|
||||
|
||||
int nPointsX = 0, nPointsY = 0;
|
||||
std::tie(nPointsX, nPointsY) = params.pointsNum;
|
||||
|
||||
initTrackingPointsArray(in.prevPoints, width, height, nPointsX, nPointsY);
|
||||
|
||||
cv::Size winSize(params.winSize, params.winSize);
|
||||
|
||||
// OpenCV code /////////////////////////////////////////////////////////////
|
||||
{
|
||||
cv::calcOpticalFlowPyrLK(in.prevData, in.nextData, in.prevPoints,
|
||||
ocvOut.nextPoints, ocvOut.statuses, ocvOut.errors,
|
||||
winSize, params.maxLevel, params.criteria,
|
||||
params.flags, params.minEigThreshold);
|
||||
}
|
||||
|
||||
// G-API code //////////////////////////////////////////////////////////////
|
||||
{
|
||||
GType inPrev, inNext;
|
||||
GArray<cv::Point2f> prevPts, predPts, nextPts;
|
||||
GArray<uchar> statuses;
|
||||
GArray<float> errors;
|
||||
std::tie(nextPts, statuses, errors) = cv::gapi::calcOpticalFlowPyrLK(
|
||||
inPrev, inNext,
|
||||
prevPts, predPts, winSize,
|
||||
params.maxLevel, params.criteria,
|
||||
params.flags, params.minEigThreshold);
|
||||
|
||||
cv::GComputation c(cv::GIn(inPrev, inNext, prevPts, predPts),
|
||||
cv::GOut(nextPts, statuses, errors));
|
||||
|
||||
c.apply(cv::gin(in.prevData, in.nextData, in.prevPoints, std::vector<cv::Point2f>{ }),
|
||||
cv::gout(gapiOut.nextPoints, gapiOut.statuses, gapiOut.errors),
|
||||
std::move(const_cast<cv::GCompileArgs&>(params.compileArgs)));
|
||||
|
||||
return c;
|
||||
}
|
||||
}
|
||||
|
||||
inline cv::GComputation runOCVnGAPIOptFlowLK(TestFunctional& testInst,
|
||||
std::vector<cv::Point2f>& inPts,
|
||||
const OptFlowLKTestParams& params,
|
||||
OptFlowLKTestOutput& ocvOut,
|
||||
OptFlowLKTestOutput& gapiOut)
|
||||
{
|
||||
testInst.initMatsFromImages(params.channels,
|
||||
params.fileNamePattern,
|
||||
params.format);
|
||||
|
||||
OptFlowLKTestInput<cv::Mat> in{ testInst.in_mat1, testInst.in_mat2, inPts };
|
||||
|
||||
return runOCVnGAPIOptFlowLK<cv::GMat>(in,
|
||||
testInst.in_mat1.cols,
|
||||
testInst.in_mat1.rows,
|
||||
params,
|
||||
ocvOut,
|
||||
gapiOut);
|
||||
}
|
||||
|
||||
inline cv::GComputation runOCVnGAPIOptFlowLKForPyr(TestFunctional& testInst,
|
||||
OptFlowLKTestInput<std::vector<cv::Mat>>& in,
|
||||
const OptFlowLKTestParams& params,
|
||||
bool withDeriv,
|
||||
OptFlowLKTestOutput& ocvOut,
|
||||
OptFlowLKTestOutput& gapiOut)
|
||||
{
|
||||
testInst.initMatsFromImages(params.channels,
|
||||
params.fileNamePattern,
|
||||
params.format);
|
||||
|
||||
cv::Size winSize(params.winSize, params.winSize);
|
||||
|
||||
OptFlowLKTestParams updatedParams(params);
|
||||
updatedParams.maxLevel = cv::buildOpticalFlowPyramid(testInst.in_mat1, in.prevData,
|
||||
winSize, params.maxLevel, withDeriv);
|
||||
updatedParams.maxLevel = cv::buildOpticalFlowPyramid(testInst.in_mat2, in.nextData,
|
||||
winSize, params.maxLevel, withDeriv);
|
||||
|
||||
|
||||
return runOCVnGAPIOptFlowLK<cv::GArray<cv::GMat>>(in,
|
||||
testInst.in_mat1.cols,
|
||||
testInst.in_mat1.rows,
|
||||
updatedParams,
|
||||
ocvOut,
|
||||
gapiOut);
|
||||
}
|
||||
|
||||
#else // !HAVE_OPENCV_VIDEO
|
||||
|
||||
inline cv::GComputation runOCVnGAPIOptFlowLK(TestFunctional&,
|
||||
std::vector<cv::Point2f>&,
|
||||
const OptFlowLKTestParams&,
|
||||
OptFlowLKTestOutput&,
|
||||
OptFlowLKTestOutput&)
|
||||
{
|
||||
GAPI_Assert(0 && "This function shouldn't be called without opencv_video");
|
||||
}
|
||||
|
||||
inline cv::GComputation runOCVnGAPIOptFlowLKForPyr(TestFunctional&,
|
||||
OptFlowLKTestInput<std::vector<cv::Mat>>&,
|
||||
const OptFlowLKTestParams&,
|
||||
bool,
|
||||
OptFlowLKTestOutput&,
|
||||
OptFlowLKTestOutput&)
|
||||
{
|
||||
GAPI_Assert(0 && "This function shouldn't be called without opencv_video");
|
||||
}
|
||||
|
||||
#endif // HAVE_OPENCV_VIDEO
|
||||
|
||||
template <typename Elem>
|
||||
inline bool compareVectorsAbsExactForOptFlow(std::vector<Elem> outOCV, std::vector<Elem> outGAPI)
|
||||
{
|
||||
return AbsExactVector<Elem>().to_compare_f()(outOCV, outGAPI);
|
||||
}
|
||||
|
||||
inline void compareOutputsOptFlow(const OptFlowLKTestOutput& outOCV,
|
||||
const OptFlowLKTestOutput& outGAPI)
|
||||
{
|
||||
EXPECT_TRUE(compareVectorsAbsExactForOptFlow(outGAPI.nextPoints, outOCV.nextPoints));
|
||||
EXPECT_TRUE(compareVectorsAbsExactForOptFlow(outGAPI.statuses, outOCV.statuses));
|
||||
EXPECT_TRUE(compareVectorsAbsExactForOptFlow(outGAPI.errors, outOCV.errors));
|
||||
}
|
||||
|
||||
|
||||
inline std::ostream& operator<<(std::ostream& os, const cv::TermCriteria& criteria)
|
||||
{
|
||||
os << "{";
|
||||
switch (criteria.type) {
|
||||
case cv::TermCriteria::COUNT:
|
||||
os << "COUNT; ";
|
||||
break;
|
||||
case cv::TermCriteria::EPS:
|
||||
os << "EPS; ";
|
||||
break;
|
||||
case cv::TermCriteria::COUNT | cv::TermCriteria::EPS:
|
||||
os << "COUNT | EPS; ";
|
||||
break;
|
||||
default:
|
||||
os << "TypeUndifined; ";
|
||||
break;
|
||||
};
|
||||
|
||||
return os << criteria.maxCount << "; " << criteria.epsilon <<"}";
|
||||
}
|
||||
} // namespace
|
||||
} // namespace opencv_test
|
||||
|
||||
|
||||
#endif // OPENCV_GAPI_VIDEO_TESTS_COMMON_HPP
|
||||
@@ -0,0 +1,53 @@
|
||||
// This file is part of OpenCV project.
|
||||
// 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
|
||||
|
||||
#ifndef OPENCV_GAPI_VIDEO_TESTS_INL_HPP
|
||||
#define OPENCV_GAPI_VIDEO_TESTS_INL_HPP
|
||||
|
||||
#include "gapi_video_tests.hpp"
|
||||
|
||||
namespace opencv_test
|
||||
{
|
||||
|
||||
TEST_P(OptFlowLKTest, AccuracyTest)
|
||||
{
|
||||
std::vector<cv::Point2f> outPtsOCV, outPtsGAPI, inPts;
|
||||
std::vector<uchar> outStatusOCV, outStatusGAPI;
|
||||
std::vector<float> outErrOCV, outErrGAPI;
|
||||
|
||||
OptFlowLKTestParams params { fileNamePattern, channels, pointsNum,
|
||||
winSize, criteria, getCompileArgs() };
|
||||
|
||||
OptFlowLKTestOutput outOCV { outPtsOCV, outStatusOCV, outErrOCV };
|
||||
OptFlowLKTestOutput outGAPI { outPtsGAPI, outStatusGAPI, outErrGAPI };
|
||||
|
||||
runOCVnGAPIOptFlowLK(*this, inPts, params, outOCV, outGAPI);
|
||||
|
||||
compareOutputsOptFlow(outOCV, outGAPI);
|
||||
}
|
||||
|
||||
TEST_P(OptFlowLKTestForPyr, AccuracyTest)
|
||||
{
|
||||
std::vector<cv::Mat> inPyr1, inPyr2;
|
||||
std::vector<cv::Point2f> outPtsOCV, outPtsGAPI, inPts;
|
||||
std::vector<uchar> outStatusOCV, outStatusGAPI;
|
||||
std::vector<float> outErrOCV, outErrGAPI;
|
||||
|
||||
OptFlowLKTestParams params { fileNamePattern, channels, pointsNum,
|
||||
winSize, criteria, getCompileArgs() };
|
||||
|
||||
OptFlowLKTestInput<std::vector<cv::Mat>> in { inPyr1, inPyr2, inPts };
|
||||
OptFlowLKTestOutput outOCV { outPtsOCV, outStatusOCV, outErrOCV };
|
||||
OptFlowLKTestOutput outGAPI { outPtsGAPI, outStatusGAPI, outErrGAPI };
|
||||
|
||||
runOCVnGAPIOptFlowLKForPyr(*this, in, params, withDeriv, outOCV, outGAPI);
|
||||
|
||||
compareOutputsOptFlow(outOCV, outGAPI);
|
||||
}
|
||||
|
||||
} // opencv_test
|
||||
|
||||
#endif // OPENCV_GAPI_VIDEO_TESTS_INL_HPP
|
||||
@@ -0,0 +1,62 @@
|
||||
// This file is part of OpenCV project.
|
||||
// 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
|
||||
|
||||
|
||||
#include "../test_precomp.hpp"
|
||||
|
||||
#include "../common/gapi_video_tests.hpp"
|
||||
#include <opencv2/gapi/cpu/video.hpp>
|
||||
|
||||
namespace
|
||||
{
|
||||
#define VIDEO_CPU [] () { return cv::compile_args(cv::gapi::video::cpu::kernels()); }
|
||||
|
||||
#ifdef HAVE_OPENCV_VIDEO
|
||||
#define WITH_VIDEO(X) X
|
||||
#else
|
||||
#define WITH_VIDEO(X) DISABLED_##X
|
||||
#endif // HAVE_OPENCV_VIDEO
|
||||
|
||||
#define INSTANTIATE_TEST_CASE_MACRO_P(prefix, test_case_name, generator, ...) \
|
||||
INSTANTIATE_TEST_CASE_P(prefix, test_case_name, generator, __VA_ARGS__)
|
||||
} // anonymous namespace
|
||||
|
||||
namespace opencv_test
|
||||
{
|
||||
INSTANTIATE_TEST_CASE_MACRO_P(WITH_VIDEO(OptFlowLKTestCPU), OptFlowLKTest,
|
||||
Combine(Values(VIDEO_CPU),
|
||||
Values("cv/optflow/rock_%01d.bmp",
|
||||
"cv/optflow/frames/1080p_%02d.png"),
|
||||
Values(1, 3, 4),
|
||||
Values(std::make_tuple(9, 9), std::make_tuple(15, 15)),
|
||||
Values(7, 11),
|
||||
Values(cv::TermCriteria(cv::TermCriteria::COUNT |
|
||||
cv::TermCriteria::EPS,
|
||||
30, 0.01))));
|
||||
|
||||
INSTANTIATE_TEST_CASE_MACRO_P(WITH_VIDEO(OptFlowLKTestForPyrCPU), OptFlowLKTestForPyr,
|
||||
Combine(Values(VIDEO_CPU),
|
||||
Values("cv/optflow/rock_%01d.bmp",
|
||||
"cv/optflow/frames/1080p_%02d.png"),
|
||||
Values(1, 3, 4),
|
||||
Values(std::make_tuple(9, 9), std::make_tuple(15, 15)),
|
||||
Values(7, 11),
|
||||
Values(cv::TermCriteria(cv::TermCriteria::COUNT |
|
||||
cv::TermCriteria::EPS,
|
||||
30, 0.01)),
|
||||
testing::Bool()));
|
||||
|
||||
INSTANTIATE_TEST_CASE_MACRO_P(WITH_VIDEO(OptFlowLKInternalTestCPU), OptFlowLKTestForPyr,
|
||||
Combine(Values(VIDEO_CPU),
|
||||
Values("cv/optflow/rock_%01d.bmp"),
|
||||
Values(1),
|
||||
Values(std::make_tuple(10, 10)),
|
||||
Values(15),
|
||||
Values(cv::TermCriteria(cv::TermCriteria::COUNT |
|
||||
cv::TermCriteria::EPS,
|
||||
21, 0.05)),
|
||||
Values(true)));
|
||||
} // opencv_test
|
||||
@@ -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 Intel Corporation
|
||||
// Copyright (C) 2018-2020 Intel Corporation
|
||||
|
||||
|
||||
// FIXME: OpenCV header
|
||||
@@ -16,8 +16,9 @@
|
||||
#include <opencv2/ts.hpp>
|
||||
|
||||
#include <opencv2/gapi.hpp>
|
||||
#include <opencv2/gapi/imgproc.hpp>
|
||||
#include <opencv2/gapi/core.hpp>
|
||||
#include <opencv2/gapi/imgproc.hpp>
|
||||
#include <opencv2/gapi/video.hpp>
|
||||
#include <opencv2/gapi/cpu/gcpukernel.hpp>
|
||||
#include <opencv2/gapi/gpu/ggpukernel.hpp>
|
||||
#include <opencv2/gapi/gpu/imgproc.hpp>
|
||||
|
||||
Reference in New Issue
Block a user