Commit 12ae11e2 authored by Vladislav Vinogradov's avatar Vladislav Vinogradov

refactored Separable Linear Filters

parent ee7eb1b8
......@@ -351,7 +351,7 @@ private:
FAST_GPU fastDetector_;
Ptr<FilterEngine_GPU> blurFilter;
Ptr<gpu::Filter> blurFilter;
GpuMat d_keypoints_;
};
......
......@@ -468,7 +468,7 @@ cv::gpu::ORB_GPU::ORB_GPU(int nFeatures, float scaleFactor, int nLevels, int edg
pattern_.upload(h_pattern);
blurFilter = createGaussianFilter_GPU(CV_8UC1, Size(7, 7), 2, 2, BORDER_REFLECT_101);
blurFilter = gpu::createGaussianFilter(CV_8UC1, -1, Size(7, 7), 2, 2, BORDER_REFLECT_101);
blurForDescriptor = false;
}
......@@ -632,7 +632,7 @@ void cv::gpu::ORB_GPU::computeDescriptors(GpuMat& descriptors)
{
// preprocess the resized image
ensureSizeIsEnough(imagePyr_[level].size(), imagePyr_[level].type(), buf_);
blurFilter->apply(imagePyr_[level], buf_, Rect(0, 0, imagePyr_[level].cols, imagePyr_[level].rows));
blurFilter->apply(imagePyr_[level], buf_);
}
computeOrbDescriptor_gpu(blurForDescriptor ? buf_ : imagePyr_[level], keyPointsPyr_[level].ptr<short2>(0), keyPointsPyr_[level].ptr<float>(2),
......
......@@ -159,13 +159,6 @@ PERF_TEST_P(Sz_Type_KernelSz, Laplacian, Combine(GPU_TYPICAL_MAT_SIZES, Values(C
}
}
//////////////////////////////////////////////////////////////////////
// Sobel
......@@ -184,9 +177,10 @@ PERF_TEST_P(Sz_Type_KernelSz, Sobel, Combine(GPU_TYPICAL_MAT_SIZES, Values(CV_8U
{
const cv::gpu::GpuMat d_src(src);
cv::gpu::GpuMat dst;
cv::gpu::GpuMat d_buf;
TEST_CYCLE() cv::gpu::Sobel(d_src, dst, -1, 1, 1, d_buf, ksize);
cv::Ptr<cv::gpu::Filter> sobel = cv::gpu::createSobelFilter(d_src.type(), -1, 1, 1, ksize);
TEST_CYCLE() sobel->apply(d_src, dst);
GPU_SANITY_CHECK(dst);
}
......@@ -217,9 +211,10 @@ PERF_TEST_P(Sz_Type, Scharr, Combine(GPU_TYPICAL_MAT_SIZES, Values(CV_8UC1, CV_8
{
const cv::gpu::GpuMat d_src(src);
cv::gpu::GpuMat dst;
cv::gpu::GpuMat d_buf;
TEST_CYCLE() cv::gpu::Scharr(d_src, dst, -1, 1, 0, d_buf);
cv::Ptr<cv::gpu::Filter> scharr = cv::gpu::createScharrFilter(d_src.type(), -1, 1, 0);
TEST_CYCLE() scharr->apply(d_src, dst);
GPU_SANITY_CHECK(dst);
}
......@@ -251,9 +246,10 @@ PERF_TEST_P(Sz_Type_KernelSz, GaussianBlur, Combine(GPU_TYPICAL_MAT_SIZES, Value
{
const cv::gpu::GpuMat d_src(src);
cv::gpu::GpuMat dst;
cv::gpu::GpuMat d_buf;
TEST_CYCLE() cv::gpu::GaussianBlur(d_src, dst, cv::Size(ksize, ksize), d_buf, 0.5);
cv::Ptr<cv::gpu::Filter> gauss = cv::gpu::createGaussianFilter(d_src.type(), -1, cv::Size(ksize, ksize), 0.5);
TEST_CYCLE() gauss->apply(d_src, dst);
GPU_SANITY_CHECK(dst);
}
......@@ -267,6 +263,13 @@ PERF_TEST_P(Sz_Type_KernelSz, GaussianBlur, Combine(GPU_TYPICAL_MAT_SIZES, Value
}
}
//////////////////////////////////////////////////////////////////////
// Erode
......
This diff is collapsed.
......@@ -215,13 +215,74 @@ INSTANTIATE_TEST_CASE_P(GPU_Filters, Laplacian, testing::Combine(
testing::Values(KSize(cv::Size(1, 1)), KSize(cv::Size(3, 3))),
WHOLE_SUBMAT));
/////////////////////////////////////////////////////////////////////////////////////////////////
// SeparableLinearFilter
PARAM_TEST_CASE(SeparableLinearFilter, cv::gpu::DeviceInfo, cv::Size, MatDepth, Channels, KSize, Anchor, BorderType, UseRoi)
{
cv::gpu::DeviceInfo devInfo;
cv::Size size;
int depth;
int cn;
cv::Size ksize;
cv::Point anchor;
int borderType;
bool useRoi;
int type;
virtual void SetUp()
{
devInfo = GET_PARAM(0);
size = GET_PARAM(1);
depth = GET_PARAM(2);
cn = GET_PARAM(3);
ksize = GET_PARAM(4);
anchor = GET_PARAM(5);
borderType = GET_PARAM(6);
useRoi = GET_PARAM(7);
cv::gpu::setDevice(devInfo.deviceID());
type = CV_MAKE_TYPE(depth, cn);
}
};
GPU_TEST_P(SeparableLinearFilter, Accuracy)
{
cv::Mat src = randomMat(size, type);
cv::Mat rowKernel = randomMat(Size(ksize.width, 1), CV_32FC1, 0.0, 1.0);
cv::Mat columnKernel = randomMat(Size(ksize.height, 1), CV_32FC1, 0.0, 1.0);
cv::Ptr<cv::gpu::Filter> filter = cv::gpu::createSeparableLinearFilter(src.type(), -1, rowKernel, columnKernel, anchor, borderType);
cv::gpu::GpuMat dst = createMat(size, type, useRoi);
filter->apply(loadMat(src, useRoi), dst);
cv::Mat dst_gold;
cv::sepFilter2D(src, dst_gold, -1, rowKernel, columnKernel, anchor, 0, borderType);
EXPECT_MAT_NEAR(dst_gold, dst, src.depth() < CV_32F ? 1.0 : 1e-2);
}
INSTANTIATE_TEST_CASE_P(GPU_Filters, SeparableLinearFilter, testing::Combine(
ALL_DEVICES,
DIFFERENT_SIZES,
testing::Values(MatDepth(CV_8U), MatDepth(CV_16U), MatDepth(CV_16S), MatDepth(CV_32F)),
IMAGE_CHANNELS,
testing::Values(KSize(cv::Size(3, 3)),
KSize(cv::Size(7, 7)),
KSize(cv::Size(13, 13)),
KSize(cv::Size(15, 15)),
KSize(cv::Size(17, 17)),
KSize(cv::Size(23, 15)),
KSize(cv::Size(31, 3))),
testing::Values(Anchor(cv::Point(-1, -1)), Anchor(cv::Point(0, 0)), Anchor(cv::Point(2, 2))),
testing::Values(BorderType(cv::BORDER_REFLECT101),
BorderType(cv::BORDER_REPLICATE),
BorderType(cv::BORDER_CONSTANT),
BorderType(cv::BORDER_REFLECT)),
WHOLE_SUBMAT));
/////////////////////////////////////////////////////////////////////////////////////////////////
// Sobel
......@@ -265,13 +326,15 @@ GPU_TEST_P(Sobel, Accuracy)
cv::Mat src = randomMat(size, type);
cv::Ptr<cv::gpu::Filter> sobel = cv::gpu::createSobelFilter(src.type(), -1, dx, dy, ksize.width, 1.0, borderType);
cv::gpu::GpuMat dst = createMat(size, type, useRoi);
cv::gpu::Sobel(loadMat(src, useRoi), dst, -1, dx, dy, ksize.width, 1.0, borderType);
sobel->apply(loadMat(src, useRoi), dst);
cv::Mat dst_gold;
cv::Sobel(src, dst_gold, -1, dx, dy, ksize.width, 1.0, 0.0, borderType);
EXPECT_MAT_NEAR(getInnerROI(dst_gold, ksize), getInnerROI(dst, ksize), CV_MAT_DEPTH(type) < CV_32F ? 0.0 : 0.1);
EXPECT_MAT_NEAR(dst_gold, dst, src.depth() < CV_32F ? 0.0 : 0.1);
}
INSTANTIATE_TEST_CASE_P(GPU_Filters, Sobel, testing::Combine(
......@@ -328,13 +391,15 @@ GPU_TEST_P(Scharr, Accuracy)
cv::Mat src = randomMat(size, type);
cv::Ptr<cv::gpu::Filter> scharr = cv::gpu::createScharrFilter(src.type(), -1, dx, dy, 1.0, borderType);
cv::gpu::GpuMat dst = createMat(size, type, useRoi);
cv::gpu::Scharr(loadMat(src, useRoi), dst, -1, dx, dy, 1.0, borderType);
scharr->apply(loadMat(src, useRoi), dst);
cv::Mat dst_gold;
cv::Scharr(src, dst_gold, -1, dx, dy, 1.0, 0.0, borderType);
EXPECT_MAT_NEAR(getInnerROI(dst_gold, cv::Size(3, 3)), getInnerROI(dst, cv::Size(3, 3)), CV_MAT_DEPTH(type) < CV_32F ? 0.0 : 0.1);
EXPECT_MAT_NEAR(dst_gold, dst, src.depth() < CV_32F ? 0.0 : 0.1);
}
INSTANTIATE_TEST_CASE_P(GPU_Filters, Scharr, testing::Combine(
......@@ -387,28 +452,15 @@ GPU_TEST_P(GaussianBlur, Accuracy)
double sigma1 = randomDouble(0.1, 1.0);
double sigma2 = randomDouble(0.1, 1.0);
if (ksize.height > 16 && !supportFeature(devInfo, cv::gpu::FEATURE_SET_COMPUTE_20))
{
try
{
cv::gpu::GpuMat dst;
cv::gpu::GaussianBlur(loadMat(src), dst, ksize, sigma1, sigma2, borderType);
}
catch (const cv::Exception& e)
{
ASSERT_EQ(cv::Error::StsNotImplemented, e.code);
}
}
else
{
cv::gpu::GpuMat dst = createMat(size, type, useRoi);
cv::gpu::GaussianBlur(loadMat(src, useRoi), dst, ksize, sigma1, sigma2, borderType);
cv::Ptr<cv::gpu::Filter> gauss = cv::gpu::createGaussianFilter(src.type(), -1, ksize, sigma1, sigma2, borderType);
cv::gpu::GpuMat dst = createMat(size, type, useRoi);
gauss->apply(loadMat(src, useRoi), dst);
cv::Mat dst_gold;
cv::GaussianBlur(src, dst_gold, ksize, sigma1, sigma2, borderType);
cv::Mat dst_gold;
cv::GaussianBlur(src, dst_gold, ksize, sigma1, sigma2, borderType);
EXPECT_MAT_NEAR(dst_gold, dst, 4.0);
}
EXPECT_MAT_NEAR(dst_gold, dst, src.depth() < CV_32F ? 4.0 : 1e-4);
}
INSTANTIATE_TEST_CASE_P(GPU_Filters, GaussianBlur, testing::Combine(
......@@ -437,6 +489,15 @@ INSTANTIATE_TEST_CASE_P(GPU_Filters, GaussianBlur, testing::Combine(
BorderType(cv::BORDER_REFLECT)),
WHOLE_SUBMAT));
/////////////////////////////////////////////////////////////////////////////////////////////////
// Erode
......
......@@ -158,7 +158,7 @@ struct CV_EXPORTS CannyBuf
GpuMat mag;
GpuMat map;
GpuMat st1, st2;
Ptr<FilterEngine_GPU> filterDX, filterDY;
Ptr<Filter> filterDX, filterDY;
};
CV_EXPORTS void Canny(const GpuMat& image, GpuMat& edges, double low_thresh, double high_thresh, int apperture_size = 3, bool L2gradient = false);
......
......@@ -65,8 +65,8 @@ void cv::gpu::CannyBuf::create(const Size& image_size, int apperture_size)
if (apperture_size != 3)
{
filterDX = createDerivFilter_GPU(CV_8UC1, CV_32S, 1, 0, apperture_size, BORDER_REPLICATE);
filterDY = createDerivFilter_GPU(CV_8UC1, CV_32S, 0, 1, apperture_size, BORDER_REPLICATE);
filterDX = createDerivFilter(CV_8UC1, CV_32S, 1, 0, apperture_size, false, 1, BORDER_REPLICATE);
filterDY = createDerivFilter(CV_8UC1, CV_32S, 0, 1, apperture_size, false, 1, BORDER_REPLICATE);
}
}
......@@ -150,8 +150,8 @@ void cv::gpu::Canny(const GpuMat& src, CannyBuf& buf, GpuMat& dst, double low_th
}
else
{
buf.filterDX->apply(src, buf.dx, Rect(0, 0, src.cols, src.rows));
buf.filterDY->apply(src, buf.dy, Rect(0, 0, src.cols, src.rows));
buf.filterDX->apply(src, buf.dx);
buf.filterDY->apply(src, buf.dy);
calcMagnitude(buf.dx, buf.dy, buf.mag, L2gradient);
}
......
......@@ -70,6 +70,8 @@ namespace
{
void extractCovData(const GpuMat& src, GpuMat& Dx, GpuMat& Dy, GpuMat& buf, int blockSize, int ksize, int borderType, Stream& stream)
{
(void) buf;
double scale = static_cast<double>(1 << ((ksize > 0 ? ksize : 3) - 1)) * blockSize;
if (ksize < 0)
......@@ -83,16 +85,21 @@ namespace
Dx.create(src.size(), CV_32F);
Dy.create(src.size(), CV_32F);
Ptr<gpu::Filter> filterDx, filterDy;
if (ksize > 0)
{
Sobel(src, Dx, CV_32F, 1, 0, buf, ksize, scale, borderType, -1, stream);
Sobel(src, Dy, CV_32F, 0, 1, buf, ksize, scale, borderType, -1, stream);
filterDx = gpu::createSobelFilter(src.type(), CV_32F, 1, 0, ksize, scale, borderType);
filterDy = gpu::createSobelFilter(src.type(), CV_32F, 0, 1, ksize, scale, borderType);
}
else
{
Scharr(src, Dx, CV_32F, 1, 0, buf, scale, borderType, -1, stream);
Scharr(src, Dy, CV_32F, 0, 1, buf, scale, borderType, -1, stream);
filterDx = gpu::createScharrFilter(src.type(), CV_32F, 1, 0, scale, borderType);
filterDy = gpu::createScharrFilter(src.type(), CV_32F, 0, 1, scale, borderType);
}
filterDx->apply(src, Dx);
filterDy->apply(src, Dy);
}
}
......
......@@ -230,7 +230,7 @@ namespace
Ptr<DenseOpticalFlowExt> opticalFlow_;
private:
std::vector<Ptr<FilterEngine_GPU> > filters_;
std::vector<Ptr<gpu::Filter> > filters_;
int curBlurKernelSize_;
double curBlurSigma_;
int curSrcType_;
......@@ -299,7 +299,7 @@ namespace
{
filters_.resize(src.size());
for (size_t i = 0; i < src.size(); ++i)
filters_[i] = createGaussianFilter_GPU(src[0].type(), Size(blurKernelSize_, blurKernelSize_), blurSigma_);
filters_[i] = gpu::createGaussianFilter(src[0].type(), -1, Size(blurKernelSize_, blurKernelSize_), blurSigma_);
curBlurKernelSize_ = blurKernelSize_;
curBlurSigma_ = blurSigma_;
curSrcType_ = src[0].type();
......@@ -346,7 +346,7 @@ namespace
// a = M * Ih
gpu::remap(highRes_, a_[k], backwardMaps_[k].first, backwardMaps_[k].second, INTER_NEAREST, BORDER_REPLICATE, Scalar(), streams_[k]);
// b = HM * Ih
filters_[k]->apply(a_[k], b_[k], Rect(0,0,-1,-1), streams_[k]);
filters_[k]->apply(a_[k], b_[k], streams_[k]);
// c = DHF * Ih
gpu::resize(b_[k], c_[k], lowResSize, 0, 0, INTER_NEAREST, streams_[k]);
......@@ -355,7 +355,7 @@ namespace
// a = Dt * diff
upscale(c_[k], a_[k], scale_, streams_[k]);
// b = HtDt * diff
filters_[k]->apply(a_[k], b_[k], Rect(0,0,-1,-1), streams_[k]);
filters_[k]->apply(a_[k], b_[k], streams_[k]);
// diffTerm = MtHtDt * diff
gpu::remap(b_[k], diffTerms_[k], forwardMaps_[k].first, forwardMaps_[k].second, INTER_NEAREST, BORDER_REPLICATE, Scalar(), streams_[k]);
}
......
......@@ -308,6 +308,8 @@ Scalar getMSSIM_GPU( const Mat& i1, const Mat& i2)
gpu::split(tmp2, vI2);
Scalar mssim;
Ptr<gpu::Filter> gauss = gpu::createGaussianFilter(vI2[0].type(), -1, Size(11, 11), 1.5);
for( int i = 0; i < gI1.channels(); ++i )
{
gpu::GpuMat I2_2, I1_2, I1_I2;
......@@ -318,8 +320,8 @@ Scalar getMSSIM_GPU( const Mat& i1, const Mat& i2)
/*************************** END INITS **********************************/
gpu::GpuMat mu1, mu2; // PRELIMINARY COMPUTING
gpu::GaussianBlur(vI1[i], mu1, Size(11, 11), 1.5);
gpu::GaussianBlur(vI2[i], mu2, Size(11, 11), 1.5);
gauss->apply(vI1[i], mu1);
gauss->apply(vI2[i], mu2);
gpu::GpuMat mu1_2, mu2_2, mu1_mu2;
gpu::multiply(mu1, mu1, mu1_2);
......@@ -328,13 +330,13 @@ Scalar getMSSIM_GPU( const Mat& i1, const Mat& i2)
gpu::GpuMat sigma1_2, sigma2_2, sigma12;
gpu::GaussianBlur(I1_2, sigma1_2, Size(11, 11), 1.5);
gauss->apply(I1_2, sigma1_2);
gpu::subtract(sigma1_2, mu1_2, sigma1_2); // sigma1_2 -= mu1_2;
gpu::GaussianBlur(I2_2, sigma2_2, Size(11, 11), 1.5);
gauss->apply(I2_2, sigma2_2);
gpu::subtract(sigma2_2, mu2_2, sigma2_2); // sigma2_2 -= mu2_2;
gpu::GaussianBlur(I1_I2, sigma12, Size(11, 11), 1.5);
gauss->apply(I1_I2, sigma12);
gpu::subtract(sigma12, mu1_mu2, sigma12); // sigma12 -= mu1_mu2;
///////////////////////////////// FORMULA ////////////////////////////////
......@@ -375,7 +377,7 @@ Scalar getMSSIM_GPU_optimized( const Mat& i1, const Mat& i2, BufferMSSIM& b)
gpu::split(b.t2, b.vI2, stream);
Scalar mssim;
gpu::GpuMat buf;
Ptr<gpu::Filter> gauss = gpu::createGaussianFilter(b.vI1[0].type(), -1, Size(11, 11), 1.5);
for( int i = 0; i < b.gI1.channels(); ++i )
{
......@@ -383,22 +385,22 @@ Scalar getMSSIM_GPU_optimized( const Mat& i1, const Mat& i2, BufferMSSIM& b)
gpu::multiply(b.vI1[i], b.vI1[i], b.I1_2, 1, -1, stream); // I1^2
gpu::multiply(b.vI1[i], b.vI2[i], b.I1_I2, 1, -1, stream); // I1 * I2
gpu::GaussianBlur(b.vI1[i], b.mu1, Size(11, 11), buf, 1.5, 0, BORDER_DEFAULT, -1, stream);
gpu::GaussianBlur(b.vI2[i], b.mu2, Size(11, 11), buf, 1.5, 0, BORDER_DEFAULT, -1, stream);
gauss->apply(b.vI1[i], b.mu1, stream);
gauss->apply(b.vI2[i], b.mu2, stream);
gpu::multiply(b.mu1, b.mu1, b.mu1_2, 1, -1, stream);
gpu::multiply(b.mu2, b.mu2, b.mu2_2, 1, -1, stream);
gpu::multiply(b.mu1, b.mu2, b.mu1_mu2, 1, -1, stream);
gpu::GaussianBlur(b.I1_2, b.sigma1_2, Size(11, 11), buf, 1.5, 0, BORDER_DEFAULT, -1, stream);
gauss->apply(b.I1_2, b.sigma1_2, stream);
gpu::subtract(b.sigma1_2, b.mu1_2, b.sigma1_2, gpu::GpuMat(), -1, stream);
//b.sigma1_2 -= b.mu1_2; - This would result in an extra data transfer operation
gpu::GaussianBlur(b.I2_2, b.sigma2_2, Size(11, 11), buf, 1.5, 0, BORDER_DEFAULT, -1, stream);
gauss->apply(b.I2_2, b.sigma2_2, stream);
gpu::subtract(b.sigma2_2, b.mu2_2, b.sigma2_2, gpu::GpuMat(), -1, stream);
//b.sigma2_2 -= b.mu2_2;
gpu::GaussianBlur(b.I1_I2, b.sigma12, Size(11, 11), buf, 1.5, 0, BORDER_DEFAULT, -1, stream);
gauss->apply(b.I1_I2, b.sigma12, stream);
gpu::subtract(b.sigma12, b.mu1_mu2, b.sigma12, gpu::GpuMat(), -1, stream);
//b.sigma12 -= b.mu1_mu2;
......
......@@ -929,10 +929,12 @@ TEST(GaussianBlur)
gpu::GpuMat d_dst(src.size(), src.type());
gpu::GpuMat d_buf;
gpu::GaussianBlur(d_src, d_dst, Size(3, 3), d_buf, 1);
cv::Ptr<cv::gpu::Filter> gauss = cv::gpu::createGaussianFilter(d_src.type(), -1, cv::Size(3, 3), 1);
gauss->apply(d_src, d_dst);
GPU_ON;
gpu::GaussianBlur(d_src, d_dst, Size(3, 3), d_buf, 1);
gauss->apply(d_src, d_dst);
GPU_OFF;
}
}
......
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