From 423bc515e5387a255105cf402c7b547d0703e105 Mon Sep 17 00:00:00 2001 From: Alexander Smorkalov Date: Fri, 9 Dec 2022 15:06:08 +0300 Subject: [PATCH 1/8] Integer underflow fix for morphologyEx in Carotene (arm). --- 3rdparty/carotene/hal/tegra_hal.hpp | 4 ++-- modules/imgproc/test/test_filter.cpp | 13 +++++++++++++ 2 files changed, 15 insertions(+), 2 deletions(-) diff --git a/3rdparty/carotene/hal/tegra_hal.hpp b/3rdparty/carotene/hal/tegra_hal.hpp index c2ae0c0d87..ce8fa90982 100644 --- a/3rdparty/carotene/hal/tegra_hal.hpp +++ b/3rdparty/carotene/hal/tegra_hal.hpp @@ -1296,13 +1296,13 @@ struct MorphCtx CAROTENE_NS::BORDER_MODE border; uchar borderValues[4]; }; -inline int TEGRA_MORPHINIT(cvhalFilter2D **context, int operation, int src_type, int dst_type, int, int, +inline int TEGRA_MORPHINIT(cvhalFilter2D **context, int operation, int src_type, int dst_type, int width, int height, int kernel_type, uchar *kernel_data, size_t kernel_step, int kernel_width, int kernel_height, int anchor_x, int anchor_y, int borderType, const double borderValue[4], int iterations, bool allowSubmatrix, bool allowInplace) { if(!context || !kernel_data || src_type != dst_type || CV_MAT_DEPTH(src_type) != CV_8U || src_type < 0 || (src_type >> CV_CN_SHIFT) > 3 || - + width < kernel_width || height < kernel_height || allowSubmatrix || allowInplace || iterations != 1 || !CAROTENE_NS::isSupportedConfiguration()) return CV_HAL_ERROR_NOT_IMPLEMENTED; diff --git a/modules/imgproc/test/test_filter.cpp b/modules/imgproc/test/test_filter.cpp index 6de6cf4f87..b0b4fdf421 100644 --- a/modules/imgproc/test/test_filter.cpp +++ b/modules/imgproc/test/test_filter.cpp @@ -2366,5 +2366,18 @@ TEST(Imgproc_GaussianBlur, regression_11303) EXPECT_LE(cv::norm(src, dst, NORM_L2), 1e-3); } +TEST(Imgproc, morphologyEx_small_input_22893) +{ + char input_data[] = {1, 2, 3, 4}; + char gold_data[] = {2, 3, 4, 4}; + cv::Mat img(1, 4, CV_8UC1, input_data); + cv::Mat gold(1, 4, CV_8UC1, gold_data); + + cv::Mat kernel = getStructuringElement(cv::MORPH_RECT, cv::Size(4,4)); + cv::Mat result; + morphologyEx(img, result, cv::MORPH_DILATE, kernel); + + ASSERT_EQ(0, cvtest::norm(result, gold, NORM_INF)); +} }} // namespace From 727feda935952e118519f193fc79d7f9aa12d632 Mon Sep 17 00:00:00 2001 From: Vadim Levin Date: Mon, 12 Dec 2022 10:41:39 +0300 Subject: [PATCH 2/8] fix: AVFoundation inconsistent camera indices --- modules/videoio/src/cap_avfoundation_mac.mm | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/modules/videoio/src/cap_avfoundation_mac.mm b/modules/videoio/src/cap_avfoundation_mac.mm index 3049b4ba6e..504bdb9ce9 100644 --- a/modules/videoio/src/cap_avfoundation_mac.mm +++ b/modules/videoio/src/cap_avfoundation_mac.mm @@ -376,6 +376,15 @@ int CvCaptureCAM::startCaptureDevice(int cameraNum) { return 0; } + // Preserve devices ordering on the system + // see AVCaptureDevice::uniqueID property documentation for more info + devices = [devices + sortedArrayUsingComparator:^NSComparisonResult(AVCaptureDevice *d1, + AVCaptureDevice *d2) { + return [d1.uniqueID compare:d2.uniqueID]; + } + ]; + mCaptureDevice = devices[cameraNum]; if ( ! mCaptureDevice ) { From 253a4c113e207748843d7aa4c8d68c8efa444f54 Mon Sep 17 00:00:00 2001 From: Vadim Levin Date: Tue, 13 Dec 2022 19:14:52 +0300 Subject: [PATCH 3/8] fix: remove function duplicates in test_misc.py --- modules/python/test/test_misc.py | 38 +++++++++----------------------- 1 file changed, 10 insertions(+), 28 deletions(-) diff --git a/modules/python/test/test_misc.py b/modules/python/test/test_misc.py index ec56585ace..b5c8c936d4 100644 --- a/modules/python/test/test_misc.py +++ b/modules/python/test/test_misc.py @@ -631,33 +631,12 @@ class Arguments(NewOpenCVTests): def test_inner_class_has_global_alias(self): self.assertTrue(hasattr(cv.SimpleBlobDetector, "Params"), msg="Class is not registered as inner class") - self.assertEqual(cv.SimpleBlobDetector.Params, cv.SimpleBlobDetector_Params, - msg="Inner class and class in global module don't refer " - "to the same type") self.assertTrue(hasattr(cv, "SimpleBlobDetector_Params"), msg="Inner class doesn't have alias in the global module") - - def test_class_from_submodule_has_global_alias(self): - self.assertTrue(hasattr(cv.ml, "Boost"), - msg="Class is not registered in the submodule") - self.assertTrue(hasattr(cv, "ml_Boost"), - msg="Class from submodule doesn't have alias in the " - "global module") - self.assertEqual(cv.ml.Boost, cv.ml_Boost, - msg="Classes from submodules and global module don't refer " + self.assertEqual(cv.SimpleBlobDetector.Params, cv.SimpleBlobDetector_Params, + msg="Inner class and class in global module don't refer " "to the same type") - def test_inner_class_has_global_alias(self): - self.assertTrue(hasattr(cv.SimpleBlobDetector, "Params"), - msg="Class is not registered as inner class") - self.assertTrue(hasattr(cv, "SimpleBlobDetector_Params"), - msg="Inner class doesn't have alias in the global module") - self.assertEqual(cv.SimpleBlobDetector.Params, cv.SimpleBlobDetector_Params, - msg="Inner class and class in global module don't refer " - "to the same type") - self.assertTrue(hasattr(cv, "SimpleBlobDetector_Params"), - msg="Inner class doesn't have alias in the global module") - def test_export_class_with_different_name(self): self.assertTrue(hasattr(cv.utils.nested, "ExportClassName"), msg="Class with export alias is not registered in the submodule") @@ -677,7 +656,8 @@ class Arguments(NewOpenCVTests): def test_export_inner_class_of_class_exported_with_different_name(self): if not hasattr(cv.utils.nested, "ExportClassName"): - raise unittest.SkipTest("Outer class with export alias is not registered in the submodule") + raise unittest.SkipTest( + "Outer class with export alias is not registered in the submodule") self.assertTrue(hasattr(cv.utils.nested.ExportClassName, "Params"), msg="Inner class with export alias is not registered in " @@ -695,13 +675,15 @@ class Arguments(NewOpenCVTests): self.assertEqual( params.int_value, instance.getIntParam(), msg="Class initialized with wrong integer parameter. Expected: {}. Actual: {}".format( - params.int_value, instance.getIntParam() - )) + params.int_value, instance.getIntParam() + ) + ) self.assertEqual( params.float_value, instance.getFloatParam(), msg="Class initialized with wrong integer parameter. Expected: {}. Actual: {}".format( - params.float_value, instance.getFloatParam() - )) + params.float_value, instance.getFloatParam() + ) + ) class SamplesFindFile(NewOpenCVTests): From 3f5f09e730fef41e4f3c3b2dc059f6324d342c86 Mon Sep 17 00:00:00 2001 From: Vadim Levin Date: Tue, 13 Dec 2022 20:24:57 +0300 Subject: [PATCH 4/8] fix: add _ suffix to properties having reserved keyword names --- .../include/opencv2/core/bindings_utils.hpp | 11 +++++++++++ modules/python/src2/gen2.py | 15 +++++++++++---- modules/python/test/test_misc.py | 17 +++++++++++++++++ 3 files changed, 39 insertions(+), 4 deletions(-) diff --git a/modules/core/include/opencv2/core/bindings_utils.hpp b/modules/core/include/opencv2/core/bindings_utils.hpp index 6e825ec816..5de2f7022e 100644 --- a/modules/core/include/opencv2/core/bindings_utils.hpp +++ b/modules/core/include/opencv2/core/bindings_utils.hpp @@ -213,6 +213,17 @@ AsyncArray testAsyncException() return p.getArrayResult(); } +struct CV_EXPORTS_W_SIMPLE ClassWithKeywordProperties { + CV_PROP_RW int lambda; + CV_PROP int except; + + CV_WRAP explicit ClassWithKeywordProperties(int lambda_arg = 24, int except_arg = 42) + { + lambda = lambda_arg; + except = except_arg; + } +}; + namespace nested { CV_WRAP static inline bool testEchoBooleanFunction(bool flag) { return flag; diff --git a/modules/python/src2/gen2.py b/modules/python/src2/gen2.py index 1a9239c07f..14508761fb 100755 --- a/modules/python/src2/gen2.py +++ b/modules/python/src2/gen2.py @@ -169,10 +169,10 @@ static int pyopencv_${name}_set_${member}(pyopencv_${name}_t* p, PyObject *value gen_template_prop_init = Template(""" - {(char*)"${member}", (getter)pyopencv_${name}_get_${member}, NULL, (char*)"${member}", NULL},""") + {(char*)"${export_member_name}", (getter)pyopencv_${name}_get_${member}, NULL, (char*)"${export_member_name}", NULL},""") gen_template_rw_prop_init = Template(""" - {(char*)"${member}", (getter)pyopencv_${name}_get_${member}, (setter)pyopencv_${name}_set_${member}, (char*)"${member}", NULL},""") + {(char*)"${export_member_name}", (getter)pyopencv_${name}_get_${member}, (setter)pyopencv_${name}_set_${member}, (char*)"${export_member_name}", NULL},""") gen_template_overloaded_function_call = Template(""" { @@ -242,6 +242,13 @@ class ClassProp(object): if "/RW" in decl[3]: self.readonly = False + @property + def export_name(self): + if self.name in python_reserved_keywords: + return self.name + "_" + return self.name + + class ClassInfo(object): def __init__(self, name, decl=None, codegen=None): # Scope name can be a module or other class e.g. cv::SimpleBlobDetector::Params @@ -357,13 +364,13 @@ class ClassInfo(object): else: getset_code.write(gen_template_get_prop.substitute(name=self.name, member=pname, membertype=p.tp, access=access_op)) if p.readonly: - getset_inits.write(gen_template_prop_init.substitute(name=self.name, member=pname)) + getset_inits.write(gen_template_prop_init.substitute(name=self.name, member=pname, export_member_name=p.export_name)) else: if self.isalgorithm: getset_code.write(gen_template_set_prop_algo.substitute(name=self.name, cname=self.cname, member=pname, membertype=p.tp, access=access_op)) else: getset_code.write(gen_template_set_prop.substitute(name=self.name, member=pname, membertype=p.tp, access=access_op)) - getset_inits.write(gen_template_rw_prop_init.substitute(name=self.name, member=pname)) + getset_inits.write(gen_template_rw_prop_init.substitute(name=self.name, member=pname, export_member_name=p.export_name)) methods_code = StringIO() methods_inits = StringIO() diff --git a/modules/python/test/test_misc.py b/modules/python/test/test_misc.py index ec56585ace..71e7f41bb5 100644 --- a/modules/python/test/test_misc.py +++ b/modules/python/test/test_misc.py @@ -119,6 +119,23 @@ class Bindings(NewOpenCVTests): test_overload_resolution('rect with float coordinates', (4.5, 4, 2, 1)) test_overload_resolution('rect with wrong number of coordinates', (4, 4, 1)) + def test_properties_with_reserved_keywords_names_are_transformed(self): + obj = cv.utils.ClassWithKeywordProperties(except_arg=23) + self.assertTrue(hasattr(obj, "lambda_"), + msg="Class doesn't have RW property with converted name") + try: + obj.lambda_ = 32 + except Exception as e: + self.fail("Failed to set value to RW property. Error: {}".format(e)) + + self.assertTrue(hasattr(obj, "except_"), + msg="Class doesn't have readonly property with converted name") + self.assertEqual(obj.except_, 23, + msg="Can't access readonly property value") + with self.assertRaises(AttributeError): + obj.except_ = 32 + + class Arguments(NewOpenCVTests): From b7b08fa0c3e5fd4fb656217210f33d9809c8efc5 Mon Sep 17 00:00:00 2001 From: Vincent Rabaud Date: Thu, 15 Dec 2022 12:28:30 +0100 Subject: [PATCH 5/8] Fix slower CV_PAUSE on SkyLake and above. This is fixing https://github.com/opencv/opencv/issues/22852 --- modules/core/src/parallel_impl.cpp | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/modules/core/src/parallel_impl.cpp b/modules/core/src/parallel_impl.cpp index 1d9690b04c..087b41233b 100644 --- a/modules/core/src/parallel_impl.cpp +++ b/modules/core/src/parallel_impl.cpp @@ -52,11 +52,14 @@ DECLARE_CV_PAUSE #endif #ifndef CV_PAUSE # if defined __GNUC__ && (defined __i386__ || defined __x86_64__) +# include /* for __rdtsc */ # if !defined(__SSE2__) static inline void cv_non_sse_mm_pause() { __asm__ __volatile__ ("rep; nop"); } # define _mm_pause cv_non_sse_mm_pause # endif -# define CV_PAUSE(v) do { for (int __delay = (v); __delay > 0; --__delay) { _mm_pause(); } } while (0) +// 5 * v is meants for backward compatibility: with pre-Skylake CPUs, _mm_pause took 4 or 5 cycles. +// With post-Skylake CPUs, _mm_pause takes 140 cycles. +# define CV_PAUSE(v) do { const uint64_t __delay = 5 * v; uint64_t __init = __rdtsc(); do { _mm_pause(); } while ((__rdtsc() - __init) < __delay); } while (0) # elif defined __GNUC__ && defined __aarch64__ # define CV_PAUSE(v) do { for (int __delay = (v); __delay > 0; --__delay) { asm volatile("yield" ::: "memory"); } } while (0) # elif defined __GNUC__ && defined __arm__ From 6a8c5a1d27663a0d498c828216db391420d02817 Mon Sep 17 00:00:00 2001 From: Alexander Alekhin Date: Thu, 8 Dec 2022 23:37:39 +0000 Subject: [PATCH 6/8] python: resolve Ptr requirement issue --- modules/core/include/opencv2/core.hpp | 6 +++--- modules/core/src/algorithm.cpp | 10 +++++----- .../features2d/include/opencv2/features2d.hpp | 4 ++-- modules/python/src2/gen2.py | 20 +++++++++++++++++-- 4 files changed, 28 insertions(+), 12 deletions(-) diff --git a/modules/core/include/opencv2/core.hpp b/modules/core/include/opencv2/core.hpp index be0a3a0dc5..1223651a83 100644 --- a/modules/core/include/opencv2/core.hpp +++ b/modules/core/include/opencv2/core.hpp @@ -3095,12 +3095,12 @@ public: /** @brief Stores algorithm parameters in a file storage */ - virtual void write(FileStorage& fs) const { CV_UNUSED(fs); } + CV_WRAP virtual void write(FileStorage& fs) const { CV_UNUSED(fs); } - /** @brief simplified API for language bindings + /** * @overload */ - CV_WRAP void write(const Ptr& fs, const String& name = String()) const; + CV_WRAP void write(FileStorage& fs, const String& name) const; /** @brief Reads algorithm parameters from a file storage */ diff --git a/modules/core/src/algorithm.cpp b/modules/core/src/algorithm.cpp index 556f5a7328..7186585323 100644 --- a/modules/core/src/algorithm.cpp +++ b/modules/core/src/algorithm.cpp @@ -55,17 +55,17 @@ Algorithm::~Algorithm() CV_TRACE_FUNCTION(); } -void Algorithm::write(const Ptr& fs, const String& name) const +void Algorithm::write(FileStorage& fs, const String& name) const { CV_TRACE_FUNCTION(); if(name.empty()) { - write(*fs); + write(fs); return; } - *fs << name << "{"; - write(*fs); - *fs << "}"; + fs << name << "{"; + write(fs); + fs << "}"; } void Algorithm::save(const String& filename) const diff --git a/modules/features2d/include/opencv2/features2d.hpp b/modules/features2d/include/opencv2/features2d.hpp index bf193599e1..633cd5c579 100644 --- a/modules/features2d/include/opencv2/features2d.hpp +++ b/modules/features2d/include/opencv2/features2d.hpp @@ -212,7 +212,7 @@ public: CV_WRAP virtual String getDefaultName() const CV_OVERRIDE; // see corresponding cv::Algorithm method - CV_WRAP inline void write(const Ptr& fs, const String& name = String()) const { Algorithm::write(fs, name); } + CV_WRAP inline void write(FileStorage& fs, const String& name) const { Algorithm::write(fs, name); } }; /** Feature detectors in OpenCV have wrappers with a common interface that enables you to easily switch @@ -1101,7 +1101,7 @@ public: // see corresponding cv::Algorithm method - CV_WRAP inline void write(const Ptr& fs, const String& name = String()) const { Algorithm::write(fs, name); } + CV_WRAP inline void write(FileStorage& fs, const String& name) const { Algorithm::write(fs, name); } protected: /** diff --git a/modules/python/src2/gen2.py b/modules/python/src2/gen2.py index 1a9239c07f..b8be4da510 100755 --- a/modules/python/src2/gen2.py +++ b/modules/python/src2/gen2.py @@ -209,7 +209,8 @@ simple_argtype_mapping = { "int": ArgTypeInfo("int", FormatStrings.int, "0", True), "float": ArgTypeInfo("float", FormatStrings.float, "0.f", True), "double": ArgTypeInfo("double", FormatStrings.double, "0", True), - "c_string": ArgTypeInfo("char*", FormatStrings.string, '(char*)""') + "c_string": ArgTypeInfo("char*", FormatStrings.string, '(char*)""'), + "UMat": ArgTypeInfo("UMat", FormatStrings.object, 'UMat()', True), # FIXIT: switch to CV_EXPORTS_W_SIMPLE as UMat is already a some kind of smart pointer } # Set of reserved keywords for Python. Can be acquired via the following call @@ -422,6 +423,7 @@ class ArgInfo(object): self.name += "_" self.defval = arg_tuple[2] self.isarray = False + self.is_smart_ptr = self.tp.startswith('Ptr<') # FIXIT: handle through modifiers - need to modify parser self.arraylen = 0 self.arraycvt = None self.inputarg = True @@ -713,7 +715,21 @@ class FuncInfo(object): if any(tp in codegen.enums.keys() for tp in tp_candidates): defval0 = "static_cast<%s>(%d)" % (a.tp, 0) - arg_type_info = simple_argtype_mapping.get(tp, ArgTypeInfo(tp, FormatStrings.object, defval0, True)) + if tp in simple_argtype_mapping: + arg_type_info = simple_argtype_mapping[tp] + else: + if tp in all_classes: + tp_classinfo = all_classes[tp] + cname_of_value = tp_classinfo.cname if tp_classinfo.issimple else "Ptr<{}>".format(tp_classinfo.cname) + arg_type_info = ArgTypeInfo(cname_of_value, FormatStrings.object, defval0, True) + assert not (a.is_smart_ptr and tp_classinfo.issimple), "Can't pass 'simple' type as Ptr<>" + if not a.is_smart_ptr and not tp_classinfo.issimple: + assert amp == '' + amp = '*' + else: + # FIXIT: Ptr_ / vector_ / enums / nested types + arg_type_info = ArgTypeInfo(tp, FormatStrings.object, defval0, True) + parse_name = a.name if a.py_inputarg: if arg_type_info.strict_conversion: From 6e3700593f46549206e52fa0659774c92e42ab13 Mon Sep 17 00:00:00 2001 From: Alexander Alekhin Date: Fri, 9 Dec 2022 21:05:17 +0000 Subject: [PATCH 7/8] compatibility: keep Ptr stubs till OpenCV 5.0 --- modules/core/include/opencv2/core.hpp | 4 ++++ modules/core/src/algorithm.cpp | 8 ++++++++ modules/features2d/include/opencv2/features2d.hpp | 6 ++++++ 3 files changed, 18 insertions(+) diff --git a/modules/core/include/opencv2/core.hpp b/modules/core/include/opencv2/core.hpp index 1223651a83..0445be1753 100644 --- a/modules/core/include/opencv2/core.hpp +++ b/modules/core/include/opencv2/core.hpp @@ -3101,6 +3101,10 @@ public: * @overload */ CV_WRAP void write(FileStorage& fs, const String& name) const; +#if CV_VERSION_MAJOR < 5 + /** @deprecated */ + void write(const Ptr& fs, const String& name = String()) const; +#endif /** @brief Reads algorithm parameters from a file storage */ diff --git a/modules/core/src/algorithm.cpp b/modules/core/src/algorithm.cpp index 7186585323..798df39638 100644 --- a/modules/core/src/algorithm.cpp +++ b/modules/core/src/algorithm.cpp @@ -68,6 +68,14 @@ void Algorithm::write(FileStorage& fs, const String& name) const fs << "}"; } +#if CV_VERSION_MAJOR < 5 +void Algorithm::write(const Ptr& fs, const String& name) const +{ + CV_Assert(fs); + write(*fs, name); +} +#endif + void Algorithm::save(const String& filename) const { CV_TRACE_FUNCTION(); diff --git a/modules/features2d/include/opencv2/features2d.hpp b/modules/features2d/include/opencv2/features2d.hpp index 633cd5c579..401fe6135c 100644 --- a/modules/features2d/include/opencv2/features2d.hpp +++ b/modules/features2d/include/opencv2/features2d.hpp @@ -213,6 +213,9 @@ public: // see corresponding cv::Algorithm method CV_WRAP inline void write(FileStorage& fs, const String& name) const { Algorithm::write(fs, name); } +#if CV_VERSION_MAJOR < 5 + inline void write(const Ptr& fs, const String& name) const { CV_Assert(fs); Algorithm::write(*fs, name); } +#endif }; /** Feature detectors in OpenCV have wrappers with a common interface that enables you to easily switch @@ -1102,6 +1105,9 @@ public: // see corresponding cv::Algorithm method CV_WRAP inline void write(FileStorage& fs, const String& name) const { Algorithm::write(fs, name); } +#if CV_VERSION_MAJOR < 5 + inline void write(const Ptr& fs, const String& name) const { CV_Assert(fs); Algorithm::write(*fs, name); } +#endif protected: /** From 5855eba9f3b23c131083072f19aa02dfc4535787 Mon Sep 17 00:00:00 2001 From: Alexander Alekhin Date: Sun, 18 Dec 2022 00:14:41 +0000 Subject: [PATCH 8/8] samples: query for Python 3.11 setup --- samples/_winpack_run_python_sample.cmd | 2 ++ 1 file changed, 2 insertions(+) diff --git a/samples/_winpack_run_python_sample.cmd b/samples/_winpack_run_python_sample.cmd index ca0d38e21a..bb56046536 100644 --- a/samples/_winpack_run_python_sample.cmd +++ b/samples/_winpack_run_python_sample.cmd @@ -23,6 +23,8 @@ IF %ERRORLEVEL% EQU 0 ( GOTO :PYTHON_FOUND ) +CALL :QUERY_PYTHON 3.11 +IF %ERRORLEVEL% EQU 0 GOTO :PYTHON_FOUND CALL :QUERY_PYTHON 3.10 IF %ERRORLEVEL% EQU 0 GOTO :PYTHON_FOUND CALL :QUERY_PYTHON 3.9