From d2760791a4e109c415020fcca72770148ca6d717 Mon Sep 17 00:00:00 2001 From: cudawarped <12133430+cudawarped@users.noreply.github.com> Date: Thu, 2 Jun 2022 13:35:44 +0100 Subject: [PATCH] Fix cudacodec and cudastereo python bindings. --- .../cudacodec/include/opencv2/cudacodec.hpp | 62 +++++++++++++++---- .../misc/python/test/test_cudacodec.py | 29 +++++++++ modules/cudacodec/src/video_reader.cpp | 24 ++++--- modules/cudacodec/test/test_video.cpp | 2 + .../cudastereo/include/opencv2/cudastereo.hpp | 5 +- .../misc/python/test/test_cudastereo.py | 28 +++++++++ 6 files changed, 129 insertions(+), 21 deletions(-) create mode 100644 modules/cudastereo/misc/python/test/test_cudastereo.py diff --git a/modules/cudacodec/include/opencv2/cudacodec.hpp b/modules/cudacodec/include/opencv2/cudacodec.hpp index 334c17f6e5f..54ec5bed0a8 100644 --- a/modules/cudacodec/include/opencv2/cudacodec.hpp +++ b/modules/cudacodec/include/opencv2/cudacodec.hpp @@ -353,8 +353,12 @@ class CV_EXPORTS_W VideoReader /** @brief Grabs, decodes and returns the next video frame. - If no frames has been grabbed (there are no more frames in video file), the methods return false . - The method throws Exception if error occurs. + @param [out] frame The video frame. + @param stream Stream for the asynchronous version. + @return `false` if no frames have been grabbed. + + If no frames have been grabbed (there are no more frames in video file), the methods return false. + The method throws an Exception if error occurs. */ CV_WRAP virtual bool nextFrame(CV_OUT GpuMat& frame, Stream &stream = Stream::Null()) = 0; @@ -364,6 +368,7 @@ class CV_EXPORTS_W VideoReader /** @brief Grabs the next frame from the video source. + @param stream Stream for the asynchronous version. @return `true` (non-zero) in the case of success. The method/function grabs the next frame from video file or camera and returns true (non-zero) in @@ -376,17 +381,44 @@ class CV_EXPORTS_W VideoReader /** @brief Returns previously grabbed video data. - @param [out] frame The returned data which depends on the provided idx. If there is no new data since the last call to grab() the image will be empty. - @param idx Determins the returned data inside image. The returned data can be the: - Decoded frame, idx = get(PROP_DECODED_FRAME_IDX). - Extra data if available, idx = get(PROP_EXTRA_DATA_INDEX). - Raw encoded data package. To retrieve package i, idx = get(PROP_RAW_PACKAGES_BASE_INDEX) + i with i < get(PROP_NUMBER_OF_RAW_PACKAGES_SINCE_LAST_GRAB) - @return `false` if no frames has been grabbed + @param [out] frame The returned data which depends on the provided idx. + @param idx Determines the returned data inside image. The returned data can be the: + - Decoded frame, idx = get(PROP_DECODED_FRAME_IDX). + - Extra data if available, idx = get(PROP_EXTRA_DATA_INDEX). + - Raw encoded data package. To retrieve package i, idx = get(PROP_RAW_PACKAGES_BASE_INDEX) + i with i < get(PROP_NUMBER_OF_RAW_PACKAGES_SINCE_LAST_GRAB) + @return `false` if no frames have been grabbed + + The method returns data associated with the current video source since the last call to grab() or the creation of the VideoReader. If no data is present + the method returns false and the function returns an empty image. + */ + virtual bool retrieve(OutputArray frame, const size_t idx = static_cast(VideoReaderProps::PROP_DECODED_FRAME_IDX)) const = 0; + + /** @brief Returns previously grabbed encoded video data. + + @param [out] frame The encoded video data. + @param idx Determines the returned data inside image. The returned data can be the: + - Extra data if available, idx = get(PROP_EXTRA_DATA_INDEX). + - Raw encoded data package. To retrieve package i, idx = get(PROP_RAW_PACKAGES_BASE_INDEX) + i with i < get(PROP_NUMBER_OF_RAW_PACKAGES_SINCE_LAST_GRAB) + @return `false` if no frames have been grabbed The method returns data associated with the current video source since the last call to grab() or the creation of the VideoReader. If no data is present the method returns false and the function returns an empty image. */ - CV_WRAP virtual bool retrieve(CV_OUT OutputArray frame, const size_t idx = static_cast(VideoReaderProps::PROP_DECODED_FRAME_IDX)) const = 0; + CV_WRAP inline bool retrieve(CV_OUT Mat& frame, const size_t idx) const { + return retrieve(OutputArray(frame), idx); + } + + /** @brief Returns the next video frame. + + @param [out] frame The video frame. If grab() has not been called then this will be empty(). + @return `false` if no frames have been grabbed + + The method returns data associated with the current video source since the last call to grab(). If no data is present + the method returns false and the function returns an empty image. + */ + CV_WRAP inline bool retrieve(CV_OUT GpuMat& frame) const { + return retrieve(OutputArray(frame)); + } /** @brief Sets a property in the VideoReader. @@ -395,7 +427,10 @@ class CV_EXPORTS_W VideoReader @param propertyVal Value of the property. @return `true` if the property has been set. */ - CV_WRAP virtual bool set(const VideoReaderProps propertyId, const double propertyVal) = 0; + virtual bool set(const VideoReaderProps propertyId, const double propertyVal) = 0; + CV_WRAP inline bool setVideoReaderProps(const VideoReaderProps propertyId, double propertyVal) { + return set(propertyId, propertyVal); + } /** @brief Set the desired ColorFormat for the frame returned by nextFrame()/retrieve(). @@ -408,11 +443,12 @@ class CV_EXPORTS_W VideoReader @param propertyId Property identifier from cv::cudacodec::VideoReaderProps (eg. cv::cudacodec::VideoReaderProps::PROP_DECODED_FRAME_IDX, cv::cudacodec::VideoReaderProps::PROP_EXTRA_DATA_INDEX, ...). @param propertyVal - In - Optional value required for querying specific propertyId's, e.g. the index of the raw package to be checked for a key frame (cv::cudacodec::VideoReaderProps::PROP_LRF_HAS_KEY_FRAME). - Out - Value of the property. + - In: Optional value required for querying specific propertyId's, e.g. the index of the raw package to be checked for a key frame (cv::cudacodec::VideoReaderProps::PROP_LRF_HAS_KEY_FRAME). + - Out: Value of the property. @return `true` unless the property is not supported. */ - CV_WRAP virtual bool get(const VideoReaderProps propertyId, CV_IN_OUT double& propertyVal) const = 0; + virtual bool get(const VideoReaderProps propertyId, double& propertyVal) const = 0; + CV_WRAP virtual bool getVideoReaderProps(const VideoReaderProps propertyId, CV_OUT double& propertyValOut, double propertyValIn = 0) const = 0; /** @brief Retrieves the specified property used by the VideoSource. diff --git a/modules/cudacodec/misc/python/test/test_cudacodec.py b/modules/cudacodec/misc/python/test/test_cudacodec.py index e2f756af245..dc9f7a40aae 100644 --- a/modules/cudacodec/misc/python/test/test_cudacodec.py +++ b/modules/cudacodec/misc/python/test/test_cudacodec.py @@ -34,6 +34,35 @@ def test_reader(self): ret, _gpu_mat2 = reader.nextFrame(gpu_mat) #TODO: self.assertTrue(gpu_mat == gpu_mat2) self.assertTrue(ret) + + params = cv.cudacodec.VideoReaderInitParams() + params.rawMode = True + ms_gs = 1234 + reader = cv.cudacodec.createVideoReader(vid_path,[cv.CAP_PROP_OPEN_TIMEOUT_MSEC, ms_gs], params) + ret, ms = reader.get(cv.CAP_PROP_OPEN_TIMEOUT_MSEC) + self.assertTrue(ret and ms == ms_gs) + ret, raw_mode = reader.getVideoReaderProps(cv.cudacodec.VideoReaderProps_PROP_RAW_MODE) + self.assertTrue(ret and raw_mode) + + ret, colour_code = reader.getVideoReaderProps(cv.cudacodec.VideoReaderProps_PROP_COLOR_FORMAT) + self.assertTrue(ret and colour_code == cv.cudacodec.ColorFormat_BGRA) + colour_code_gs = cv.cudacodec.ColorFormat_GRAY + reader.set(colour_code_gs) + ret, colour_code = reader.getVideoReaderProps(cv.cudacodec.VideoReaderProps_PROP_COLOR_FORMAT) + self.assertTrue(ret and colour_code == colour_code_gs) + + ret, i_base = reader.getVideoReaderProps(cv.cudacodec.VideoReaderProps_PROP_RAW_PACKAGES_BASE_INDEX) + self.assertTrue(ret and i_base == 2.0) + self.assertTrue(reader.grab()) + ret, gpu_mat3 = reader.retrieve() + self.assertTrue(ret and isinstance(gpu_mat3,cv.cuda.GpuMat) and not gpu_mat3.empty()) + ret = reader.retrieve(gpu_mat3) + self.assertTrue(ret and isinstance(gpu_mat3,cv.cuda.GpuMat) and not gpu_mat3.empty()) + ret, n_raw_packages_since_last_grab = reader.getVideoReaderProps(cv.cudacodec.VideoReaderProps_PROP_NUMBER_OF_RAW_PACKAGES_SINCE_LAST_GRAB) + self.assertTrue(ret and n_raw_packages_since_last_grab > 0) + ret, raw_data = reader.retrieve(int(i_base)) + self.assertTrue(ret and isinstance(raw_data,np.ndarray) and np.any(raw_data)) + except cv.error as e: notSupported = (e.code == cv.Error.StsNotImplemented or e.code == cv.Error.StsUnsupportedFormat or e.code == cv.Error.GPU_API_CALL_ERROR) self.assertTrue(notSupported) diff --git a/modules/cudacodec/src/video_reader.cpp b/modules/cudacodec/src/video_reader.cpp index d1a41fbff05..903defaf379 100644 --- a/modules/cudacodec/src/video_reader.cpp +++ b/modules/cudacodec/src/video_reader.cpp @@ -102,6 +102,7 @@ namespace void set(const ColorFormat _colorFormat) CV_OVERRIDE; bool get(const VideoReaderProps propertyId, double& propertyVal) const CV_OVERRIDE; + bool getVideoReaderProps(const VideoReaderProps propertyId, double& propertyValOut, double propertyValIn) const CV_OVERRIDE; bool get(const int propertyId, double& propertyVal) const CV_OVERRIDE; @@ -246,13 +247,13 @@ namespace } else if (idx == extraDataIdx) { if (!frame.isMat()) - CV_Error(Error::StsUnsupportedFormat, "Extra data is stored on the host and must be retrueved using a cv::Mat"); + CV_Error(Error::StsUnsupportedFormat, "Extra data is stored on the host and must be retrieved using a cv::Mat"); videoSource_->getExtraData(frame.getMatRef()); } else{ if (idx >= rawPacketsBaseIdx && idx < rawPacketsBaseIdx + rawPackets.size()) { if (!frame.isMat()) - CV_Error(Error::StsUnsupportedFormat, "Raw data is stored on the host and must retrievd using a cv::Mat"); + CV_Error(Error::StsUnsupportedFormat, "Raw data is stored on the host and must be retrieved using a cv::Mat"); Mat tmp(1, rawPackets.at(idx - rawPacketsBaseIdx).size, CV_8UC1, rawPackets.at(idx - rawPacketsBaseIdx).Data(), rawPackets.at(idx - rawPacketsBaseIdx).size); frame.getMatRef() = tmp; } @@ -264,8 +265,9 @@ namespace switch (propertyId) { case VideoReaderProps::PROP_RAW_MODE : videoSource_->SetRawMode(static_cast(propertyVal)); + return true; } - return true; + return false; } void VideoReaderImpl::set(const ColorFormat _colorFormat) { @@ -303,20 +305,28 @@ namespace else break; } - case VideoReaderProps::PROP_ALLOW_FRAME_DROP: { + case VideoReaderProps::PROP_ALLOW_FRAME_DROP: propertyVal = videoParser_->allowFrameDrops(); return true; - } - case VideoReaderProps::PROP_UDP_SOURCE: { + case VideoReaderProps::PROP_UDP_SOURCE: propertyVal = videoParser_->udpSource(); return true; - } + case VideoReaderProps::PROP_COLOR_FORMAT: + propertyVal = static_cast(colorFormat); + return true; default: break; } return false; } + bool VideoReaderImpl::getVideoReaderProps(const VideoReaderProps propertyId, double& propertyValOut, double propertyValIn) const { + double propertyValInOut = propertyValIn; + const bool ret = get(propertyId, propertyValInOut); + propertyValOut = propertyValInOut; + return ret; + } + bool VideoReaderImpl::get(const int propertyId, double& propertyVal) const { return videoSource_->get(propertyId, propertyVal); } diff --git a/modules/cudacodec/test/test_video.cpp b/modules/cudacodec/test/test_video.cpp index c2eb7a38102..e37833ef8bd 100644 --- a/modules/cudacodec/test/test_video.cpp +++ b/modules/cudacodec/test/test_video.cpp @@ -201,6 +201,8 @@ CUDA_TEST_P(Video, Reader) // request a different colour format for each frame const std::pair< cudacodec::ColorFormat, int>& formatToChannels = formatsToChannels[i % formatsToChannels.size()]; reader->set(formatToChannels.first); + double colorFormat; + ASSERT_TRUE(reader->get(cudacodec::VideoReaderProps::PROP_COLOR_FORMAT, colorFormat) && static_cast(colorFormat) == formatToChannels.first); ASSERT_TRUE(reader->nextFrame(frame)); if(!fmt.valid) fmt = reader->format(); diff --git a/modules/cudastereo/include/opencv2/cudastereo.hpp b/modules/cudastereo/include/opencv2/cudastereo.hpp index 9cadd123b53..27291c2e97d 100644 --- a/modules/cudastereo/include/opencv2/cudastereo.hpp +++ b/modules/cudastereo/include/opencv2/cudastereo.hpp @@ -355,7 +355,10 @@ disparity map. @sa reprojectImageTo3D */ -CV_EXPORTS_W void reprojectImageTo3D(InputArray disp, OutputArray xyzw, InputArray Q, int dst_cn = 4, Stream& stream = Stream::Null()); +CV_EXPORTS void reprojectImageTo3D(InputArray disp, OutputArray xyzw, InputArray Q, int dst_cn = 4, Stream& stream = Stream::Null()); +CV_EXPORTS_W inline void reprojectImageTo3D(GpuMat disp, CV_OUT GpuMat& xyzw, Mat Q, int dst_cn = 4, Stream& stream = Stream::Null()) { + reprojectImageTo3D((InputArray)disp, (OutputArray)xyzw, (InputArray)Q, dst_cn, stream); +} /** @brief Colors a disparity image. diff --git a/modules/cudastereo/misc/python/test/test_cudastereo.py b/modules/cudastereo/misc/python/test/test_cudastereo.py new file mode 100644 index 00000000000..8cd7c6cf762 --- /dev/null +++ b/modules/cudastereo/misc/python/test/test_cudastereo.py @@ -0,0 +1,28 @@ +#!/usr/bin/env python +import os +import cv2 as cv +import numpy as np + +from tests_common import NewOpenCVTests, unittest + +class cudastereo_test(NewOpenCVTests): + def setUp(self): + super(cudastereo_test, self).setUp() + if not cv.cuda.getCudaEnabledDeviceCount(): + self.skipTest("No CUDA-capable device is detected") + + def test_reprojectImageTo3D(self): + # Test's the functionality but not the results from reprojectImageTo3D + sz = (128,128) + np_disparity = np.random.randint(0, 64, sz, dtype=np.int16) + cu_disparity = cv.cuda_GpuMat(np_disparity) + np_q = np.random.randint(0, 100, (4, 4)).astype(np.float32) + stream = cv.cuda.Stream() + cu_xyz = cv.cuda.reprojectImageTo3D(cu_disparity, np_q, stream = stream) + self.assertTrue(cu_xyz.type() == cv.CV_32FC4 and cu_xyz.size() == sz) + cu_xyz1 = cv.cuda.GpuMat(sz, cv.CV_32FC3) + cv.cuda.reprojectImageTo3D(cu_disparity, np_q, cu_xyz1, 3, stream) + self.assertTrue(cu_xyz1.type() == cv.CV_32FC3 and cu_xyz1.size() == sz) + +if __name__ == '__main__': + NewOpenCVTests.bootstrap() \ No newline at end of file