Skip to content

Exposing CV_MAKETYPE(depth, cn) and CV_8UC(n), CV_8SC(n) etc., macros to the Python binding for arbitrary channel number handling in cv2.cuda.GpuMat #23628

@alllexx88

Description

@alllexx88

Describe the feature and motivation

It would be great to expose the following macros to the Python binding:

#define CV_MAKETYPE(depth, cn)   (CV_MAT_DEPTH(depth) + (((cn)-1) << CV_CN_SHIFT))
#define CV_8UC(n)   CV_MAKETYPE(CV_8U,(n))
#define CV_8SC(n)   CV_MAKETYPE(CV_8S,(n))
#define CV_16UC(n)   CV_MAKETYPE(CV_16U,(n))
#define CV_16SC(n)   CV_MAKETYPE(CV_16S,(n))
#define CV_32SC(n)   CV_MAKETYPE(CV_32S,(n))
#define CV_32FC(n)   CV_MAKETYPE(CV_32F,(n))
#define CV_64FC(n)   CV_MAKETYPE(CV_64F,(n))

While they aren't of much use for the general Python interface (which uses NumPy arrays with shape and dtype attributes readily available), they can be useful for Cuda GpuMat handling. Consider the following code to initialize a GpuMat from Cuda memory from a CuPy array (it uses createGpuMatFromCudaMemory from #23371):

import cv2
import cupy as cp


def cv_cuda_gpumat_from_cp_array(arr: cp.ndarray) -> cv2.cuda.GpuMat:
    assert len(arr.shape) in (2, 3), "CuPy array must have 2 or 3 dimensions to be a valid GpuMat"
    type_map = {
        cp.dtype('uint8'): cv2.CV_8U,
        cp.dtype('int8'): cv2.CV_8S,
        cp.dtype('uint16'): cv2.CV_16U,
        cp.dtype('int16'): cv2.CV_16S,
        cp.dtype('int32'): cv2.CV_32S,
        cp.dtype('float32'): cv2.CV_32F,
        cp.dtype('float64'): cv2.CV_64F
    }
    depth = type_map.get(arr.dtype)
    assert depth is not None, "Unsupported CuPy array dtype"
    channels = 1 if len(arr.shape) == 2 else arr.shape[2]
    # equivalent to unexposed opencv C++ macro CV_MAKETYPE(depth,channels):
    # (depth&7) + ((channels - 1) << 3)
    mat_type = depth + ((channels - 1) << 3)
    mat = cv2.cuda.createGpuMatFromCudaMemory(arr.__cuda_array_interface__['shape'][1::-1],
                                              mat_type,
                                              arr.__cuda_array_interface__['data'][0])
    return mat

The mat_type =... line would be more readable with CV_MAKETYPE available, e.g.,

mat_type = cv2.CV_MAKETYPE(depth, channels)

Thanks in advance!

Additional context

No response

Metadata

Metadata

Assignees

Type

No type

Projects

No projects

Milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions