gapi: buildOpticalFlowPyramid() interface, CPUkernel and CPUtests implementation
- kernel added to a cv::gapi::video namespace
- tests to check a kernels (based on cv::video tests for cv::buildOpticalFlowPyramid())
- tests for a combined G-API-pipeline (buildOpticalFlowPyramid() -> calcOpticalFlowPyrLK())
- tests for internal purposes added
- custom function for comparison in tests implemented
This commit is contained in:
@@ -11,6 +11,11 @@
|
||||
|
||||
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)
|
||||
@@ -18,6 +23,11 @@ GAPI_TEST_FIXTURE_SPEC_PARAMS(OptFlowLKTest, FIXTURE_API(std::string,int,tuple<i
|
||||
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
|
||||
|
||||
|
||||
|
||||
@@ -20,6 +20,15 @@ namespace 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)
|
||||
{
|
||||
@@ -46,6 +55,14 @@ inline void initTrackingPointsArray(std::vector<cv::Point2f>& points, int width,
|
||||
}
|
||||
}
|
||||
|
||||
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
|
||||
{
|
||||
@@ -61,6 +78,31 @@ struct OptFlowLKTestOutput
|
||||
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},
|
||||
@@ -90,6 +132,42 @@ struct OptFlowLKTestParams
|
||||
|
||||
#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,
|
||||
@@ -184,8 +262,77 @@ inline cv::GComputation runOCVnGAPIOptFlowLKForPyr(TestFunctional& testInst,
|
||||
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&,
|
||||
@@ -205,8 +352,29 @@ inline cv::GComputation runOCVnGAPIOptFlowLKForPyr(TestFunctional&,
|
||||
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)
|
||||
{
|
||||
@@ -221,7 +389,6 @@ inline void compareOutputsOptFlow(const OptFlowLKTestOutput& outOCV,
|
||||
EXPECT_TRUE(compareVectorsAbsExactForOptFlow(outGAPI.errors, outOCV.errors));
|
||||
}
|
||||
|
||||
|
||||
inline std::ostream& operator<<(std::ostream& os, const cv::TermCriteria& criteria)
|
||||
{
|
||||
os << "{";
|
||||
@@ -236,7 +403,7 @@ inline std::ostream& operator<<(std::ostream& os, const cv::TermCriteria& criter
|
||||
os << "COUNT | EPS; ";
|
||||
break;
|
||||
default:
|
||||
os << "TypeUndifined; ";
|
||||
os << "TypeUndefined; ";
|
||||
break;
|
||||
};
|
||||
|
||||
|
||||
@@ -12,6 +12,23 @@
|
||||
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;
|
||||
@@ -48,6 +65,29 @@ TEST_P(OptFlowLKTestForPyr, AccuracyTest)
|
||||
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
|
||||
|
||||
Reference in New Issue
Block a user