Skip to content

Commit

Permalink
Merge pull request opencv#17088 from mpashchenkov:mp/ocv-gapi-kernel-…
Browse files Browse the repository at this point in the history
…laplacian

G-API: Laplacian and bilateralFilter standard kernels

* Added Laplacian kernel and tests

* Added: Laplacian kernel, Bilateral kernel (CPU, GPU); Performance and accuracy tests for this kernels

* Changed tolerance for GPU test

* boner

* Some changes with alignment; Tests's parameters are the same as for OCV

* Cut tests

* Compressed tests

* Minor changes (rsrt bb)

* Returned types
  • Loading branch information
Maxim Pashchenkov authored Apr 23, 2020
1 parent 189fc43 commit 51a42c0
Show file tree
Hide file tree
Showing 12 changed files with 368 additions and 27 deletions.
76 changes: 76 additions & 0 deletions modules/gapi/include/opencv2/gapi/imgproc.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -90,6 +90,20 @@ namespace imgproc {
}
};

G_TYPED_KERNEL(GLaplacian, <GMat(GMat,int, int, double, double, int)>,
"org.opencv.imgproc.filters.laplacian") {
static GMatDesc outMeta(GMatDesc in, int ddepth, int, double, double, int) {
return in.withDepth(ddepth);
}
};

G_TYPED_KERNEL(GBilateralFilter, <GMat(GMat,int, double, double, int)>,
"org.opencv.imgproc.filters.bilateralfilter") {
static GMatDesc outMeta(GMatDesc in, int, double, double, int) {
return in;
}
};

G_TYPED_KERNEL(GEqHist, <GMat(GMat)>, "org.opencv.imgproc.equalizeHist"){
static GMatDesc outMeta(GMatDesc in) {
return in.withType(CV_8U, 1);
Expand Down Expand Up @@ -643,6 +657,68 @@ GAPI_EXPORTS std::tuple<GMat, GMat> SobelXY(const GMat& src, int ddepth, int ord
int borderType = BORDER_DEFAULT,
const Scalar& borderValue = Scalar(0));

/** @brief Calculates the Laplacian of an image.
The function calculates the Laplacian of the source image by adding up the second x and y
derivatives calculated using the Sobel operator:
\f[\texttt{dst} = \Delta \texttt{src} = \frac{\partial^2 \texttt{src}}{\partial x^2} + \frac{\partial^2 \texttt{src}}{\partial y^2}\f]
This is done when `ksize > 1`. When `ksize == 1`, the Laplacian is computed by filtering the image
with the following \f$3 \times 3\f$ aperture:
\f[\vecthreethree {0}{1}{0}{1}{-4}{1}{0}{1}{0}\f]
@note Function textual ID is "org.opencv.imgproc.filters.laplacian"
@param src Source image.
@param ddepth Desired depth of the destination image.
@param ksize Aperture size used to compute the second-derivative filters. See #getDerivKernels for
details. The size must be positive and odd.
@param scale Optional scale factor for the computed Laplacian values. By default, no scaling is
applied. See #getDerivKernels for details.
@param delta Optional delta value that is added to the results prior to storing them in dst .
@param borderType Pixel extrapolation method, see #BorderTypes. #BORDER_WRAP is not supported.
@return Destination image of the same size and the same number of channels as src.
@sa Sobel, Scharr
*/
GAPI_EXPORTS GMat Laplacian(const GMat& src, int ddepth, int ksize = 1,
double scale = 1, double delta = 0, int borderType = BORDER_DEFAULT);

/** @brief Applies the bilateral filter to an image.
The function applies bilateral filtering to the input image, as described in
http://www.dai.ed.ac.uk/CVonline/LOCAL_COPIES/MANDUCHI1/Bilateral_Filtering.html
bilateralFilter can reduce unwanted noise very well while keeping edges fairly sharp. However, it is
very slow compared to most filters.
_Sigma values_: For simplicity, you can set the 2 sigma values to be the same. If they are small (\<
10), the filter will not have much effect, whereas if they are large (\> 150), they will have a very
strong effect, making the image look "cartoonish".
_Filter size_: Large filters (d \> 5) are very slow, so it is recommended to use d=5 for real-time
applications, and perhaps d=9 for offline applications that need heavy noise filtering.
This filter does not work inplace.
@note Function textual ID is "org.opencv.imgproc.filters.bilateralfilter"
@param src Source 8-bit or floating-point, 1-channel or 3-channel image.
@param d Diameter of each pixel neighborhood that is used during filtering. If it is non-positive,
it is computed from sigmaSpace.
@param sigmaColor Filter sigma in the color space. A larger value of the parameter means that
farther colors within the pixel neighborhood (see sigmaSpace) will be mixed together, resulting
in larger areas of semi-equal color.
@param sigmaSpace Filter sigma in the coordinate space. A larger value of the parameter means that
farther pixels will influence each other as long as their colors are close enough (see sigmaColor
). When d\>0, it specifies the neighborhood size regardless of sigmaSpace. Otherwise, d is
proportional to sigmaSpace.
@param borderType border mode used to extrapolate pixels outside of the image, see #BorderTypes
@return Destination image of the same size and type as src.
*/
GAPI_EXPORTS GMat bilateralFilter(const GMat& src, int d, double sigmaColor, double sigmaSpace,
int borderType = BORDER_DEFAULT);

/** @brief Finds edges in an image using the Canny algorithm.
The function finds edges in the input image and marks them in the output map edges using the
Expand Down
59 changes: 32 additions & 27 deletions modules/gapi/perf/common/gapi_imgproc_perf_tests.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -20,33 +20,38 @@ namespace opencv_test

//------------------------------------------------------------------------------

class SepFilterPerfTest : public TestPerfParams<tuple<compare_f, MatType, int, cv::Size, int, cv::GCompileArgs>> {};
class Filter2DPerfTest : public TestPerfParams<tuple<compare_f, MatType,int,cv::Size,int,int, cv::GCompileArgs>> {};
class BoxFilterPerfTest : public TestPerfParams<tuple<compare_f, MatType,int,cv::Size,int,int, cv::GCompileArgs>> {};
class BlurPerfTest : public TestPerfParams<tuple<compare_f, MatType,int,cv::Size,int, cv::GCompileArgs>> {};
class GaussianBlurPerfTest : public TestPerfParams<tuple<compare_f, MatType, int, cv::Size, cv::GCompileArgs>> {};
class MedianBlurPerfTest : public TestPerfParams<tuple<compare_f, MatType,int,cv::Size, cv::GCompileArgs>> {};
class ErodePerfTest : public TestPerfParams<tuple<compare_f, MatType,int,cv::Size,int, cv::GCompileArgs>> {};
class Erode3x3PerfTest : public TestPerfParams<tuple<compare_f, MatType, cv::Size, int, cv::GCompileArgs>> {};
class DilatePerfTest : public TestPerfParams<tuple<compare_f, MatType,int,cv::Size,int, cv::GCompileArgs>> {};
class Dilate3x3PerfTest : public TestPerfParams<tuple<compare_f, MatType,cv::Size,int, cv::GCompileArgs>> {};
class SobelPerfTest : public TestPerfParams<tuple<compare_f, MatType,int,cv::Size,int,int,int, cv::GCompileArgs>> {};
class SobelXYPerfTest : public TestPerfParams<tuple<compare_f, MatType,int,cv::Size,int,int, cv::GCompileArgs>> {};
class CannyPerfTest : public TestPerfParams<tuple<compare_f, MatType,cv::Size,double,double,int,bool, cv::GCompileArgs>> {};
class GoodFeaturesPerfTest : public TestPerfParams<tuple<compare_vector_f<cv::Point2f>, std::string,
int,int,double,double,int,bool,
cv::GCompileArgs>> {};
class EqHistPerfTest : public TestPerfParams<tuple<compare_f, cv::Size, cv::GCompileArgs >> {};
class RGB2GrayPerfTest : public TestPerfParams<tuple<compare_f, cv::Size, cv::GCompileArgs >> {};
class BGR2GrayPerfTest : public TestPerfParams<tuple<compare_f, cv::Size, cv::GCompileArgs >> {};
class RGB2YUVPerfTest : public TestPerfParams<tuple<compare_f, cv::Size, cv::GCompileArgs >> {};
class YUV2RGBPerfTest : public TestPerfParams<tuple<compare_f, cv::Size, cv::GCompileArgs >> {};
class RGB2LabPerfTest : public TestPerfParams<tuple<compare_f, cv::Size, cv::GCompileArgs>> {};
class BGR2LUVPerfTest : public TestPerfParams<tuple<compare_f, cv::Size, cv::GCompileArgs>> {};
class LUV2BGRPerfTest : public TestPerfParams<tuple<compare_f, cv::Size, cv::GCompileArgs>> {};
class BGR2YUVPerfTest : public TestPerfParams<tuple<compare_f, cv::Size, cv::GCompileArgs>> {};
class YUV2BGRPerfTest : public TestPerfParams<tuple<compare_f, cv::Size, cv::GCompileArgs>> {};
class RGB2HSVPerfTest : public TestPerfParams<tuple<compare_f, cv::Size, cv::GCompileArgs>> {};
class SepFilterPerfTest : public TestPerfParams<tuple<compare_f, MatType,int,cv::Size,int, cv::GCompileArgs>> {};
class Filter2DPerfTest : public TestPerfParams<tuple<compare_f, MatType,int,cv::Size,int,int, cv::GCompileArgs>> {};
class BoxFilterPerfTest : public TestPerfParams<tuple<compare_f, MatType,int,cv::Size,int,int, cv::GCompileArgs>> {};
class BlurPerfTest : public TestPerfParams<tuple<compare_f, MatType,int,cv::Size,int, cv::GCompileArgs>> {};
class GaussianBlurPerfTest : public TestPerfParams<tuple<compare_f, MatType,int, cv::Size, cv::GCompileArgs>> {};
class MedianBlurPerfTest : public TestPerfParams<tuple<compare_f, MatType,int,cv::Size, cv::GCompileArgs>> {};
class ErodePerfTest : public TestPerfParams<tuple<compare_f, MatType,int,cv::Size,int, cv::GCompileArgs>> {};
class Erode3x3PerfTest : public TestPerfParams<tuple<compare_f, MatType,cv::Size,int, cv::GCompileArgs>> {};
class DilatePerfTest : public TestPerfParams<tuple<compare_f, MatType,int,cv::Size,int, cv::GCompileArgs>> {};
class Dilate3x3PerfTest : public TestPerfParams<tuple<compare_f, MatType,cv::Size,int, cv::GCompileArgs>> {};
class SobelPerfTest : public TestPerfParams<tuple<compare_f, MatType,int,cv::Size,int,int,int, cv::GCompileArgs>> {};
class SobelXYPerfTest : public TestPerfParams<tuple<compare_f, MatType,int,cv::Size,int,int, cv::GCompileArgs>> {};
class LaplacianPerfTest : public TestPerfParams<tuple<compare_f, MatType,int,cv::Size,int,
cv::GCompileArgs>> {};
class BilateralFilterPerfTest : public TestPerfParams<tuple<compare_f, MatType,int,cv::Size,int, double,double,
cv::GCompileArgs>> {};
class CannyPerfTest : public TestPerfParams<tuple<compare_f, MatType,cv::Size,double,double,int,bool,
cv::GCompileArgs>> {};
class GoodFeaturesPerfTest : public TestPerfParams<tuple<compare_vector_f<cv::Point2f>, std::string,
int,int,double,double,int,bool,
cv::GCompileArgs>> {};
class EqHistPerfTest : public TestPerfParams<tuple<compare_f, cv::Size, cv::GCompileArgs>> {};
class RGB2GrayPerfTest : public TestPerfParams<tuple<compare_f, cv::Size, cv::GCompileArgs>> {};
class BGR2GrayPerfTest : public TestPerfParams<tuple<compare_f, cv::Size, cv::GCompileArgs>> {};
class RGB2YUVPerfTest : public TestPerfParams<tuple<compare_f, cv::Size, cv::GCompileArgs>> {};
class YUV2RGBPerfTest : public TestPerfParams<tuple<compare_f, cv::Size, cv::GCompileArgs>> {};
class RGB2LabPerfTest : public TestPerfParams<tuple<compare_f, cv::Size, cv::GCompileArgs>> {};
class BGR2LUVPerfTest : public TestPerfParams<tuple<compare_f, cv::Size, cv::GCompileArgs>> {};
class LUV2BGRPerfTest : public TestPerfParams<tuple<compare_f, cv::Size, cv::GCompileArgs>> {};
class BGR2YUVPerfTest : public TestPerfParams<tuple<compare_f, cv::Size, cv::GCompileArgs>> {};
class YUV2BGRPerfTest : public TestPerfParams<tuple<compare_f, cv::Size, cv::GCompileArgs>> {};
class RGB2HSVPerfTest : public TestPerfParams<tuple<compare_f, cv::Size, cv::GCompileArgs>> {};
class BayerGR2RGBPerfTest : public TestPerfParams<tuple<compare_f, cv::Size, cv::GCompileArgs>> {};
class RGB2YUV422PerfTest : public TestPerfParams<tuple<compare_f, cv::Size, cv::GCompileArgs>> {};
} // opencv_test
Expand Down
83 changes: 83 additions & 0 deletions modules/gapi/perf/common/gapi_imgproc_perf_tests_inl.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -579,6 +579,89 @@ PERF_TEST_P_(SobelXYPerfTest, TestPerformance)

//------------------------------------------------------------------------------

PERF_TEST_P_(LaplacianPerfTest, TestPerformance)
{
compare_f cmpF;
MatType type = 0;
int kernSize = 0, dtype = 0;
cv::Size sz;
cv::GCompileArgs compile_args;
std::tie(cmpF, type, kernSize, sz, dtype, compile_args) = GetParam();

initMatrixRandN(type, sz, dtype, false);

// OpenCV code /////////////////////////////////////////////////////////////
{
cv::Laplacian(in_mat1, out_mat_ocv, dtype, kernSize);
}

// G-API code //////////////////////////////////////////////////////////////
cv::GMat in;
auto out = cv::gapi::Laplacian(in, dtype, kernSize);
cv::GComputation c(in, out);

// Warm-up graph engine:
c.apply(in_mat1, out_mat_gapi, std::move(compile_args));

TEST_CYCLE()
{
c.apply(in_mat1, out_mat_gapi);
}

// Comparison //////////////////////////////////////////////////////////////
{
EXPECT_TRUE(cmpF(out_mat_gapi, out_mat_ocv));
EXPECT_EQ(out_mat_gapi.size(), sz);
}

SANITY_CHECK_NOTHING();
}

//------------------------------------------------------------------------------

PERF_TEST_P_(BilateralFilterPerfTest, TestPerformance)
{
compare_f cmpF;
MatType type = 0;
int dtype = 0, d = 0, borderType = BORDER_DEFAULT;
double sigmaColor = 0, sigmaSpace = 0;
cv::Size sz;
cv::GCompileArgs compile_args;
std::tie(cmpF, type, dtype, sz, d, sigmaColor, sigmaSpace,
compile_args) = GetParam();

initMatrixRandN(type, sz, dtype, false);

// OpenCV code /////////////////////////////////////////////////////////////
{
cv::bilateralFilter(in_mat1, out_mat_ocv, d, sigmaColor, sigmaSpace, borderType);
}

// G-API code //////////////////////////////////////////////////////////////
cv::GMat in;
auto out = cv::gapi::bilateralFilter(in, d, sigmaColor, sigmaSpace, borderType);
cv::GComputation c(in, out);

// Warm-up graph engine:
c.apply(in_mat1, out_mat_gapi, std::move(compile_args));

TEST_CYCLE()
{
c.apply(in_mat1, out_mat_gapi);
}

// Comparison //////////////////////////////////////////////////////////////
{
EXPECT_TRUE(cmpF(out_mat_gapi, out_mat_ocv));
EXPECT_EQ(out_mat_gapi.size(), sz);
}

SANITY_CHECK_NOTHING();
}

//------------------------------------------------------------------------------


PERF_TEST_P_(CannyPerfTest, TestPerformance)
{
compare_f cmpF;
Expand Down
18 changes: 18 additions & 0 deletions modules/gapi/perf/cpu/gapi_imgproc_perf_tests_cpu.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -124,6 +124,24 @@ INSTANTIATE_TEST_CASE_P(SobelPerfTestCPU32F, SobelPerfTest,
Values(1, 2),
Values(cv::compile_args(IMGPROC_CPU))));

INSTANTIATE_TEST_CASE_P(LaplacianPerfTestCPU, LaplacianPerfTest,
Combine(Values(AbsExact().to_compare_f()),
Values(CV_8UC1, CV_8UC3),
Values(3),
Values(szVGA, sz720p, sz1080p),
Values(-1),
Values(cv::compile_args(IMGPROC_CPU))));

INSTANTIATE_TEST_CASE_P(BilateralFilterPerfTestCPU, BilateralFilterPerfTest,
Combine(Values(AbsExact().to_compare_f()),
Values(CV_32FC1, CV_32FC3),
Values(-1),
Values(szVGA, sz720p, sz1080p),
Values(3),
Values(20),
Values(10),
Values(cv::compile_args(IMGPROC_CPU))));

INSTANTIATE_TEST_CASE_P(CannyPerfTestCPU, CannyPerfTest,
Combine(Values(AbsExact().to_compare_f()),
Values(CV_8UC1, CV_8UC3),
Expand Down
18 changes: 18 additions & 0 deletions modules/gapi/perf/gpu/gapi_imgproc_perf_tests_gpu.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -126,6 +126,24 @@ INSTANTIATE_TEST_CASE_P(SobelPerfTestGPU32F, SobelPerfTest,
Values(1, 2),
Values(cv::compile_args(IMGPROC_GPU))));

INSTANTIATE_TEST_CASE_P(LaplacianPerfTestGPU, LaplacianPerfTest,
Combine(Values(ToleranceFilter(1e-4f, 0.01).to_compare_f()),
Values(CV_8UC1, CV_8UC3),
Values(5),
Values(szVGA, sz720p, sz1080p),
Values(-1),
Values(cv::compile_args(IMGPROC_GPU))));

INSTANTIATE_TEST_CASE_P(BilateralFilterPerfTestGPU, BilateralFilterPerfTest,
Combine(Values(ToleranceFilter(1e-4f, 0.01).to_compare_f()),
Values(CV_32FC1, CV_32FC3),
Values(-1),
Values(szVGA, sz720p, sz1080p),
Values(5),
Values(100),
Values(40),
Values(cv::compile_args(IMGPROC_GPU))));

INSTANTIATE_TEST_CASE_P(CannyPerfTestGPU, CannyPerfTest,
Combine(Values(AbsSimilarPoints(1, 0.05).to_compare_f()),
Values(CV_8UC1, CV_8UC3),
Expand Down
10 changes: 10 additions & 0 deletions modules/gapi/src/api/kernels_imgproc.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -87,6 +87,16 @@ std::tuple<GMat, GMat> SobelXY(const GMat& src, int ddepth, int order, int ksize
return imgproc::GSobelXY::on(src, ddepth, order, ksize, scale, delta, borderType, bordVal);
}

GMat Laplacian(const GMat& src, int ddepth, int ksize, double scale, double delta, int borderType)
{
return imgproc::GLaplacian::on(src, ddepth, ksize, scale, delta, borderType);
}

GMat bilateralFilter(const GMat& src, int d, double sigmaColor, double sigmaSpace, int borderType)
{
return imgproc::GBilateralFilter::on(src, d, sigmaColor, sigmaSpace, borderType);
}

GMat equalizeHist(const GMat& src)
{
return imgproc::GEqHist::on(src);
Expand Down
20 changes: 20 additions & 0 deletions modules/gapi/src/backends/cpu/gcpuimgproc.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -166,6 +166,24 @@ GAPI_OCV_KERNEL(GCPUSobelXY, cv::gapi::imgproc::GSobelXY)
}
};

GAPI_OCV_KERNEL(GCPULaplacian, cv::gapi::imgproc::GLaplacian)
{
static void run(const cv::Mat& in, int ddepth, int ksize, double scale,
double delta, int borderType, cv::Mat &out)
{
cv::Laplacian(in, out, ddepth, ksize, scale, delta, borderType);
}
};

GAPI_OCV_KERNEL(GCPUBilateralFilter, cv::gapi::imgproc::GBilateralFilter)
{
static void run(const cv::Mat& in, int d, double sigmaColor,
double sigmaSpace, int borderType, cv::Mat &out)
{
cv::bilateralFilter(in, out, d, sigmaColor, sigmaSpace, borderType);
}
};

GAPI_OCV_KERNEL(GCPUEqualizeHist, cv::gapi::imgproc::GEqHist)
{
static void run(const cv::Mat& in, cv::Mat &out)
Expand Down Expand Up @@ -422,6 +440,8 @@ cv::gapi::GKernelPackage cv::gapi::imgproc::cpu::kernels()
, GCPUDilate
, GCPUSobel
, GCPUSobelXY
, GCPULaplacian
, GCPUBilateralFilter
, GCPUCanny
, GCPUGoodFeatures
, GCPUEqualizeHist
Expand Down
20 changes: 20 additions & 0 deletions modules/gapi/src/backends/ocl/goclimgproc.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -147,6 +147,24 @@ GAPI_OCL_KERNEL(GOCLSobel, cv::gapi::imgproc::GSobel)
}
};

GAPI_OCL_KERNEL(GOCLLaplacian, cv::gapi::imgproc::GLaplacian)
{
static void run(const cv::UMat& in, int ddepth, int ksize, double scale,
double delta, int borderType, cv::UMat &out)
{
cv::Laplacian(in, out, ddepth, ksize, scale, delta, borderType);
}
};

GAPI_OCL_KERNEL(GOCLBilateralFilter, cv::gapi::imgproc::GBilateralFilter)
{
static void run(const cv::UMat& in, int ddepth, double sigmaColor,
double sigmaSpace, int borderType, cv::UMat &out)
{
cv::bilateralFilter(in, out, ddepth, sigmaColor, sigmaSpace, borderType);
}
};

GAPI_OCL_KERNEL(GOCLEqualizeHist, cv::gapi::imgproc::GEqHist)
{
static void run(const cv::UMat& in, cv::UMat &out)
Expand Down Expand Up @@ -260,6 +278,8 @@ cv::gapi::GKernelPackage cv::gapi::imgproc::ocl::kernels()
, GOCLErode
, GOCLDilate
, GOCLSobel
, GOCLLaplacian
, GOCLBilateralFilter
, GOCLCanny
, GOCLEqualizeHist
, GOCLRGB2YUV
Expand Down
6 changes: 6 additions & 0 deletions modules/gapi/test/common/gapi_imgproc_tests.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,12 @@ GAPI_TEST_FIXTURE(SobelTest, initMatrixRandN, FIXTURE_API(CompareMats,int,int,in
cmpF, kernSize, dx, dy)
GAPI_TEST_FIXTURE(SobelXYTest, initMatrixRandN, FIXTURE_API(CompareMats,int,int,int,int), 5,
cmpF, kernSize, order, border_type, border_val)
GAPI_TEST_FIXTURE(LaplacianTest, initMatrixRandN,
FIXTURE_API(CompareMats,int,double,int), 4,
cmpF, kernSize, scale, borderType)
GAPI_TEST_FIXTURE(BilateralFilterTest, initMatrixRandN,
FIXTURE_API(CompareMats,int,double,double,int), 5,
cmpF, d, sigmaColor, sigmaSpace, borderType)
GAPI_TEST_FIXTURE(EqHistTest, initMatrixRandN, FIXTURE_API(CompareMats), 1, cmpF)
GAPI_TEST_FIXTURE(CannyTest, initMatrixRandN, FIXTURE_API(CompareMats,double,double,int,bool), 5,
cmpF, thrLow, thrUp, apSize, l2gr)
Expand Down
Loading

0 comments on commit 51a42c0

Please sign in to comment.