Files
opencv--opencv/modules/core/misc/python/pyopencv_cuda.hpp
T
2026-07-13 12:06:04 +08:00

196 lines
6.9 KiB
C++

#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