Merge pull request #19712 from OrestChura:oc/Kalm_ptest
authorOrest Chura <orest.chura@intel.com>
Fri, 26 Mar 2021 09:41:54 +0000 (12:41 +0300)
committerGitHub <noreply@github.com>
Fri, 26 Mar 2021 09:41:54 +0000 (09:41 +0000)
[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

modules/gapi/perf/common/gapi_video_perf_tests.hpp
modules/gapi/perf/common/gapi_video_perf_tests_inl.hpp
modules/gapi/perf/cpu/gapi_video_perf_tests_cpu.cpp
modules/gapi/src/backends/cpu/gcpuvideo.cpp
modules/gapi/test/common/gapi_video_tests_common.hpp
modules/gapi/test/common/gapi_video_tests_inl.hpp

index 59e1555df090c9f0d872c79a089a0dc34deeb4a3..a4796fab895f6287a595503ac4b44aa8de957fe2 100644 (file)
@@ -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
index 68a96b04425e13b0735521bf4d23245534e13027..700d2f6e7ed901b4dfa8d70c96216f8d2f29c452 100644 (file)
@@ -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
index 9a1a47adca4e59be09d4760713ec47f33f17dc42..0da776a3ffae3ea82e0e14bf4a01c1e9dc0b0653 100644 (file)
@@ -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
index 075b5f9ad50b82dcc856c91c3766840fd0d47d2b..cf64c240d07cbceb713dbc352f123174ff27458d 100644 (file)
@@ -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,
index d6a99ce8aa4a5342ffe036171fdc666b72e5db6c..f3e7e5aa6c947083dfec8fc17ef591c48adb841d 100644 (file)
@@ -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&,
index 75fd50b208973cc7ffe7426cfe0b00005ec1a28b..7827680561d235d5387ef9191506d553a1abdbb0 100644 (file)
@@ -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);