Merge pull request #21157 from alexgiving:atrutnev/move_resize

GAPI: Move Resize kernel from core to imgproc

* Move Resize kernel from core to imgproc

* Applied style comments

* Adding backward compatibility

* Applied Asya PR
This commit is contained in:
Trutnev Aleksei 2021-12-29 18:13:43 +03:00 committed by GitHub
parent 80c2fefc43
commit 43c04c29ce
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
26 changed files with 640 additions and 626 deletions

View File

@ -9,10 +9,10 @@
#define OPENCV_GAPI_CORE_HPP
#include <math.h>
#include <utility> // std::tuple
#include <opencv2/imgproc.hpp>
#include <opencv2/gapi/imgproc.hpp>
#include <opencv2/gapi/gmat.hpp>
#include <opencv2/gapi/gscalar.hpp>
@ -34,6 +34,9 @@ namespace cv { namespace gapi {
* Core module functionality.
*/
namespace core {
using GResize = cv::gapi::imgproc::GResize;
using GResizeP = cv::gapi::imgproc::GResizeP;
using GMat2 = std::tuple<GMat,GMat>;
using GMat3 = std::tuple<GMat,GMat,GMat>; // FIXME: how to avoid this?
using GMat4 = std::tuple<GMat,GMat,GMat,GMat>;
@ -100,7 +103,7 @@ namespace core {
}
};
G_TYPED_KERNEL(GMulC, <GMat(GMat, GScalar, int)>, "org.opencv.core.math.mulC"){
G_TYPED_KERNEL(GMulC, <GMat(GMat, GScalar, int)>, "org.opencv.core.math.mulC") {
static GMatDesc outMeta(GMatDesc a, GScalarDesc, int ddepth) {
return a.withDepth(ddepth);
}
@ -201,37 +204,37 @@ namespace core {
}
};
G_TYPED_KERNEL(GCmpGTScalar, <GMat(GMat, GScalar)>, "org.opencv.core.pixelwise.compare.cmpGTScalar"){
G_TYPED_KERNEL(GCmpGTScalar, <GMat(GMat, GScalar)>, "org.opencv.core.pixelwise.compare.cmpGTScalar") {
static GMatDesc outMeta(GMatDesc a, GScalarDesc) {
return a.withDepth(CV_8U);
}
};
G_TYPED_KERNEL(GCmpGEScalar, <GMat(GMat, GScalar)>, "org.opencv.core.pixelwise.compare.cmpGEScalar"){
G_TYPED_KERNEL(GCmpGEScalar, <GMat(GMat, GScalar)>, "org.opencv.core.pixelwise.compare.cmpGEScalar") {
static GMatDesc outMeta(GMatDesc a, GScalarDesc) {
return a.withDepth(CV_8U);
}
};
G_TYPED_KERNEL(GCmpLEScalar, <GMat(GMat, GScalar)>, "org.opencv.core.pixelwise.compare.cmpLEScalar"){
G_TYPED_KERNEL(GCmpLEScalar, <GMat(GMat, GScalar)>, "org.opencv.core.pixelwise.compare.cmpLEScalar") {
static GMatDesc outMeta(GMatDesc a, GScalarDesc) {
return a.withDepth(CV_8U);
}
};
G_TYPED_KERNEL(GCmpLTScalar, <GMat(GMat, GScalar)>, "org.opencv.core.pixelwise.compare.cmpLTScalar"){
G_TYPED_KERNEL(GCmpLTScalar, <GMat(GMat, GScalar)>, "org.opencv.core.pixelwise.compare.cmpLTScalar") {
static GMatDesc outMeta(GMatDesc a, GScalarDesc) {
return a.withDepth(CV_8U);
}
};
G_TYPED_KERNEL(GCmpEQScalar, <GMat(GMat, GScalar)>, "org.opencv.core.pixelwise.compare.cmpEQScalar"){
G_TYPED_KERNEL(GCmpEQScalar, <GMat(GMat, GScalar)>, "org.opencv.core.pixelwise.compare.cmpEQScalar") {
static GMatDesc outMeta(GMatDesc a, GScalarDesc) {
return a.withDepth(CV_8U);
}
};
G_TYPED_KERNEL(GCmpNEScalar, <GMat(GMat, GScalar)>, "org.opencv.core.pixelwise.compare.cmpNEScalar"){
G_TYPED_KERNEL(GCmpNEScalar, <GMat(GMat, GScalar)>, "org.opencv.core.pixelwise.compare.cmpNEScalar") {
static GMatDesc outMeta(GMatDesc a, GScalarDesc) {
return a.withDepth(CV_8U);
}
@ -398,32 +401,6 @@ namespace core {
}
};
G_TYPED_KERNEL(GResize, <GMat(GMat,Size,double,double,int)>, "org.opencv.core.transform.resize") {
static GMatDesc outMeta(GMatDesc in, Size sz, double fx, double fy, int /*interp*/) {
if (sz.width != 0 && sz.height != 0)
{
return in.withSize(sz);
}
else
{
int outSz_w = static_cast<int>(round(in.size.width * fx));
int outSz_h = static_cast<int>(round(in.size.height * fy));
GAPI_Assert(outSz_w > 0 && outSz_h > 0);
return in.withSize(Size(outSz_w, outSz_h));
}
}
};
G_TYPED_KERNEL(GResizeP, <GMatP(GMatP,Size,int)>, "org.opencv.core.transform.resizeP") {
static GMatDesc outMeta(GMatDesc in, Size sz, int interp) {
GAPI_Assert(in.depth == CV_8U);
GAPI_Assert(in.chan == 3);
GAPI_Assert(in.planar);
GAPI_Assert(interp == cv::INTER_LINEAR);
return in.withSize(sz);
}
};
G_TYPED_KERNEL(GMerge3, <GMat(GMat,GMat,GMat)>, "org.opencv.core.transform.merge3") {
static GMatDesc outMeta(GMatDesc in, GMatDesc, GMatDesc) {
// Preserve depth and add channel component
@ -1467,63 +1444,6 @@ GAPI_EXPORTS GMat inRange(const GMat& src, const GScalar& threshLow, const GScal
//! @addtogroup gapi_transform
//! @{
/** @brief Resizes an image.
The function resizes the image src down to or up to the specified size.
Output image size will have the size dsize (when dsize is non-zero) or the size computed from
src.size(), fx, and fy; the depth of output is the same as of src.
If you want to resize src so that it fits the pre-created dst,
you may call the function as follows:
@code
// explicitly specify dsize=dst.size(); fx and fy will be computed from that.
resize(src, dst, dst.size(), 0, 0, interpolation);
@endcode
If you want to decimate the image by factor of 2 in each direction, you can call the function this
way:
@code
// specify fx and fy and let the function compute the destination image size.
resize(src, dst, Size(), 0.5, 0.5, interpolation);
@endcode
To shrink an image, it will generally look best with cv::INTER_AREA interpolation, whereas to
enlarge an image, it will generally look best with cv::INTER_CUBIC (slow) or cv::INTER_LINEAR
(faster but still looks OK).
@note Function textual ID is "org.opencv.core.transform.resize"
@param src input image.
@param dsize output image size; if it equals zero, it is computed as:
\f[\texttt{dsize = Size(round(fx*src.cols), round(fy*src.rows))}\f]
Either dsize or both fx and fy must be non-zero.
@param fx scale factor along the horizontal axis; when it equals 0, it is computed as
\f[\texttt{(double)dsize.width/src.cols}\f]
@param fy scale factor along the vertical axis; when it equals 0, it is computed as
\f[\texttt{(double)dsize.height/src.rows}\f]
@param interpolation interpolation method, see cv::InterpolationFlags
@sa warpAffine, warpPerspective, remap, resizeP
*/
GAPI_EXPORTS_W GMat resize(const GMat& src, const Size& dsize, double fx = 0, double fy = 0, int interpolation = INTER_LINEAR);
/** @brief Resizes a planar image.
The function resizes the image src down to or up to the specified size.
Planar image memory layout is three planes laying in the memory contiguously,
so the image height should be plane_height*plane_number, image type is @ref CV_8UC1.
Output image size will have the size dsize, the depth of output is the same as of src.
@note Function textual ID is "org.opencv.core.transform.resizeP"
@param src input image, must be of @ref CV_8UC1 type;
@param dsize output image size;
@param interpolation interpolation method, only cv::INTER_LINEAR is supported at the moment
@sa warpAffine, warpPerspective, remap, resize
*/
GAPI_EXPORTS GMatP resizeP(const GMatP& src, const Size& dsize, int interpolation = cv::INTER_LINEAR);
/** @brief Creates one 4-channel matrix out of 4 single-channel ones.
The function merges several matrices to make a single multi-channel matrix. That is, each

View File

@ -23,6 +23,7 @@
@defgroup gapi_colorconvert Graph API: Converting image from one color space to another
@defgroup gapi_feature Graph API: Image Feature Detection
@defgroup gapi_shape Graph API: Image Structural Analysis and Shape Descriptors
@defgroup gapi_transform Graph API: Image and channel composition functions
@}
*/
@ -56,7 +57,7 @@ namespace imgproc {
using GMat3 = std::tuple<GMat,GMat,GMat>; // FIXME: how to avoid this?
using GFindContoursOutput = std::tuple<GArray<GArray<Point>>,GArray<Vec4i>>;
G_TYPED_KERNEL(GFilter2D, <GMat(GMat,int,Mat,Point,Scalar,int,Scalar)>,"org.opencv.imgproc.filters.filter2D") {
G_TYPED_KERNEL(GFilter2D, <GMat(GMat,int,Mat,Point,Scalar,int,Scalar)>, "org.opencv.imgproc.filters.filter2D") {
static GMatDesc outMeta(GMatDesc in, int ddepth, Mat, Point, Scalar, int, Scalar) {
return in.withDepth(ddepth);
}
@ -74,7 +75,7 @@ namespace imgproc {
}
};
G_TYPED_KERNEL(GBlur, <GMat(GMat,Size,Point,int,Scalar)>, "org.opencv.imgproc.filters.blur"){
G_TYPED_KERNEL(GBlur, <GMat(GMat,Size,Point,int,Scalar)>, "org.opencv.imgproc.filters.blur") {
static GMatDesc outMeta(GMatDesc in, Size, Point, int, Scalar) {
return in;
}
@ -138,13 +139,13 @@ namespace imgproc {
}
};
G_TYPED_KERNEL(GEqHist, <GMat(GMat)>, "org.opencv.imgproc.equalizeHist"){
G_TYPED_KERNEL(GEqHist, <GMat(GMat)>, "org.opencv.imgproc.equalizeHist") {
static GMatDesc outMeta(GMatDesc in) {
return in.withType(CV_8U, 1);
}
};
G_TYPED_KERNEL(GCanny, <GMat(GMat,double,double,int,bool)>, "org.opencv.imgproc.feature.canny"){
G_TYPED_KERNEL(GCanny, <GMat(GMat,double,double,int,bool)>, "org.opencv.imgproc.feature.canny") {
static GMatDesc outMeta(GMatDesc in, double, double, int, bool) {
return in.withType(CV_8U, 1);
}
@ -495,6 +496,32 @@ namespace imgproc {
}
};
G_TYPED_KERNEL(GResize, <GMat(GMat,Size,double,double,int)>, "org.opencv.imgproc.transform.resize") {
static GMatDesc outMeta(GMatDesc in, Size sz, double fx, double fy, int /*interp*/) {
if (sz.width != 0 && sz.height != 0)
{
return in.withSize(sz);
}
else
{
int outSz_w = static_cast<int>(round(in.size.width * fx));
int outSz_h = static_cast<int>(round(in.size.height * fy));
GAPI_Assert(outSz_w > 0 && outSz_h > 0);
return in.withSize(Size(outSz_w, outSz_h));
}
}
};
G_TYPED_KERNEL(GResizeP, <GMatP(GMatP,Size,int)>, "org.opencv.imgproc.transform.resizeP") {
static GMatDesc outMeta(GMatDesc in, Size sz, int interp) {
GAPI_Assert(in.depth == CV_8U);
GAPI_Assert(in.chan == 3);
GAPI_Assert(in.planar);
GAPI_Assert(interp == cv::INTER_LINEAR);
return in.withSize(sz);
}
};
} //namespace imgproc
//! @addtogroup gapi_filters
@ -1676,6 +1703,66 @@ image type is @ref CV_8UC1.
GAPI_EXPORTS GMatP NV12toBGRp(const GMat &src_y, const GMat &src_uv);
//! @} gapi_colorconvert
//! @addtogroup gapi_transform
//! @{
/** @brief Resizes an image.
The function resizes the image src down to or up to the specified size.
Output image size will have the size dsize (when dsize is non-zero) or the size computed from
src.size(), fx, and fy; the depth of output is the same as of src.
If you want to resize src so that it fits the pre-created dst,
you may call the function as follows:
@code
// explicitly specify dsize=dst.size(); fx and fy will be computed from that.
resize(src, dst, dst.size(), 0, 0, interpolation);
@endcode
If you want to decimate the image by factor of 2 in each direction, you can call the function this
way:
@code
// specify fx and fy and let the function compute the destination image size.
resize(src, dst, Size(), 0.5, 0.5, interpolation);
@endcode
To shrink an image, it will generally look best with cv::INTER_AREA interpolation, whereas to
enlarge an image, it will generally look best with cv::INTER_CUBIC (slow) or cv::INTER_LINEAR
(faster but still looks OK).
@note Function textual ID is "org.opencv.imgproc.transform.resize"
@param src input image.
@param dsize output image size; if it equals zero, it is computed as:
\f[\texttt{dsize = Size(round(fx*src.cols), round(fy*src.rows))}\f]
Either dsize or both fx and fy must be non-zero.
@param fx scale factor along the horizontal axis; when it equals 0, it is computed as
\f[\texttt{(double)dsize.width/src.cols}\f]
@param fy scale factor along the vertical axis; when it equals 0, it is computed as
\f[\texttt{(double)dsize.height/src.rows}\f]
@param interpolation interpolation method, see cv::InterpolationFlags
@sa warpAffine, warpPerspective, remap, resizeP
*/
GAPI_EXPORTS_W GMat resize(const GMat& src, const Size& dsize, double fx = 0, double fy = 0, int interpolation = INTER_LINEAR);
/** @brief Resizes a planar image.
The function resizes the image src down to or up to the specified size.
Planar image memory layout is three planes laying in the memory contiguously,
so the image height should be plane_height*plane_number, image type is @ref CV_8UC1.
Output image size will have the size dsize, the depth of output is the same as of src.
@note Function textual ID is "org.opencv.imgproc.transform.resizeP"
@param src input image, must be of @ref CV_8UC1 type;
@param dsize output image size;
@param interpolation interpolation method, only cv::INTER_LINEAR is supported at the moment
@sa warpAffine, warpPerspective, remap, resize
*/
GAPI_EXPORTS GMatP resizeP(const GMatP& src, const Size& dsize, int interpolation = cv::INTER_LINEAR);
//! @} gapi_transform
} //namespace gapi
} //namespace cv

View File

@ -301,16 +301,6 @@ GMat merge4(const GMat& src1, const GMat& src2, const GMat& src3, const GMat& sr
return core::GMerge4::on(src1, src2, src3, src4);
}
GMat resize(const GMat& src, const Size& dsize, double fx, double fy, int interpolation)
{
return core::GResize::on(src, dsize, fx, fy, interpolation);
}
GMatP resizeP(const GMatP& src, const Size& dsize, int interpolation)
{
return core::GResizeP::on(src, dsize, interpolation);
}
GMat remap(const GMat& src, const Mat& map1, const Mat& map2,
int interpolation, int borderMode,
const Scalar& borderValue)

View File

@ -14,6 +14,16 @@
namespace cv { namespace gapi {
GMat resize(const GMat& src, const Size& dsize, double fx, double fy, int interpolation)
{
return imgproc::GResize::on(src, dsize, fx, fy, interpolation);
}
GMatP resizeP(const GMatP& src, const Size& dsize, int interpolation)
{
return imgproc::GResizeP::on(src, dsize, interpolation);
}
GMat sepFilter(const GMat& src, int ddepth, const Mat& kernelX, const Mat& kernelY, const Point& anchor,
const Scalar& delta, int borderType, const Scalar& borderVal)
{

View File

@ -462,30 +462,6 @@ GAPI_OCV_KERNEL(GCPUMerge4, cv::gapi::core::GMerge4)
}
};
GAPI_OCV_KERNEL(GCPUResize, cv::gapi::core::GResize)
{
static void run(const cv::Mat& in, cv::Size sz, double fx, double fy, int interp, cv::Mat &out)
{
cv::resize(in, out, sz, fx, fy, interp);
}
};
GAPI_OCV_KERNEL(GCPUResizeP, cv::gapi::core::GResizeP)
{
static void run(const cv::Mat& in, cv::Size out_sz, int interp, cv::Mat& out)
{
int inH = in.rows / 3;
int inW = in.cols;
int outH = out.rows / 3;
int outW = out.cols;
for (int i = 0; i < 3; i++) {
auto in_plane = in(cv::Rect(0, i*inH, inW, inH));
auto out_plane = out(cv::Rect(0, i*outH, outW, outH));
cv::resize(in_plane, out_plane, out_sz, 0, 0, interp);
}
}
};
GAPI_OCV_KERNEL(GCPURemap, cv::gapi::core::GRemap)
{
static void run(const cv::Mat& in, const cv::Mat& x, const cv::Mat& y, int a, int b, cv::Scalar s, cv::Mat& out)
@ -775,8 +751,6 @@ cv::GKernelPackage cv::gapi::core::cpu::kernels()
, GCPUInRange
, GCPUSplit3
, GCPUSplit4
, GCPUResize
, GCPUResizeP
, GCPUMerge3
, GCPUMerge4
, GCPURemap

View File

@ -28,6 +28,30 @@ namespace {
}
}
GAPI_OCV_KERNEL(GCPUResize, cv::gapi::imgproc::GResize)
{
static void run(const cv::Mat& in, cv::Size sz, double fx, double fy, int interp, cv::Mat &out)
{
cv::resize(in, out, sz, fx, fy, interp);
}
};
GAPI_OCV_KERNEL(GCPUResizeP, cv::gapi::imgproc::GResizeP)
{
static void run(const cv::Mat& in, cv::Size out_sz, int interp, cv::Mat& out)
{
int inH = in.rows / 3;
int inW = in.cols;
int outH = out.rows / 3;
int outW = out.cols;
for (int i = 0; i < 3; i++) {
auto in_plane = in(cv::Rect(0, i*inH, inW, inH));
auto out_plane = out(cv::Rect(0, i*outH, outW, outH));
cv::resize(in_plane, out_plane, out_sz, 0, 0, interp);
}
}
};
GAPI_OCV_KERNEL(GCPUSepFilter, cv::gapi::imgproc::GSepFilter)
{
static void run(const cv::Mat& in, int ddepth, const cv::Mat& kernX, const cv::Mat& kernY, const cv::Point& anchor, const cv::Scalar& delta,
@ -617,6 +641,8 @@ cv::GKernelPackage cv::gapi::imgproc::cpu::kernels()
{
static auto pkg = cv::gapi::kernels
< GCPUFilter2D
, GCPUResize
, GCPUResizeP
, GCPUSepFilter
, GCPUBoxFilter
, GCPUBlur

View File

@ -23,10 +23,6 @@
#include <opencv2/gapi/fluid/gfluidkernel.hpp>
#include <opencv2/gapi/fluid/core.hpp>
#if CV_SSE4_1
#include "gfluidcore_simd_sse41.hpp"
#endif
#include "gfluidbuffer_priv.hpp"
#include "gfluidbackend.hpp"
#include "gfluidutils.hpp"
@ -2760,301 +2756,6 @@ GAPI_FLUID_KERNEL(GFluidPhase, cv::gapi::core::GPhase, false)
}
};
template<typename T, typename Mapper, int chanNum>
struct LinearScratchDesc {
using alpha_t = typename Mapper::alpha_type;
using index_t = typename Mapper::index_type;
alpha_t* alpha;
alpha_t* clone;
index_t* mapsx;
alpha_t* beta;
index_t* mapsy;
T* tmp;
LinearScratchDesc(int /*inW*/, int /*inH*/, int outW, int outH, void* data) {
alpha = reinterpret_cast<alpha_t*>(data);
clone = reinterpret_cast<alpha_t*>(alpha + outW);
mapsx = reinterpret_cast<index_t*>(clone + outW*4);
beta = reinterpret_cast<alpha_t*>(mapsx + outW);
mapsy = reinterpret_cast<index_t*>(beta + outH);
tmp = reinterpret_cast<T*> (mapsy + outH*2);
}
static int bufSize(int inW, int /*inH*/, int outW, int outH, int lpi) {
auto size = outW * sizeof(alpha_t) +
outW * sizeof(alpha_t) * 4 + // alpha clones
outW * sizeof(index_t) +
outH * sizeof(alpha_t) +
outH * sizeof(index_t) * 2 +
inW * sizeof(T) * lpi * chanNum;
return static_cast<int>(size);
}
};
static inline double invRatio(int inSz, int outSz) {
return static_cast<double>(outSz) / inSz;
}
static inline double ratio(int inSz, int outSz) {
return 1 / invRatio(inSz, outSz);
}
template<typename T, typename Mapper, int chanNum = 1>
static inline void initScratchLinear(const cv::GMatDesc& in,
const Size& outSz,
cv::gapi::fluid::Buffer& scratch,
int lpi) {
using alpha_type = typename Mapper::alpha_type;
static const auto unity = Mapper::unity;
auto inSz = in.size;
auto sbufsize = LinearScratchDesc<T, Mapper, chanNum>::bufSize(inSz.width, inSz.height, outSz.width, outSz.height, lpi);
Size scratch_size{sbufsize, 1};
cv::GMatDesc desc;
desc.chan = 1;
desc.depth = CV_8UC1;
desc.size = scratch_size;
cv::gapi::fluid::Buffer buffer(desc);
scratch = std::move(buffer);
double hRatio = ratio(in.size.width, outSz.width);
double vRatio = ratio(in.size.height, outSz.height);
LinearScratchDesc<T, Mapper, chanNum> scr(inSz.width, inSz.height, outSz.width, outSz.height, scratch.OutLineB());
auto *alpha = scr.alpha;
auto *clone = scr.clone;
auto *index = scr.mapsx;
for (int x = 0; x < outSz.width; x++) {
auto map = Mapper::map(hRatio, 0, in.size.width, x);
auto alpha0 = map.alpha0;
auto index0 = map.index0;
// TRICK:
// Algorithm takes pair of input pixels, sx0'th and sx1'th,
// and compute result as alpha0*src[sx0] + alpha1*src[sx1].
// By definition: sx1 == sx0 + 1 either sx1 == sx0, and
// alpha0 + alpha1 == unity (scaled appropriately).
// Here we modify formulas for alpha0 and sx1: by assuming
// that sx1 == sx0 + 1 always, and patching alpha0 so that
// result remains intact.
// Note that we need in.size.width >= 2, for both sx0 and
// sx0+1 were indexing pixels inside the input's width.
if (map.index1 != map.index0 + 1) {
GAPI_DbgAssert(map.index1 == map.index0);
GAPI_DbgAssert(in.size.width >= 2);
if (map.index0 < in.size.width-1) {
// sx1=sx0+1 fits inside row,
// make sure alpha0=unity and alpha1=0,
// so that result equals src[sx0]*unity
alpha0 = saturate_cast<alpha_type>(unity);
} else {
// shift sx0 to left by 1 pixel,
// and make sure that alpha0=0 and alpha1==1,
// so that result equals to src[sx0+1]*unity
alpha0 = 0;
index0--;
}
}
alpha[x] = alpha0;
index[x] = index0;
for (int l = 0; l < 4; l++) {
clone[4*x + l] = alpha0;
}
}
auto *beta = scr.beta;
auto *index_y = scr.mapsy;
for (int y = 0; y < outSz.height; y++) {
auto mapY = Mapper::map(vRatio, 0, in.size.height, y);
beta[y] = mapY.alpha0;
index_y[y] = mapY.index0;
index_y[outSz.height + y] = mapY.index1;
}
}
template<typename F, typename I>
struct MapperUnit {
F alpha0, alpha1;
I index0, index1;
};
inline static uint8_t calc(short alpha0, uint8_t src0, short alpha1, uint8_t src1) {
constexpr static const int half = 1 << 14;
return (src0 * alpha0 + src1 * alpha1 + half) >> 15;
}
struct Mapper {
constexpr static const int ONE = 1 << 15;
typedef short alpha_type;
typedef short index_type;
constexpr static const int unity = ONE;
typedef MapperUnit<short, short> Unit;
static inline Unit map(double ratio, int start, int max, int outCoord) {
float f = static_cast<float>((outCoord + 0.5) * ratio - 0.5);
int s = cvFloor(f);
f -= s;
Unit u;
u.index0 = static_cast<short>(std::max(s - start, 0));
u.index1 = static_cast<short>(((f == 0.0) || s + 1 >= max) ? s - start : s - start + 1);
u.alpha0 = saturate_cast<short>(ONE * (1.0f - f));
u.alpha1 = saturate_cast<short>(ONE * f);
return u;
}
};
template<typename T, class Mapper, int numChan>
static void calcRowLinearC(const cv::gapi::fluid::View & in,
cv::gapi::fluid::Buffer& out,
cv::gapi::fluid::Buffer& scratch) {
using alpha_type = typename Mapper::alpha_type;
auto inSz = in.meta().size;
auto outSz = out.meta().size;
auto inY = in.y();
int outY = out.y();
int lpi = out.lpi();
GAPI_DbgAssert(outY + lpi <= outSz.height);
GAPI_DbgAssert(lpi <= 4);
LinearScratchDesc<T, Mapper, numChan> scr(inSz.width, inSz.height, outSz.width, outSz.height, scratch.OutLineB());
const auto *alpha = scr.alpha;
const auto *mapsx = scr.mapsx;
const auto *beta_0 = scr.beta;
const auto *mapsy = scr.mapsy;
const auto *beta = beta_0 + outY;
const T *src0[4];
const T *src1[4];
T* dst[4];
for (int l = 0; l < lpi; l++) {
auto index0 = mapsy[outY + l] - inY;
auto index1 = mapsy[outSz.height + outY + l] - inY;
src0[l] = in.InLine<const T>(index0);
src1[l] = in.InLine<const T>(index1);
dst[l] = out.OutLine<T>(l);
}
#if 0 // Disabling SSE4.1 path due to Valgrind issues: https://github.com/opencv/opencv/issues/21097
#if CV_SSE4_1
const auto* clone = scr.clone;
auto* tmp = scr.tmp;
if (inSz.width >= 16 && outSz.width >= 16)
{
sse42::calcRowLinear_8UC_Impl_<numChan>(reinterpret_cast<uint8_t**>(dst),
reinterpret_cast<const uint8_t**>(src0),
reinterpret_cast<const uint8_t**>(src1),
reinterpret_cast<const short*>(alpha),
reinterpret_cast<const short*>(clone),
reinterpret_cast<const short*>(mapsx),
reinterpret_cast<const short*>(beta),
reinterpret_cast<uint8_t*>(tmp),
inSz, outSz, lpi);
return;
}
#endif // CV_SSE4_1
#endif
int length = out.length();
for (int l = 0; l < lpi; l++) {
constexpr static const auto unity = Mapper::unity;
auto beta0 = beta[l];
auto beta1 = saturate_cast<alpha_type>(unity - beta[l]);
for (int x = 0; x < length; x++) {
auto alpha0 = alpha[x];
auto alpha1 = saturate_cast<alpha_type>(unity - alpha[x]);
auto sx0 = mapsx[x];
auto sx1 = sx0 + 1;
for (int c = 0; c < numChan; c++) {
auto idx0 = numChan*sx0 + c;
auto idx1 = numChan*sx1 + c;
T tmp0 = calc(beta0, src0[l][idx0], beta1, src1[l][idx0]);
T tmp1 = calc(beta0, src0[l][idx1], beta1, src1[l][idx1]);
dst[l][numChan * x + c] = calc(alpha0, tmp0, alpha1, tmp1);
}
}
}
}
GAPI_FLUID_KERNEL(GFluidResize, cv::gapi::core::GResize, true)
{
static const int Window = 1;
static const int LPI = 4;
static const auto Kind = GFluidKernel::Kind::Resize;
constexpr static const int INTER_RESIZE_COEF_BITS = 11;
constexpr static const int INTER_RESIZE_COEF_SCALE = 1 << INTER_RESIZE_COEF_BITS;
constexpr static const short ONE = INTER_RESIZE_COEF_SCALE;
static void initScratch(const cv::GMatDesc& in,
cv::Size outSz, double fx, double fy, int /*interp*/,
cv::gapi::fluid::Buffer &scratch)
{
int outSz_w;
int outSz_h;
if (outSz.width == 0 || outSz.height == 0)
{
outSz_w = static_cast<int>(round(in.size.width * fx));
outSz_h = static_cast<int>(round(in.size.height * fy));
}
else
{
outSz_w = outSz.width;
outSz_h = outSz.height;
}
cv::Size outSize(outSz_w, outSz_h);
if (in.chan == 3)
{
initScratchLinear<uchar, Mapper, 3>(in, outSize, scratch, LPI);
}
else if (in.chan == 4)
{
initScratchLinear<uchar, Mapper, 4>(in, outSize, scratch, LPI);
}
}
static void resetScratch(cv::gapi::fluid::Buffer& /*scratch*/)
{}
static void run(const cv::gapi::fluid::View& in, cv::Size /*sz*/, double /*fx*/, double /*fy*/, int interp,
cv::gapi::fluid::Buffer& out,
cv::gapi::fluid::Buffer& scratch) {
const int channels = in.meta().chan;
GAPI_Assert((channels == 3 || channels == 4) && (interp == cv::INTER_LINEAR));
if (channels == 3)
{
calcRowLinearC<uint8_t, Mapper, 3>(in, out, scratch);
}
else if (channels == 4)
{
calcRowLinearC<uint8_t, Mapper, 4>(in, out, scratch);
}
}
};
GAPI_FLUID_KERNEL(GFluidSqrt, cv::gapi::core::GSqrt, false)
{
static const int Window = 1;
@ -3134,7 +2835,6 @@ cv::GKernelPackage cv::gapi::core::fluid::kernels()
,GFluidCmpNEScalar
,GFluidThreshold
,GFluidInRange
,GFluidResize
,GFluidSqrt
#if 0
,GFluidMean -- not fluid

View File

@ -25,6 +25,10 @@
#include "gfluidimgproc_func.hpp"
#if CV_SSE4_1
#include "gfluidcore_simd_sse41.hpp"
#endif
#include <opencv2/imgproc/hal/hal.hpp>
#include <opencv2/core/hal/intrin.hpp>
@ -1821,6 +1825,301 @@ GAPI_FLUID_KERNEL(GFluidBayerGR2RGB, cv::gapi::imgproc::GBayerGR2RGB, false)
}
};
template<typename T, typename Mapper, int chanNum>
struct LinearScratchDesc {
using alpha_t = typename Mapper::alpha_type;
using index_t = typename Mapper::index_type;
alpha_t* alpha;
alpha_t* clone;
index_t* mapsx;
alpha_t* beta;
index_t* mapsy;
T* tmp;
LinearScratchDesc(int /*inW*/, int /*inH*/, int outW, int outH, void* data) {
alpha = reinterpret_cast<alpha_t*>(data);
clone = reinterpret_cast<alpha_t*>(alpha + outW);
mapsx = reinterpret_cast<index_t*>(clone + outW*4);
beta = reinterpret_cast<alpha_t*>(mapsx + outW);
mapsy = reinterpret_cast<index_t*>(beta + outH);
tmp = reinterpret_cast<T*> (mapsy + outH*2);
}
static int bufSize(int inW, int /*inH*/, int outW, int outH, int lpi) {
auto size = outW * sizeof(alpha_t) +
outW * sizeof(alpha_t) * 4 + // alpha clones
outW * sizeof(index_t) +
outH * sizeof(alpha_t) +
outH * sizeof(index_t) * 2 +
inW * sizeof(T) * lpi * chanNum;
return static_cast<int>(size);
}
};
static inline double invRatio(int inSz, int outSz) {
return static_cast<double>(outSz) / inSz;
}
static inline double ratio(int inSz, int outSz) {
return 1 / invRatio(inSz, outSz);
}
template<typename T, typename Mapper, int chanNum = 1>
static inline void initScratchLinear(const cv::GMatDesc& in,
const Size& outSz,
cv::gapi::fluid::Buffer& scratch,
int lpi) {
using alpha_type = typename Mapper::alpha_type;
static const auto unity = Mapper::unity;
auto inSz = in.size;
auto sbufsize = LinearScratchDesc<T, Mapper, chanNum>::bufSize(inSz.width, inSz.height, outSz.width, outSz.height, lpi);
Size scratch_size{sbufsize, 1};
cv::GMatDesc desc;
desc.chan = 1;
desc.depth = CV_8UC1;
desc.size = scratch_size;
cv::gapi::fluid::Buffer buffer(desc);
scratch = std::move(buffer);
double hRatio = ratio(in.size.width, outSz.width);
double vRatio = ratio(in.size.height, outSz.height);
LinearScratchDesc<T, Mapper, chanNum> scr(inSz.width, inSz.height, outSz.width, outSz.height, scratch.OutLineB());
auto *alpha = scr.alpha;
auto *clone = scr.clone;
auto *index = scr.mapsx;
for (int x = 0; x < outSz.width; x++) {
auto map = Mapper::map(hRatio, 0, in.size.width, x);
auto alpha0 = map.alpha0;
auto index0 = map.index0;
// TRICK:
// Algorithm takes pair of input pixels, sx0'th and sx1'th,
// and compute result as alpha0*src[sx0] + alpha1*src[sx1].
// By definition: sx1 == sx0 + 1 either sx1 == sx0, and
// alpha0 + alpha1 == unity (scaled appropriately).
// Here we modify formulas for alpha0 and sx1: by assuming
// that sx1 == sx0 + 1 always, and patching alpha0 so that
// result remains intact.
// Note that we need in.size.width >= 2, for both sx0 and
// sx0+1 were indexing pixels inside the input's width.
if (map.index1 != map.index0 + 1) {
GAPI_DbgAssert(map.index1 == map.index0);
GAPI_DbgAssert(in.size.width >= 2);
if (map.index0 < in.size.width-1) {
// sx1=sx0+1 fits inside row,
// make sure alpha0=unity and alpha1=0,
// so that result equals src[sx0]*unity
alpha0 = saturate_cast<alpha_type>(unity);
} else {
// shift sx0 to left by 1 pixel,
// and make sure that alpha0=0 and alpha1==1,
// so that result equals to src[sx0+1]*unity
alpha0 = 0;
index0--;
}
}
alpha[x] = alpha0;
index[x] = index0;
for (int l = 0; l < 4; l++) {
clone[4*x + l] = alpha0;
}
}
auto *beta = scr.beta;
auto *index_y = scr.mapsy;
for (int y = 0; y < outSz.height; y++) {
auto mapY = Mapper::map(vRatio, 0, in.size.height, y);
beta[y] = mapY.alpha0;
index_y[y] = mapY.index0;
index_y[outSz.height + y] = mapY.index1;
}
}
template<typename F, typename I>
struct MapperUnit {
F alpha0, alpha1;
I index0, index1;
};
inline static uint8_t calc(short alpha0, uint8_t src0, short alpha1, uint8_t src1) {
constexpr static const int half = 1 << 14;
return (src0 * alpha0 + src1 * alpha1 + half) >> 15;
}
struct Mapper {
constexpr static const int ONE = 1 << 15;
typedef short alpha_type;
typedef short index_type;
constexpr static const int unity = ONE;
typedef MapperUnit<short, short> Unit;
static inline Unit map(double ratio, int start, int max, int outCoord) {
float f = static_cast<float>((outCoord + 0.5) * ratio - 0.5);
int s = cvFloor(f);
f -= s;
Unit u;
u.index0 = static_cast<short>(std::max(s - start, 0));
u.index1 = static_cast<short>(((f == 0.0) || s + 1 >= max) ? s - start : s - start + 1);
u.alpha0 = saturate_cast<short>(ONE * (1.0f - f));
u.alpha1 = saturate_cast<short>(ONE * f);
return u;
}
};
template<typename T, class Mapper, int numChan>
static void calcRowLinearC(const cv::gapi::fluid::View & in,
cv::gapi::fluid::Buffer& out,
cv::gapi::fluid::Buffer& scratch) {
using alpha_type = typename Mapper::alpha_type;
auto inSz = in.meta().size;
auto outSz = out.meta().size;
auto inY = in.y();
int outY = out.y();
int lpi = out.lpi();
GAPI_DbgAssert(outY + lpi <= outSz.height);
GAPI_DbgAssert(lpi <= 4);
LinearScratchDesc<T, Mapper, numChan> scr(inSz.width, inSz.height, outSz.width, outSz.height, scratch.OutLineB());
const auto *alpha = scr.alpha;
const auto *mapsx = scr.mapsx;
const auto *beta_0 = scr.beta;
const auto *mapsy = scr.mapsy;
const auto *beta = beta_0 + outY;
const T *src0[4];
const T *src1[4];
T* dst[4];
for (int l = 0; l < lpi; l++) {
auto index0 = mapsy[outY + l] - inY;
auto index1 = mapsy[outSz.height + outY + l] - inY;
src0[l] = in.InLine<const T>(index0);
src1[l] = in.InLine<const T>(index1);
dst[l] = out.OutLine<T>(l);
}
#if 0 // Disabling SSE4.1 path due to Valgrind issues: https://github.com/opencv/opencv/issues/21097
#if CV_SSE4_1
const auto* clone = scr.clone;
auto* tmp = scr.tmp;
if (inSz.width >= 16 && outSz.width >= 16)
{
sse42::calcRowLinear_8UC_Impl_<numChan>(reinterpret_cast<uint8_t**>(dst),
reinterpret_cast<const uint8_t**>(src0),
reinterpret_cast<const uint8_t**>(src1),
reinterpret_cast<const short*>(alpha),
reinterpret_cast<const short*>(clone),
reinterpret_cast<const short*>(mapsx),
reinterpret_cast<const short*>(beta),
reinterpret_cast<uint8_t*>(tmp),
inSz, outSz, lpi);
return;
}
#endif // CV_SSE4_1
#endif
int length = out.length();
for (int l = 0; l < lpi; l++) {
constexpr static const auto unity = Mapper::unity;
auto beta0 = beta[l];
auto beta1 = saturate_cast<alpha_type>(unity - beta[l]);
for (int x = 0; x < length; x++) {
auto alpha0 = alpha[x];
auto alpha1 = saturate_cast<alpha_type>(unity - alpha[x]);
auto sx0 = mapsx[x];
auto sx1 = sx0 + 1;
for (int c = 0; c < numChan; c++) {
auto idx0 = numChan*sx0 + c;
auto idx1 = numChan*sx1 + c;
T tmp0 = calc(beta0, src0[l][idx0], beta1, src1[l][idx0]);
T tmp1 = calc(beta0, src0[l][idx1], beta1, src1[l][idx1]);
dst[l][numChan * x + c] = calc(alpha0, tmp0, alpha1, tmp1);
}
}
}
}
GAPI_FLUID_KERNEL(GFluidResize, cv::gapi::imgproc::GResize, true)
{
static const int Window = 1;
static const int LPI = 4;
static const auto Kind = GFluidKernel::Kind::Resize;
constexpr static const int INTER_RESIZE_COEF_BITS = 11;
constexpr static const int INTER_RESIZE_COEF_SCALE = 1 << INTER_RESIZE_COEF_BITS;
constexpr static const short ONE = INTER_RESIZE_COEF_SCALE;
static void initScratch(const cv::GMatDesc& in,
cv::Size outSz, double fx, double fy, int /*interp*/,
cv::gapi::fluid::Buffer &scratch)
{
int outSz_w;
int outSz_h;
if (outSz.width == 0 || outSz.height == 0)
{
outSz_w = static_cast<int>(round(in.size.width * fx));
outSz_h = static_cast<int>(round(in.size.height * fy));
}
else
{
outSz_w = outSz.width;
outSz_h = outSz.height;
}
cv::Size outSize(outSz_w, outSz_h);
if (in.chan == 3)
{
initScratchLinear<uchar, Mapper, 3>(in, outSize, scratch, LPI);
}
else if (in.chan == 4)
{
initScratchLinear<uchar, Mapper, 4>(in, outSize, scratch, LPI);
}
}
static void resetScratch(cv::gapi::fluid::Buffer& /*scratch*/)
{}
static void run(const cv::gapi::fluid::View& in, cv::Size /*sz*/, double /*fx*/, double /*fy*/, int interp,
cv::gapi::fluid::Buffer& out,
cv::gapi::fluid::Buffer& scratch) {
const int channels = in.meta().chan;
GAPI_Assert((channels == 3 || channels == 4) && (interp == cv::INTER_LINEAR));
if (channels == 3)
{
calcRowLinearC<uint8_t, Mapper, 3>(in, out, scratch);
}
else if (channels == 4)
{
calcRowLinearC<uint8_t, Mapper, 4>(in, out, scratch);
}
}
};
} // namespace fluid
} // namespace gapi
} // namespace cv
@ -1831,6 +2130,7 @@ cv::GKernelPackage cv::gapi::imgproc::fluid::kernels()
return cv::gapi::kernels
< GFluidBGR2Gray
, GFluidResize
, GFluidRGB2Gray
, GFluidRGB2GrayCustom
, GFluidRGB2YUV

View File

@ -458,14 +458,6 @@ GAPI_OCL_KERNEL(GOCLMerge4, cv::gapi::core::GMerge4)
}
};
GAPI_OCL_KERNEL(GOCLResize, cv::gapi::core::GResize)
{
static void run(const cv::UMat& in, cv::Size sz, double fx, double fy, int interp, cv::UMat &out)
{
cv::resize(in, out, sz, fx, fy, interp);
}
};
GAPI_OCL_KERNEL(GOCLRemap, cv::gapi::core::GRemap)
{
static void run(const cv::UMat& in, const cv::Mat& x, const cv::Mat& y, int a, int b, cv::Scalar s, cv::UMat& out)
@ -585,7 +577,6 @@ cv::GKernelPackage cv::gapi::core::ocl::kernels()
, GOCLInRange
, GOCLSplit3
, GOCLSplit4
, GOCLResize
, GOCLMerge3
, GOCLMerge4
, GOCLRemap

View File

@ -11,6 +11,13 @@
#include <opencv2/gapi/ocl/imgproc.hpp>
#include "backends/ocl/goclimgproc.hpp"
GAPI_OCL_KERNEL(GOCLResize, cv::gapi::imgproc::GResize)
{
static void run(const cv::UMat& in, cv::Size sz, double fx, double fy, int interp, cv::UMat &out)
{
cv::resize(in, out, sz, fx, fy, interp);
}
};
GAPI_OCL_KERNEL(GOCLSepFilter, cv::gapi::imgproc::GSepFilter)
{
@ -270,6 +277,7 @@ cv::GKernelPackage cv::gapi::imgproc::ocl::kernels()
{
static auto pkg = cv::gapi::kernels
< GOCLFilter2D
, GOCLResize
, GOCLSepFilter
, GOCLBoxFilter
, GOCLBlur

View File

@ -107,12 +107,6 @@ GAPI_TEST_FIXTURE(ThresholdOTTest, initMatrixRandU, FIXTURE_API(int), 1, tt)
GAPI_TEST_FIXTURE(InRangeTest, initMatrixRandU, <>, 0)
GAPI_TEST_FIXTURE(Split3Test, initMatrixRandU, <>, 0)
GAPI_TEST_FIXTURE(Split4Test, initMatrixRandU, <>, 0)
GAPI_TEST_FIXTURE(ResizeTest, initNothing, FIXTURE_API(CompareMats,int,cv::Size), 3,
cmpF, interp, sz_out)
GAPI_TEST_FIXTURE(ResizePTest, initNothing, FIXTURE_API(CompareMats,int,cv::Size), 3,
cmpF, interp, sz_out)
GAPI_TEST_FIXTURE(ResizeTestFxFy, initNothing, FIXTURE_API(CompareMats,int,double,double), 4,
cmpF, interp, fx, fy)
GAPI_TEST_FIXTURE(Merge3Test, initMatsRandU, <>, 0)
GAPI_TEST_FIXTURE(Merge4Test, initMatsRandU, <>, 0)
GAPI_TEST_FIXTURE(RemapTest, initMatrixRandU, <>, 0)

View File

@ -847,78 +847,6 @@ TEST_P(Split4Test, AccuracyTest)
}
}
static void ResizeAccuracyTest(const CompareMats& cmpF, int type, int interp, cv::Size sz_in,
cv::Size sz_out, double fx, double fy, cv::GCompileArgs&& compile_args)
{
cv::Mat in_mat1 (sz_in, type );
cv::Scalar mean = cv::Scalar::all(127);
cv::Scalar stddev = cv::Scalar::all(40.f);
cv::randn(in_mat1, mean, stddev);
auto out_mat_sz = sz_out.area() == 0 ? cv::Size(saturate_cast<int>(sz_in.width *fx),
saturate_cast<int>(sz_in.height*fy))
: sz_out;
cv::Mat out_mat(out_mat_sz, type);
cv::Mat out_mat_ocv(out_mat_sz, type);
// G-API code //////////////////////////////////////////////////////////////
cv::GMat in;
auto out = cv::gapi::resize(in, sz_out, fx, fy, interp);
cv::GComputation c(in, out);
c.apply(in_mat1, out_mat, std::move(compile_args));
// OpenCV code /////////////////////////////////////////////////////////////
{
cv::resize(in_mat1, out_mat_ocv, sz_out, fx, fy, interp);
}
// Comparison //////////////////////////////////////////////////////////////
{
EXPECT_TRUE(cmpF(out_mat, out_mat_ocv));
}
}
TEST_P(ResizeTest, AccuracyTest)
{
ResizeAccuracyTest(cmpF, type, interp, sz, sz_out, 0.0, 0.0, getCompileArgs());
}
TEST_P(ResizeTestFxFy, AccuracyTest)
{
ResizeAccuracyTest(cmpF, type, interp, sz, cv::Size{0, 0}, fx, fy, getCompileArgs());
}
TEST_P(ResizePTest, AccuracyTest)
{
constexpr int planeNum = 3;
cv::Size sz_in_p {sz.width, sz.height*planeNum};
cv::Size sz_out_p{sz_out.width, sz_out.height*planeNum};
cv::Mat in_mat(sz_in_p, CV_8UC1);
cv::randn(in_mat, cv::Scalar::all(127.0f), cv::Scalar::all(40.f));
cv::Mat out_mat (sz_out_p, CV_8UC1);
cv::Mat out_mat_ocv_p(sz_out_p, CV_8UC1);
cv::GMatP in;
auto out = cv::gapi::resizeP(in, sz_out, interp);
cv::GComputation c(cv::GIn(in), cv::GOut(out));
c.compile(cv::descr_of(in_mat).asPlanar(planeNum), getCompileArgs())
(cv::gin(in_mat), cv::gout(out_mat));
for (int i = 0; i < planeNum; i++) {
const cv::Mat in_mat_roi = in_mat(cv::Rect(0, i*sz.height, sz.width, sz.height));
cv::Mat out_mat_roi = out_mat_ocv_p(cv::Rect(0, i*sz_out.height, sz_out.width, sz_out.height));
cv::resize(in_mat_roi, out_mat_roi, sz_out, 0, 0, interp);
}
// Comparison //////////////////////////////////////////////////////////////
{
EXPECT_TRUE(cmpF(out_mat, out_mat_ocv_p));
}
}
TEST_P(Merge3Test, AccuracyTest)
{
cv::Mat in_mat3(sz, type);

View File

@ -119,6 +119,12 @@ GAPI_TEST_FIXTURE(YUV2BGRTest, initMatrixRandN, FIXTURE_API(CompareMats), 1, cmp
GAPI_TEST_FIXTURE(RGB2HSVTest, initMatrixRandN, FIXTURE_API(CompareMats), 1, cmpF)
GAPI_TEST_FIXTURE(BayerGR2RGBTest, initMatrixRandN, FIXTURE_API(CompareMats), 1, cmpF)
GAPI_TEST_FIXTURE(RGB2YUV422Test, initMatrixRandN, FIXTURE_API(CompareMats), 1, cmpF)
GAPI_TEST_FIXTURE(ResizeTest, initNothing, FIXTURE_API(CompareMats,int,cv::Size), 3,
cmpF, interp, sz_out)
GAPI_TEST_FIXTURE(ResizePTest, initNothing, FIXTURE_API(CompareMats,int,cv::Size), 3,
cmpF, interp, sz_out)
GAPI_TEST_FIXTURE(ResizeTestFxFy, initNothing, FIXTURE_API(CompareMats,int,double,double), 4,
cmpF, interp, fx, fy)
} // opencv_test
#endif //OPENCV_GAPI_IMGPROC_TESTS_HPP

View File

@ -1067,6 +1067,79 @@ TEST_P(RGB2YUV422Test, AccuracyTest)
EXPECT_EQ(sz, out_mat_gapi.size());
}
}
static void ResizeAccuracyTest(const CompareMats& cmpF, int type, int interp, cv::Size sz_in,
cv::Size sz_out, double fx, double fy, cv::GCompileArgs&& compile_args)
{
cv::Mat in_mat1 (sz_in, type );
cv::Scalar mean = cv::Scalar::all(127);
cv::Scalar stddev = cv::Scalar::all(40.f);
cv::randn(in_mat1, mean, stddev);
auto out_mat_sz = sz_out.area() == 0 ? cv::Size(saturate_cast<int>(sz_in.width *fx),
saturate_cast<int>(sz_in.height*fy))
: sz_out;
cv::Mat out_mat(out_mat_sz, type);
cv::Mat out_mat_ocv(out_mat_sz, type);
// G-API code //////////////////////////////////////////////////////////////
cv::GMat in;
auto out = cv::gapi::resize(in, sz_out, fx, fy, interp);
cv::GComputation c(in, out);
c.apply(in_mat1, out_mat, std::move(compile_args));
// OpenCV code /////////////////////////////////////////////////////////////
{
cv::resize(in_mat1, out_mat_ocv, sz_out, fx, fy, interp);
}
// Comparison //////////////////////////////////////////////////////////////
{
EXPECT_TRUE(cmpF(out_mat, out_mat_ocv));
}
}
TEST_P(ResizeTest, AccuracyTest)
{
ResizeAccuracyTest(cmpF, type, interp, sz, sz_out, 0.0, 0.0, getCompileArgs());
}
TEST_P(ResizeTestFxFy, AccuracyTest)
{
ResizeAccuracyTest(cmpF, type, interp, sz, cv::Size{0, 0}, fx, fy, getCompileArgs());
}
TEST_P(ResizePTest, AccuracyTest)
{
constexpr int planeNum = 3;
cv::Size sz_in_p {sz.width, sz.height*planeNum};
cv::Size sz_out_p{sz_out.width, sz_out.height*planeNum};
cv::Mat in_mat(sz_in_p, CV_8UC1);
cv::randn(in_mat, cv::Scalar::all(127.0f), cv::Scalar::all(40.f));
cv::Mat out_mat (sz_out_p, CV_8UC1);
cv::Mat out_mat_ocv_p(sz_out_p, CV_8UC1);
cv::GMatP in;
auto out = cv::gapi::resizeP(in, sz_out, interp);
cv::GComputation c(cv::GIn(in), cv::GOut(out));
c.compile(cv::descr_of(in_mat).asPlanar(planeNum), getCompileArgs())
(cv::gin(in_mat), cv::gout(out_mat));
for (int i = 0; i < planeNum; i++) {
const cv::Mat in_mat_roi = in_mat(cv::Rect(0, i*sz.height, sz.width, sz.height));
cv::Mat out_mat_roi = out_mat_ocv_p(cv::Rect(0, i*sz_out.height, sz_out.width, sz_out.height));
cv::resize(in_mat_roi, out_mat_roi, sz_out, 0, 0, interp);
}
// Comparison //////////////////////////////////////////////////////////////
{
EXPECT_TRUE(cmpF(out_mat, out_mat_ocv_p));
}
}
} // opencv_test
#endif //OPENCV_GAPI_IMGPROC_TESTS_INL_HPP

View File

@ -301,42 +301,6 @@ INSTANTIATE_TEST_CASE_P(Split4TestCPU, Split4Test,
Values(CV_8UC1),
Values(CORE_CPU)));
INSTANTIATE_TEST_CASE_P(ResizeTestCPU, ResizeTest,
Combine(Values( CV_8UC1, CV_8UC3, CV_16UC1, CV_16SC1, CV_32FC1 ),
Values(cv::Size(1280, 720),
cv::Size(640, 480),
cv::Size(128, 128)),
Values(-1),
Values(CORE_CPU),
Values(AbsSimilarPoints(2, 0.05).to_compare_obj()),
Values(cv::INTER_NEAREST, cv::INTER_LINEAR, cv::INTER_AREA),
Values(cv::Size(64,64),
cv::Size(30,30))));
INSTANTIATE_TEST_CASE_P(ResizePTestCPU, ResizePTest,
Combine(Values( CV_8UC1, CV_8UC3, CV_16UC1, CV_16SC1, CV_32FC1 ),
Values(cv::Size(1280, 720),
cv::Size(640, 480),
cv::Size(128, 128)),
Values(-1),
Values(CORE_CPU),
Values(AbsSimilarPoints(2, 0.05).to_compare_obj()),
Values(cv::INTER_LINEAR),
Values(cv::Size(64,64),
cv::Size(30,30))));
INSTANTIATE_TEST_CASE_P(ResizeTestCPU, ResizeTestFxFy,
Combine(Values( CV_8UC1, CV_8UC3, CV_16UC1, CV_16SC1, CV_32FC1 ),
Values(cv::Size(1280, 720),
cv::Size(640, 480),
cv::Size(128, 128)),
Values(-1),
Values(CORE_CPU),
Values(AbsSimilarPoints(2, 0.05).to_compare_obj()),
Values(cv::INTER_NEAREST, cv::INTER_LINEAR, cv::INTER_AREA),
Values(0.5, 0.1),
Values(0.5, 0.1)));
INSTANTIATE_TEST_CASE_P(Merge3TestCPU, Merge3Test,
Combine(Values(CV_8UC1),
Values(cv::Size(1280, 720),

View File

@ -384,37 +384,6 @@ INSTANTIATE_TEST_CASE_P(InRangeTestFluid, InRangeTest,
Values(-1),
Values(CORE_FLUID)));
INSTANTIATE_TEST_CASE_P(ResizeTestFluid, ResizeTest,
Combine(Values(CV_8UC3/*CV_8UC1, CV_16UC1, CV_16SC1*/),
Values(cv::Size(1280, 720),
cv::Size(640, 480),
cv::Size(128, 128),
cv::Size(64, 64),
cv::Size(30, 30)),
Values(-1),
Values(CORE_FLUID),
Values(Tolerance_FloatRel_IntAbs(1e-5, 1).to_compare_obj()),
Values(/*cv::INTER_NEAREST,*/ cv::INTER_LINEAR/*, cv::INTER_AREA*/),
Values(cv::Size(1280, 720),
cv::Size(640, 480),
cv::Size(128, 128),
cv::Size(64, 64),
cv::Size(30, 30))));
INSTANTIATE_TEST_CASE_P(ResizeTestFxFyFluid, ResizeTestFxFy,
Combine(Values(CV_8UC3/*CV_8UC1, CV_16UC1, CV_16SC1*/),
Values(cv::Size(1280, 720),
cv::Size(640, 480),
cv::Size(128, 128),
cv::Size(64, 64),
cv::Size(30, 30)),
Values(-1),
Values(CORE_FLUID),
Values(Tolerance_FloatRel_IntAbs(1e-5, 1).to_compare_obj()),
Values(/*cv::INTER_NEAREST,*/ cv::INTER_LINEAR/*, cv::INTER_AREA*/),
Values(0.5, 1, 2),
Values(0.5, 1, 2)));
INSTANTIATE_TEST_CASE_P(BackendOutputAllocationTestFluid, BackendOutputAllocationTest,
Combine(Values(CV_8UC3, CV_16SC2, CV_32FC1),
Values(cv::Size(50, 50)),

View File

@ -18,6 +18,42 @@ namespace
namespace opencv_test
{
INSTANTIATE_TEST_CASE_P(ResizeTestCPU, ResizeTest,
Combine(Values(CV_8UC1, CV_8UC3, CV_16UC1, CV_16SC1, CV_32FC1),
Values(cv::Size(1280, 720),
cv::Size(640, 480),
cv::Size(128, 128)),
Values(-1),
Values(IMGPROC_CPU),
Values(AbsSimilarPoints(2, 0.05).to_compare_obj()),
Values(cv::INTER_NEAREST, cv::INTER_LINEAR, cv::INTER_AREA),
Values(cv::Size(64,64),
cv::Size(30,30))));
INSTANTIATE_TEST_CASE_P(ResizePTestCPU, ResizePTest,
Combine(Values(CV_8UC1, CV_8UC3, CV_16UC1, CV_16SC1, CV_32FC1),
Values(cv::Size(1280, 720),
cv::Size(640, 480),
cv::Size(128, 128)),
Values(-1),
Values(IMGPROC_CPU),
Values(AbsSimilarPoints(2, 0.05).to_compare_obj()),
Values(cv::INTER_LINEAR),
Values(cv::Size(64,64),
cv::Size(30,30))));
INSTANTIATE_TEST_CASE_P(ResizeTestCPU, ResizeTestFxFy,
Combine(Values(CV_8UC1, CV_8UC3, CV_16UC1, CV_16SC1, CV_32FC1),
Values(cv::Size(1280, 720),
cv::Size(640, 480),
cv::Size(128, 128)),
Values(-1),
Values(IMGPROC_CPU),
Values(AbsSimilarPoints(2, 0.05).to_compare_obj()),
Values(cv::INTER_NEAREST, cv::INTER_LINEAR, cv::INTER_AREA),
Values(0.5, 0.1),
Values(0.5, 0.1)));
INSTANTIATE_TEST_CASE_P(Filter2DTestCPU, Filter2DTest,
Combine(Values(CV_8UC1, CV_8UC3, CV_16UC1, CV_16SC1, CV_32FC1),
Values(cv::Size(1280, 720),

View File

@ -16,6 +16,37 @@ namespace
namespace opencv_test
{
INSTANTIATE_TEST_CASE_P(ResizeTestFluid, ResizeTest,
Combine(Values(CV_8UC3/*CV_8UC1, CV_16UC1, CV_16SC1*/),
Values(cv::Size(1280, 720),
cv::Size(640, 480),
cv::Size(128, 128),
cv::Size(64, 64),
cv::Size(30, 30)),
Values(-1),
Values(IMGPROC_FLUID),
Values(Tolerance_FloatRel_IntAbs(1e-5, 1).to_compare_obj()),
Values(/*cv::INTER_NEAREST,*/ cv::INTER_LINEAR/*, cv::INTER_AREA*/),
Values(cv::Size(1280, 720),
cv::Size(640, 480),
cv::Size(128, 128),
cv::Size(64, 64),
cv::Size(30, 30))));
INSTANTIATE_TEST_CASE_P(ResizeTestFxFyFluid, ResizeTestFxFy,
Combine(Values(CV_8UC3/*CV_8UC1, CV_16UC1, CV_16SC1*/),
Values(cv::Size(1280, 720),
cv::Size(640, 480),
cv::Size(128, 128),
cv::Size(64, 64),
cv::Size(30, 30)),
Values(-1),
Values(IMGPROC_FLUID),
Values(Tolerance_FloatRel_IntAbs(1e-5, 1).to_compare_obj()),
Values(/*cv::INTER_NEAREST,*/ cv::INTER_LINEAR/*, cv::INTER_AREA*/),
Values(0.5, 1, 2),
Values(0.5, 1, 2)));
INSTANTIATE_TEST_CASE_P(RGB2GrayTestFluid, RGB2GrayTest,
Combine(Values(CV_8UC3),
Values(cv::Size(1280, 720),

View File

@ -41,7 +41,7 @@ GAPI_FLUID_KERNEL(FCopy, TCopy, false)
}
};
GAPI_FLUID_KERNEL(FResizeNN1Lpi, cv::gapi::core::GResize, false)
GAPI_FLUID_KERNEL(FResizeNN1Lpi, cv::gapi::imgproc::GResize, false)
{
static const int Window = 1;
static const auto Kind = GFluidKernel::Kind::Resize;
@ -203,7 +203,7 @@ struct Mapper
} // namespace areaUpscale
} // anonymous namespace
GAPI_FLUID_KERNEL(FResizeLinear1Lpi, cv::gapi::core::GResize, true)
GAPI_FLUID_KERNEL(FResizeLinear1Lpi, cv::gapi::imgproc::GResize, true)
{
static const int Window = 1;
static const auto Kind = GFluidKernel::Kind::Resize;
@ -238,7 +238,7 @@ auto endInCoord = [](int outCoord, double ratio) {
};
} // namespace
GAPI_FLUID_KERNEL(FResizeArea1Lpi, cv::gapi::core::GResize, false)
GAPI_FLUID_KERNEL(FResizeArea1Lpi, cv::gapi::imgproc::GResize, false)
{
static const int Window = 1;
static const auto Kind = GFluidKernel::Kind::Resize;
@ -302,7 +302,7 @@ GAPI_FLUID_KERNEL(FResizeArea1Lpi, cv::gapi::core::GResize, false)
}
};
GAPI_FLUID_KERNEL(FResizeAreaUpscale1Lpi, cv::gapi::core::GResize, true)
GAPI_FLUID_KERNEL(FResizeAreaUpscale1Lpi, cv::gapi::imgproc::GResize, true)
{
static const int Window = 1;
static const auto Kind = GFluidKernel::Kind::Resize;
@ -326,7 +326,7 @@ GAPI_FLUID_KERNEL(FResizeAreaUpscale1Lpi, cv::gapi::core::GResize, true)
#define ADD_RESIZE_KERNEL_WITH_LPI(interp, lpi, scratch) \
struct Resize##interp##lpi##LpiHelper : public FResize##interp##1Lpi { static const int LPI = lpi; }; \
struct FResize##interp##lpi##Lpi : public cv::GFluidKernelImpl<Resize##interp##lpi##LpiHelper, cv::gapi::core::GResize, scratch>{};
struct FResize##interp##lpi##Lpi : public cv::GFluidKernelImpl<Resize##interp##lpi##LpiHelper, cv::gapi::imgproc::GResize, scratch>{};
ADD_RESIZE_KERNEL_WITH_LPI(NN, 2, false)
ADD_RESIZE_KERNEL_WITH_LPI(NN, 3, false)
@ -742,7 +742,7 @@ TEST_P(NV12PlusResizeTest, Test)
auto out = cv::gapi::resize(rgb, out_sz, 0, 0, interp);
cv::GComputation c(cv::GIn(y, uv), cv::GOut(out));
auto pkg = cv::gapi::combine(fluidTestPackage, cv::gapi::core::fluid::kernels());
auto pkg = cv::gapi::combine(fluidTestPackage, cv::gapi::imgproc::fluid::kernels());
c.apply(cv::gin(y_mat, uv_mat), cv::gout(out_mat)
,cv::compile_args(pkg, cv::GFluidOutputRois{{roi}}));

View File

@ -791,8 +791,15 @@ TEST(Fluid, UnusedNodeOutputCompileTest)
TEST(Fluid, UnusedNodeOutputReshapeTest)
{
const auto test_size = cv::Size(8, 8);
const auto get_compile_args =
[] () { return cv::compile_args(cv::gapi::core::fluid::kernels()); };
const auto get_compile_args = [] () {
return cv::compile_args(
cv::gapi::combine(
cv::gapi::core::fluid::kernels(),
cv::gapi::imgproc::fluid::kernels()
)
);
};
cv::GMat in;
cv::GMat a, b, c, d;

View File

@ -293,30 +293,6 @@ INSTANTIATE_TEST_CASE_P(Split4TestGPU, Split4Test,
Values(CV_8UC1),
Values(CORE_GPU)));
INSTANTIATE_TEST_CASE_P(ResizeTestGPU, ResizeTest,
Combine(Values( CV_8UC1, CV_8UC3, CV_16UC1, CV_16SC1, CV_32FC1 ),
Values(cv::Size(1280, 720),
cv::Size(640, 480),
cv::Size(128, 128)),
Values(-1),
Values(CORE_GPU),
Values(AbsSimilarPoints(2, 0.05).to_compare_obj()),
Values(cv::INTER_NEAREST, cv::INTER_LINEAR, cv::INTER_AREA),
Values(cv::Size(64,64),
cv::Size(30,30))));
INSTANTIATE_TEST_CASE_P(ResizeTestGPU, ResizeTestFxFy,
Combine(Values( CV_8UC1, CV_8UC3, CV_16UC1, CV_16SC1, CV_32FC1 ),
Values(cv::Size(1280, 720),
cv::Size(640, 480),
cv::Size(128, 128)),
Values(-1),
Values(CORE_GPU),
Values(AbsSimilarPoints(2, 0.05).to_compare_obj()),
Values(cv::INTER_NEAREST, cv::INTER_LINEAR, cv::INTER_AREA),
Values(0.5, 0.1),
Values(0.5, 0.1)));
INSTANTIATE_TEST_CASE_P(Merge3TestGPU, Merge3Test,
Combine(Values(CV_8UC1),
Values(cv::Size(1280, 720),

View File

@ -17,6 +17,30 @@ namespace
namespace opencv_test
{
INSTANTIATE_TEST_CASE_P(ResizeTestGPU, ResizeTest,
Combine(Values(CV_8UC1, CV_8UC3, CV_16UC1, CV_16SC1, CV_32FC1),
Values(cv::Size(1280, 720),
cv::Size(640, 480),
cv::Size(128, 128)),
Values(-1),
Values(IMGPROC_GPU),
Values(AbsSimilarPoints(2, 0.05).to_compare_obj()),
Values(cv::INTER_NEAREST, cv::INTER_LINEAR, cv::INTER_AREA),
Values(cv::Size(64,64),
cv::Size(30,30))));
INSTANTIATE_TEST_CASE_P(ResizeTestGPU, ResizeTestFxFy,
Combine(Values(CV_8UC1, CV_8UC3, CV_16UC1, CV_16SC1, CV_32FC1),
Values(cv::Size(1280, 720),
cv::Size(640, 480),
cv::Size(128, 128)),
Values(-1),
Values(IMGPROC_GPU),
Values(AbsSimilarPoints(2, 0.05).to_compare_obj()),
Values(cv::INTER_NEAREST, cv::INTER_LINEAR, cv::INTER_AREA),
Values(0.5, 0.1),
Values(0.5, 0.1)));
INSTANTIATE_TEST_CASE_P(Filter2DTestGPU, Filter2DTest,
Combine(Values(CV_8UC1, CV_8UC3, CV_16UC1, CV_16SC1, CV_32FC1),
Values(cv::Size(1280, 720),

View File

@ -318,7 +318,7 @@ TEST(PatternMatching, TestPrepResizeSplit3)
r_nh, op1_nh, op2_nh}),
nodes);
EXPECT_EQ(cv::gapi::core::GResize::id(), matching_test::opName(tgm, op1_nh));
EXPECT_EQ(cv::gapi::imgproc::GResize::id(), matching_test::opName(tgm, op1_nh));
EXPECT_EQ(cv::gapi::core::GSplit3::id(), matching_test::opName(tgm, op2_nh));
EXPECT_EQ(1u, tmp_nh->outEdges().size());
@ -385,7 +385,7 @@ TEST(PatternMatching, TestPrepResizeToNCHW)
EXPECT_EQ(matching_test::S({bgr_nh, tmp_nh, plr_nh, op1_nh, op2_nh}),
nodes);
EXPECT_EQ(cv::gapi::core::GResize::id(), matching_test::opName(tgm, op1_nh));
EXPECT_EQ(cv::gapi::imgproc::GResize::id(), matching_test::opName(tgm, op1_nh));
EXPECT_EQ(GToNCHW::id(), matching_test::opName(tgm, op2_nh));
EXPECT_EQ(1u, tmp_nh->outEdges().size());

View File

@ -63,7 +63,7 @@ GAPI_OCV_KERNEL(MyNV12toBGRImpl, MyNV12toBGR)
};
G_TYPED_KERNEL(MyPlanarResize, <GMatP(GMatP, Size, int)>, "test.my_planar_resize") {
static GMatDesc outMeta(GMatDesc in, Size sz, int interp) {
return cv::gapi::core::GResizeP::outMeta(in, sz, interp);
return cv::gapi::imgproc::GResizeP::outMeta(in, sz, interp);
}
};
GAPI_OCV_KERNEL(MyPlanarResizeImpl, MyPlanarResize) {
@ -83,7 +83,7 @@ GAPI_OCV_KERNEL(MyPlanarResizeImpl, MyPlanarResize) {
};
G_TYPED_KERNEL(MyInterleavedResize, <GMat(GMat, Size, int)>, "test.my_interleaved_resize") {
static GMatDesc outMeta(GMatDesc in, Size sz, int interp) {
return cv::gapi::core::GResize::outMeta(in, sz, 0.0, 0.0, interp);
return cv::gapi::imgproc::GResize::outMeta(in, sz, 0.0, 0.0, interp);
}
};
GAPI_OCV_KERNEL(MyInterleavedResizeImpl, MyInterleavedResize) {

View File

@ -104,7 +104,7 @@ TEST(GComputationCompile, FluidReshapeResizeDownScale)
cv::randu(in_mat2, cv::Scalar::all(0), cv::Scalar::all(255));
cv::Mat out_mat1, out_mat2;
cc.apply(in_mat1, out_mat1, cv::compile_args(cv::gapi::core::fluid::kernels()));
cc.apply(in_mat1, out_mat1, cv::compile_args(cv::gapi::imgproc::fluid::kernels()));
auto comp1 = cc.priv().m_lastCompiled;
cc.apply(in_mat2, out_mat2);
@ -136,7 +136,7 @@ TEST(GComputationCompile, FluidReshapeSwitchToUpscaleFromDownscale)
cv::randu(in_mat3, cv::Scalar::all(0), cv::Scalar::all(255));
cv::Mat out_mat1, out_mat2, out_mat3;
cc.apply(in_mat1, out_mat1, cv::compile_args(cv::gapi::core::fluid::kernels()));
cc.apply(in_mat1, out_mat1, cv::compile_args(cv::gapi::imgproc::fluid::kernels()));
auto comp1 = cc.priv().m_lastCompiled;
cc.apply(in_mat2, out_mat2);

View File

@ -1,6 +1,6 @@
#include <opencv2/gapi.hpp>
#include <opencv2/gapi/core.hpp>
#include <opencv2/gapi/cpu/core.hpp>
#include <opencv2/gapi/cpu/imgproc.hpp>
#include <opencv2/gapi/imgproc.hpp>
int main(int argc, char *argv[])
{
@ -57,7 +57,7 @@ int main(int argc, char *argv[])
out_vector += cv::gout(out_mat2);
// ! [GRunArgsP usage]
auto stream = cc.compileStreaming(cv::compile_args(cv::gapi::core::cpu::kernels()));
auto stream = cc.compileStreaming(cv::compile_args(cv::gapi::imgproc::cpu::kernels()));
stream.setSource(std::move(in_vector));
stream.start();