Commit 3e840cb7 authored by Vladislav Vinogradov's avatar Vladislav Vinogradov

added min/max filters to gpu module.

added supports of 4-channels image to gpu::minMax and gpu::cvtColor for RGB <-> YCrCB, RGB <-> YUV and RGB <-> XYZ color conversion.
parent 1cf405d8
......@@ -411,7 +411,7 @@ namespace cv
CV_EXPORTS Scalar sum(const GpuMat& m);
//! finds global minimum and maximum array elements and returns their values
//! supports only CV_8UC1 type
//! supports CV_8UC1 and CV_8UC4 type
//! disabled until fix npp bug
CV_EXPORTS void minMax(const GpuMat& src, double* minVal, double* maxVal = 0);
......@@ -649,6 +649,12 @@ namespace cv
//! returns the Gaussian filter engine
CV_EXPORTS Ptr<FilterEngine_GPU> createGaussianFilter_GPU(int type, Size ksize, double sigma1, double sigma2 = 0);
//! returns maximum filter
CV_EXPORTS Ptr<BaseFilter_GPU> getMaxFilter_GPU(int srcType, int dstType, const Size& ksize, Point anchor = Point(-1,-1));
//! returns minimum filter
CV_EXPORTS Ptr<BaseFilter_GPU> getMinFilter_GPU(int srcType, int dstType, const Size& ksize, Point anchor = Point(-1,-1));
//! smooths the image using the normalized box filter
//! supports CV_8UC1, CV_8UC4 types
CV_EXPORTS void boxFilter(const GpuMat& src, GpuMat& dst, int ddepth, Size ksize, Point anchor = Point(-1,-1));
......
......@@ -419,24 +419,55 @@ Scalar cv::gpu::sum(const GpuMat& src)
////////////////////////////////////////////////////////////////////////
// minMax
void cv::gpu::minMax(const GpuMat& src, double* minVal, double* maxVal)
namespace
{
CV_Assert(!"disabled until fix npp bug");
CV_Assert(src.type() == CV_8UC1);
void minMax_c1(const GpuMat& src, double* minVal, double* maxVal)
{
NppiSize sz;
sz.width = src.cols;
sz.height = src.rows;
NppiSize sz;
sz.width = src.cols;
sz.height = src.rows;
Npp8u min_res, max_res;
nppSafeCall( nppiMinMax_8u_C1R(src.ptr<Npp8u>(), src.step, sz, &min_res, &max_res) );
Npp8u min_res, max_res;
if (minVal)
*minVal = min_res;
nppSafeCall( nppiMinMax_8u_C1R(src.ptr<Npp8u>(), src.step, sz, &min_res, &max_res) );
if (maxVal)
*maxVal = max_res;
}
void minMax_c4(const GpuMat& src, double* minVal, double* maxVal)
{
NppiSize sz;
sz.width = src.cols;
sz.height = src.rows;
if (minVal)
*minVal = min_res;
Npp8u* cuMin = nppsMalloc_8u(4);
Npp8u* cuMax = nppsMalloc_8u(4);
nppSafeCall( nppiMinMax_8u_C4R(src.ptr<Npp8u>(), src.step, sz, cuMin, cuMax) );
if (minVal)
cudaMemcpy(minVal, cuMin, 4 * sizeof(Npp8u), cudaMemcpyDeviceToHost);
if (maxVal)
cudaMemcpy(maxVal, cuMax, 4 * sizeof(Npp8u), cudaMemcpyDeviceToHost);
nppsFree(cuMin);
nppsFree(cuMax);
}
}
void cv::gpu::minMax(const GpuMat& src, double* minVal, double* maxVal)
{
typedef void (*minMax_t)(const GpuMat& src, double* minVal, double* maxVal);
static const minMax_t minMax_callers[] = {0, minMax_c1, 0, 0, minMax_c4};
CV_Assert(!"disabled until fix npp bug");
CV_Assert(src.type() == CV_8UC1 || src.type() == CV_8UC4);
if (maxVal)
*maxVal = max_res;
minMax_callers[src.channels()](src, minVal, maxVal);
}
////////////////////////////////////////////////////////////////////////
......
This diff is collapsed.
......@@ -63,6 +63,9 @@ Ptr<BaseColumnFilter_GPU> cv::gpu::getLinearColumnFilter_GPU(int, int, const Gpu
Ptr<FilterEngine_GPU> cv::gpu::createSeparableLinearFilter_GPU(int, int, const Mat&, const Mat&, const Point&) { throw_nogpu(); return Ptr<FilterEngine_GPU>(0); }
Ptr<FilterEngine_GPU> cv::gpu::createDerivFilter_GPU(int, int, int, int, int) { throw_nogpu(); return Ptr<FilterEngine_GPU>(0); }
Ptr<FilterEngine_GPU> cv::gpu::createGaussianFilter_GPU(int, Size, double, double) { throw_nogpu(); return Ptr<FilterEngine_GPU>(0); }
Ptr<BaseFilter_GPU> cv::gpu::getMaxFilter_GPU(int, int, const Size&, Point) { throw_nogpu(); return Ptr<BaseFilter_GPU>(0); }
Ptr<BaseFilter_GPU> cv::gpu::getMinFilter_GPU(int, int, const Size&, Point) { throw_nogpu(); return Ptr<BaseFilter_GPU>(0); }
void cv::gpu::boxFilter(const GpuMat&, GpuMat&, int, Size, Point) { throw_nogpu(); }
void cv::gpu::erode( const GpuMat&, GpuMat&, const Mat&, Point, int) { throw_nogpu(); }
void cv::gpu::dilate( const GpuMat&, GpuMat&, const Mat&, Point, int) { throw_nogpu(); }
......@@ -105,20 +108,20 @@ namespace
int scale = nDivisor && (kernel.depth() == CV_32F || kernel.depth() == CV_64F) ? 256 : 1;
if (nDivisor) *nDivisor = scale;
Mat cont_krnl = (kernel.isContinuous() ? kernel : kernel.clone()).reshape(1, 1);
Mat temp;
cont_krnl.convertTo(temp, type, scale);
Mat temp(kernel.size(), type);
kernel.convertTo(temp, type, scale);
Mat cont_krnl = temp.reshape(1, 1);
if (reverse)
{
int count = temp.cols >> 1;
int count = cont_krnl.cols >> 1;
for (int i = 0; i < count; ++i)
{
std::swap(temp.at<int>(0, i), temp.at<int>(0, temp.cols - 1 - i));
std::swap(cont_krnl.at<int>(0, i), cont_krnl.at<int>(0, cont_krnl.cols - 1 - i));
}
}
gpu_krnl.upload(temp);
gpu_krnl.upload(cont_krnl);
}
}
......@@ -785,4 +788,58 @@ void cv::gpu::GaussianBlur(const GpuMat& src, GpuMat& dst, Size ksize, double si
f->apply(src, dst);
}
////////////////////////////////////////////////////////////////////////////////////////////////////
// Image Rank Filter
namespace
{
typedef NppStatus (*nppFilterRank_t)(const Npp8u * pSrc, Npp32s nSrcStep, Npp8u * pDst, Npp32s nDstStep, NppiSize oSizeROI,
NppiSize oMaskSize, NppiPoint oAnchor);
class NPPRankFilter : public BaseFilter_GPU
{
public:
NPPRankFilter(const Size& ksize_, const Point& anchor_, nppFilterRank_t func_) : BaseFilter_GPU(ksize_, anchor_), func(func_) {}
virtual void operator()(const GpuMat& src, GpuMat& dst)
{
NppiSize sz;
sz.width = src.cols;
sz.height = src.rows;
NppiSize oKernelSize;
oKernelSize.height = ksize.height;
oKernelSize.width = ksize.width;
NppiPoint oAnchor;
oAnchor.x = anchor.x;
oAnchor.y = anchor.y;
nppSafeCall( func(src.ptr<Npp8u>(), src.step, dst.ptr<Npp8u>(), dst.step, sz, oKernelSize, oAnchor) );
}
nppFilterRank_t func;
};
}
Ptr<BaseFilter_GPU> cv::gpu::getMaxFilter_GPU(int srcType, int dstType, const Size& ksize, Point anchor)
{
static const nppFilterRank_t nppFilterRank_callers[] = {0, nppiFilterMax_8u_C1R, 0, 0, nppiFilterMax_8u_C4R};
CV_Assert((srcType == CV_8UC1 || srcType == CV_8UC4) && dstType == srcType);
normalizeAnchor(anchor, ksize);
return Ptr<BaseFilter_GPU>(new NPPRankFilter(ksize, anchor, nppFilterRank_callers[CV_MAT_CN(srcType)]));
}
Ptr<BaseFilter_GPU> cv::gpu::getMinFilter_GPU(int srcType, int dstType, const Size& ksize, Point anchor)
{
static const nppFilterRank_t nppFilterRank_callers[] = {0, nppiFilterMin_8u_C1R, 0, 0, nppiFilterMin_8u_C4R};
CV_Assert((srcType == CV_8UC1 || srcType == CV_8UC4) && dstType == srcType);
normalizeAnchor(anchor, ksize);
return Ptr<BaseFilter_GPU>(new NPPRankFilter(ksize, anchor, nppFilterRank_callers[CV_MAT_CN(srcType)]));
}
#endif
......@@ -98,21 +98,21 @@ namespace cv { namespace gpu
void RGB2Gray_gpu_32f(const DevMem2D& src, int srccn, const DevMem2D& dst, int bidx, cudaStream_t stream);
void RGB5x52Gray_gpu(const DevMem2D& src, int green_bits, const DevMem2D& dst, cudaStream_t stream);
void RGB2YCrCb_gpu_8u(const DevMem2D& src, int srccn, const DevMem2D& dst, int bidx, const int* coeffs, cudaStream_t stream);
void RGB2YCrCb_gpu_16u(const DevMem2D& src, int srccn, const DevMem2D& dst, int bidx, const int* coeffs, cudaStream_t stream);
void RGB2YCrCb_gpu_32f(const DevMem2D& src, int srccn, const DevMem2D& dst, int bidx, const float* coeffs, cudaStream_t stream);
void RGB2YCrCb_gpu_8u(const DevMem2D& src, int srccn, const DevMem2D& dst, int dstcn, int bidx, const int* coeffs, cudaStream_t stream);
void RGB2YCrCb_gpu_16u(const DevMem2D& src, int srccn, const DevMem2D& dst, int dstcn, int bidx, const int* coeffs, cudaStream_t stream);
void RGB2YCrCb_gpu_32f(const DevMem2D& src, int srccn, const DevMem2D& dst, int dstcn, int bidx, const float* coeffs, cudaStream_t stream);
void YCrCb2RGB_gpu_8u(const DevMem2D& src, const DevMem2D& dst, int dstcn, int bidx, const int* coeffs, cudaStream_t stream);
void YCrCb2RGB_gpu_16u(const DevMem2D& src, const DevMem2D& dst, int dstcn, int bidx, const int* coeffs, cudaStream_t stream);
void YCrCb2RGB_gpu_32f(const DevMem2D& src, const DevMem2D& dst, int dstcn, int bidx, const float* coeffs, cudaStream_t stream);
void YCrCb2RGB_gpu_8u(const DevMem2D& src, int srccn, const DevMem2D& dst, int dstcn, int bidx, const int* coeffs, cudaStream_t stream);
void YCrCb2RGB_gpu_16u(const DevMem2D& src, int srccn, const DevMem2D& dst, int dstcn, int bidx, const int* coeffs, cudaStream_t stream);
void YCrCb2RGB_gpu_32f(const DevMem2D& src, int srccn, const DevMem2D& dst, int dstcn, int bidx, const float* coeffs, cudaStream_t stream);
void RGB2XYZ_gpu_8u(const DevMem2D& src, int srccn, const DevMem2D& dst, const int* coeffs, cudaStream_t stream);
void RGB2XYZ_gpu_16u(const DevMem2D& src, int srccn, const DevMem2D& dst, const int* coeffs, cudaStream_t stream);
void RGB2XYZ_gpu_32f(const DevMem2D& src, int srccn, const DevMem2D& dst, const float* coeffs, cudaStream_t stream);
void RGB2XYZ_gpu_8u(const DevMem2D& src, int srccn, const DevMem2D& dst, int dstcn, const int* coeffs, cudaStream_t stream);
void RGB2XYZ_gpu_16u(const DevMem2D& src, int srccn, const DevMem2D& dst, int dstcn, const int* coeffs, cudaStream_t stream);
void RGB2XYZ_gpu_32f(const DevMem2D& src, int srccn, const DevMem2D& dst, int dstcn, const float* coeffs, cudaStream_t stream);
void XYZ2RGB_gpu_8u(const DevMem2D& src, const DevMem2D& dst, int dstcn, const int* coeffs, cudaStream_t stream);
void XYZ2RGB_gpu_16u(const DevMem2D& src, const DevMem2D& dst, int dstcn, const int* coeffs, cudaStream_t stream);
void XYZ2RGB_gpu_32f(const DevMem2D& src, const DevMem2D& dst, int dstcn, const float* coeffs, cudaStream_t stream);
void XYZ2RGB_gpu_8u(const DevMem2D& src, int srccn, const DevMem2D& dst, int dstcn, const int* coeffs, cudaStream_t stream);
void XYZ2RGB_gpu_16u(const DevMem2D& src, int srccn, const DevMem2D& dst, int dstcn, const int* coeffs, cudaStream_t stream);
void XYZ2RGB_gpu_32f(const DevMem2D& src, int srccn, const DevMem2D& dst, int dstcn, const float* coeffs, cudaStream_t stream);
}
}}
......@@ -361,7 +361,8 @@ namespace
case CV_BGR2YCrCb: case CV_RGB2YCrCb:
case CV_BGR2YUV: case CV_RGB2YUV:
{
CV_Assert( scn == 3 || scn == 4 );
if(dcn <= 0) dcn = 3;
CV_Assert( (scn == 3 || scn == 4) && (dcn == 3 || dcn == 4) );
bidx = code == CV_BGR2YCrCb || code == CV_RGB2YUV ? 0 : 2;
......@@ -382,14 +383,14 @@ namespace
std::swap(coeffs_i[0], coeffs_i[2]);
}
out.create(sz, CV_MAKETYPE(depth, 3));
out.create(sz, CV_MAKETYPE(depth, dcn));
if( depth == CV_8U )
improc::RGB2YCrCb_gpu_8u(src, scn, out, bidx, coeffs_i, stream);
improc::RGB2YCrCb_gpu_8u(src, scn, out, dcn, bidx, coeffs_i, stream);
else if( depth == CV_16U )
improc::RGB2YCrCb_gpu_16u(src, scn, out, bidx, coeffs_i, stream);
improc::RGB2YCrCb_gpu_16u(src, scn, out, dcn, bidx, coeffs_i, stream);
else
improc::RGB2YCrCb_gpu_32f(src, scn, out, bidx, coeffs_f, stream);
improc::RGB2YCrCb_gpu_32f(src, scn, out, dcn, bidx, coeffs_f, stream);
}
break;
......@@ -398,7 +399,7 @@ namespace
{
if (dcn <= 0) dcn = 3;
CV_Assert( scn == 3 && (dcn == 3 || dcn == 4) );
CV_Assert( (scn == 3 || scn == 4) && (dcn == 3 || dcn == 4) );
bidx = code == CV_YCrCb2BGR || code == CV_YUV2RGB ? 0 : 2;
......@@ -414,17 +415,18 @@ namespace
out.create(sz, CV_MAKETYPE(depth, dcn));
if( depth == CV_8U )
improc::YCrCb2RGB_gpu_8u(src, out, dcn, bidx, coeffs_i, stream);
improc::YCrCb2RGB_gpu_8u(src, scn, out, dcn, bidx, coeffs_i, stream);
else if( depth == CV_16U )
improc::YCrCb2RGB_gpu_16u(src, out, dcn, bidx, coeffs_i, stream);
improc::YCrCb2RGB_gpu_16u(src, scn, out, dcn, bidx, coeffs_i, stream);
else
improc::YCrCb2RGB_gpu_32f(src, out, dcn, bidx, coeffs_f, stream);
improc::YCrCb2RGB_gpu_32f(src, scn, out, dcn, bidx, coeffs_f, stream);
}
break;
case CV_BGR2XYZ: case CV_RGB2XYZ:
{
CV_Assert( scn == 3 || scn == 4 );
{
if(dcn <= 0) dcn = 3;
CV_Assert( (scn == 3 || scn == 4) && (dcn == 3 || dcn == 4) );
bidx = code == CV_BGR2XYZ ? 0 : 2;
......@@ -457,21 +459,21 @@ namespace
std::swap(coeffs_i[6], coeffs_i[8]);
}
out.create(sz, CV_MAKETYPE(depth, 3));
out.create(sz, CV_MAKETYPE(depth, dcn));
if( depth == CV_8U )
improc::RGB2XYZ_gpu_8u(src, scn, out, coeffs_i, stream);
improc::RGB2XYZ_gpu_8u(src, scn, out, dcn, coeffs_i, stream);
else if( depth == CV_16U )
improc::RGB2XYZ_gpu_16u(src, scn, out, coeffs_i, stream);
improc::RGB2XYZ_gpu_16u(src, scn, out, dcn, coeffs_i, stream);
else
improc::RGB2XYZ_gpu_32f(src, scn, out, coeffs_f, stream);
improc::RGB2XYZ_gpu_32f(src, scn, out, dcn, coeffs_f, stream);
}
break;
case CV_XYZ2BGR: case CV_XYZ2RGB:
{
if (dcn <= 0) dcn = 3;
CV_Assert( scn == 3 && (dcn == 3 || dcn == 4) );
CV_Assert( (scn == 3 || scn == 4) && (dcn == 3 || dcn == 4) );
bidx = code == CV_XYZ2BGR ? 0 : 2;
static const float XYZ2sRGB_D65f[] =
......@@ -506,11 +508,11 @@ namespace
out.create(sz, CV_MAKETYPE(depth, dcn));
if( depth == CV_8U )
improc::XYZ2RGB_gpu_8u(src, out, dcn, coeffs_i, stream);
improc::XYZ2RGB_gpu_8u(src, scn, out, dcn, coeffs_i, stream);
else if( depth == CV_16U )
improc::XYZ2RGB_gpu_16u(src, out, dcn, coeffs_i, stream);
improc::XYZ2RGB_gpu_16u(src, scn, out, dcn, coeffs_i, stream);
else
improc::XYZ2RGB_gpu_32f(src, out, dcn, coeffs_f, stream);
improc::XYZ2RGB_gpu_32f(src, scn, out, dcn, coeffs_f, stream);
}
break;
......
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