Conversation
6e4d4c3 to
f677428
Compare
modules/python/src2/hdr_parser.py
Outdated
| decls.append(decl) | ||
| if "cv.cudacodec.VideoReader.nextFrame" not in decl[0]: | ||
| # Disable Mat decl for specific cudacodec function which can take zero args, to allow python call to | ||
| # fall through to correct GpuMat decl |
There was a problem hiding this comment.
Try this instead:
ret, gpu_mat = .nextFrame(frame=cv.cuda_GpuMat())
or add separate wrapper for GPU-only (remove WRAP from nextFrame(OutputArray)):
CV_WRAP inline bool nextFrame(CV_OUT GpuMat& frame) { return nextFrame(OutputArray(frame); }
There was a problem hiding this comment.
Hi,
The problem is that a zero argument function will not fall through to the CUDA bindings, therefore your suggestion
ret, gpu_mat = _reader.nextFrame(frame=cv.cuda_GpuMat())
is a good workaround, the only issue is that this is inconsistent with the documentation
nextFrame([, frame[, stream]]) -> retval, frame
which has frame as an optional input argument.
The alternative which removes the MAT bindings
CV_WRAP inline bool nextFrame(CV_OUT GpuMat& frame, Stream& stream = Stream::Null()) { return nextFrame(OutputArray(frame), stream); }
does not work when called by
ret,_ = _reader.nextFrame(gpu_mat)
because CV_OUT and OutputArray generate different python bindings. That is OutputArray results in
const char* keywords[] = { "frame", "stream", NULL }; if( PyArg_ParseTupleAndKeywords(args, kw, "|OO:cudacodec_VideoReader.nextFrame", (char**)keywords, &pyobj_frame, &pyobj_stream) && pyopencv_to(pyobj_frame, frame, ArgInfo("frame", 1)) && pyopencv_to(pyobj_stream, stream, ArgInfo("stream", 0)) )
where frame is an optional input argument. However CV_OUT results in
const char* keywords[] = { "stream", NULL }; if( PyArg_ParseTupleAndKeywords(args, kw, "|O:cudacodec_VideoReader.nextFrame", (char**)keywords, &pyobj_stream) && pyopencv_to(pyobj_stream, stream, ArgInfo("stream", 0)) )
where frame is output only.
Should I remove the additional checks as you suggested and allow the documentation inconsistency because the test case will highlight the required calling convention?
There was a problem hiding this comment.
@alalek
The latest changes to the python bindings generation code are to ensure that
CV_WRAP inline bool nextFrame(CV_OUT GpuMat& frame, Stream& stream = Stream::Null()) { return nextFrame(frame, stream); }
will work with both
ret,_ = _reader.nextFrame(gpu_mat)
and
ret,gpu_mat = _reader.nextFrame()
There was a problem hiding this comment.
Please run it locally - it doesn't work.
$ OPENCV_PYTHON_DEBUG=1 OPENCV_PYTEST_FILTER=test_cuda ./setup_vars.sh python ${OPENCV_SRC_DIR}/modules/ts/misc/run.py -a -t python3
...
test_cudacodec (test_cuda.cuda_test) ...
OpenCV(4.1.2-dev) Error: The function/feature is not implemented (getGpuMat is available only for cuda::GpuMat and cuda::HostMem) in getGpuMat, file modules/core/src/matrix_wrap.cpp, line 359
skipped 'NVCUVID is not installed'
(generated overloads are in this order: "Mat", "GpuMat", "UMat")
This works somehow:
ret,gpu_mat = _reader.nextFrame(cv.cuda_GpuMat())
self.assertTrue(ret)
print(type(gpu_mat)) # <== add check for this
#print(cv.utils.dumpInputArray(gpu_mat)) # - no support for GpuMat
There was a problem hiding this comment.
Is that with the addition of the function declaration you suggested?
CV_WRAP inline bool nextFrame(CV_OUT GpuMat& frame, Stream& stream = Stream::Null()) { return nextFrame(frame, stream); }
I should have mentioned that I have not created a PR for that yet.
The wrapper for nextFrame() in pyopencv_generated_types_content.h with that change locally for me is
using namespace cv::cudacodec; Ptr<cv::cudacodec::VideoReader> * self1 = 0; if (!pyopencv_cudacodec_VideoReader_getp(self, self1)) return failmsgp("Incorrect type of self (must be 'cudacodec_VideoReader' or its derivative)"); Ptr<cv::cudacodec::VideoReader> _self_ = *(self1); PyObject* pyobj_frame = NULL; GpuMat frame; PyObject* pyobj_stream = NULL; Stream stream=Stream::Null(); bool retval; const char* keywords[] = { "frame", "stream", NULL }; if( PyArg_ParseTupleAndKeywords(args, kw, "|OO:cudacodec_VideoReader.nextFrame", (char**)keywords, &pyobj_frame, &pyobj_stream) && pyopencv_to(pyobj_frame, frame, ArgInfo("frame", 1)) && pyopencv_to(pyobj_stream, stream, ArgInfo("stream", 0)) ) { ERRWRAP2(retval = _self_->nextFrame(frame, stream)); return Py_BuildValue("(NN)", pyopencv_from(retval), pyopencv_from(frame)); } return NULL;
If you agree with the changes I can start a PR in the contrib repo for the additional function declaration?
There was a problem hiding this comment.
@alalek
Would it make more sense to have an additional flag to signal that the OutputArray is a GpuMat instead of adding additional overides? For example adding CV_GPU
CV_WRAP virtual bool nextFrame(CV_GPU OutputArray frame, Stream &stream = Stream::Null()) = 0;
and excluding the Mat bindings when it is present
if "CV_GPU" in arg_str:
modlist.append("/G")
arg_str = arg_str.replace("CV_GPU", "")
has_gpu_mat = any(flag == '/G' for var in decl[3] for flag in var[3])
if not has_gpu_mat:
decls.append(decl)
I guess this could them be extended to work if there was a mixture of array types to a function.
There was a problem hiding this comment.
excluding the Mat bindings
Perhaps reordering should be better.
if "CV_GPU" in arg_str:
Not sure if we need separate notation for that. Lets try to reuse this condition:
if self._generate_gpumat_decls and "cv.cuda" in decl[0]:
There was a problem hiding this comment.
Can you expand on what you mean by reordering? If we move the Mat bindings below GpuMat then GpuMat.download() will fail.
There was a problem hiding this comment.
move the Mat bindings below GpuMat
Yes, I mean this. Mat overload below GpuMat
then GpuMat.download() will fail
Is this for case with result of Mat type? (so we need to remove Mat completely)
This make sense for outputs (like OutputArray), but perhaps we should accept InputArray as numpy (Mat) array. Anyway, lets try with "excluding the Mat bindings".
There was a problem hiding this comment.
Yes the problem is that OutputArray could be a Mat or GpuMat and currently there is no way to tell until the input is parsed. This works fine if the python function has input arguments because the correct bindings will be chosen when this happens.
Currently this also works when there are no input arguments because GpuMat.download() is the only function this applies to, so returning a Mat works. Unfortunately this fails for nextFrame(). Therefore if we reorder it will work for nextFrame() but fail for GpuMat.download().
This make sense for outputs (like OutputArray), but perhaps we should accept InputArray as numpy (Mat) array. Anyway, lets try with "excluding the Mat bindings".
I agree and I think that signaling that OutputArray is a GpuMat will allow input arrays which are a mixture of both types to be processed. Currently I don't think there are any cuda functions which take a mixture of Mat and GpuMat but I may be wrong.
…thon bindings that allow the argument to be an optional output in the same way as OutputArray.
If the function signature includes the cuda namespace, i.e.
the compilation will fail because Is there a way to tell the type of the |
|
Just don't include Mixture of parameters is not supported. Current overloads can handle all |
Fair enough, should it be documented somewhere, that cuda functions with only an Is
redundant?
This was a bad example but I would have thought the size of the generated code would be the same, because you would have a single wrapper for the function containing a mixture of input types? |
Would you prefer or |
If size is an issue wouldn't it be better to add a flag to
and then all of the CUDA function wrappers except |
|
Please avoid adding of CV_GPU/CV_MAT modifiers.
Remove wrapping of generic |
Thank you for clarifying this, I have been completely confused because for most (probably all) functions in the cuda namespace, the arguments of type Therefore would it be correct to say the existing
If so should all cuda functions have |
Fix cudacodec python * Add python bindings to cudacodec. * Allow args with CV_OUT GpuMat& or CV_OUT cuda::GpuMat& to generate python bindings that allow the argument to be an optional output in the same way as OutputArray. * Add wrapper flag to indicate that an OutputArray is a GpuMat. * python: drop CV_GPU, extra checks in test * Remove "cuda::GpuMat" check rom python parser
Merge with contrib: https://github.com/opencv/opencv_contrib/pull/2362/files
This pullrequest adds python bindings to cudacodec
Because cudacodec is in it's own namespace, python bindings are not currently generated for it. This PR fixes this and adds tests to confirm the new functionality is working.