mirror of
https://github.com/opencv/opencv.git
synced 2024-12-11 14:39:11 +08:00
380caa1a87
Import and export np.float16 in Python #23691 ### Pull Request Readiness Checklist * Also, fixes `cv::norm` with `NORM_INF` and `CV_16F` resolves https://github.com/opencv/opencv/issues/23687 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 - [x] There is a reference to the original bug report and related work - [x] There is accuracy test, performance test and test data in opencv_extra repository, if applicable Patch to opencv_extra has the same branch name. - [x] The feature is well documented and sample code can be built with the project CMake
74 lines
2.5 KiB
C++
74 lines
2.5 KiB
C++
// must be defined before importing numpy headers
|
|
// https://numpy.org/doc/1.17/reference/c-api.array.html#importing-the-api
|
|
#define NO_IMPORT_ARRAY
|
|
#define PY_ARRAY_UNIQUE_SYMBOL opencv_ARRAY_API
|
|
|
|
#include "cv2_numpy.hpp"
|
|
#include "cv2_util.hpp"
|
|
|
|
NumpyAllocator g_numpyAllocator;
|
|
|
|
using namespace cv;
|
|
|
|
UMatData* NumpyAllocator::allocate(PyObject* o, int dims, const int* sizes, int type, size_t* step) const
|
|
{
|
|
UMatData* u = new UMatData(this);
|
|
u->data = u->origdata = (uchar*)PyArray_DATA((PyArrayObject*) o);
|
|
npy_intp* _strides = PyArray_STRIDES((PyArrayObject*) o);
|
|
for( int i = 0; i < dims - 1; i++ )
|
|
step[i] = (size_t)_strides[i];
|
|
step[dims-1] = CV_ELEM_SIZE(type);
|
|
u->size = sizes[0]*step[0];
|
|
u->userdata = o;
|
|
return u;
|
|
}
|
|
|
|
UMatData* NumpyAllocator::allocate(int dims0, const int* sizes, int type, void* data, size_t* step, AccessFlag flags, UMatUsageFlags usageFlags) const
|
|
{
|
|
if( data != 0 )
|
|
{
|
|
// issue #6969: CV_Error(Error::StsAssert, "The data should normally be NULL!");
|
|
// probably this is safe to do in such extreme case
|
|
return stdAllocator->allocate(dims0, sizes, type, data, step, flags, usageFlags);
|
|
}
|
|
PyEnsureGIL gil;
|
|
|
|
int depth = CV_MAT_DEPTH(type);
|
|
int cn = CV_MAT_CN(type);
|
|
const int f = (int)(sizeof(size_t)/8);
|
|
int typenum = depth == CV_8U ? NPY_UBYTE : depth == CV_8S ? NPY_BYTE :
|
|
depth == CV_16U ? NPY_USHORT : depth == CV_16S ? NPY_SHORT :
|
|
depth == CV_32S ? NPY_INT : depth == CV_32F ? NPY_FLOAT :
|
|
depth == CV_64F ? NPY_DOUBLE : depth == CV_16F ? NPY_HALF : f*NPY_ULONGLONG + (f^1)*NPY_UINT;
|
|
int i, dims = dims0;
|
|
cv::AutoBuffer<npy_intp> _sizes(dims + 1);
|
|
for( i = 0; i < dims; i++ )
|
|
_sizes[i] = sizes[i];
|
|
if( cn > 1 )
|
|
_sizes[dims++] = cn;
|
|
PyObject* o = PyArray_SimpleNew(dims, _sizes.data(), typenum);
|
|
if(!o)
|
|
CV_Error_(Error::StsError, ("The numpy array of typenum=%d, ndims=%d can not be created", typenum, dims));
|
|
return allocate(o, dims0, sizes, type, step);
|
|
}
|
|
|
|
bool NumpyAllocator::allocate(UMatData* u, AccessFlag accessFlags, UMatUsageFlags usageFlags) const
|
|
{
|
|
return stdAllocator->allocate(u, accessFlags, usageFlags);
|
|
}
|
|
|
|
void NumpyAllocator::deallocate(UMatData* u) const
|
|
{
|
|
if(!u)
|
|
return;
|
|
PyEnsureGIL gil;
|
|
CV_Assert(u->urefcount >= 0);
|
|
CV_Assert(u->refcount >= 0);
|
|
if(u->refcount == 0)
|
|
{
|
|
PyObject* o = (PyObject*)u->userdata;
|
|
Py_XDECREF(o);
|
|
delete u;
|
|
}
|
|
}
|