From 26bd26e400706cfcbb7b305df2dcd66f67d73454 Mon Sep 17 00:00:00 2001 From: Abhishek Gola Date: Fri, 30 Oct 2026 16:00:13 +0530 Subject: [PATCH] python: rename setAllowNonConventionalDataTypes() / getAllowNonConventionalDataTypes() to setUseExactNumpyDtypes() / useExactNumpyDtypes() Signed-off-by: Abhishek Gola --- .../py_bindings_basics.markdown | 10 +++---- modules/dnn/include/opencv2/dnn/dnn.hpp | 2 +- modules/python/src2/cv2.cpp | 20 ++++++------- modules/python/src2/cv2_convert.cpp | 4 +-- modules/python/src2/cv2_numpy.cpp | 4 +-- modules/python/src2/cv2_util.cpp | 12 ++++---- modules/python/src2/cv2_util.hpp | 8 +++--- .../typing_stubs_generation/api_refinement.py | 6 ++-- modules/python/test/test_ml_dtypes.py | 28 +++++++++---------- 9 files changed, 47 insertions(+), 47 deletions(-) diff --git a/doc/py_tutorials/py_bindings/py_bindings_basics/py_bindings_basics.markdown b/doc/py_tutorials/py_bindings/py_bindings_basics/py_bindings_basics.markdown index 275093b9e1..62d470f808 100644 --- a/doc/py_tutorials/py_bindings/py_bindings_basics/py_bindings_basics.markdown +++ b/doc/py_tutorials/py_bindings/py_bindings_basics/py_bindings_basics.markdown @@ -212,14 +212,14 @@ the exact type back, enable it once for the whole process: import cv2 as cv import ml_dtypes -cv.setAllowNonConventionalDataTypes(True) +cv.setUseExactNumpyDtypes(True) out = net.forward() # bfloat16 / float8 outputs keep their type @endcode -`cv.getAllowNonConventionalDataTypes()` returns the current value, which is `False` by -default. An array passed as an output argument, such as `dst`, is filled in place and -returned as is, whatever the setting. If the setting is on but `ml_dtypes` has not been -imported, outputs are still converted to `float32` and a warning is printed once. +`cv.useExactNumpyDtypes()` returns the current value, which is `False` by default. An +array passed as an output argument, such as `dst`, is filled in place and returned as is, +whatever the setting. If the setting is on but `ml_dtypes` has not been imported, outputs +are still converted to `float32` and a warning is printed once. The setting is global, so it changes the outputs of every piece of code in the process that calls OpenCV. Turn it on in your application. A library should not change it, because the diff --git a/modules/dnn/include/opencv2/dnn/dnn.hpp b/modules/dnn/include/opencv2/dnn/dnn.hpp index b64a4a3fa8..f8aa04051f 100644 --- a/modules/dnn/include/opencv2/dnn/dnn.hpp +++ b/modules/dnn/include/opencv2/dnn/dnn.hpp @@ -724,7 +724,7 @@ CV__DNN_INLINE_NS_BEGIN * @note In Python, CV_16BF / CV_8F_E4M3FN / CV_8F_E4M3FNUZ output blobs are * returned as NumPy float32 arrays by default. To preserve their exact dtypes, * import the optional ml_dtypes package and call - * `cv.setAllowNonConventionalDataTypes(True)` before forward(). This process-wide + * `cv.setUseExactNumpyDtypes(True)` before forward(). This process-wide * setting affects outputs only; registered bfloat16 / float8 input arrays are * accepted regardless of it. It belongs to the application: libraries should not * change it. See @ref tutorial_py_bindings_basics for details. diff --git a/modules/python/src2/cv2.cpp b/modules/python/src2/cv2.cpp index 156b404cb6..c3f930aa81 100644 --- a/modules/python/src2/cv2.cpp +++ b/modules/python/src2/cv2.cpp @@ -118,29 +118,29 @@ static PyObject* pycvRegisterMatType(PyObject *self, PyObject *value) Py_RETURN_NONE; } -static PyObject* pycvSetAllowNonConventionalDataTypes(PyObject*, PyObject* value) +static PyObject* pycvSetUseExactNumpyDtypes(PyObject*, PyObject* value) { - int allow = PyObject_IsTrue(value); - if (allow < 0) + int flag = PyObject_IsTrue(value); + if (flag < 0) return NULL; - setAllowNonConventionalDataTypes(allow != 0); + setUseExactNumpyDtypes(flag != 0); Py_RETURN_NONE; } -static PyObject* pycvGetAllowNonConventionalDataTypes(PyObject*, PyObject*) +static PyObject* pycvUseExactNumpyDtypes(PyObject*, PyObject*) { - return PyBool_FromLong(getAllowNonConventionalDataTypes()); + return PyBool_FromLong(useExactNumpyDtypes()); } static PyMethodDef special_methods[] = { {"_registerMatType", (PyCFunction)(pycvRegisterMatType), METH_O, "_registerMatType(cv.Mat) -> None (Internal)"}, {"redirectError", CV_PY_FN_WITH_KW(pycvRedirectError), "redirectError(onError) -> None"}, - {"setAllowNonConventionalDataTypes", (PyCFunction)(pycvSetAllowNonConventionalDataTypes), METH_O, - "setAllowNonConventionalDataTypes(allow) -> None\n. Keep output bfloat16 / float8 arrays at their exact dtype " + {"setUseExactNumpyDtypes", (PyCFunction)(pycvSetUseExactNumpyDtypes), METH_O, + "setUseExactNumpyDtypes(flag) -> None\n. Keep output bfloat16 / float8 arrays at their exact dtype " "(registered by the ml_dtypes package, which must be imported) instead of widening them to float32. Off by default. Input arrays are accepted regardless of this flag. " "The flag is process-wide: set it in the application, libraries should not change it."}, - {"getAllowNonConventionalDataTypes", (PyCFunction)(pycvGetAllowNonConventionalDataTypes), METH_NOARGS, - "getAllowNonConventionalDataTypes() -> retval"}, + {"useExactNumpyDtypes", (PyCFunction)(pycvUseExactNumpyDtypes), METH_NOARGS, + "useExactNumpyDtypes() -> retval"}, #ifdef HAVE_OPENCV_HIGHGUI {"createTrackbar", (PyCFunction)pycvCreateTrackbar, METH_VARARGS, "createTrackbar(trackbarName, windowName, value, count, onChange) -> None"}, {"createButton", CV_PY_FN_WITH_KW(pycvCreateButton), "createButton(buttonName, onChange [, userData, buttonType, initialButtonState]) -> None"}, diff --git a/modules/python/src2/cv2_convert.cpp b/modules/python/src2/cv2_convert.cpp index dc251bca86..8f617e4bd9 100644 --- a/modules/python/src2/cv2_convert.cpp +++ b/modules/python/src2/cv2_convert.cpp @@ -370,8 +370,8 @@ PyObject* pyopencv_from(const cv::Mat& m) Py_INCREF(o); return o; } - if( getAllowNonConventionalDataTypes() ) - CV_LOG_ONCE_WARNING(NULL, "Python bindings: non-conventional data types are allowed, " + if( useExactNumpyDtypes() ) + CV_LOG_ONCE_WARNING(NULL, "Python bindings: setUseExactNumpyDtypes(True) is set, " "but NumPy does not know bfloat16 / float8 and they are returned as float32. " "Import ml_dtypes to keep the exact dtype."); // NumPy alone cannot name these; widen to float32 (lossless). diff --git a/modules/python/src2/cv2_numpy.cpp b/modules/python/src2/cv2_numpy.cpp index 7a2e803c17..92023d4fd9 100644 --- a/modules/python/src2/cv2_numpy.cpp +++ b/modules/python/src2/cv2_numpy.cpp @@ -55,10 +55,10 @@ UMatData* NumpyAllocator::allocate(int dims0, const int* sizes, int type, void* } // Mat::create() falls back to the default allocator on this error; pyopencv_from() then widens to float32. if( isNonConventionalDepth(depth) ) - CV_Error(Error::StsNotImplemented, getAllowNonConventionalDataTypes() + CV_Error(Error::StsNotImplemented, useExactNumpyDtypes() ? "bfloat16 / float8 arrays cannot be allocated through the NumPy allocator: import ml_dtypes first" : "bfloat16 / float8 arrays cannot be allocated through the NumPy allocator: " - "call cv.setAllowNonConventionalDataTypes(True) first"); + "call cv.setUseExactNumpyDtypes(True) first"); int typenum = cvDepthToNumpyType(depth); PyObject* o = PyArray_SimpleNew(dims, _sizes.data(), typenum); diff --git a/modules/python/src2/cv2_util.cpp b/modules/python/src2/cv2_util.cpp index 790a237d37..9680b78607 100644 --- a/modules/python/src2/cv2_util.cpp +++ b/modules/python/src2/cv2_util.cpp @@ -55,7 +55,7 @@ const NonConventionalDtype kNonConventionalDtypes[] = { }; const int kNumNonConventionalDtypes = sizeof(kNonConventionalDtypes) / sizeof(kNonConventionalDtypes[0]); -bool g_allowNonConventionalDataTypes = false; +bool g_useExactNumpyDtypes = false; // Process-lifetime cache, accessed under the GIL. Misses are not cached, so a later // `import ml_dtypes` still takes effect. @@ -93,14 +93,14 @@ int nonConventionalIndex(int depth) } // namespace -void setAllowNonConventionalDataTypes(bool allow) +void setUseExactNumpyDtypes(bool flag) { - g_allowNonConventionalDataTypes = allow; + g_useExactNumpyDtypes = flag; } -bool getAllowNonConventionalDataTypes() +bool useExactNumpyDtypes() { - return g_allowNonConventionalDataTypes; + return g_useExactNumpyDtypes; } bool isNonConventionalDepth(int depth) @@ -111,7 +111,7 @@ bool isNonConventionalDepth(int depth) PyArray_Descr* nonConventionalDescrForCvDepth(int depth) { const int idx = nonConventionalIndex(depth); - if (!g_allowNonConventionalDataTypes || idx < 0) + if (!g_useExactNumpyDtypes || idx < 0) return nullptr; return nonConventionalDescr(idx); } diff --git a/modules/python/src2/cv2_util.hpp b/modules/python/src2/cv2_util.hpp index cd62a284a2..df3b5c6933 100644 --- a/modules/python/src2/cv2_util.hpp +++ b/modules/python/src2/cv2_util.hpp @@ -17,11 +17,11 @@ PyObject* failmsgp(const char *fmt, ...); int cvDepthToNumpyType(int depth); int numpyTypeToCvDepth(int typenum); -// Output bfloat16 / float8 Mats keep their exact dtype only when allowed (off by default). -void setAllowNonConventionalDataTypes(bool allow); -bool getAllowNonConventionalDataTypes(); +// Output bfloat16 / float8 Mats keep their exact dtype only when enabled (off by default). +void setUseExactNumpyDtypes(bool flag); +bool useExactNumpyDtypes(); bool isNonConventionalDepth(int depth); -// Output descriptor: nullptr when disallowed, unregistered, or without an OpenCV counterpart. +// Output descriptor: nullptr when disabled, unregistered, or without an OpenCV counterpart. PyArray_Descr* nonConventionalDescrForCvDepth(int depth); // Input depth: -1 when unregistered or without an OpenCV counterpart; ignores the output flag. int nonConventionalTypeToCvDepth(int typenum); diff --git a/modules/python/src2/typing_stubs_generation/api_refinement.py b/modules/python/src2/typing_stubs_generation/api_refinement.py index 1edac68b55..f64c478e9f 100644 --- a/modules/python/src2/typing_stubs_generation/api_refinement.py +++ b/modules/python/src2/typing_stubs_generation/api_refinement.py @@ -58,10 +58,10 @@ def apply_manual_api_refinement(root: NamespaceNode) -> None: ) ]) - root.add_function("setAllowNonConventionalDataTypes", [ - FunctionNode.Arg("allow", PrimitiveTypeNode.bool_()) + root.add_function("setUseExactNumpyDtypes", [ + FunctionNode.Arg("flag", PrimitiveTypeNode.bool_()) ]) - root.add_function("getAllowNonConventionalDataTypes", + root.add_function("useExactNumpyDtypes", return_type=FunctionNode.RetType(PrimitiveTypeNode.bool_())) diff --git a/modules/python/test/test_ml_dtypes.py b/modules/python/test/test_ml_dtypes.py index 56ff180793..94028c890d 100644 --- a/modules/python/test/test_ml_dtypes.py +++ b/modules/python/test/test_ml_dtypes.py @@ -18,24 +18,24 @@ class non_conventional_dtypes_test(NewOpenCVTests): def setUp(self): super(non_conventional_dtypes_test, self).setUp() - self.addCleanup(cv.setAllowNonConventionalDataTypes, cv.getAllowNonConventionalDataTypes()) - cv.setAllowNonConventionalDataTypes(False) + self.addCleanup(cv.setUseExactNumpyDtypes, cv.useExactNumpyDtypes()) + cv.setUseExactNumpyDtypes(False) def test_flag_roundtrip(self): - cv.setAllowNonConventionalDataTypes(True) - self.assertTrue(cv.getAllowNonConventionalDataTypes()) - cv.setAllowNonConventionalDataTypes(False) - self.assertFalse(cv.getAllowNonConventionalDataTypes()) + cv.setUseExactNumpyDtypes(True) + self.assertTrue(cv.useExactNumpyDtypes()) + cv.setUseExactNumpyDtypes(False) + self.assertFalse(cv.useExactNumpyDtypes()) - def test_disallowed_widens_to_float32(self): + def test_disabled_widens_to_float32(self): for depth in NON_CONVENTIONAL_DEPTHS: for m in cv.utils.generateVectorOfMat(1, 3, 4, depth): self.assertEqual(m.dtype, np.float32) - def test_allowed_without_ml_dtypes_widens_to_float32(self): + def test_enabled_without_ml_dtypes_widens_to_float32(self): if ml_dtypes is not None: self.skipTest("ml_dtypes is installed") - cv.setAllowNonConventionalDataTypes(True) + cv.setUseExactNumpyDtypes(True) for depth in NON_CONVENTIONAL_DEPTHS: for m in cv.utils.generateVectorOfMat(1, 3, 4, depth): self.assertEqual(m.dtype, np.float32) @@ -54,8 +54,8 @@ class ml_dtypes_test(NewOpenCVTests): super(ml_dtypes_test, self).setUp() if ml_dtypes is None: self.skipTest("ml_dtypes is not installed") - self.addCleanup(cv.setAllowNonConventionalDataTypes, cv.getAllowNonConventionalDataTypes()) - cv.setAllowNonConventionalDataTypes(True) + self.addCleanup(cv.setUseExactNumpyDtypes, cv.useExactNumpyDtypes()) + cv.setUseExactNumpyDtypes(True) # (numpy dtype, OpenCV depth, typeToString prefix, relative half-ULP) self.cases = [ (ml_dtypes.bfloat16, cv.CV_16BF, "CV_16BF", 2.0 ** -8), @@ -77,7 +77,7 @@ class ml_dtypes_test(NewOpenCVTests): self.assertIn("type(-1)=%sC1" % name, cv.utils.dumpInputArray(np.array(1.5, dtype=dt))) def test_inputs_accepted_with_outputs_disabled(self): - cv.setAllowNonConventionalDataTypes(False) + cv.setUseExactNumpyDtypes(False) for dt, _, name, _ in self.cases: a = np.arange(6, dtype=np.float32).reshape(2, 3).astype(dt) self.assertIn("type(-1)=%sC1" % name, cv.utils.dumpInputArray(a)) @@ -91,8 +91,8 @@ class ml_dtypes_test(NewOpenCVTests): def test_short_array_scalar_operands(self): # A float32 src keeps the result float32, so the operand is checked with the flag off too. - for allow in (False, True): - cv.setAllowNonConventionalDataTypes(allow) + for exact in (False, True): + cv.setUseExactNumpyDtypes(exact) for dt, _, _, _ in self.cases: for channels in range(1, 5): src = np.zeros((2, 3, channels), dtype=np.float32)