Merge pull request #19712 from OrestChura:oc/Kalm_ptest
[G-API]: Performance tests for KalmanFilter * Kalman perf.tests and some tests refactoring * Input generation moved to a separate function; Slowest case sneario testing added * Generating refactored * Generating refactoring * Addressing comments
This commit is contained in:
parent
77bfd9434b
commit
ad2f5ccc66
@ -29,6 +29,12 @@ class BuildPyr_CalcOptFlow_PipelinePerfTest : public TestPerfParams<tuple<std::s
|
||||
class BackgroundSubtractorPerfTest:
|
||||
public TestPerfParams<tuple<cv::gapi::video::BackgroundSubtractorType, std::string,
|
||||
bool, double, std::size_t, cv::GCompileArgs, CompareMats>> {};
|
||||
|
||||
class KalmanFilterControlPerfTest :
|
||||
public TestPerfParams<tuple<MatType2, int, int, size_t, bool, cv::GCompileArgs>> {};
|
||||
class KalmanFilterNoControlPerfTest :
|
||||
public TestPerfParams<tuple<MatType2, int, int, size_t, bool, cv::GCompileArgs>> {};
|
||||
|
||||
} // opencv_test
|
||||
|
||||
#endif // OPENCV_GAPI_VIDEO_PERF_TESTS_HPP
|
||||
|
||||
@ -241,6 +241,156 @@ PERF_TEST_P_(BackgroundSubtractorPerfTest, TestPerformance)
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
inline void generateInputKalman(const int mDim, const MatType2& type,
|
||||
const size_t testNumMeasurements, const bool receiveRandMeas,
|
||||
std::vector<bool>& haveMeasurements,
|
||||
std::vector<cv::Mat>& measurements)
|
||||
{
|
||||
cv::RNG& rng = cv::theRNG();
|
||||
measurements.clear();
|
||||
haveMeasurements = std::vector<bool>(testNumMeasurements, true);
|
||||
for (size_t i = 0; i < testNumMeasurements; i++)
|
||||
{
|
||||
if (receiveRandMeas)
|
||||
{
|
||||
haveMeasurements[i] = rng(2u) == 1; // returns 0 or 1 - whether we have measurement
|
||||
// at this iteration or not
|
||||
} // if not - testing the slowest case in which we have measurements at every iteration
|
||||
|
||||
cv::Mat measurement = cv::Mat::zeros(mDim, 1, type);
|
||||
if (haveMeasurements[i])
|
||||
{
|
||||
cv::randu(measurement, cv::Scalar::all(-1), cv::Scalar::all(1));
|
||||
}
|
||||
measurements.push_back(measurement.clone());
|
||||
}
|
||||
}
|
||||
|
||||
inline void generateInputKalman(const int mDim, const int cDim, const MatType2& type,
|
||||
const size_t testNumMeasurements, const bool receiveRandMeas,
|
||||
std::vector<bool>& haveMeasurements,
|
||||
std::vector<cv::Mat>& measurements,
|
||||
std::vector<cv::Mat>& ctrls)
|
||||
{
|
||||
generateInputKalman(mDim, type, testNumMeasurements, receiveRandMeas,
|
||||
haveMeasurements, measurements);
|
||||
ctrls.clear();
|
||||
cv::Mat ctrl(cDim, 1, type);
|
||||
for (size_t i = 0; i < testNumMeasurements; i++)
|
||||
{
|
||||
cv::randu(ctrl, cv::Scalar::all(-1), cv::Scalar::all(1));
|
||||
ctrls.push_back(ctrl.clone());
|
||||
}
|
||||
}
|
||||
|
||||
PERF_TEST_P_(KalmanFilterControlPerfTest, TestPerformance)
|
||||
{
|
||||
MatType2 type = -1;
|
||||
int dDim = -1, mDim = -1;
|
||||
size_t testNumMeasurements = 0;
|
||||
bool receiveRandMeas = true;
|
||||
cv::GCompileArgs compileArgs;
|
||||
std::tie(type, dDim, mDim, testNumMeasurements, receiveRandMeas, compileArgs) = GetParam();
|
||||
|
||||
const int cDim = 2;
|
||||
cv::gapi::KalmanParams kp;
|
||||
initKalmanParams(type, dDim, mDim, cDim, kp);
|
||||
|
||||
// Generating input
|
||||
std::vector<bool> haveMeasurements;
|
||||
std::vector<cv::Mat> measurements, ctrls;
|
||||
generateInputKalman(mDim, cDim, type, testNumMeasurements, receiveRandMeas,
|
||||
haveMeasurements, measurements, ctrls);
|
||||
|
||||
// G-API graph declaration
|
||||
cv::GMat m, ctrl;
|
||||
cv::GOpaque<bool> have_m;
|
||||
cv::GMat out = cv::gapi::KalmanFilter(m, have_m, ctrl, kp);
|
||||
cv::GComputation c(cv::GIn(m, have_m, ctrl), cv::GOut(out));
|
||||
auto cc = c.compile(
|
||||
cv::descr_of(cv::gin(cv::Mat(mDim, 1, type), true, cv::Mat(cDim, 1, type))),
|
||||
std::move(compileArgs));
|
||||
|
||||
cv::Mat gapiKState(dDim, 1, type);
|
||||
TEST_CYCLE()
|
||||
{
|
||||
cc.prepareForNewStream();
|
||||
for (size_t i = 0; i < testNumMeasurements; i++)
|
||||
{
|
||||
bool hvMeas = haveMeasurements[i];
|
||||
cc(cv::gin(measurements[i], hvMeas, ctrls[i]), cv::gout(gapiKState));
|
||||
}
|
||||
}
|
||||
|
||||
// OpenCV reference KalmanFilter initialization
|
||||
cv::KalmanFilter ocvKalman(dDim, mDim, cDim, type);
|
||||
initKalmanFilter(kp, true, ocvKalman);
|
||||
|
||||
cv::Mat ocvKState(dDim, 1, type);
|
||||
for (size_t i = 0; i < testNumMeasurements; i++)
|
||||
{
|
||||
ocvKState = ocvKalman.predict(ctrls[i]);
|
||||
if (haveMeasurements[i])
|
||||
ocvKState = ocvKalman.correct(measurements[i]);
|
||||
}
|
||||
// Validation
|
||||
EXPECT_TRUE(AbsExact().to_compare_f()(gapiKState, ocvKState));
|
||||
SANITY_CHECK_NOTHING();
|
||||
}
|
||||
|
||||
PERF_TEST_P_(KalmanFilterNoControlPerfTest, TestPerformance)
|
||||
{
|
||||
MatType2 type = -1;
|
||||
int dDim = -1, mDim = -1;
|
||||
size_t testNumMeasurements = 0;
|
||||
bool receiveRandMeas = true;
|
||||
cv::GCompileArgs compileArgs;
|
||||
std::tie(type, dDim, mDim, testNumMeasurements, receiveRandMeas, compileArgs) = GetParam();
|
||||
|
||||
const int cDim = 0;
|
||||
cv::gapi::KalmanParams kp;
|
||||
initKalmanParams(type, dDim, mDim, cDim, kp);
|
||||
|
||||
// Generating input
|
||||
std::vector<bool> haveMeasurements;
|
||||
std::vector<cv::Mat> measurements;
|
||||
generateInputKalman(mDim, type, testNumMeasurements, receiveRandMeas,
|
||||
haveMeasurements, measurements);
|
||||
|
||||
// G-API graph declaration
|
||||
cv::GMat m;
|
||||
cv::GOpaque<bool> have_m;
|
||||
cv::GMat out = cv::gapi::KalmanFilter(m, have_m, kp);
|
||||
cv::GComputation c(cv::GIn(m, have_m), cv::GOut(out));
|
||||
auto cc = c.compile(cv::descr_of(cv::gin(cv::Mat(mDim, 1, type), true)),
|
||||
std::move(compileArgs));
|
||||
|
||||
cv::Mat gapiKState(dDim, 1, type);
|
||||
TEST_CYCLE()
|
||||
{
|
||||
cc.prepareForNewStream();
|
||||
for (size_t i = 0; i < testNumMeasurements; i++)
|
||||
{
|
||||
bool hvMeas = haveMeasurements[i];
|
||||
cc(cv::gin(measurements[i], hvMeas), cv::gout(gapiKState));
|
||||
}
|
||||
}
|
||||
|
||||
// OpenCV reference KalmanFilter declaration
|
||||
cv::KalmanFilter ocvKalman(dDim, mDim, cDim, type);
|
||||
initKalmanFilter(kp, false, ocvKalman);
|
||||
|
||||
cv::Mat ocvKState(dDim, 1, type);
|
||||
for (size_t i = 0; i < testNumMeasurements; i++)
|
||||
{
|
||||
ocvKState = ocvKalman.predict();
|
||||
if (haveMeasurements[i])
|
||||
ocvKState = ocvKalman.correct(measurements[i]);
|
||||
}
|
||||
// Validation
|
||||
EXPECT_TRUE(AbsExact().to_compare_f()(gapiKState, ocvKState));
|
||||
SANITY_CHECK_NOTHING();
|
||||
}
|
||||
#endif // HAVE_OPENCV_VIDEO
|
||||
|
||||
} // opencv_test
|
||||
|
||||
@ -111,4 +111,22 @@ INSTANTIATE_TEST_CASE_MACRO_P(WITH_VIDEO(BackgroundSubtractorPerfTestCPU),
|
||||
Values(5),
|
||||
Values(cv::compile_args(VIDEO_CPU)),
|
||||
Values(AbsExact().to_compare_obj())));
|
||||
|
||||
INSTANTIATE_TEST_CASE_MACRO_P(WITH_VIDEO(KalmanFilterControlPerfTestCPU),
|
||||
KalmanFilterControlPerfTest,
|
||||
Combine(Values(CV_32FC1, CV_64FC1),
|
||||
Values(2, 5),
|
||||
Values(2, 5),
|
||||
Values(5),
|
||||
testing::Bool(),
|
||||
Values(cv::compile_args(VIDEO_CPU))));
|
||||
|
||||
INSTANTIATE_TEST_CASE_MACRO_P(WITH_VIDEO(KalmanFilterNoControlPerfTestCPU),
|
||||
KalmanFilterNoControlPerfTest,
|
||||
Combine(Values(CV_32FC1, CV_64FC1),
|
||||
Values(2, 5),
|
||||
Values(2, 5),
|
||||
Values(5),
|
||||
testing::Bool(),
|
||||
Values(cv::compile_args(VIDEO_CPU))));
|
||||
} // opencv_test
|
||||
|
||||
@ -117,15 +117,15 @@ GAPI_OCV_KERNEL_ST(GCPUKalmanFilter, cv::gapi::video::GKalmanFilter, cv::KalmanF
|
||||
kfParams.controlMatrix.cols, kfParams.transitionMatrix.type());
|
||||
|
||||
// initial state
|
||||
state->statePost = kfParams.state;
|
||||
state->errorCovPost = kfParams.errorCov;
|
||||
kfParams.state.copyTo(state->statePost);
|
||||
kfParams.errorCov.copyTo(state->errorCovPost);
|
||||
|
||||
// dynamic system initialization
|
||||
state->controlMatrix = kfParams.controlMatrix;
|
||||
state->measurementMatrix = kfParams.measurementMatrix;
|
||||
state->transitionMatrix = kfParams.transitionMatrix;
|
||||
state->processNoiseCov = kfParams.processNoiseCov;
|
||||
state->measurementNoiseCov = kfParams.measurementNoiseCov;
|
||||
kfParams.controlMatrix.copyTo(state->controlMatrix);
|
||||
kfParams.measurementMatrix.copyTo(state->measurementMatrix);
|
||||
kfParams.transitionMatrix.copyTo(state->transitionMatrix);
|
||||
kfParams.processNoiseCov.copyTo(state->processNoiseCov);
|
||||
kfParams.measurementNoiseCov.copyTo(state->measurementNoiseCov);
|
||||
}
|
||||
|
||||
static void run(const cv::Mat& measurements, bool haveMeasurement,
|
||||
@ -151,14 +151,14 @@ GAPI_OCV_KERNEL_ST(GCPUKalmanFilterNoControl, cv::gapi::video::GKalmanFilterNoCo
|
||||
state = std::make_shared<cv::KalmanFilter>(kfParams.transitionMatrix.rows, kfParams.measurementMatrix.rows,
|
||||
0, kfParams.transitionMatrix.type());
|
||||
// initial state
|
||||
state->statePost = kfParams.state;
|
||||
state->errorCovPost = kfParams.errorCov;
|
||||
kfParams.state.copyTo(state->statePost);
|
||||
kfParams.errorCov.copyTo(state->errorCovPost);
|
||||
|
||||
// dynamic system initialization
|
||||
state->measurementMatrix = kfParams.measurementMatrix;
|
||||
state->transitionMatrix = kfParams.transitionMatrix;
|
||||
state->processNoiseCov = kfParams.processNoiseCov;
|
||||
state->measurementNoiseCov = kfParams.measurementNoiseCov;
|
||||
kfParams.measurementMatrix.copyTo(state->measurementMatrix);
|
||||
kfParams.transitionMatrix.copyTo(state->transitionMatrix);
|
||||
kfParams.processNoiseCov.copyTo(state->processNoiseCov);
|
||||
kfParams.measurementNoiseCov.copyTo(state->measurementNoiseCov);
|
||||
}
|
||||
|
||||
static void run(const cv::Mat& measurements, bool haveMeasurement,
|
||||
|
||||
@ -397,6 +397,37 @@ inline void testBackgroundSubtractorStreaming(cv::GStreamingCompiled& gapiBackSu
|
||||
EXPECT_FALSE(gapiBackSub.running());
|
||||
}
|
||||
|
||||
inline void initKalmanParams(const int type, const int dDim, const int mDim, const int cDim,
|
||||
cv::gapi::KalmanParams& kp)
|
||||
{
|
||||
kp.state = Mat::zeros(dDim, 1, type);
|
||||
cv::randu(kp.state, Scalar::all(0), Scalar::all(0.1));
|
||||
kp.errorCov = Mat::eye(dDim, dDim, type);
|
||||
|
||||
kp.transitionMatrix = Mat::ones(dDim, dDim, type) * 2;
|
||||
kp.processNoiseCov = Mat::eye(dDim, dDim, type) * (1e-5);
|
||||
kp.measurementMatrix = Mat::eye(mDim, dDim, type) * 2;
|
||||
kp.measurementNoiseCov = Mat::eye(mDim, mDim, type) * (1e-5);
|
||||
|
||||
if (cDim > 0)
|
||||
kp.controlMatrix = Mat::eye(dDim, cDim, type) * (1e-3);
|
||||
}
|
||||
|
||||
inline void initKalmanFilter(const cv::gapi::KalmanParams& kp, const bool control,
|
||||
cv::KalmanFilter& ocvKalman)
|
||||
{
|
||||
kp.state.copyTo(ocvKalman.statePost);
|
||||
kp.errorCov.copyTo(ocvKalman.errorCovPost);
|
||||
|
||||
kp.transitionMatrix.copyTo(ocvKalman.transitionMatrix);
|
||||
kp.measurementMatrix.copyTo(ocvKalman.measurementMatrix);
|
||||
kp.measurementNoiseCov.copyTo(ocvKalman.measurementNoiseCov);
|
||||
kp.processNoiseCov.copyTo(ocvKalman.processNoiseCov);
|
||||
|
||||
if (control)
|
||||
kp.controlMatrix.copyTo(ocvKalman.controlMatrix);
|
||||
}
|
||||
|
||||
#else // !HAVE_OPENCV_VIDEO
|
||||
|
||||
inline cv::GComputation runOCVnGAPIBuildOptFlowPyramid(TestFunctional&,
|
||||
|
||||
@ -132,49 +132,19 @@ TEST_P(BackgroundSubtractorTest, AccuracyTest)
|
||||
testBackgroundSubtractorStreaming(gapiBackSub, pOCVBackSub, 1, 1, learningRate, testNumFrames);
|
||||
}
|
||||
|
||||
inline void initKalmanParams(cv::gapi::KalmanParams& kp, int type, int dDim, int mDim, int cDim)
|
||||
{
|
||||
kp.state = Mat::zeros(dDim, 1, type);
|
||||
cv::randu(kp.state, Scalar::all(0), Scalar::all(0.1));
|
||||
kp.errorCov = Mat::eye(dDim, dDim, type);
|
||||
|
||||
kp.transitionMatrix = Mat::ones(dDim, dDim, type) * 2;
|
||||
kp.processNoiseCov = Mat::eye(dDim, dDim, type)*(1e-5);
|
||||
kp.measurementMatrix = Mat::eye(mDim, dDim, type) * 2;
|
||||
kp.measurementNoiseCov = Mat::eye(mDim, mDim, type)*(1e-5);
|
||||
|
||||
if (cDim > 0)
|
||||
kp.controlMatrix = Mat::eye(dDim, cDim, type)* (1e-3);
|
||||
}
|
||||
|
||||
inline void initKalmanFilter(const cv::gapi::KalmanParams& kp,
|
||||
cv::KalmanFilter& ocvKalman, bool control)
|
||||
{
|
||||
kp.state.copyTo(ocvKalman.statePost);
|
||||
kp.errorCov.copyTo(ocvKalman.errorCovPost);
|
||||
|
||||
kp.transitionMatrix.copyTo(ocvKalman.transitionMatrix);
|
||||
kp.measurementMatrix.copyTo(ocvKalman.measurementMatrix);
|
||||
kp.measurementNoiseCov.copyTo(ocvKalman.measurementNoiseCov);
|
||||
kp.processNoiseCov.copyTo(ocvKalman.processNoiseCov);
|
||||
|
||||
if (control)
|
||||
kp.controlMatrix.copyTo(ocvKalman.controlMatrix);
|
||||
}
|
||||
|
||||
TEST_P(KalmanFilterTest, AccuracyTest)
|
||||
{
|
||||
cv::gapi::KalmanParams kp;
|
||||
initKalmanParams(kp, type, dDim, mDim, cDim);
|
||||
initKalmanParams(type, dDim, mDim, cDim, kp);
|
||||
|
||||
// OpenCV reference KalmanFilter initialization
|
||||
cv::KalmanFilter ocvKalman(dDim, mDim, cDim, type);
|
||||
initKalmanFilter(kp, ocvKalman, true);
|
||||
initKalmanFilter(kp, true, ocvKalman);
|
||||
|
||||
//measurement vector
|
||||
// measurement vector
|
||||
cv::Mat measure_vec(mDim, 1, type);
|
||||
|
||||
//control vector
|
||||
// control vector
|
||||
cv::Mat ctrl_vec = Mat::zeros(cDim > 0 ? cDim : 2, 1, type);
|
||||
|
||||
// G-API Kalman's output state
|
||||
@ -193,7 +163,7 @@ TEST_P(KalmanFilterTest, AccuracyTest)
|
||||
|
||||
for (int i = 0; i < numIter; i++)
|
||||
{
|
||||
haveMeasure = (rng(2u) == 1) ? true : false; // returns 0 or 1 - whether we have measurement at this iteration or not
|
||||
haveMeasure = (rng(2u) == 1); // returns 0 or 1 - whether we have measurement at this iteration or not
|
||||
|
||||
if (haveMeasure)
|
||||
cv::randu(measure_vec, Scalar::all(-1), Scalar::all(1));
|
||||
@ -210,22 +180,20 @@ TEST_P(KalmanFilterTest, AccuracyTest)
|
||||
|
||||
// Comparison //////////////////////////////////////////////////////////////
|
||||
{
|
||||
double diff = 0;
|
||||
vector<int> idx;
|
||||
EXPECT_TRUE(cmpEps(gapiKState, ocvKState, &diff, 1.0, &idx, false) >= 0);
|
||||
EXPECT_TRUE(AbsExact().to_compare_f()(gapiKState, ocvKState));
|
||||
}
|
||||
}
|
||||
|
||||
TEST_P(KalmanFilterNoControlTest, AccuracyTest)
|
||||
{
|
||||
cv::gapi::KalmanParams kp;
|
||||
initKalmanParams(kp, type, dDim, mDim, 0);
|
||||
initKalmanParams(type, dDim, mDim, 0, kp);
|
||||
|
||||
// OpenCV reference KalmanFilter initialization
|
||||
cv::KalmanFilter ocvKalman(dDim, mDim, 0, type);
|
||||
initKalmanFilter(kp, ocvKalman, false);
|
||||
initKalmanFilter(kp, false, ocvKalman);
|
||||
|
||||
//measurement vector
|
||||
// measurement vector
|
||||
cv::Mat measure_vec(mDim, 1, type);
|
||||
|
||||
// G-API Kalman's output state
|
||||
@ -244,7 +212,7 @@ TEST_P(KalmanFilterNoControlTest, AccuracyTest)
|
||||
|
||||
for (int i = 0; i < numIter; i++)
|
||||
{
|
||||
haveMeasure = (rng(2u) == 1) ? true : false; // returns 0 or 1 - whether we have measurement at this iteration or not
|
||||
haveMeasure = (rng(2u) == 1); // returns 0 or 1 - whether we have measurement at this iteration or not
|
||||
|
||||
if (haveMeasure)
|
||||
cv::randu(measure_vec, Scalar::all(-1), Scalar::all(1));
|
||||
@ -260,9 +228,7 @@ TEST_P(KalmanFilterNoControlTest, AccuracyTest)
|
||||
|
||||
// Comparison //////////////////////////////////////////////////////////////
|
||||
{
|
||||
double diff = 0;
|
||||
vector<int> idx;
|
||||
EXPECT_TRUE(cmpEps(gapiKState, ocvKState, &diff, 1.0, &idx, false) >= 0);
|
||||
EXPECT_TRUE(AbsExact().to_compare_f()(gapiKState, ocvKState));
|
||||
}
|
||||
}
|
||||
|
||||
@ -270,11 +236,8 @@ TEST_P(KalmanFilterCircleSampleTest, AccuracyTest)
|
||||
{
|
||||
// auxiliary variables
|
||||
cv::Mat processNoise(2, 1, type);
|
||||
// For comparison
|
||||
double diff = 0;
|
||||
vector<int> idx;
|
||||
|
||||
// Input mesurement
|
||||
// Input measurement
|
||||
cv::Mat measurement = Mat::zeros(1, 1, type);
|
||||
// Angle and it's delta(phi, delta_phi)
|
||||
cv::Mat state(2, 1, type);
|
||||
@ -303,7 +266,7 @@ TEST_P(KalmanFilterCircleSampleTest, AccuracyTest)
|
||||
|
||||
// OCV Kalman initialization
|
||||
cv::KalmanFilter KF(2, 1, 0);
|
||||
initKalmanFilter(kp, KF, false);
|
||||
initKalmanFilter(kp, false, KF);
|
||||
|
||||
cv::randn(state, Scalar::all(0), Scalar::all(0.1));
|
||||
|
||||
@ -334,14 +297,14 @@ TEST_P(KalmanFilterCircleSampleTest, AccuracyTest)
|
||||
haveMeasure = true;
|
||||
ocvCorrState = KF.correct(measurement);
|
||||
comp.apply(cv::gin(measurement, haveMeasure), cv::gout(gapiState));
|
||||
EXPECT_TRUE(cmpEps(gapiState, ocvCorrState, &diff, 1.0, &idx, false) >= 0);
|
||||
EXPECT_TRUE(AbsExact().to_compare_f()(gapiState, ocvCorrState));
|
||||
}
|
||||
else
|
||||
{
|
||||
// Get GAPI Prediction
|
||||
haveMeasure = false;
|
||||
comp.apply(cv::gin(measurement, haveMeasure), cv::gout(gapiState));
|
||||
EXPECT_TRUE(cmpEps(gapiState, ocvPreState, &diff, 1.0, &idx, false) >= 0);
|
||||
EXPECT_TRUE(AbsExact().to_compare_f()(gapiState, ocvPreState));
|
||||
}
|
||||
|
||||
GAPI_DbgAssert(cv::norm(kp.processNoiseCov, KF.processNoiseCov, cv::NORM_INF) == 0);
|
||||
|
||||
Loading…
Reference in New Issue
Block a user