From: Vladislav Vinogradov Date: Fri, 26 Apr 2013 06:53:15 +0000 (+0400) Subject: made createContinuous & ensureSizeIsEnough generic (OutputArray support) X-Git-Tag: accepted/tizen/6.0/unified/20201030.111113~3878^2~4 X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=1db4afac6aa52be3e158a5fdc03572ee0d51baf1;p=platform%2Fupstream%2Fopencv.git made createContinuous & ensureSizeIsEnough generic (OutputArray support) --- diff --git a/modules/core/include/opencv2/core/gpu.hpp b/modules/core/include/opencv2/core/gpu.hpp index bbeda31..7ddbf7f 100644 --- a/modules/core/include/opencv2/core/gpu.hpp +++ b/modules/core/include/opencv2/core/gpu.hpp @@ -252,11 +252,11 @@ public: }; //! creates continuous GPU matrix -CV_EXPORTS void createContinuous(int rows, int cols, int type, GpuMat& m); +CV_EXPORTS void createContinuous(int rows, int cols, int type, OutputArray arr); //! ensures that size of the given matrix is not less than (rows, cols) size //! and matrix type is match specified one too -CV_EXPORTS void ensureSizeIsEnough(int rows, int cols, int type, GpuMat& m); +CV_EXPORTS void ensureSizeIsEnough(int rows, int cols, int type, OutputArray arr); CV_EXPORTS GpuMat allocMatFromBuf(int rows, int cols, int type, GpuMat& mat); @@ -296,6 +296,10 @@ public: void create(int rows, int cols, int type); void create(Size size, int type); + //! creates alternative CudaMem header for the same data, with different + //! number of channels and/or different number of rows + CudaMem reshape(int cn, int rows = 0) const; + //! decrements reference counter and released memory if needed. void release(); diff --git a/modules/core/include/opencv2/core/gpu.inl.hpp b/modules/core/include/opencv2/core/gpu.inl.hpp index a30f1b6..b44c2b1 100644 --- a/modules/core/include/opencv2/core/gpu.inl.hpp +++ b/modules/core/include/opencv2/core/gpu.inl.hpp @@ -347,9 +347,9 @@ GpuMat createContinuous(int rows, int cols, int type) } static inline -void createContinuous(Size size, int type, GpuMat& m) +void createContinuous(Size size, int type, OutputArray arr) { - createContinuous(size.height, size.width, type, m); + createContinuous(size.height, size.width, type, arr); } static inline @@ -361,9 +361,9 @@ GpuMat createContinuous(Size size, int type) } static inline -void ensureSizeIsEnough(Size size, int type, GpuMat& m) +void ensureSizeIsEnough(Size size, int type, OutputArray arr) { - ensureSizeIsEnough(size.height, size.width, type, m); + ensureSizeIsEnough(size.height, size.width, type, arr); } static inline diff --git a/modules/core/src/gpu_cuda_mem.cpp b/modules/core/src/gpu_cuda_mem.cpp index 3681fd7..52de069 100644 --- a/modules/core/src/gpu_cuda_mem.cpp +++ b/modules/core/src/gpu_cuda_mem.cpp @@ -121,6 +121,49 @@ void cv::gpu::CudaMem::create(int rows_, int cols_, int type_) #endif } +CudaMem cv::gpu::CudaMem::reshape(int new_cn, int new_rows) const +{ + CudaMem hdr = *this; + + int cn = channels(); + if (new_cn == 0) + new_cn = cn; + + int total_width = cols * cn; + + if ((new_cn > total_width || total_width % new_cn != 0) && new_rows == 0) + new_rows = rows * total_width / new_cn; + + if (new_rows != 0 && new_rows != rows) + { + int total_size = total_width * rows; + + if (!isContinuous()) + CV_Error(cv::Error::BadStep, "The matrix is not continuous, thus its number of rows can not be changed"); + + if ((unsigned)new_rows > (unsigned)total_size) + CV_Error(cv::Error::StsOutOfRange, "Bad new number of rows"); + + total_width = total_size / new_rows; + + if (total_width * new_rows != total_size) + CV_Error(cv::Error::StsBadArg, "The total number of matrix elements is not divisible by the new number of rows"); + + hdr.rows = new_rows; + hdr.step = total_width * elemSize1(); + } + + int new_width = total_width / new_cn; + + if (new_width * new_cn != total_width) + CV_Error(cv::Error::BadNumChannels, "The total width is not divisible by the new number of channels"); + + hdr.cols = new_width; + hdr.flags = (hdr.flags & ~CV_MAT_CN_MASK) | ((new_cn - 1) << CV_CN_SHIFT); + + return hdr; +} + void cv::gpu::CudaMem::release() { #ifdef HAVE_CUDA diff --git a/modules/core/src/gpu_mat.cpp b/modules/core/src/gpu_mat.cpp index fb8251c..1bbcb84 100644 --- a/modules/core/src/gpu_mat.cpp +++ b/modules/core/src/gpu_mat.cpp @@ -1022,48 +1022,95 @@ GpuMat& cv::gpu::GpuMat::adjustROI(int dtop, int dbottom, int dleft, int dright) return *this; } -void cv::gpu::createContinuous(int rows, int cols, int type, GpuMat& m) +namespace { - const int area = rows * cols; + template + void createContinuousImpl(int rows, int cols, int type, ObjType& obj) + { + const int area = rows * cols; - if (m.empty() || m.type() != type || !m.isContinuous() || m.size().area() < area) - m.create(1, area, type); + if (obj.empty() || obj.type() != type || !obj.isContinuous() || obj.size().area() < area) + obj.create(1, area, type); - m.cols = cols; - m.rows = rows; - m.step = m.elemSize() * cols; - m.flags |= Mat::CONTINUOUS_FLAG; + obj = obj.reshape(obj.channels(), rows); + } } -void cv::gpu::ensureSizeIsEnough(int rows, int cols, int type, GpuMat& m) +void cv::gpu::createContinuous(int rows, int cols, int type, OutputArray arr) { - if (m.empty() || m.type() != type || m.data != m.datastart) + switch (arr.kind()) { - m.create(rows, cols, type); - } - else - { - const size_t esz = m.elemSize(); - const ptrdiff_t delta2 = m.dataend - m.datastart; + case _InputArray::MAT: + ::createContinuousImpl(rows, cols, type, arr.getMatRef()); + break; + + case _InputArray::GPU_MAT: + ::createContinuousImpl(rows, cols, type, arr.getGpuMatRef()); + break; - const size_t minstep = m.cols * esz; + case _InputArray::CUDA_MEM: + ::createContinuousImpl(rows, cols, type, arr.getCudaMemRef()); + break; - Size wholeSize; - wholeSize.height = std::max(static_cast((delta2 - minstep) / m.step + 1), m.rows); - wholeSize.width = std::max(static_cast((delta2 - m.step * (wholeSize.height - 1)) / esz), m.cols); + default: + arr.create(rows, cols, type); + } +} - if (wholeSize.height < rows || wholeSize.width < cols) +namespace +{ + template + void ensureSizeIsEnoughImpl(int rows, int cols, int type, ObjType& obj) + { + if (obj.empty() || obj.type() != type || obj.data != obj.datastart) { - m.create(rows, cols, type); + obj.create(rows, cols, type); } else { - m.cols = cols; - m.rows = rows; + const size_t esz = obj.elemSize(); + const ptrdiff_t delta2 = obj.dataend - obj.datastart; + + const size_t minstep = obj.cols * esz; + + Size wholeSize; + wholeSize.height = std::max(static_cast((delta2 - minstep) / static_cast(obj.step) + 1), obj.rows); + wholeSize.width = std::max(static_cast((delta2 - static_cast(obj.step) * (wholeSize.height - 1)) / esz), obj.cols); + + if (wholeSize.height < rows || wholeSize.width < cols) + { + obj.create(rows, cols, type); + } + else + { + obj.cols = cols; + obj.rows = rows; + } } } } +void cv::gpu::ensureSizeIsEnough(int rows, int cols, int type, OutputArray arr) +{ + switch (arr.kind()) + { + case _InputArray::MAT: + ::ensureSizeIsEnoughImpl(rows, cols, type, arr.getMatRef()); + break; + + case _InputArray::GPU_MAT: + ::ensureSizeIsEnoughImpl(rows, cols, type, arr.getGpuMatRef()); + break; + + case _InputArray::CUDA_MEM: + ::ensureSizeIsEnoughImpl(rows, cols, type, arr.getCudaMemRef()); + break; + + default: + arr.create(rows, cols, type); + } +} + GpuMat cv::gpu::allocMatFromBuf(int rows, int cols, int type, GpuMat& mat) { if (!mat.empty() && mat.type() == type && mat.rows >= rows && mat.cols >= cols)