chore: import upstream snapshot with attribution

This commit is contained in:
wehub-resource-sync
2026-07-13 12:06:04 +08:00
commit 86c9b1c39f
7743 changed files with 3316339 additions and 0 deletions
@@ -0,0 +1,40 @@
__all__ = []
import numpy as np
import cv2 as cv
from typing import TYPE_CHECKING, Any
# Same as cv2.typing.NumPyArrayNumeric, but avoids circular dependencies
if TYPE_CHECKING:
_NumPyArrayNumeric = np.ndarray[Any, np.dtype[np.integer[Any] | np.floating[Any]]]
else:
_NumPyArrayNumeric = np.ndarray
# NumPy documentation: https://numpy.org/doc/stable/user/basics.subclassing.html
class Mat(_NumPyArrayNumeric):
'''
cv.Mat wrapper for numpy array.
Stores extra metadata information how to interpret and process of numpy array for underlying C++ code.
'''
def __new__(cls, arr, **kwargs):
obj = arr.view(Mat)
return obj
def __init__(self, arr, **kwargs):
self.wrap_channels = kwargs.pop('wrap_channels', getattr(arr, 'wrap_channels', False))
if len(kwargs) > 0:
raise TypeError('Unknown parameters: {}'.format(repr(kwargs)))
def __array_finalize__(self, obj):
if obj is None:
return
self.wrap_channels = getattr(obj, 'wrap_channels', None)
Mat.__module__ = cv.__name__
cv.Mat = Mat
cv._registerMatType(Mat)
@@ -0,0 +1,14 @@
from collections import namedtuple
import cv2
NativeMethodPatchedResult = namedtuple("NativeMethodPatchedResult",
("py", "native"))
def testOverwriteNativeMethod(arg):
return NativeMethodPatchedResult(
arg + 1,
cv2.utils._native.testOverwriteNativeMethod(arg)
)
@@ -0,0 +1,8 @@
#ifdef HAVE_OPENCV_CORE
#include "opencv2/core/async.hpp"
CV_PY_TO_CLASS(AsyncArray)
CV_PY_FROM_CLASS(AsyncArray)
#endif
+232
View File
@@ -0,0 +1,232 @@
#ifndef OPENCV_CORE_PYOPENCV_CORE_HPP
#define OPENCV_CORE_PYOPENCV_CORE_HPP
#ifdef HAVE_OPENCV_CORE
#include "dlpack/dlpack.h"
static PyObject* pycvMakeType(PyObject* , PyObject* args, PyObject* kw) {
const char *keywords[] = { "depth", "channels", NULL };
int depth, channels;
if (!PyArg_ParseTupleAndKeywords(args, kw, "ii", (char**)keywords, &depth, &channels))
return NULL;
int type = CV_MAKETYPE(depth, channels);
return PyInt_FromLong(type);
}
template <int depth>
static PyObject* pycvMakeTypeCh(PyObject*, PyObject *value) {
int channels = (int)PyLong_AsLong(value);
return PyInt_FromLong(CV_MAKETYPE(depth, channels));
}
#define CV_DLPACK_CAPSULE_NAME "dltensor"
#define CV_DLPACK_USED_CAPSULE_NAME "used_dltensor"
template<typename T>
bool fillDLPackTensor(const T& src, DLManagedTensor* tensor, const DLDevice& device);
template<typename T>
bool parseDLPackTensor(DLManagedTensor* tensor, T& obj, bool copy);
template<typename T>
int GetNumDims(const T& src);
// source: https://github.com/dmlc/dlpack/blob/7f393bbb86a0ddd71fde3e700fc2affa5cdce72d/docs/source/python_spec.rst#L110
static void dlpack_capsule_deleter(PyObject *self){
if (PyCapsule_IsValid(self, CV_DLPACK_USED_CAPSULE_NAME)) {
return;
}
DLManagedTensor *managed = (DLManagedTensor *)PyCapsule_GetPointer(self, CV_DLPACK_CAPSULE_NAME);
if (managed == NULL) {
PyErr_WriteUnraisable(self);
return;
}
if (managed->deleter) {
managed->deleter(managed);
}
}
static void array_dlpack_deleter(DLManagedTensor *self)
{
if (!Py_IsInitialized()) {
return;
}
PyGILState_STATE state = PyGILState_Ensure();
PyObject *array = (PyObject *)self->manager_ctx;
PyMem_Free(self);
Py_XDECREF(array);
PyGILState_Release(state);
}
template<typename T>
static PyObject* to_dlpack(const T& src, PyObject* self, PyObject* py_args, PyObject* kw)
{
int stream = 0;
PyObject* maxVersion = nullptr;
PyObject* dlDevice = nullptr;
bool copy = false;
const char* keywords[] = { "stream", "max_version", "dl_device", "copy", NULL };
if (!PyArg_ParseTupleAndKeywords(py_args, kw, "|iOOp:__dlpack__", (char**)keywords, &stream, &maxVersion, &dlDevice, &copy))
return nullptr;
DLDevice device = {(DLDeviceType)-1, 0};
if (dlDevice && dlDevice != Py_None && PyTuple_Check(dlDevice))
{
device.device_type = static_cast<DLDeviceType>(PyLong_AsLong(PyTuple_GetItem(dlDevice, 0)));
device.device_id = PyLong_AsLong(PyTuple_GetItem(dlDevice, 1));
}
int ndim = GetNumDims(src);
void* ptr = PyMem_Malloc(sizeof(DLManagedTensor) + sizeof(int64_t) * ndim * 2);
if (!ptr) {
PyErr_NoMemory();
return nullptr;
}
DLManagedTensor* tensor = reinterpret_cast<DLManagedTensor*>(ptr);
tensor->manager_ctx = self;
tensor->deleter = array_dlpack_deleter;
tensor->dl_tensor.ndim = ndim;
tensor->dl_tensor.shape = reinterpret_cast<int64_t*>(reinterpret_cast<char*>(ptr) + sizeof(DLManagedTensor));
tensor->dl_tensor.strides = tensor->dl_tensor.shape + ndim;
fillDLPackTensor(src, tensor, device);
PyObject* capsule = PyCapsule_New(ptr, CV_DLPACK_CAPSULE_NAME, dlpack_capsule_deleter);
if (!capsule) {
PyMem_Free(ptr);
return nullptr;
}
// the capsule holds a reference
Py_INCREF(self);
return capsule;
}
template<typename T>
static PyObject* from_dlpack(PyObject* py_args, PyObject* kw)
{
PyObject* arr = nullptr;
PyObject* device = nullptr;
bool copy = false;
const char* keywords[] = { "device", "copy", NULL };
if (!PyArg_ParseTupleAndKeywords(py_args, kw, "O|Op:from_dlpack", (char**)keywords, &arr, &device, &copy))
return nullptr;
PyObject* capsule = nullptr;
if (PyCapsule_CheckExact(arr))
{
capsule = arr;
}
else
{
PyGILState_STATE gstate;
gstate = PyGILState_Ensure();
capsule = PyObject_CallMethodObjArgs(arr, PyString_FromString("__dlpack__"), NULL);
PyGILState_Release(gstate);
}
DLManagedTensor* tensor = reinterpret_cast<DLManagedTensor*>(PyCapsule_GetPointer(capsule, CV_DLPACK_CAPSULE_NAME));
if (tensor == nullptr)
{
if (capsule != arr)
Py_DECREF(capsule);
return nullptr;
}
T retval;
bool success = parseDLPackTensor(tensor, retval, copy);
if (success)
{
PyCapsule_SetName(capsule, CV_DLPACK_USED_CAPSULE_NAME);
}
if (capsule != arr)
Py_DECREF(capsule);
return success ? pyopencv_from(retval) : nullptr;
}
static DLDataType GetDLPackType(size_t elemSize1, int depth) {
DLDataType dtype;
dtype.bits = static_cast<uint8_t>(8 * elemSize1);
dtype.lanes = 1;
switch (depth)
{
case CV_8S: case CV_16S: case CV_32S: dtype.code = kDLInt; break;
case CV_8U: case CV_16U: dtype.code = kDLUInt; break;
case CV_16F: case CV_32F: case CV_64F: dtype.code = kDLFloat; break;
default:
CV_Error(Error::StsNotImplemented, "__dlpack__ data type");
}
return dtype;
}
static int DLPackTypeToCVType(const DLDataType& dtype, int channels) {
if (dtype.code == kDLInt)
{
switch (dtype.bits)
{
case 8: return CV_8SC(channels);
case 16: return CV_16SC(channels);
case 32: return CV_32SC(channels);
default:
{
PyErr_SetString(PyExc_BufferError,
format("Unsupported int dlpack depth: %d", dtype.bits).c_str());
return -1;
}
}
}
if (dtype.code == kDLUInt)
{
switch (dtype.bits)
{
case 8: return CV_8UC(channels);
case 16: return CV_16UC(channels);
default:
{
PyErr_SetString(PyExc_BufferError,
format("Unsupported uint dlpack depth: %d", dtype.bits).c_str());
return -1;
}
}
}
if (dtype.code == kDLFloat)
{
switch (dtype.bits)
{
case 16: return CV_16FC(channels);
case 32: return CV_32FC(channels);
case 64: return CV_64FC(channels);
default:
{
PyErr_SetString(PyExc_BufferError,
format("Unsupported float dlpack depth: %d", dtype.bits).c_str());
return -1;
}
}
}
PyErr_SetString(PyExc_BufferError, format("Unsupported dlpack data type: %d", dtype.code).c_str());
return -1;
}
#define PYOPENCV_EXTRA_METHODS_CV \
{"CV_MAKETYPE", CV_PY_FN_WITH_KW(pycvMakeType), "CV_MAKETYPE(depth, channels) -> retval"}, \
{"CV_8UC", (PyCFunction)(pycvMakeTypeCh<CV_8U>), METH_O, "CV_8UC(channels) -> retval"}, \
{"CV_8SC", (PyCFunction)(pycvMakeTypeCh<CV_8S>), METH_O, "CV_8SC(channels) -> retval"}, \
{"CV_16UC", (PyCFunction)(pycvMakeTypeCh<CV_16U>), METH_O, "CV_16UC(channels) -> retval"}, \
{"CV_16SC", (PyCFunction)(pycvMakeTypeCh<CV_16S>), METH_O, "CV_16SC(channels) -> retval"}, \
{"CV_32SC", (PyCFunction)(pycvMakeTypeCh<CV_32S>), METH_O, "CV_32SC(channels) -> retval"}, \
{"CV_32FC", (PyCFunction)(pycvMakeTypeCh<CV_32F>), METH_O, "CV_32FC(channels) -> retval"}, \
{"CV_64FC", (PyCFunction)(pycvMakeTypeCh<CV_64F>), METH_O, "CV_64FC(channels) -> retval"}, \
{"CV_16FC", (PyCFunction)(pycvMakeTypeCh<CV_16F>), METH_O, "CV_16FC(channels) -> retval"},
#endif // HAVE_OPENCV_CORE
#endif // OPENCV_CORE_PYOPENCV_CORE_HPP
+195
View File
@@ -0,0 +1,195 @@
#ifdef HAVE_OPENCV_CORE
#include "opencv2/core/cuda.hpp"
typedef std::vector<cuda::GpuMat> vector_GpuMat;
typedef cuda::GpuMat::Allocator GpuMat_Allocator;
typedef cuda::HostMem::AllocType HostMem_AllocType;
typedef cuda::Event::CreateFlags Event_CreateFlags;
template<> struct pyopencvVecConverter<cuda::GpuMat>
{
static bool to(PyObject* obj, std::vector<cuda::GpuMat>& value, const ArgInfo& info)
{
return pyopencv_to_generic_vec(obj, value, info);
}
static PyObject* from(const std::vector<cuda::GpuMat>& value)
{
return pyopencv_from_generic_vec(value);
}
};
CV_PY_TO_CLASS(cuda::GpuMat)
CV_PY_TO_CLASS(cuda::GpuMatND)
CV_PY_TO_CLASS(cuda::Stream)
CV_PY_TO_CLASS(cuda::Event)
CV_PY_TO_CLASS(cuda::HostMem)
CV_PY_TO_CLASS_PTR(cuda::GpuMat)
CV_PY_TO_CLASS_PTR(cuda::GpuMatND)
CV_PY_TO_CLASS_PTR(cuda::GpuMat::Allocator)
CV_PY_FROM_CLASS(cuda::GpuMat)
CV_PY_FROM_CLASS(cuda::GpuMatND)
CV_PY_FROM_CLASS(cuda::Stream)
CV_PY_FROM_CLASS(cuda::HostMem)
CV_PY_FROM_CLASS_PTR(cuda::GpuMat::Allocator)
template<>
bool fillDLPackTensor(const Ptr<cv::cuda::GpuMat>& src, DLManagedTensor* tensor, const DLDevice& device)
{
if ((device.device_type != -1 && device.device_type != kDLCUDA) || device.device_id != 0)
{
PyErr_SetString(PyExc_BufferError, "GpuMat can be exported only on GPU:0");
return false;
}
tensor->dl_tensor.data = src->cudaPtr();
tensor->dl_tensor.device.device_type = kDLCUDA;
tensor->dl_tensor.device.device_id = 0;
tensor->dl_tensor.dtype = GetDLPackType(src->elemSize1(), src->depth());
tensor->dl_tensor.shape[0] = src->rows;
tensor->dl_tensor.shape[1] = src->cols;
tensor->dl_tensor.shape[2] = src->channels();
tensor->dl_tensor.strides[0] = src->step1();
tensor->dl_tensor.strides[1] = src->channels();
tensor->dl_tensor.strides[2] = 1;
tensor->dl_tensor.byte_offset = 0;
return true;
}
template<>
bool fillDLPackTensor(const Ptr<cv::cuda::GpuMatND>& src, DLManagedTensor* tensor, const DLDevice& device)
{
if ((device.device_type != -1 && device.device_type != kDLCUDA) || device.device_id != 0)
{
PyErr_SetString(PyExc_BufferError, "GpuMatND can be exported only on GPU:0");
return false;
}
tensor->dl_tensor.data = src->getDevicePtr();
tensor->dl_tensor.device.device_type = kDLCUDA;
tensor->dl_tensor.device.device_id = 0;
tensor->dl_tensor.dtype = GetDLPackType(src->elemSize1(), CV_MAT_DEPTH(src->flags));
for (int i = 0; i < src->dims; ++i)
tensor->dl_tensor.shape[i] = src->size[i];
for (int i = 0; i < src->dims; ++i)
tensor->dl_tensor.strides[i] = src->step[i];
tensor->dl_tensor.byte_offset = 0;
return true;
}
template<>
bool parseDLPackTensor(DLManagedTensor* tensor, cv::cuda::GpuMat& obj, bool copy)
{
if (tensor->dl_tensor.byte_offset != 0)
{
PyErr_SetString(PyExc_BufferError, "Unimplemented from_dlpack for GpuMat with memory offset");
return false;
}
if (tensor->dl_tensor.ndim != 3)
{
PyErr_SetString(PyExc_BufferError, "cuda_GpuMat.from_dlpack expects a 3D tensor. Use cuda_GpuMatND.from_dlpack instead");
return false;
}
if (tensor->dl_tensor.device.device_type != kDLCUDA)
{
PyErr_SetString(PyExc_BufferError, "cuda_GpuMat.from_dlpack expects a tensor on CUDA device");
return false;
}
if (tensor->dl_tensor.strides[1] != tensor->dl_tensor.shape[2] ||
tensor->dl_tensor.strides[2] != 1)
{
PyErr_SetString(PyExc_BufferError, "Unexpected strides for image. Try use GpuMatND");
return false;
}
int type = DLPackTypeToCVType(tensor->dl_tensor.dtype, (int)tensor->dl_tensor.shape[2]);
if (type == -1)
return false;
obj = cv::cuda::GpuMat(
static_cast<int>(tensor->dl_tensor.shape[0]),
static_cast<int>(tensor->dl_tensor.shape[1]),
type,
tensor->dl_tensor.data,
static_cast<size_t>(tensor->dl_tensor.strides[0] * tensor->dl_tensor.dtype.bits / 8)
);
if (copy)
obj = obj.clone();
return true;
}
template<>
bool parseDLPackTensor(DLManagedTensor* tensor, cv::cuda::GpuMatND& obj, bool copy)
{
if (tensor->dl_tensor.byte_offset != 0)
{
PyErr_SetString(PyExc_BufferError, "Unimplemented from_dlpack for GpuMat with memory offset");
return false;
}
if (tensor->dl_tensor.device.device_type != kDLCUDA)
{
PyErr_SetString(PyExc_BufferError, "cuda_GpuMat.from_dlpack expects a tensor on CUDA device");
return false;
}
int type = DLPackTypeToCVType(tensor->dl_tensor.dtype, (int)tensor->dl_tensor.shape[2]);
if (type == -1)
return false;
std::vector<size_t> steps(tensor->dl_tensor.ndim - 1);
std::vector<int> sizes(tensor->dl_tensor.ndim);
for (int i = 0; i < tensor->dl_tensor.ndim - 1; ++i)
{
steps[i] = static_cast<size_t>(tensor->dl_tensor.strides[i] * tensor->dl_tensor.dtype.bits / 8);
sizes[i] = static_cast<int>(tensor->dl_tensor.shape[i]);
}
sizes.back() = static_cast<int>(tensor->dl_tensor.shape[tensor->dl_tensor.ndim - 1]);
obj = cv::cuda::GpuMatND(sizes, type, tensor->dl_tensor.data, steps);
if (copy)
obj = obj.clone();
return true;
}
template<>
int GetNumDims(const Ptr<cv::cuda::GpuMat>& src) { return 3; }
template<>
int GetNumDims(const Ptr<cv::cuda::GpuMatND>& src) { return src->dims; }
static PyObject* pyDLPackGpuMat(PyObject* self, PyObject* py_args, PyObject* kw) {
Ptr<cv::cuda::GpuMat> * self1 = 0;
if (!pyopencv_cuda_GpuMat_getp(self, self1))
return failmsgp("Incorrect type of self (must be 'cuda_GpuMat' or its derivative)");
return to_dlpack(*(self1), self, py_args, kw);
}
static PyObject* pyDLPackGpuMatND(PyObject* self, PyObject* py_args, PyObject* kw) {
Ptr<cv::cuda::GpuMatND> * self1 = 0;
if (!pyopencv_cuda_GpuMatND_getp(self, self1))
return failmsgp("Incorrect type of self (must be 'cuda_GpuMatND' or its derivative)");
return to_dlpack(*(self1), self, py_args, kw);
}
static PyObject* pyDLPackDeviceCUDA(PyObject*, PyObject*, PyObject*) {
return pyopencv_from(std::tuple<int, int>(kDLCUDA, 0));
}
static PyObject* pyGpuMatFromDLPack(PyObject*, PyObject* py_args, PyObject* kw) {
return from_dlpack<cv::cuda::GpuMat>(py_args, kw);
}
static PyObject* pyGpuMatNDFromDLPack(PyObject*, PyObject* py_args, PyObject* kw) {
return from_dlpack<cv::cuda::GpuMatND>(py_args, kw);
}
#define PYOPENCV_EXTRA_METHODS_cuda_GpuMat \
{"__dlpack__", CV_PY_FN_WITH_KW(pyDLPackGpuMat), ""}, \
{"__dlpack_device__", CV_PY_FN_WITH_KW(pyDLPackDeviceCUDA), ""}, \
{"from_dlpack", CV_PY_FN_WITH_KW_(pyGpuMatFromDLPack, METH_STATIC), ""}, \
#define PYOPENCV_EXTRA_METHODS_cuda_GpuMatND \
{"__dlpack__", CV_PY_FN_WITH_KW(pyDLPackGpuMatND), ""}, \
{"__dlpack_device__", CV_PY_FN_WITH_KW(pyDLPackDeviceCUDA), ""}, \
{"from_dlpack", CV_PY_FN_WITH_KW_(pyGpuMatNDFromDLPack, METH_STATIC), ""}, \
#endif
@@ -0,0 +1,36 @@
#ifdef HAVE_OPENCV_CORE
#include "opencv2/core/mat.hpp"
typedef std::vector<Range> vector_Range;
CV_PY_TO_CLASS(UMat)
CV_PY_FROM_CLASS(UMat)
static bool cv_mappable_to(const Ptr<Mat>& src, Ptr<UMat>& dst)
{
//dst.reset(new UMat(src->getUMat(ACCESS_RW)));
dst.reset(new UMat());
src->copyTo(*dst);
return true;
}
static void* cv_UMat_queue()
{
return cv::ocl::Queue::getDefault().ptr();
}
static void* cv_UMat_context()
{
return cv::ocl::Context::getDefault().ptr();
}
static Mat cv_UMat_get(const UMat* _self)
{
Mat m;
m.allocator = &GetNumpyAllocator();
_self->copyTo(m);
return m;
}
#endif
+59
View File
@@ -0,0 +1,59 @@
#error This is a shadow header file, which is not intended for processing by any compiler. \
Only bindings parser should handle this file.
namespace cv
{
class CV_EXPORTS_W UMat
{
public:
//! default constructor
CV_WRAP UMat(UMatUsageFlags usageFlags = USAGE_DEFAULT);
//! constructs 2D matrix of the specified size and type
// (_type is CV_8UC1, CV_64FC3, CV_32SC(12) etc.)
CV_WRAP UMat(int rows, int cols, int type, UMatUsageFlags usageFlags = USAGE_DEFAULT);
CV_WRAP UMat(Size size, int type, UMatUsageFlags usageFlags = USAGE_DEFAULT);
//! constructs 2D matrix and fills it with the specified value _s.
CV_WRAP UMat(int rows, int cols, int type, const Scalar& s, UMatUsageFlags usageFlags = USAGE_DEFAULT);
CV_WRAP UMat(Size size, int type, const Scalar& s, UMatUsageFlags usageFlags = USAGE_DEFAULT);
//! Mat is mappable to UMat
CV_WRAP_MAPPABLE(Ptr<Mat>);
//! returns the OpenCL queue used by OpenCV UMat
CV_WRAP_PHANTOM(static void* queue());
//! returns the OpenCL context used by OpenCV UMat
CV_WRAP_PHANTOM(static void* context());
//! copy constructor
CV_WRAP UMat(const UMat& m);
//! creates a matrix header for a part of the bigger matrix
CV_WRAP UMat(const UMat& m, const Range& rowRange, const Range& colRange = Range::all());
CV_WRAP UMat(const UMat& m, const Rect& roi);
CV_WRAP UMat(const UMat& m, const std::vector<Range>& ranges);
//CV_WRAP_AS(get) Mat getMat(int flags CV_WRAP_DEFAULT(ACCESS_RW)) const;
//! returns a numpy matrix
CV_WRAP_PHANTOM(Mat get() const);
//! returns true iff the matrix data is continuous
// (i.e. when there are no gaps between successive rows).
// similar to CV_IS_MAT_CONT(cvmat->type)
CV_WRAP bool isContinuous() const;
//! returns true if the matrix is a submatrix of another matrix
CV_WRAP bool isSubmatrix() const;
/*! Returns the OpenCL buffer handle on which UMat operates on.
The UMat instance should be kept alive during the use of the handle to prevent the buffer to be
returned to the OpenCV buffer pool.
*/
CV_WRAP void* handle(AccessFlag accessFlags) const;
// offset of the submatrix (or 0)
CV_PROP_RW size_t offset;
};
} // namespace cv