};
//! 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);
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();
}
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
}
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
#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
return *this;
}
-void cv::gpu::createContinuous(int rows, int cols, int type, GpuMat& m)
+namespace
{
- const int area = rows * cols;
+ template <class ObjType>
+ 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<int>((delta2 - minstep) / m.step + 1), m.rows);
- wholeSize.width = std::max(static_cast<int>((delta2 - m.step * (wholeSize.height - 1)) / esz), m.cols);
+ default:
+ arr.create(rows, cols, type);
+ }
+}
- if (wholeSize.height < rows || wholeSize.width < cols)
+namespace
+{
+ template <class ObjType>
+ 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<int>((delta2 - minstep) / static_cast<size_t>(obj.step) + 1), obj.rows);
+ wholeSize.width = std::max(static_cast<int>((delta2 - static_cast<size_t>(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)