From 5fcdb9b01e540792f19a11dd1f5080f5b7aad40d Mon Sep 17 00:00:00 2001 From: vrooomy Date: Mon, 3 Aug 2026 14:41:43 +0530 Subject: [PATCH] code cleanup --- .../dnn/misc/python/test/test_onnx_conformance.py | 2 -- .../misc/python/test/test_feature_homography.py | 2 +- modules/python/src2/cv2_convert.cpp | 11 ++--------- modules/python/src2/cv2_numpy.cpp | 6 ++---- modules/python/src2/cv2_util.cpp | 11 +++-------- modules/python/test/test_misc.py | 13 ++++--------- modules/python/test/test_squares.py | 3 +-- modules/python/test/tests_common.py | 2 +- 8 files changed, 14 insertions(+), 36 deletions(-) diff --git a/modules/dnn/misc/python/test/test_onnx_conformance.py b/modules/dnn/misc/python/test/test_onnx_conformance.py index d69ad6e167..33d8a085bb 100644 --- a/modules/dnn/misc/python/test/test_onnx_conformance.py +++ b/modules/dnn/misc/python/test/test_onnx_conformance.py @@ -632,8 +632,6 @@ TOLERANCE_OVERRIDES = { "test_roialign_aligned_true": (3e-05, 0.0001), } -# Cases the C++ suite passes but that fail only through the Python bindings. -# Not a port of the C++ denylist; empty is the expected state. KNOWN_SKIPS = { # "test_name": "reason", } diff --git a/modules/features/misc/python/test/test_feature_homography.py b/modules/features/misc/python/test/test_feature_homography.py index 22dd3e08f0..af57564401 100755 --- a/modules/features/misc/python/test/test_feature_homography.py +++ b/modules/features/misc/python/test/test_feature_homography.py @@ -26,7 +26,7 @@ from tst_scene_render import TestSceneRender def intersectionRate(s1, s2): x1, y1, x2, y2 = s1 - # dtype is explicit: the geometry functions accept only CV_32S/CV_32F points. + # intersectConvexConvex()/contourArea() accept only CV_32S/CV_32F points s1 = np.array([[x1, y1], [x2,y1], [x2, y2], [x1, y2]], dtype=np.int32) s2 = np.array(s2, dtype=np.int32) diff --git a/modules/python/src2/cv2_convert.cpp b/modules/python/src2/cv2_convert.cpp index 04087fb3cb..61814c64ad 100644 --- a/modules/python/src2/cv2_convert.cpp +++ b/modules/python/src2/cv2_convert.cpp @@ -133,10 +133,6 @@ bool pyopencv_to(PyObject* o, Mat& m, const ArgInfo& info) if( type < 0 ) { - // 64-bit integers used to be force-cast to CV_32S here, which silently - // truncated any value outside the int32 range. They now map to - // CV_64S/CV_64U in numpyTypeToCvDepth(), so reaching this point means - // the dtype genuinely has no cv::Mat equivalent. const std::string dtype_name = getArrayTypeName(oarr); failmsg("%s data type = %s is not supported", info.name, dtype_name.c_str()); @@ -304,15 +300,12 @@ bool pyopencv_to(PyObject* o, Mat& m, const ArgInfo& info) template<> PyObject* pyopencv_from(const cv::Mat& m) { - // NumPy has no bfloat16 dtype, so CV_16BF is widened to float32 (lossless). - // The values must actually be converted, not just relabelled: cvDepthToNumpyType() - // reports NPY_FLOAT for CV_16BF, and handing a 2-byte-per-element buffer to the - // NumPy allocator under a 4-byte dtype would misinterpret the payload. + // NumPy has no bfloat16 dtype: widen CV_16BF to float32 (lossless). if( m.depth() == CV_16BF ) { cv::Mat m32f; ERRWRAP2(m.convertTo(m32f, CV_32F)); - return pyopencv_from(m32f); // m32f is CV_32F, so this recurses at most once + return pyopencv_from(m32f); } if( m.empty() ) { diff --git a/modules/python/src2/cv2_numpy.cpp b/modules/python/src2/cv2_numpy.cpp index 4ba944c374..d30e777285 100644 --- a/modules/python/src2/cv2_numpy.cpp +++ b/modules/python/src2/cv2_numpy.cpp @@ -34,10 +34,8 @@ UMatData* NumpyAllocator::allocate(int dims0, const int* sizes, int type, void* int depth = CV_MAT_DEPTH(type); int cn = CV_MAT_CN(type); - // cvDepthToNumpyType() widens CV_16BF to NPY_FLOAT for export, which is only - // valid when the values are converted (see pyopencv_from). Backing a CV_16BF - // Mat with a float32 buffer here would instead pair a 2-byte element step with - // 4-byte NumPy strides and silently corrupt the data, so refuse it outright. + // Backing a CV_16BF Mat with the float32 buffer cvDepthToNumpyType() asks for + // would pair a 2-byte element step with 4-byte NumPy strides and corrupt the data. if( depth == CV_16BF ) CV_Error(Error::StsNotImplemented, "CV_16BF (bfloat16) arrays cannot be allocated through the NumPy allocator: " diff --git a/modules/python/src2/cv2_util.cpp b/modules/python/src2/cv2_util.cpp index 9ad875e104..8ff3f76adb 100644 --- a/modules/python/src2/cv2_util.cpp +++ b/modules/python/src2/cv2_util.cpp @@ -21,14 +21,10 @@ int cvDepthToNumpyType(int depth) case CV_32F: return NPY_FLOAT; case CV_64F: return NPY_DOUBLE; case CV_16F: return NPY_HALF; - // NumPy has no bfloat16 dtype, so CV_16BF is exported as float32 (a lossless - // widening). pyopencv_from() performs the value conversion; without it the - // 2-byte payload would be reinterpreted as 4-byte elements. + // NumPy has no bfloat16 dtype; pyopencv_from() converts the values to float32. case CV_16BF: return NPY_FLOAT; case CV_Bool: return NPY_BOOL; default: - // Deliberately an error rather than a fallback: silently mapping an - // unknown depth to some default dtype mislabels the payload. CV_Error(cv::Error::StsNotImplemented, cv::format("Mat depth %d has no corresponding NumPy dtype", depth)); } @@ -36,7 +32,7 @@ int cvDepthToNumpyType(int depth) int numpyTypeToCvDepth(int typenum) { - // Only canonical NPY_* values may appear as case labels: the fixed-width + // Only canonical NPY_* values may be used as case labels: the fixed-width // aliases (NPY_INT32, NPY_INT64, ...) expand to these and would collide. switch (typenum) { @@ -48,8 +44,7 @@ int numpyTypeToCvDepth(int typenum) case NPY_INT: return CV_32S; case NPY_ULONGLONG: return CV_64U; case NPY_LONGLONG: return CV_64S; - // 'long' is 64-bit on LP64 (Linux/macOS) but 32-bit on LLP64 (Windows), - // so this must be decided by size rather than by name. + // 'long' is 64-bit on LP64 but 32-bit on LLP64, so decide by size, not by name. case NPY_ULONG: return NPY_SIZEOF_LONG == 8 ? CV_64U : CV_32U; case NPY_LONG: return NPY_SIZEOF_LONG == 8 ? CV_64S : CV_32S; case NPY_HALF: return CV_16F; diff --git a/modules/python/test/test_misc.py b/modules/python/test/test_misc.py index 2d5b1f07a9..6f0626be64 100644 --- a/modules/python/test/test_misc.py +++ b/modules/python/test/test_misc.py @@ -263,8 +263,7 @@ class Arguments(NewOpenCVTests): self.assertEqual(res2_1, "InputArray: empty()=false kind=0x00010000 flags=0x01010000 total(-1)=2 dims(-1)=2 size(-1)=1x2 type(-1)=CV_64FC1") res2_2 = cv.utils.dumpInputArray(1.5) # Scalar(1.5, 1.5, 1.5, 1.5) self.assertEqual(res2_2, "InputArray: empty()=false kind=0x00010000 flags=0x01010000 total(-1)=4 dims(-1)=2 size(-1)=1x4 type(-1)=CV_64FC1") - # dtype is explicit: NumPy's default integer type is platform/version - # dependent, and 64-bit integers now map to CV_64S rather than CV_32S. + # explicit dtype: NumPy's default integer type is platform dependent a = np.array([[1, 2], [3, 4], [5, 6]], dtype=np.int32) res3 = cv.utils.dumpInputArray(a) # 32SC1 self.assertEqual(res3, "InputArray: empty()=false kind=0x00010000 flags=0x01010000 total(-1)=6 dims(-1)=2 size(-1)=2x3 type(-1)=CV_32SC1") @@ -295,7 +294,6 @@ class Arguments(NewOpenCVTests): self.assertEqual(res2_1, "InputArrayOfArrays: empty()=false kind=0x00050000 flags=0x01050000 total(-1)=2 dims(-1)=1 size(-1)=2x1 type(0)=CV_64FC1 dims(0)=2 size(0)=1x4") res2_2 = cv.utils.dumpInputArrayOfArrays([1.5]) self.assertEqual(res2_2, "InputArrayOfArrays: empty()=false kind=0x00050000 flags=0x01050000 total(-1)=1 dims(-1)=1 size(-1)=1x1 type(0)=CV_64FC1 dims(0)=2 size(0)=1x4") - # see test_InputArray: keep the integer dtype explicit a = np.array([[1, 2], [3, 4], [5, 6]], dtype=np.int32) b = np.array([[1, 2, 3], [4, 5, 6], [7, 8, 9]], dtype=np.int32) res3 = cv.utils.dumpInputArrayOfArrays([a, b]) @@ -331,14 +329,12 @@ class Arguments(NewOpenCVTests): cv.rectangle(array, (0, 0), (5, 5), (255), 2) def test_64bit_integers_map_to_64bit_depths(self): - # 64-bit integer arrays used to fall through to a CV_32S cast. for dtype, expected in ((np.int64, "CV_64SC1"), (np.uint64, "CV_64UC1")): array = np.zeros((2, 2), dtype=dtype) self.assertIn(expected, cv.utils.dumpInputArray(array)) def test_64bit_integers_are_not_truncated(self): - # Regression: values outside the int32 range were silently truncated - # (2**40 came back as 0) because of that cast. + # Values outside the int32 range used to be silently truncated. for dtype in (np.int64, np.uint64): for value in (2 ** 40, 2 ** 40 + 12345): array = np.array([[value]], dtype=dtype) @@ -349,9 +345,8 @@ class Arguments(NewOpenCVTests): self.assertEqual(cv.add(signed, np.zeros_like(signed))[0, 0], -2 ** 40) def test_64bit_integer_dtype_number_is_preserved(self): - # np.dtype('uint64') == np.dtype('ulonglong') compares equal even though - # their type numbers differ, so an exported array can look correct while - # being unusable as an input. Compare .num explicitly. + # np.dtype('uint64') == np.dtype('ulonglong') compares equal despite having + # different type numbers, so compare .num explicitly. for dtype in (np.int64, np.uint64): array = np.zeros((2, 2), dtype=dtype) self.assertEqual(cv.add(array, array).dtype.num, np.dtype(dtype).num) diff --git a/modules/python/test/test_squares.py b/modules/python/test/test_squares.py index 0778ab1bb9..d8a9e42a4a 100644 --- a/modules/python/test/test_squares.py +++ b/modules/python/test/test_squares.py @@ -44,8 +44,7 @@ def find_squares(img): return squares def intersectionRate(s1, s2): - # dtype is explicit: these helpers take plain integer lists, and the geometry - # functions accept only CV_32S/CV_32F point coordinates. + # intersectConvexConvex()/contourArea() accept only CV_32S/CV_32F points s1 = np.array(s1, dtype=np.int32) s2 = np.array(s2, dtype=np.int32) area, _intersection = cv.intersectConvexConvex(s1, s2) diff --git a/modules/python/test/tests_common.py b/modules/python/test/tests_common.py index 75e4aff13e..76c4328657 100644 --- a/modules/python/test/tests_common.py +++ b/modules/python/test/tests_common.py @@ -102,7 +102,7 @@ class NewOpenCVTests(unittest.TestCase): def intersectionRate(s1, s2): - # dtype is explicit: the geometry functions accept only CV_32S/CV_32F points. + # intersectConvexConvex()/contourArea() accept only CV_32S/CV_32F points x1, y1, x2, y2 = s1 s1 = np.array([[x1, y1], [x2,y1], [x2, y2], [x1, y2]], dtype=np.int32)