Merge pull request #13030 from dmatveev:tutorial
* G-API: First steps with tutorial * G-API Tutorial: First iteration * G-API port of anisotropic image segmentation tutorial; * Currently works via OpenCV only; * Some new kernels have been required. * G-API Tutorial: added chapters on execution code, inspection, and profiling * G-API Tutorial: make Fluid kernel headers public For some reason, these headers were not moved to the public headers subtree during the initial development. Somehow it even worked for the existing workloads. * G-API Tutorial: Fix a couple of issues found during the work * Introduced Phase & Sqrt kernels, OCV & Fluid versions * Extended GKernelPackage to allow kernel removal & policies on include() All the above stuff needs to be tested, tests will be added later * G-API Tutorial: added chapter on running Fluid backend * G-API Tutorial: fix a number of issues in the text * G-API Tutorial - some final updates - Fixed post-merge issues after Sobel kernel renaming; - Simplified G-API code a little bit; - Put a conclusion note in text. * G-API Tutorial - fix build issues in test/perf targets Public headers were refactored but tests suites were not updated in time * G-API Tutorial: Added tests & reference docs on new kernels * Phase * Sqrt * G-API Tutorial: added link to the tutorial from the main module doc * G-API Tutorial: Added tests on new GKernelPackage functionality * G-API Tutorial: Extended InRange tests to cover 32F * G-API Tutorial: Misc fixes * Avoid building examples when gapi module is not there * Added a volatile API disclaimer to G-API root documentation page * G-API Tutorial: Fix perf tests build issue This change came from master where Fluid kernels are still used incorrectly. * G-API Tutorial: Fixed channels support in Sqrt/Phase fluid kernels Extended tests to cover this case * G-API Tutorial: Fix text problems found on team review
This commit is contained in:
committed by
Alexander Alekhin
parent
1d10d56651
commit
85fad1504a
@@ -34,6 +34,12 @@ bool cv::gapi::GKernelPackage::includesAPI(const std::string &id) const
|
||||
return (it != m_backend_kernels.end());
|
||||
}
|
||||
|
||||
void cv::gapi::GKernelPackage::removeAPI(const std::string &id)
|
||||
{
|
||||
for (auto &bk : m_backend_kernels)
|
||||
bk.second.erase(id);
|
||||
}
|
||||
|
||||
std::size_t cv::gapi::GKernelPackage::size() const
|
||||
{
|
||||
return std::accumulate(m_backend_kernels.begin(),
|
||||
@@ -53,7 +59,7 @@ cv::gapi::GKernelPackage cv::gapi::combine(const GKernelPackage &lhs,
|
||||
{
|
||||
// REPLACE policy: if there is a collision, prefer RHS
|
||||
// to LHS
|
||||
// since OTHER package has a prefernece, start with its copy
|
||||
// since RHS package has a precedense, start with its copy
|
||||
GKernelPackage result(rhs);
|
||||
// now iterate over LHS package and put kernel if and only
|
||||
// if there's no such one
|
||||
|
||||
@@ -104,6 +104,11 @@ std::tuple<GMat, GMat> cartToPolar(const GMat& x, const GMat& y,
|
||||
return core::GCartToPolar::on(x, y, angleInDegrees);
|
||||
}
|
||||
|
||||
GMat phase(const GMat &x, const GMat &y, bool angleInDegrees)
|
||||
{
|
||||
return core::GPhase::on(x, y, angleInDegrees);
|
||||
}
|
||||
|
||||
GMat cmpGT(const GMat& src1, const GMat& src2)
|
||||
{
|
||||
return core::GCmpGT::on(src1, src2);
|
||||
@@ -345,5 +350,10 @@ GMat convertTo(const GMat& m, int rtype, double alpha, double beta)
|
||||
return core::GConvertTo::on(m, rtype, alpha, beta);
|
||||
}
|
||||
|
||||
GMat sqrt(const GMat& src)
|
||||
{
|
||||
return core::GSqrt::on(src);
|
||||
}
|
||||
|
||||
} //namespace gapi
|
||||
} //namespace cv
|
||||
|
||||
@@ -132,6 +132,14 @@ GAPI_OCV_KERNEL(GCPUCartToPolar, cv::gapi::core::GCartToPolar)
|
||||
}
|
||||
};
|
||||
|
||||
GAPI_OCV_KERNEL(GCPUPhase, cv::gapi::core::GPhase)
|
||||
{
|
||||
static void run(const cv::Mat &x, const cv::Mat &y, bool angleInDegrees, cv::Mat &out)
|
||||
{
|
||||
cv::phase(x, y, out, angleInDegrees);
|
||||
}
|
||||
};
|
||||
|
||||
GAPI_OCV_KERNEL(GCPUCmpGT, cv::gapi::core::GCmpGT)
|
||||
{
|
||||
static void run(const cv::Mat& a, const cv::Mat& b, cv::Mat& out)
|
||||
@@ -509,6 +517,14 @@ GAPI_OCV_KERNEL(GCPUConvertTo, cv::gapi::core::GConvertTo)
|
||||
}
|
||||
};
|
||||
|
||||
GAPI_OCV_KERNEL(GCPUSqrt, cv::gapi::core::GSqrt)
|
||||
{
|
||||
static void run(const cv::Mat& in, cv::Mat &out)
|
||||
{
|
||||
cv::sqrt(in, out);
|
||||
}
|
||||
};
|
||||
|
||||
cv::gapi::GKernelPackage cv::gapi::core::cpu::kernels()
|
||||
{
|
||||
static auto pkg = cv::gapi::kernels
|
||||
@@ -527,6 +543,7 @@ cv::gapi::GKernelPackage cv::gapi::core::cpu::kernels()
|
||||
, GCPUMask
|
||||
, GCPUPolarToCart
|
||||
, GCPUCartToPolar
|
||||
, GCPUPhase
|
||||
, GCPUCmpGT
|
||||
, GCPUCmpGE
|
||||
, GCPUCmpLE
|
||||
@@ -572,6 +589,7 @@ cv::gapi::GKernelPackage cv::gapi::core::cpu::kernels()
|
||||
, GCPUConcatVert
|
||||
, GCPULUT
|
||||
, GCPUConvertTo
|
||||
, GCPUSqrt
|
||||
>();
|
||||
return pkg;
|
||||
}
|
||||
|
||||
@@ -32,8 +32,6 @@
|
||||
|
||||
#include "backends/fluid/gfluidbuffer_priv.hpp"
|
||||
#include "backends/fluid/gfluidbackend.hpp"
|
||||
#include "backends/fluid/gfluidimgproc.hpp"
|
||||
#include "backends/fluid/gfluidcore.hpp"
|
||||
|
||||
#include "api/gbackend_priv.hpp" // FIXME: Make it part of Backend SDK!
|
||||
|
||||
|
||||
@@ -10,17 +10,18 @@
|
||||
|
||||
#include "opencv2/gapi/own/assert.hpp"
|
||||
#include "opencv2/core/traits.hpp"
|
||||
#include "opencv2/core/hal/hal.hpp"
|
||||
#include "opencv2/core/hal/intrin.hpp"
|
||||
|
||||
#include "opencv2/gapi/core.hpp"
|
||||
|
||||
#include "opencv2/gapi/fluid/gfluidbuffer.hpp"
|
||||
#include "opencv2/gapi/fluid/gfluidkernel.hpp"
|
||||
#include "opencv2/gapi/fluid/core.hpp"
|
||||
|
||||
#include "gfluidbuffer_priv.hpp"
|
||||
#include "gfluidbackend.hpp"
|
||||
#include "gfluidutils.hpp"
|
||||
#include "gfluidcore.hpp"
|
||||
|
||||
#include <cassert>
|
||||
#include <cmath>
|
||||
@@ -1543,7 +1544,6 @@ static void run_inrange(Buffer &dst, const View &src, const cv::Scalar &upperb,
|
||||
const cv::Scalar &lowerb)
|
||||
{
|
||||
static_assert(std::is_same<DST, uchar>::value, "wrong types");
|
||||
static_assert(std::is_integral<SRC>::value, "wrong types");
|
||||
|
||||
const auto *in = src.InLine<SRC>(0);
|
||||
auto *out = dst.OutLine<DST>();
|
||||
@@ -1552,13 +1552,26 @@ static void run_inrange(Buffer &dst, const View &src, const cv::Scalar &upperb,
|
||||
int chan = src.meta().chan;
|
||||
GAPI_Assert(dst.meta().chan == 1);
|
||||
|
||||
// for integral input, in[i] >= lower equals in[i] >= ceil(lower)
|
||||
// so we can optimize compare operations by rounding lower/upper
|
||||
SRC lower[4], upper[4];
|
||||
for (int c=0; c < chan; c++)
|
||||
{
|
||||
lower[c] = saturate<SRC>(lowerb[c], ceild);
|
||||
upper[c] = saturate<SRC>(upperb[c], floord);
|
||||
if (std::is_integral<SRC>::value)
|
||||
{
|
||||
// for integral input, in[i] >= lower equals in[i] >= ceil(lower)
|
||||
// so we can optimize compare operations by rounding lower/upper
|
||||
lower[c] = saturate<SRC>(lowerb[c], ceild);
|
||||
upper[c] = saturate<SRC>(upperb[c], floord);
|
||||
}
|
||||
else
|
||||
{
|
||||
// FIXME: now values used in comparison are floats (while they
|
||||
// have double precision initially). Comparison float/float
|
||||
// may differ from float/double (how it should work in this case)
|
||||
//
|
||||
// Example: threshold=1/3 (or 1/10)
|
||||
lower[c] = static_cast<SRC>(lowerb[c]);
|
||||
upper[c] = static_cast<SRC>(upperb[c]);
|
||||
}
|
||||
}
|
||||
|
||||
// manually SIMD for important case if RGB/BGR
|
||||
@@ -1611,6 +1624,7 @@ GAPI_FLUID_KERNEL(GFluidInRange, cv::gapi::core::GInRange, false)
|
||||
INRANGE_(uchar, uchar , run_inrange, dst, src, upperb, lowerb);
|
||||
INRANGE_(uchar, ushort, run_inrange, dst, src, upperb, lowerb);
|
||||
INRANGE_(uchar, short, run_inrange, dst, src, upperb, lowerb);
|
||||
INRANGE_(uchar, float, run_inrange, dst, src, upperb, lowerb);
|
||||
|
||||
CV_Error(cv::Error::StsBadArg, "unsupported combination of types");
|
||||
}
|
||||
@@ -1951,6 +1965,35 @@ GAPI_FLUID_KERNEL(GFluidCartToPolar, cv::gapi::core::GCartToPolar, false)
|
||||
}
|
||||
};
|
||||
|
||||
GAPI_FLUID_KERNEL(GFluidPhase, cv::gapi::core::GPhase, false)
|
||||
{
|
||||
static const int Window = 1;
|
||||
|
||||
static void run(const View &src_x,
|
||||
const View &src_y,
|
||||
bool angleInDegrees,
|
||||
Buffer &dst)
|
||||
{
|
||||
const auto w = dst.length() * dst.meta().chan;
|
||||
if (src_x.meta().depth == CV_32F && src_y.meta().depth == CV_32F)
|
||||
{
|
||||
hal::fastAtan32f(src_y.InLine<float>(0),
|
||||
src_x.InLine<float>(0),
|
||||
dst.OutLine<float>(),
|
||||
w,
|
||||
angleInDegrees);
|
||||
}
|
||||
else if (src_x.meta().depth == CV_64F && src_y.meta().depth == CV_64F)
|
||||
{
|
||||
hal::fastAtan64f(src_y.InLine<double>(0),
|
||||
src_x.InLine<double>(0),
|
||||
dst.OutLine<double>(),
|
||||
w,
|
||||
angleInDegrees);
|
||||
} else GAPI_Assert(false && !"Phase supports 32F/64F input only!");
|
||||
}
|
||||
};
|
||||
|
||||
GAPI_FLUID_KERNEL(GFluidResize, cv::gapi::core::GResize, true)
|
||||
{
|
||||
static const int Window = 1;
|
||||
@@ -2052,6 +2095,28 @@ GAPI_FLUID_KERNEL(GFluidResize, cv::gapi::core::GResize, true)
|
||||
}
|
||||
};
|
||||
|
||||
GAPI_FLUID_KERNEL(GFluidSqrt, cv::gapi::core::GSqrt, false)
|
||||
{
|
||||
static const int Window = 1;
|
||||
|
||||
static void run(const View &in, Buffer &out)
|
||||
{
|
||||
const auto w = out.length() * out.meta().chan;
|
||||
if (in.meta().depth == CV_32F)
|
||||
{
|
||||
hal::sqrt32f(in.InLine<float>(0),
|
||||
out.OutLine<float>(0),
|
||||
w);
|
||||
}
|
||||
else if (in.meta().depth == CV_64F)
|
||||
{
|
||||
hal::sqrt64f(in.InLine<double>(0),
|
||||
out.OutLine<double>(0),
|
||||
w);
|
||||
} else GAPI_Assert(false && !"Sqrt supports 32F/64F input only!");
|
||||
}
|
||||
};
|
||||
|
||||
} // namespace fliud
|
||||
} // namespace gapi
|
||||
} // namespace cv
|
||||
@@ -2088,6 +2153,7 @@ cv::gapi::GKernelPackage cv::gapi::core::fluid::kernels()
|
||||
,GFluidSelect
|
||||
,GFluidPolarToCart
|
||||
,GFluidCartToPolar
|
||||
,GFluidPhase
|
||||
,GFluidAddC
|
||||
,GFluidSubC
|
||||
,GFluidSubRC
|
||||
@@ -2105,6 +2171,7 @@ cv::gapi::GKernelPackage cv::gapi::core::fluid::kernels()
|
||||
,GFluidThreshold
|
||||
,GFluidInRange
|
||||
,GFluidResize
|
||||
,GFluidSqrt
|
||||
#if 0
|
||||
,GFluidMean -- not fluid
|
||||
,GFluidSum -- not fluid
|
||||
|
||||
@@ -1,19 +0,0 @@
|
||||
// This file is part of OpenCV project.
|
||||
// It is subject to the license terms in the LICENSE file found in the top-level directory
|
||||
// of this distribution and at http://opencv.org/license.html.
|
||||
//
|
||||
// Copyright (C) 2018 Intel Corporation
|
||||
|
||||
|
||||
#ifndef OPENCV_GAPI_GFLUIDCORE_HPP
|
||||
#define OPENCV_GAPI_GFLUIDCORE_HPP
|
||||
|
||||
#include "opencv2/gapi/fluid/gfluidkernel.hpp"
|
||||
|
||||
namespace cv { namespace gapi { namespace core { namespace fluid {
|
||||
|
||||
GAPI_EXPORTS GKernelPackage kernels();
|
||||
|
||||
}}}}
|
||||
|
||||
#endif // OPENCV_GAPI_GFLUIDCORE_HPP
|
||||
@@ -19,10 +19,10 @@
|
||||
|
||||
#include "opencv2/gapi/fluid/gfluidbuffer.hpp"
|
||||
#include "opencv2/gapi/fluid/gfluidkernel.hpp"
|
||||
#include "opencv2/gapi/fluid/imgproc.hpp"
|
||||
|
||||
#include "gfluidbuffer_priv.hpp"
|
||||
#include "gfluidbackend.hpp"
|
||||
#include "gfluidimgproc.hpp"
|
||||
#include "gfluidutils.hpp"
|
||||
|
||||
#include "gfluidimgproc_func.hpp"
|
||||
|
||||
@@ -1,19 +0,0 @@
|
||||
// This file is part of OpenCV project.
|
||||
// It is subject to the license terms in the LICENSE file found in the top-level directory
|
||||
// of this distribution and at http://opencv.org/license.html.
|
||||
//
|
||||
// Copyright (C) 2018 Intel Corporation
|
||||
|
||||
|
||||
#ifndef OPENCV_GAPI_GFLUIDIMGPROC_HPP
|
||||
#define OPENCV_GAPI_GFLUIDIMGPROC_HPP
|
||||
|
||||
#include "opencv2/gapi/fluid/gfluidkernel.hpp"
|
||||
|
||||
namespace cv { namespace gapi { namespace imgproc { namespace fluid {
|
||||
|
||||
GAPI_EXPORTS GKernelPackage kernels();
|
||||
|
||||
}}}}
|
||||
|
||||
#endif // OPENCV_GAPI_GFLUIDIMGPROC_HPP
|
||||
Reference in New Issue
Block a user