Commit b5c92a7d authored by Vladislav Vinogradov's avatar Vladislav Vinogradov

Added implementation and test for the GPU version of flip, resize, sum, minMax,…

Added implementation and test for the GPU version of flip, resize, sum, minMax, copyConstBorder, setTo, based on NPP.
parent 3d9c78f4
......@@ -45,6 +45,7 @@
#include <vector>
#include "opencv2/core/core.hpp"
#include "opencv2/imgproc/imgproc.hpp"
#include "opencv2/gpu/devmem2d.hpp"
namespace cv
......@@ -372,9 +373,29 @@ namespace cv
//! computes mean value and standard deviation of all or selected array elements
CV_EXPORTS void meanStdDev(const GpuMat& mtx, Scalar& mean, Scalar& stddev);
//! computes norm of array
//! Supports NORM_INF, NORM_L1, NORM_L2
CV_EXPORTS double norm(const GpuMat& src1, int normType=NORM_L2);
//! computes norm of the difference between two arrays
//! Supports NORM_INF, NORM_L1, NORM_L2
CV_EXPORTS double norm(const GpuMat& src1, const GpuMat& src2, int normType=NORM_L2);
//! reverses the order of the rows, columns or both in a matrix
CV_EXPORTS void flip(const GpuMat& a, GpuMat& b, int flipCode);
//! resizes the image
//! Supports INTER_NEAREST, INTER_LINEAR, INTER_CUBIC, INTER_LANCZOS4
CV_EXPORTS void resize(const GpuMat& src, GpuMat& dst, Size dsize, double fx=0, double fy=0, int interpolation=INTER_LINEAR);
//! computes sum of array elements
CV_EXPORTS Scalar sum(const GpuMat& m);
//! finds global minimum and maximum array elements and returns their values
CV_EXPORTS void minMax(const GpuMat& src, double* minVal, double* maxVal = 0);
//! copies 2D array to a larger destination array and pads borders with user-specifiable constant
CV_EXPORTS void copyConstBorder(const GpuMat& src, GpuMat& dst, int top, int bottom, int left, int right, const Scalar& value = Scalar());
////////////////////////////// Image processing //////////////////////////////
// DST[x,y] = SRC[xmap[x,y],ymap[x,y]] with bilinear interpolation.
// xymap.type() == xymap.type() == CV_32FC1
......
......@@ -66,6 +66,16 @@ void cv::gpu::meanStdDev(const GpuMat& mtx, Scalar& mean, Scalar& stddev) { thro
double cv::gpu::norm(const GpuMat& src1, int normType) { throw_nogpu(); return 0.0; }
double cv::gpu::norm(const GpuMat& src1, const GpuMat& src2, int normType) { throw_nogpu(); return 0.0; }
void cv::gpu::flip(const GpuMat& a, GpuMat& b, int flipCode) { throw_nogpu(); }
void cv::gpu::resize(const GpuMat& src, GpuMat& dst, Size dsize, double fx, double fy, int interpolation) { throw_nogpu(); }
Scalar cv::gpu::sum(const GpuMat& m) { throw_nogpu(); return Scalar(); }
void cv::gpu::minMax(const GpuMat& src, double* minVal, double* maxVal) { throw_nogpu(); }
void cv::gpu::copyConstBorder(const GpuMat& src, GpuMat& dst, int top, int bottom, int left, int right, const Scalar& value) { throw_nogpu(); }
#else /* !defined (HAVE_CUDA) */
namespace
......@@ -247,13 +257,157 @@ double cv::gpu::norm(const GpuMat& src1, const GpuMat& src2, int normType)
sz.height = src1.rows;
int funcIdx = normType >> 1;
Npp64f retVal[3];
Scalar retVal;
npp_norm_diff_func[funcIdx]((const Npp8u*)src1.ptr<char>(), src1.step,
(const Npp8u*)src2.ptr<char>(), src2.step,
sz, retVal);
sz, retVal.val);
return retVal[0];
}
void cv::gpu::flip(const GpuMat& src, GpuMat& dst, int flipCode)
{
CV_Assert(src.type() == CV_8UC1 || src.type() == CV_8UC4);
dst.create( src.size(), src.type() );
NppiSize sz;
sz.width = src.cols;
sz.height = src.rows;
if (src.channels() == 1)
{
nppiMirror_8u_C1R((const Npp8u*)src.ptr<char>(), src.step,
(Npp8u*)dst.ptr<char>(), dst.step, sz,
(flipCode == 0 ? NPP_HORIZONTAL_AXIS : (flipCode > 0 ? NPP_VERTICAL_AXIS : NPP_BOTH_AXIS)));
}
else
{
nppiMirror_8u_C4R((const Npp8u*)src.ptr<char>(), src.step,
(Npp8u*)dst.ptr<char>(), dst.step, sz,
(flipCode == 0 ? NPP_HORIZONTAL_AXIS : (flipCode > 0 ? NPP_VERTICAL_AXIS : NPP_BOTH_AXIS)));
}
}
void cv::gpu::resize(const GpuMat& src, GpuMat& dst, Size dsize, double fx, double fy, int interpolation)
{
static const int npp_inter[] = {NPPI_INTER_NN, NPPI_INTER_LINEAR, NPPI_INTER_CUBIC, 0, NPPI_INTER_LANCZOS};
CV_Assert((src.type() == CV_8UC1 || src.type() == CV_8UC4) &&
(interpolation == INTER_NEAREST || interpolation == INTER_LINEAR || interpolation == INTER_CUBIC || interpolation == INTER_LANCZOS4));
CV_Assert( src.size().area() > 0 );
CV_Assert( !(dsize == Size()) || (fx > 0 && fy > 0) );
if( dsize == Size() )
{
dsize = Size(saturate_cast<int>(src.cols * fx), saturate_cast<int>(src.rows * fy));
}
else
{
fx = (double)dsize.width / src.cols;
fy = (double)dsize.height / src.rows;
}
dst.create(dsize, src.type());
NppiSize srcsz;
srcsz.width = src.cols;
srcsz.height = src.rows;
NppiRect srcrect;
srcrect.x = srcrect.y = 0;
srcrect.width = src.cols;
srcrect.height = src.rows;
NppiSize dstsz;
dstsz.width = dst.cols;
dstsz.height = dst.rows;
if (src.channels() == 1)
{
nppiResize_8u_C1R((const Npp8u*)src.ptr<char>(), srcsz, src.step, srcrect,
(Npp8u*)dst.ptr<char>(), dst.step, dstsz, fx, fy, npp_inter[interpolation]);
}
else
{
nppiResize_8u_C4R((const Npp8u*)src.ptr<char>(), srcsz, src.step, srcrect,
(Npp8u*)dst.ptr<char>(), dst.step, dstsz, fx, fy, npp_inter[interpolation]);
}
}
Scalar cv::gpu::sum(const GpuMat& src)
{
CV_Assert(src.type() == CV_8UC1 || src.type() == CV_8UC4);
Scalar res;
NppiSize sz;
sz.width = src.cols;
sz.height = src.rows;
if (src.channels() == 1)
{
nppiSum_8u_C1R((const Npp8u*)src.ptr<char>(), src.step, sz, res.val);
}
else
{
nppiSum_8u_C4R((const Npp8u*)src.ptr<char>(), src.step, sz, res.val);
}
return res;
}
void cv::gpu::minMax(const GpuMat& src, double* minVal, double* maxVal)
{
CV_Assert(src.type() == CV_8UC1);
NppiSize sz;
sz.width = src.cols;
sz.height = src.rows;
Npp8u min_res, max_res;
nppiMinMax_8u_C1R((const Npp8u*)src.ptr<char>(), src.step, sz, &min_res, &max_res);
if (minVal)
*minVal = min_res;
if (maxVal)
*maxVal = max_res;
}
void cv::gpu::copyConstBorder(const GpuMat& src, GpuMat& dst, int top, int bottom, int left, int right, const Scalar& value)
{
CV_Assert(src.type() == CV_8UC1 || src.type() == CV_8UC4 || src.type() == CV_32SC1);
dst.create(src.rows + top + bottom, src.cols + left + right, src.type());
NppiSize srcsz;
srcsz.width = src.cols;
srcsz.height = src.rows;
NppiSize dstsz;
dstsz.width = dst.cols;
dstsz.height = dst.rows;
if (src.depth() == CV_8U)
{
if (src.channels() == 1)
{
Npp8u nVal = (Npp8u)value[0];
nppiCopyConstBorder_8u_C1R((const Npp8u*)src.ptr<char>(), src.step, srcsz,
(Npp8u*)dst.ptr<char>(), dst.step, dstsz, top, left, nVal);
}
else
{
Npp8u nVal[] = {(Npp8u)value[0], (Npp8u)value[1], (Npp8u)value[2], (Npp8u)value[3]};
nppiCopyConstBorder_8u_C4R((const Npp8u*)src.ptr<char>(), src.step, srcsz,
(Npp8u*)dst.ptr<char>(), dst.step, dstsz, top, left, nVal);
}
}
else //if (src.depth() == CV_32S)
{
Npp32s nVal = (Npp32s)value[0];
nppiCopyConstBorder_32s_C1R((const Npp32s*)src.ptr<char>(), src.step, srcsz,
(Npp32s*)dst.ptr<char>(), dst.step, dstsz, top, left, nVal);
}
}
#endif /* !defined (HAVE_CUDA) */
\ No newline at end of file
......@@ -162,7 +162,49 @@ GpuMat& GpuMat::setTo(const Scalar& s, const GpuMat& mask)
CV_DbgAssert(!this->empty());
if (mask.empty())
matrix_operations::set_to_without_mask( *this, depth(), s.val, channels());
{
switch (type())
{
case CV_8UC1:
{
NppiSize sz;
sz.width = cols;
sz.height = rows;
Npp8u nVal = (Npp8u)s[0];
nppiSet_8u_C1R(nVal, (Npp8u*)ptr<char>(), step, sz);
break;
}
case CV_8UC4:
{
NppiSize sz;
sz.width = cols;
sz.height = rows;
Npp8u nVal[] = {(Npp8u)s[0], (Npp8u)s[1], (Npp8u)s[2], (Npp8u)s[3]};
nppiSet_8u_C4R(nVal, (Npp8u*)ptr<char>(), step, sz);
break;
}
case CV_32SC1:
{
NppiSize sz;
sz.width = cols;
sz.height = rows;
Npp32s nVal = (Npp32s)s[0];
nppiSet_32s_C1R(nVal, (Npp32s*)ptr<char>(), step, sz);
break;
}
case CV_32FC1:
{
NppiSize sz;
sz.width = cols;
sz.height = rows;
Npp32f nVal = (Npp32f)s[0];
nppiSet_32f_C1R(nVal, (Npp32f*)ptr<char>(), step, sz);
break;
}
default:
matrix_operations::set_to_without_mask( *this, depth(), s.val, channels());
}
}
else
matrix_operations::set_to_with_mask( *this, depth(), s.val, mask, channels());
......
This diff is collapsed.
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment