made createContinuous & ensureSizeIsEnough generic (OutputArray support)

This commit is contained in:
Vladislav Vinogradov 2013-04-26 10:53:15 +04:00
parent f17b836d24
commit 1db4afac6a
4 changed files with 125 additions and 31 deletions

View File

@ -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();

View File

@ -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

View File

@ -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

View File

@ -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 <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);
case _InputArray::MAT:
::createContinuousImpl(rows, cols, type, arr.getMatRef());
break;
case _InputArray::GPU_MAT:
::createContinuousImpl(rows, cols, type, arr.getGpuMatRef());
break;
case _InputArray::CUDA_MEM:
::createContinuousImpl(rows, cols, type, arr.getCudaMemRef());
break;
default:
arr.create(rows, cols, type);
}
else
}
namespace
{
template <class ObjType>
void ensureSizeIsEnoughImpl(int rows, int cols, int type, ObjType& obj)
{
const size_t esz = m.elemSize();
const ptrdiff_t delta2 = m.dataend - m.datastart;
const size_t minstep = m.cols * esz;
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);
if (wholeSize.height < rows || wholeSize.width < cols)
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)