return ctx.outVecR<U>(idx);
}
};
+
+//FIXME(dm): GArray<Mat>/GArray<GMat> conversion should be done more gracefully in the system
+template<> struct get_out<cv::GArray<cv::GMat> >: public get_out<cv::GArray<cv::Mat> >
+{
+};
+
template<typename U> struct get_out<cv::GOpaque<U>>
{
static U& get(GCPUContext &ctx, int idx)
namespace cv { namespace gapi {
namespace video
{
- using GOptFlowLKOutput = std::tuple<cv::GArray<cv::Point2f>,
- cv::GArray<uchar>,
- cv::GArray<float>>;
-
- G_TYPED_KERNEL(GCalcOptFlowLK,
- <GOptFlowLKOutput(GMat,GMat,cv::GArray<cv::Point2f>,cv::GArray<cv::Point2f>,Size,
- int,TermCriteria,int,double)>,
- "org.opencv.video.calcOpticalFlowPyrLK")
+using GBuildPyrOutput = std::tuple<GArray<GMat>, GScalar>;
+
+using GOptFlowLKOutput = std::tuple<cv::GArray<cv::Point2f>,
+ cv::GArray<uchar>,
+ cv::GArray<float>>;
+
+G_TYPED_KERNEL(GBuildOptFlowPyramid, <GBuildPyrOutput(GMat,Size,GScalar,bool,int,int,bool)>,
+ "org.opencv.video.buildOpticalFlowPyramid")
+{
+ static std::tuple<GArrayDesc,GScalarDesc>
+ outMeta(GMatDesc,const Size&,GScalarDesc,bool,int,int,bool)
+ {
+ return std::make_tuple(empty_array_desc(), empty_scalar_desc());
+ }
+};
+
+G_TYPED_KERNEL(GCalcOptFlowLK,
+ <GOptFlowLKOutput(GMat,GMat,cv::GArray<cv::Point2f>,cv::GArray<cv::Point2f>,Size,
+ GScalar,TermCriteria,int,double)>,
+ "org.opencv.video.calcOpticalFlowPyrLK")
+{
+ static std::tuple<GArrayDesc,GArrayDesc,GArrayDesc> outMeta(GMatDesc,GMatDesc,GArrayDesc,
+ GArrayDesc,const Size&,GScalarDesc,
+ const TermCriteria&,int,double)
{
- static std::tuple<GArrayDesc,GArrayDesc,GArrayDesc> outMeta(GMatDesc,GMatDesc,GArrayDesc,
- GArrayDesc,const Size&,int,
- const TermCriteria&,int,double)
- {
- return std::make_tuple(empty_array_desc(), empty_array_desc(), empty_array_desc());
- }
-
- };
-
- G_TYPED_KERNEL(GCalcOptFlowLKForPyr,
- <GOptFlowLKOutput(cv::GArray<cv::GMat>,cv::GArray<cv::GMat>,
- cv::GArray<cv::Point2f>,cv::GArray<cv::Point2f>,Size,int,
- TermCriteria,int,double)>,
- "org.opencv.video.calcOpticalFlowPyrLKForPyr")
+ return std::make_tuple(empty_array_desc(), empty_array_desc(), empty_array_desc());
+ }
+
+};
+
+G_TYPED_KERNEL(GCalcOptFlowLKForPyr,
+ <GOptFlowLKOutput(cv::GArray<cv::GMat>,cv::GArray<cv::GMat>,
+ cv::GArray<cv::Point2f>,cv::GArray<cv::Point2f>,Size,GScalar,
+ TermCriteria,int,double)>,
+ "org.opencv.video.calcOpticalFlowPyrLKForPyr")
+{
+ static std::tuple<GArrayDesc,GArrayDesc,GArrayDesc> outMeta(GArrayDesc,GArrayDesc,
+ GArrayDesc,GArrayDesc,
+ const Size&,GScalarDesc,
+ const TermCriteria&,int,double)
{
- static std::tuple<GArrayDesc,GArrayDesc,GArrayDesc> outMeta(GArrayDesc,GArrayDesc,
- GArrayDesc,GArrayDesc,
- const Size&,int,
- const TermCriteria&,int,double)
- {
- return std::make_tuple(empty_array_desc(), empty_array_desc(), empty_array_desc());
- }
- };
+ return std::make_tuple(empty_array_desc(), empty_array_desc(), empty_array_desc());
+ }
+};
} //namespace video
//! @addtogroup gapi_video
//! @{
+/** @brief Constructs the image pyramid which can be passed to calcOpticalFlowPyrLK.
+
+@note Function textual ID is "org.opencv.video.buildOpticalFlowPyramid"
+
+@param img 8-bit input image.
+@param winSize window size of optical flow algorithm. Must be not less than winSize
+ argument of calcOpticalFlowPyrLK. It is needed to calculate required
+ padding for pyramid levels.
+@param maxLevel 0-based maximal pyramid level number.
+@param withDerivatives set to precompute gradients for the every pyramid level. If pyramid is
+ constructed without the gradients then calcOpticalFlowPyrLK will calculate
+ them internally.
+@param pyrBorder the border mode for pyramid layers.
+@param derivBorder the border mode for gradients.
+@param tryReuseInputImage put ROI of input image into the pyramid if possible. You can pass false
+ to force data copying.
+
+@return output pyramid.
+@return number of levels in constructed pyramid. Can be less than maxLevel.
+ */
+GAPI_EXPORTS std::tuple<GArray<GMat>, GScalar>
+buildOpticalFlowPyramid(const GMat &img,
+ const Size &winSize,
+ const GScalar &maxLevel,
+ bool withDerivatives = true,
+ int pyrBorder = BORDER_REFLECT_101,
+ int derivBorder = BORDER_CONSTANT,
+ bool tryReuseInputImage = true);
+
/** @brief Calculates an optical flow for a sparse feature set using the iterative Lucas-Kanade
method with pyramids.
const GArray<Point2f> &prevPts,
const GArray<Point2f> &predPts,
const Size &winSize = Size(21, 21),
- int maxLevel = 3,
+ const GScalar &maxLevel = 3,
const TermCriteria &criteria = TermCriteria(TermCriteria::COUNT |
TermCriteria::EPS,
30, 0.01),
const GArray<Point2f> &prevPts,
const GArray<Point2f> &predPts,
const Size &winSize = Size(21, 21),
- int maxLevel = 3,
+ const GScalar &maxLevel = 3,
const TermCriteria &criteria = TermCriteria(TermCriteria::COUNT |
TermCriteria::EPS,
30, 0.01),
//------------------------------------------------------------------------------
+class BuildOptFlowPyramidPerfTest : public TestPerfParams<tuple<std::string,int,int,bool,int,int,
+ bool,GCompileArgs>> {};
class OptFlowLKPerfTest : public TestPerfParams<tuple<std::string,int,tuple<int,int>,int,
cv::TermCriteria,cv::GCompileArgs>> {};
class OptFlowLKForPyrPerfTest : public TestPerfParams<tuple<std::string,int,tuple<int,int>,int,
cv::TermCriteria,bool,
cv::GCompileArgs>> {};
+class BuildPyr_CalcOptFlow_PipelinePerfTest : public TestPerfParams<tuple<std::string,int,int,bool,
+ cv::GCompileArgs>> {};
+
} // opencv_test
#endif // OPENCV_GAPI_VIDEO_PERF_TESTS_HPP
//------------------------------------------------------------------------------
+PERF_TEST_P_(BuildOptFlowPyramidPerfTest, TestPerformance)
+{
+ std::vector<Mat> outPyrOCV, outPyrGAPI;
+ int outMaxLevelOCV = 0, outMaxLevelGAPI = 0;
+ Scalar outMaxLevelSc;
+
+ BuildOpticalFlowPyramidTestParams params;
+ std::tie(params.fileName, params.winSize,
+ params.maxLevel, params.withDerivatives,
+ params.pyrBorder, params.derivBorder,
+ params.tryReuseInputImage, params.compileArgs) = GetParam();
+
+ BuildOpticalFlowPyramidTestOutput outOCV { outPyrOCV, outMaxLevelOCV };
+ BuildOpticalFlowPyramidTestOutput outGAPI { outPyrGAPI, outMaxLevelGAPI };
+
+ GComputation c = runOCVnGAPIBuildOptFlowPyramid(*this, params, outOCV, outGAPI);
+
+ declare.in(in_mat1).out(outPyrGAPI);
+
+ TEST_CYCLE()
+ {
+ c.apply(cv::gin(in_mat1), cv::gout(outPyrGAPI, outMaxLevelSc));
+ }
+ outMaxLevelGAPI = static_cast<int>(outMaxLevelSc[0]);
+
+ // Comparison //////////////////////////////////////////////////////////////
+ compareOutputPyramids(outOCV, outGAPI);
+
+ SANITY_CHECK_NOTHING();
+}
+
PERF_TEST_P_(OptFlowLKPerfTest, TestPerformance)
{
std::vector<cv::Point2f> outPtsOCV, outPtsGAPI, inPts;
SANITY_CHECK_NOTHING();
}
+PERF_TEST_P_(BuildPyr_CalcOptFlow_PipelinePerfTest, TestPerformance)
+{
+ std::vector<Point2f> outPtsOCV, outPtsGAPI, inPts;
+ std::vector<uchar> outStatusOCV, outStatusGAPI;
+ std::vector<float> outErrOCV, outErrGAPI;
+
+ BuildOpticalFlowPyramidTestParams params;
+ params.pyrBorder = BORDER_DEFAULT;
+ params.derivBorder = BORDER_DEFAULT;
+ params.tryReuseInputImage = true;
+ std::tie(params.fileName, params.winSize,
+ params.maxLevel, params.withDerivatives,
+ params.compileArgs) = GetParam();
+
+ auto customKernel = gapi::kernels<GCPUMinScalar>();
+ auto kernels = gapi::combine(customKernel,
+ params.compileArgs[0].get<gapi::GKernelPackage>());
+ params.compileArgs = compile_args(kernels);
+
+ OptFlowLKTestOutput outOCV { outPtsOCV, outStatusOCV, outErrOCV };
+ OptFlowLKTestOutput outGAPI { outPtsGAPI, outStatusGAPI, outErrGAPI };
+
+ cv::GComputation c = runOCVnGAPIOptFlowPipeline(*this, params, outOCV, outGAPI, inPts);
+
+ declare.in(in_mat1, in_mat2, inPts).out(outPtsGAPI, outStatusGAPI, outErrGAPI);
+
+ TEST_CYCLE()
+ {
+ c.apply(cv::gin(in_mat1, in_mat2, inPts, std::vector<cv::Point2f>{ }),
+ cv::gout(outPtsGAPI, outStatusGAPI, outErrGAPI));
+ }
+
+ // Comparison //////////////////////////////////////////////////////////////
+ compareOutputsOptFlow(outOCV, outGAPI);
+
+ SANITY_CHECK_NOTHING();
+}
+
//------------------------------------------------------------------------------
} // opencv_test
namespace opencv_test
{
+INSTANTIATE_TEST_CASE_MACRO_P(WITH_VIDEO(BuildOptFlowPyramidPerfTestCPU),
+ BuildOptFlowPyramidPerfTest,
+ Combine(Values("cv/optflow/rock_1.bmp",
+ "cv/optflow/frames/1080p_01.png"),
+ Values(7, 11),
+ Values(1000),
+ testing::Bool(),
+ Values(BORDER_DEFAULT, BORDER_TRANSPARENT),
+ Values(BORDER_DEFAULT, BORDER_TRANSPARENT),
+ testing::Bool(),
+ Values(cv::compile_args(VIDEO_CPU))));
+
+INSTANTIATE_TEST_CASE_MACRO_P(WITH_VIDEO(BuildOptFlowPyramidInternalPerfTestCPU),
+ BuildOptFlowPyramidPerfTest,
+ Combine(Values("cv/optflow/rock_1.bmp"),
+ Values(15),
+ Values(3),
+ Values(true),
+ Values(BORDER_REFLECT_101),
+ Values(BORDER_CONSTANT),
+ Values(true),
+ Values(cv::compile_args(VIDEO_CPU))));
+
INSTANTIATE_TEST_CASE_MACRO_P(WITH_VIDEO(OptFlowLKPerfTestCPU), OptFlowLKPerfTest,
Combine(Values("cv/optflow/rock_%01d.bmp",
"cv/optflow/frames/1080p_%02d.png"),
21, 0.05)),
Values(true),
Values(cv::compile_args(VIDEO_CPU))));
+
+INSTANTIATE_TEST_CASE_MACRO_P(WITH_VIDEO(BuildPyr_CalcOptFlow_PipelinePerfTestCPU),
+ BuildPyr_CalcOptFlow_PipelinePerfTest,
+ Combine(Values("cv/optflow/frames/1080p_%02d.png"),
+ Values(7, 11),
+ Values(1000),
+ Values(true, false),
+ Values(cv::compile_args(VIDEO_CPU))));
+
+INSTANTIATE_TEST_CASE_MACRO_P(WITH_VIDEO(BuildPyr_CalcOptFlow_PipelineInternalTestPerfCPU),
+ BuildPyr_CalcOptFlow_PipelinePerfTest,
+ Combine(Values("cv/optflow/rock_%01d.bmp"),
+ Values(15),
+ Values(3),
+ Values(true),
+ Values(cv::compile_args(VIDEO_CPU))));
} // opencv_test
namespace cv { namespace gapi {
using namespace video;
+GBuildPyrOutput buildOpticalFlowPyramid(const GMat &img,
+ const Size &winSize,
+ const GScalar &maxLevel,
+ bool withDerivatives,
+ int pyrBorder,
+ int derivBorder,
+ bool tryReuseInputImage)
+{
+ return GBuildOptFlowPyramid::on(img, winSize, maxLevel, withDerivatives, pyrBorder,
+ derivBorder, tryReuseInputImage);
+}
GOptFlowLKOutput calcOpticalFlowPyrLK(const GMat &prevImg,
const GMat &nextImg,
const cv::GArray<cv::Point2f> &prevPts,
const cv::GArray<cv::Point2f> &predPts,
const Size &winSize,
- int maxLevel,
+ const GScalar &maxLevel,
const TermCriteria &criteria,
int flags,
double minEigThresh)
const cv::GArray<cv::Point2f> &prevPts,
const cv::GArray<cv::Point2f> &predPts,
const Size &winSize,
- int maxLevel,
+ const GScalar &maxLevel,
const TermCriteria &criteria,
int flags,
double minEigThresh)
#ifdef HAVE_OPENCV_VIDEO
+GAPI_OCV_KERNEL(GCPUBuildOptFlowPyramid, cv::gapi::video::GBuildOptFlowPyramid)
+{
+ static void run(const cv::Mat &img,
+ const cv::Size &winSize,
+ const cv::Scalar &maxLevel,
+ bool withDerivatives,
+ int pyrBorder,
+ int derivBorder,
+ bool tryReuseInputImage,
+ std::vector<cv::Mat> &outPyr,
+ cv::Scalar &outMaxLevel)
+ {
+ outMaxLevel = cv::buildOpticalFlowPyramid(img, outPyr, winSize,
+ static_cast<int>(maxLevel[0]),
+ withDerivatives, pyrBorder,
+ derivBorder, tryReuseInputImage);
+ }
+};
+
GAPI_OCV_KERNEL(GCPUCalcOptFlowLK, cv::gapi::video::GCalcOptFlowLK)
{
static void run(const cv::Mat &prevImg,
const std::vector<cv::Point2f> &prevPts,
const std::vector<cv::Point2f> &predPts,
const cv::Size &winSize,
- int maxLevel,
+ const cv::Scalar &maxLevel,
const cv::TermCriteria &criteria,
int flags,
double minEigThresh,
{
if (flags & cv::OPTFLOW_USE_INITIAL_FLOW)
outPts = predPts;
- cv::calcOpticalFlowPyrLK(prevImg, nextImg, prevPts, outPts, status, err, winSize, maxLevel,
- criteria, flags, minEigThresh);
+ cv::calcOpticalFlowPyrLK(prevImg, nextImg, prevPts, outPts, status, err, winSize,
+ static_cast<int>(maxLevel[0]), criteria, flags, minEigThresh);
}
};
const std::vector<cv::Point2f> &prevPts,
const std::vector<cv::Point2f> &predPts,
const cv::Size &winSize,
- int maxLevel,
+ const cv::Scalar &maxLevel,
const cv::TermCriteria &criteria,
int flags,
double minEigThresh,
{
if (flags & cv::OPTFLOW_USE_INITIAL_FLOW)
outPts = predPts;
- cv::calcOpticalFlowPyrLK(prevPyr, nextPyr, prevPts, outPts, status, err, winSize, maxLevel,
- criteria, flags, minEigThresh);
+ cv::calcOpticalFlowPyrLK(prevPyr, nextPyr, prevPts, outPts, status, err, winSize,
+ static_cast<int>(maxLevel[0]), criteria, flags, minEigThresh);
}
};
cv::gapi::GKernelPackage cv::gapi::video::cpu::kernels()
{
static auto pkg = cv::gapi::kernels
- < GCPUCalcOptFlowLK
+ < GCPUBuildOptFlowPyramid
+ , GCPUCalcOptFlowLK
, GCPUCalcOptFlowLKForPyr
>();
return pkg;
namespace opencv_test
{
+GAPI_TEST_FIXTURE_SPEC_PARAMS(BuildOptFlowPyramidTest,
+ FIXTURE_API(std::string,int,int,bool,int,int,bool), 7,
+ fileName, winSize, maxLevel, withDerivatives, pyrBorder,
+ derivBorder, tryReuseInputImage)
+
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)
+
+GAPI_TEST_FIXTURE_SPEC_PARAMS(BuildPyr_CalcOptFlow_PipelineTest,
+ FIXTURE_API(std::string,int,int,bool), 4,
+ fileNamePattern, winSize, maxLevel, withDerivatives)
+
} // opencv_test
{
namespace
{
+G_TYPED_KERNEL(GMinScalar, <GScalar(GScalar,GScalar)>, "custom.MinScalar") {
+ static GScalarDesc outMeta(GScalarDesc,GScalarDesc) { return empty_scalar_desc(); }
+};
+GAPI_OCV_KERNEL(GCPUMinScalar, GMinScalar) {
+ static void run(const Scalar &sc1, const Scalar &sc2, Scalar &scOut) {
+ scOut = Scalar(std::min(sc1[0], sc2[0]));
+ }
+};
+
inline void initTrackingPointsArray(std::vector<cv::Point2f>& points, int width, int height,
int nPointsX, int nPointsY)
{
}
}
+struct BuildOpticalFlowPyramidTestOutput
+{
+ BuildOpticalFlowPyramidTestOutput(std::vector<Mat> &pyr, int maxLvl) :
+ pyramid(pyr), maxLevel(maxLvl) { }
+ std::vector<Mat> &pyramid;
+ int maxLevel = 0;
+};
+
template<typename Type>
struct OptFlowLKTestInput
{
std::vector<float> &errors;
};
+struct BuildOpticalFlowPyramidTestParams
+{
+ BuildOpticalFlowPyramidTestParams(): fileName(""), winSize(-1), maxLevel(-1),
+ withDerivatives(false), pyrBorder(-1),
+ derivBorder(-1), tryReuseInputImage(false) { }
+
+ BuildOpticalFlowPyramidTestParams(const std::string& name, int winSz, int maxLvl,
+ bool withDeriv, int pBorder, int dBorder,
+ bool tryReuse, const GCompileArgs& compArgs):
+
+ fileName(name), winSize(winSz), maxLevel(maxLvl),
+ withDerivatives(withDeriv), pyrBorder(pBorder),
+ derivBorder(dBorder), tryReuseInputImage(tryReuse),
+ compileArgs(compArgs) { }
+
+ std::string fileName = "";
+ int winSize = -1;
+ int maxLevel = -1;
+ bool withDerivatives = false;
+ int pyrBorder = -1;
+ int derivBorder = -1;
+ bool tryReuseInputImage = false;
+ cv::GCompileArgs compileArgs;
+};
+
struct OptFlowLKTestParams
{
OptFlowLKTestParams(): fileNamePattern(""), format(1), channels(0), pointsNum{0, 0},
#ifdef HAVE_OPENCV_VIDEO
+inline GComputation runOCVnGAPIBuildOptFlowPyramid(TestFunctional& testInst,
+ const BuildOpticalFlowPyramidTestParams& params,
+ BuildOpticalFlowPyramidTestOutput& outOCV,
+ BuildOpticalFlowPyramidTestOutput& outGAPI)
+{
+ testInst.initMatFromImage(CV_8UC1, params.fileName);
+
+ // OpenCV code /////////////////////////////////////////////////////////////
+ {
+ outOCV.maxLevel = cv::buildOpticalFlowPyramid(testInst.in_mat1, outOCV.pyramid,
+ Size(params.winSize, params.winSize),
+ params.maxLevel, params.withDerivatives,
+ params.pyrBorder, params.derivBorder,
+ params.tryReuseInputImage);
+ }
+
+ // G-API code //////////////////////////////////////////////////////////////
+ GMat in;
+ GArray<GMat> out;
+ GScalar outMaxLevel;
+ std::tie(out, outMaxLevel) =
+ cv::gapi::buildOpticalFlowPyramid(in, Size(params.winSize, params.winSize),
+ params.maxLevel, params.withDerivatives,
+ params.pyrBorder, params.derivBorder,
+ params.tryReuseInputImage);
+
+ GComputation c(GIn(in), GOut(out, outMaxLevel));
+
+ Scalar outMaxLevelSc;
+ c.apply(gin(testInst.in_mat1), gout(outGAPI.pyramid, outMaxLevelSc),
+ std::move(const_cast<GCompileArgs&>(params.compileArgs)));
+ outGAPI.maxLevel = static_cast<int>(outMaxLevelSc[0]);
+
+ return c;
+}
+
template<typename GType, typename Type>
cv::GComputation runOCVnGAPIOptFlowLK(OptFlowLKTestInput<Type>& in,
int width, int height,
gapiOut);
}
+inline GComputation runOCVnGAPIOptFlowPipeline(TestFunctional& testInst,
+ const BuildOpticalFlowPyramidTestParams& params,
+ OptFlowLKTestOutput& outOCV,
+ OptFlowLKTestOutput& outGAPI,
+ std::vector<Point2f>& prevPoints)
+{
+ testInst.initMatsFromImages(3, params.fileName, 1);
+
+ initTrackingPointsArray(prevPoints, testInst.in_mat1.cols, testInst.in_mat1.rows, 15, 15);
+
+ Size winSize = Size(params.winSize, params.winSize);
+
+ // OpenCV code /////////////////////////////////////////////////////////////
+ {
+ std::vector<Mat> pyr1, pyr2;
+ int maxLevel1 = cv::buildOpticalFlowPyramid(testInst.in_mat1, pyr1, winSize,
+ params.maxLevel, params.withDerivatives,
+ params.pyrBorder, params.derivBorder,
+ params.tryReuseInputImage);
+ int maxLevel2 = cv::buildOpticalFlowPyramid(testInst.in_mat2, pyr2, winSize,
+ params.maxLevel, params.withDerivatives,
+ params.pyrBorder, params.derivBorder,
+ params.tryReuseInputImage);
+ cv::calcOpticalFlowPyrLK(pyr1, pyr2, prevPoints,
+ outOCV.nextPoints, outOCV.statuses, outOCV.errors,
+ winSize, std::min(maxLevel1, maxLevel2));
+ }
+
+ // G-API code //////////////////////////////////////////////////////////////
+ GMat in1, in2;
+ GArray<GMat> gpyr1, gpyr2;
+ GScalar gmaxLevel1, gmaxLevel2;
+ GArray<cv::Point2f> gprevPts, gpredPts, gnextPts;
+ GArray<uchar> gstatuses;
+ GArray<float> gerrors;
+
+ std::tie(gpyr1, gmaxLevel1) = cv::gapi::buildOpticalFlowPyramid(
+ in1, winSize, params.maxLevel,
+ params.withDerivatives, params.pyrBorder,
+ params.derivBorder, params.tryReuseInputImage);
+
+ std::tie(gpyr2, gmaxLevel2) = cv::gapi::buildOpticalFlowPyramid(
+ in2, winSize, params.maxLevel,
+ params.withDerivatives, params.pyrBorder,
+ params.derivBorder, params.tryReuseInputImage);
+
+ GScalar gmaxLevel = GMinScalar::on(gmaxLevel1, gmaxLevel2);
+
+ std::tie(gnextPts, gstatuses, gerrors) = cv::gapi::calcOpticalFlowPyrLK(
+ gpyr1, gpyr2, gprevPts, gpredPts, winSize,
+ gmaxLevel);
+
+ cv::GComputation c(GIn(in1, in2, gprevPts, gpredPts), cv::GOut(gnextPts, gstatuses, gerrors));
+
+ c.apply(cv::gin(testInst.in_mat1, testInst.in_mat2, prevPoints, std::vector<cv::Point2f>{ }),
+ cv::gout(outGAPI.nextPoints, outGAPI.statuses, outGAPI.errors),
+ std::move(const_cast<cv::GCompileArgs&>(params.compileArgs)));
+
+ return c;
+}
+
#else // !HAVE_OPENCV_VIDEO
+inline cv::GComputation runOCVnGAPIBuildOptFlowPyramid(TestFunctional&,
+ const BuildOpticalFlowPyramidTestParams&,
+ BuildOpticalFlowPyramidTestOutput&,
+ BuildOpticalFlowPyramidTestOutput&)
+{
+ GAPI_Assert(0 && "This function shouldn't be called without opencv_video");
+}
+
inline cv::GComputation runOCVnGAPIOptFlowLK(TestFunctional&,
std::vector<cv::Point2f>&,
const OptFlowLKTestParams&,
GAPI_Assert(0 && "This function shouldn't be called without opencv_video");
}
+inline GComputation runOCVnGAPIOptFlowPipeline(TestFunctional&,
+ const BuildOpticalFlowPyramidTestParams&,
+ OptFlowLKTestOutput&,
+ OptFlowLKTestOutput&,
+ std::vector<Point2f>&)
+{
+ GAPI_Assert(0 && "This function shouldn't be called without opencv_video");
+}
+
#endif // HAVE_OPENCV_VIDEO
+inline void compareOutputPyramids(const BuildOpticalFlowPyramidTestOutput& outOCV,
+ const BuildOpticalFlowPyramidTestOutput& outGAPI)
+{
+ GAPI_Assert(outGAPI.maxLevel == outOCV.maxLevel);
+ GAPI_Assert(outOCV.maxLevel >= 0);
+ size_t maxLevel = static_cast<size_t>(outOCV.maxLevel);
+ for (size_t i = 0; i <= maxLevel; i++)
+ {
+ EXPECT_TRUE(AbsExact().to_compare_f()(outOCV.pyramid[i], outGAPI.pyramid[i]));
+ }
+}
+
template <typename Elem>
inline bool compareVectorsAbsExactForOptFlow(std::vector<Elem> outOCV, std::vector<Elem> outGAPI)
{
EXPECT_TRUE(compareVectorsAbsExactForOptFlow(outGAPI.errors, outOCV.errors));
}
-
inline std::ostream& operator<<(std::ostream& os, const cv::TermCriteria& criteria)
{
os << "{";
os << "COUNT | EPS; ";
break;
default:
- os << "TypeUndifined; ";
+ os << "TypeUndefined; ";
break;
};
namespace opencv_test
{
+TEST_P(BuildOptFlowPyramidTest, AccuracyTest)
+{
+ std::vector<Mat> outPyrOCV, outPyrGAPI;
+ int outMaxLevelOCV = 0, outMaxLevelGAPI = 0;
+
+ BuildOpticalFlowPyramidTestParams params { fileName, winSize, maxLevel,
+ withDerivatives, pyrBorder, derivBorder,
+ tryReuseInputImage, getCompileArgs() };
+
+ BuildOpticalFlowPyramidTestOutput outOCV { outPyrOCV, outMaxLevelOCV };
+ BuildOpticalFlowPyramidTestOutput outGAPI { outPyrGAPI, outMaxLevelGAPI };
+
+ runOCVnGAPIBuildOptFlowPyramid(*this, params, outOCV, outGAPI);
+
+ compareOutputPyramids(outOCV, outGAPI);
+}
+
TEST_P(OptFlowLKTest, AccuracyTest)
{
std::vector<cv::Point2f> outPtsOCV, outPtsGAPI, inPts;
compareOutputsOptFlow(outOCV, outGAPI);
}
+TEST_P(BuildPyr_CalcOptFlow_PipelineTest, AccuracyTest)
+{
+ std::vector<Point2f> outPtsOCV, outPtsGAPI, inPts;
+ std::vector<uchar> outStatusOCV, outStatusGAPI;
+ std::vector<float> outErrOCV, outErrGAPI;
+
+ BuildOpticalFlowPyramidTestParams params { fileNamePattern, winSize, maxLevel,
+ withDerivatives, BORDER_DEFAULT, BORDER_DEFAULT,
+ true, getCompileArgs() };
+
+ auto customKernel = gapi::kernels<GCPUMinScalar>();
+ auto kernels = gapi::combine(customKernel,
+ params.compileArgs[0].get<gapi::GKernelPackage>());
+ params.compileArgs = compile_args(kernels);
+
+ OptFlowLKTestOutput outOCV { outPtsOCV, outStatusOCV, outErrOCV };
+ OptFlowLKTestOutput outGAPI { outPtsGAPI, outStatusGAPI, outErrGAPI };
+
+ runOCVnGAPIOptFlowPipeline(*this, params, outOCV, outGAPI, inPts);
+
+ compareOutputsOptFlow(outOCV, outGAPI);
+}
+
} // opencv_test
#endif // OPENCV_GAPI_VIDEO_TESTS_INL_HPP
namespace opencv_test
{
+INSTANTIATE_TEST_CASE_MACRO_P(WITH_VIDEO(BuildOptFlowPyramidTestCPU), BuildOptFlowPyramidTest,
+ Combine(Values(VIDEO_CPU),
+ Values("cv/optflow/rock_1.bmp",
+ "cv/optflow/frames/1080p_01.png"),
+ Values(7, 11),
+ Values(1000),
+ testing::Bool(),
+ Values(BORDER_DEFAULT, BORDER_TRANSPARENT),
+ Values(BORDER_DEFAULT, BORDER_TRANSPARENT),
+ testing::Bool()));
+
+INSTANTIATE_TEST_CASE_MACRO_P(WITH_VIDEO(BuildOptFlowPyramidInternalTestCPU),
+ BuildOptFlowPyramidTest,
+ Combine(Values(VIDEO_CPU),
+ Values("cv/optflow/rock_1.bmp"),
+ Values(15),
+ Values(3),
+ Values(true),
+ Values(BORDER_REFLECT_101),
+ Values(BORDER_CONSTANT),
+ Values(true)));
+
INSTANTIATE_TEST_CASE_MACRO_P(WITH_VIDEO(OptFlowLKTestCPU), OptFlowLKTest,
Combine(Values(VIDEO_CPU),
Values("cv/optflow/rock_%01d.bmp",
cv::TermCriteria::EPS,
21, 0.05)),
Values(true)));
+
+INSTANTIATE_TEST_CASE_MACRO_P(WITH_VIDEO(BuildPyr_CalcOptFlow_PipelineTestCPU),
+ BuildPyr_CalcOptFlow_PipelineTest,
+ Combine(Values(VIDEO_CPU),
+ Values("cv/optflow/frames/1080p_%02d.png"),
+ Values(7, 11),
+ Values(1000),
+ testing::Bool()));
+
+INSTANTIATE_TEST_CASE_MACRO_P(WITH_VIDEO(BuildPyr_CalcOptFlow_PipelineInternalTestCPU),
+ BuildPyr_CalcOptFlow_PipelineTest,
+ Combine(Values(VIDEO_CPU),
+ Values("cv/optflow/rock_%01d.bmp"),
+ Values(15),
+ Values(3),
+ Values(true)));
} // opencv_test