diff --git a/modules/cudacodec/include/opencv2/cudacodec.hpp b/modules/cudacodec/include/opencv2/cudacodec.hpp index 334c17f6e..54ec5bed0 100644 --- a/modules/cudacodec/include/opencv2/cudacodec.hpp +++ b/modules/cudacodec/include/opencv2/cudacodec.hpp @@ -353,8 +353,12 @@ public: /** @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 @@ public: /** @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 @@ public: /** @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. */ - CV_WRAP virtual bool retrieve(CV_OUT OutputArray frame, const size_t idx = static_cast(VideoReaderProps::PROP_DECODED_FRAME_IDX)) const = 0; + 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 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 @@ public: @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 @@ public: @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 e2f756af2..dc9f7a40a 100644 --- a/modules/cudacodec/misc/python/test/test_cudacodec.py +++ b/modules/cudacodec/misc/python/test/test_cudacodec.py @@ -34,6 +34,35 @@ class cudacodec_test(NewOpenCVTests): 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 d1a41fbff..903defaf3 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 c2eb7a381..e37833ef8 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 9cadd123b..27291c2e9 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 000000000..8cd7c6cf7 --- /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