From f59c654bfcb2c33037516b4b891450c567da0970 Mon Sep 17 00:00:00 2001 From: 4ekmah Date: Fri, 29 May 2026 11:18:20 +0300 Subject: [PATCH] Merge pull request #29148 from 4ekmah:eccms_fixpython Fixing python wrapper around ECCParameters to include itersPerLevel #29148 ### Pull Request Readiness Checklist See details at https://github.com/opencv/opencv/wiki/How_to_contribute#making-a-good-pull-request - [x] I agree to contribute to the project under Apache 2 License. - [x] To the best of my knowledge, the proposed patch is not based on a code under GPL or another license that is incompatible with OpenCV - [x] The PR is proposed to the proper branch --- modules/python/test/test_eccms.py | 47 +++++++++++++++++++ .../video/include/opencv2/video/tracking.hpp | 6 +-- modules/video/src/eccms.cpp | 3 ++ 3 files changed, 53 insertions(+), 3 deletions(-) create mode 100644 modules/python/test/test_eccms.py diff --git a/modules/python/test/test_eccms.py b/modules/python/test/test_eccms.py new file mode 100644 index 0000000000..6a3726f7cd --- /dev/null +++ b/modules/python/test/test_eccms.py @@ -0,0 +1,47 @@ +#!/usr/bin/env python + +''' +ECC multiscale alignment test +''' + +# Python 2/3 compatibility +from __future__ import print_function + +import numpy as np +import cv2 as cv +import inspect +import math + +from tests_common import NewOpenCVTests + +class eccms_test(NewOpenCVTests): + def test_eccms(self): + expected_res = np.array([ + [1.0225, 0.0606, -28.6452], + [-0.0475, 1.0314, 11.819], + [8.21e-06, -3.65e-07, 1.0] + ], dtype=np.float32) + + largeGray0 = self.get_sample('cv/shared/halmosh0.jpg', cv.IMREAD_GRAYSCALE) + largeGray1 = self.get_sample('cv/shared/halmosh2.jpg', cv.IMREAD_GRAYSCALE) + roiMask0 = self.get_sample('cv/shared/halmosh0mask.png', cv.IMREAD_GRAYSCALE) + roiMask1 = self.get_sample('cv/shared/halmosh2mask.png', cv.IMREAD_GRAYSCALE) + + if largeGray0 is None or largeGray1 is None or roiMask0 is None or roiMask1 is None: + self.assertEqual(0, 1, 'Missing test data') + + found = np.eye(3, 3, dtype=np.float32) + n_iters = 23 + termination_eps = 1e-6 + params = cv.ECCParameters() + params.criteria = (cv.TERM_CRITERIA_COUNT + cv.TERM_CRITERIA_EPS, n_iters, termination_eps) + params.motionType = cv.MOTION_HOMOGRAPHY + params.nlevels = 5 + params.itersPerLevel = [5, 10, 300, 300, 1000] + + _, found = cv.findTransformECCMultiScale(largeGray0,largeGray1, found, params, roiMask0, roiMask1) + + self.assertLess(cv.norm(found - expected_res, cv.NORM_L1), 0.1) + +if __name__ == '__main__': + NewOpenCVTests.bootstrap() diff --git a/modules/video/include/opencv2/video/tracking.hpp b/modules/video/include/opencv2/video/tracking.hpp index f62660494c..790f7442cf 100644 --- a/modules/video/include/opencv2/video/tracking.hpp +++ b/modules/video/include/opencv2/video/tracking.hpp @@ -444,10 +444,10 @@ Affects accuracy, especially when motionType == MOTION_TRANSLATION. (DEFAULT: IN */ struct CV_EXPORTS_W_SIMPLE ECCParameters { - CV_WRAP ECCParameters() {} + CV_WRAP ECCParameters(); CV_PROP_RW int motionType = MOTION_AFFINE; - CV_PROP_RW cv::TermCriteria criteria = TermCriteria(TermCriteria::COUNT + TermCriteria::EPS, 50, 1e-6); - CV_PROP_RW std::vector itersPerLevel = std::vector(); + CV_PROP_RW cv::TermCriteria criteria; + CV_PROP_RW std::vector itersPerLevel; CV_PROP_RW int gaussFiltSize = 5; CV_PROP_RW int nlevels = 4; CV_PROP_RW int interpolation = INTER_LINEAR; diff --git a/modules/video/src/eccms.cpp b/modules/video/src/eccms.cpp index 963763d5d3..97557bde89 100644 --- a/modules/video/src/eccms.cpp +++ b/modules/video/src/eccms.cpp @@ -9,6 +9,9 @@ \****************************************************************************************/ namespace cv { +ECCParameters::ECCParameters() : criteria(TermCriteria::COUNT + TermCriteria::EPS, 50, 1e-6) +{} + typedef std::vector MatPyramid; template struct MotionTraits {};