feat: update NumPy type to Mat type fail message

Output string representation of NumPy array type if it is not
convertible to OpenCV Mat type
This commit is contained in:
Vadim Levin 2023-07-10 18:05:32 +03:00
parent fdc0c12b7f
commit 953de60ff0
3 changed files with 37 additions and 2 deletions

View File

@ -5,6 +5,7 @@
#include "cv2_convert.hpp"
#include "cv2_numpy.hpp"
#include "cv2_util.hpp"
#include "opencv2/core/utils/logger.hpp"
PyTypeObject* pyopencv_Mat_TypePtr = nullptr;
@ -24,6 +25,26 @@ static std::string pycv_dumpArray(const T* arr, int n)
return out.str();
}
static inline std::string getArrayTypeName(PyArrayObject* arr)
{
PyArray_Descr* dtype = PyArray_DESCR(arr);
PySafeObject dtype_str(PyObject_Str(reinterpret_cast<PyObject*>(dtype)));
if (!dtype_str)
{
// Fallback to typenum value
return cv::format("%d", PyArray_TYPE(arr));
}
std::string type_name;
if (!getUnicodeString(dtype_str, type_name))
{
// Failed to get string from bytes object - clear set TypeError and
// fallback to typenum value
PyErr_Clear();
return cv::format("%d", PyArray_TYPE(arr));
}
return type_name;
}
//======================================================================================================================
// --- Mat
@ -102,7 +123,9 @@ bool pyopencv_to(PyObject* o, Mat& m, const ArgInfo& info)
}
else
{
failmsg("%s data type = %d is not supported", info.name, typenum);
const std::string dtype_name = getArrayTypeName(oarr);
failmsg("%s data type = %s is not supported", info.name,
dtype_name.c_str());
return false;
}
}

View File

@ -42,7 +42,7 @@ private:
/**
* Light weight RAII wrapper for `PyObject*` owning references.
* In comparisson to C++11 `std::unique_ptr` with custom deleter, it provides
* In comparison to C++11 `std::unique_ptr` with custom deleter, it provides
* implicit conversion functions that might be useful to initialize it with
* Python functions those returns owning references through the `PyObject**`
* e.g. `PyErr_Fetch` or directly pass it to functions those want to borrow
@ -70,6 +70,10 @@ public:
return &obj_;
}
operator bool() {
return static_cast<bool>(obj_);
}
PyObject* release()
{
PyObject* obj = obj_;

View File

@ -219,6 +219,14 @@ class Arguments(NewOpenCVTests):
#res6 = cv.utils.dumpInputArray([a, b])
#self.assertEqual(res6, "InputArrayOfArrays: empty()=false kind=0x00050000 flags=0x01050000 total(-1)=2 dims(-1)=1 size(-1)=2x1 type(0)=CV_32FC1 dims(0)=4 size(0)=[2 3 4 5]")
def test_unsupported_numpy_data_types_string_description(self):
for dtype in (object, str, np.complex128):
test_array = np.zeros((4, 4, 3), dtype=dtype)
msg = ".*type = {} is not supported".format(test_array.dtype)
self.assertRaisesRegex(
Exception, msg, cv.utils.dumpInputArray, test_array
)
def test_20968(self):
pixel = np.uint8([[[40, 50, 200]]])
_ = cv.cvtColor(pixel, cv.COLOR_RGB2BGR) # should not raise exception