未验证 提交 3cfca013 编写于 作者: A Anna Khakimova 提交者: GitHub

Merge pull request #20664 from anna-khakimova:ak/resize_simd

Fluid: SIMD for Resize Linear 8UC3

* SIMD for fluid::Resize 8U3C

* Rework horizontal pass + add 8U4C case

* Reproduce stackoverflow test

* StackOverflow test

* SSE42 impl

* SSE42 impl improvement

* GAPI:SSE42 simd opt for Resize 8UC3. Final version

* Fix tests

* Conditional compilation fix

* Applied comments

* Applied comments. Step2

* Applied comments. Step2
上级 d934bb15
......@@ -398,7 +398,7 @@ 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) {
static GMatDesc outMeta(GMatDesc in, Size sz, double fx, double fy, int /*interp*/) {
if (sz.width != 0 && sz.height != 0)
{
return in.withSize(sz);
......
......@@ -81,7 +81,9 @@ namespace opencv_test
cv::GCompileArgs>> {};
class TransposePerfTest : public TestPerfParams<tuple<compare_f, cv::Size, MatType, cv::GCompileArgs>> {};
class ResizePerfTest : public TestPerfParams<tuple<compare_f, MatType, int, cv::Size, cv::Size, cv::GCompileArgs>> {};
class BottleneckKernelsConstInputPerfTest : public TestPerfParams<tuple<compare_f, std::string, cv::GCompileArgs>> {};
class ResizeFxFyPerfTest : public TestPerfParams<tuple<compare_f, MatType, int, cv::Size, double, double, cv::GCompileArgs>> {};
class ResizeInSimpleGraphPerfTest : public TestPerfParams<tuple<compare_f, MatType, cv::Size, cv::GCompileArgs>> {};
class ParseSSDBLPerfTest : public TestPerfParams<tuple<cv::Size, float, int, cv::GCompileArgs>>, public ParserSSDTest {};
class ParseSSDPerfTest : public TestPerfParams<tuple<cv::Size, float, bool, bool, cv::GCompileArgs>>, public ParserSSDTest {};
class ParseYoloPerfTest : public TestPerfParams<tuple<cv::Size, float, float, int, cv::GCompileArgs>>, public ParserYoloTest {};
......
......@@ -2151,6 +2151,89 @@ PERF_TEST_P_(ResizeFxFyPerfTest, TestPerformance)
{
cc(gin(in_mat1), gout(out_mat_gapi));
}
// Comparison ////////////////////////////////////////////////////////////
{
EXPECT_TRUE(cmpF(out_mat_gapi, out_mat_ocv));
}
SANITY_CHECK_NOTHING();
}
//------------------------------------------------------------------------------
// This test cases were created to control performance result of test scenario mentioned here:
// https://stackoverflow.com/questions/60629331/opencv-gapi-performance-not-good-as-expected
PERF_TEST_P_(BottleneckKernelsConstInputPerfTest, TestPerformance)
{
compare_f cmpF = get<0>(GetParam());
std::string fileName = get<1>(GetParam());
cv::GCompileArgs compile_args = get<2>(GetParam());
in_mat1 = cv::imread(findDataFile(fileName));
cv::Mat cvvga;
cv::Mat cvgray;
cv::Mat cvblurred;
cv::resize(in_mat1, cvvga, cv::Size(), 0.5, 0.5);
cv::cvtColor(cvvga, cvgray, cv::COLOR_BGR2GRAY);
cv::blur(cvgray, cvblurred, cv::Size(3, 3));
cv::Canny(cvblurred, out_mat_ocv, 32, 128, 3);
cv::GMat in;
cv::GMat vga = cv::gapi::resize(in, cv::Size(), 0.5, 0.5, INTER_LINEAR);
cv::GMat gray = cv::gapi::BGR2Gray(vga);
cv::GMat blurred = cv::gapi::blur(gray, cv::Size(3, 3));
cv::GMat out = cv::gapi::Canny(blurred, 32, 128, 3);
cv::GComputation ac(in, out);
auto cc = ac.compile(descr_of(gin(in_mat1)),
std::move(compile_args));
cc(gin(in_mat1), gout(out_mat_gapi));
TEST_CYCLE()
{
cc(gin(in_mat1), gout(out_mat_gapi));
}
// Comparison ////////////////////////////////////////////////////////////
{
EXPECT_TRUE(cmpF(out_mat_gapi, out_mat_ocv));
}
SANITY_CHECK_NOTHING();
}
//------------------------------------------------------------------------------
PERF_TEST_P_(ResizeInSimpleGraphPerfTest, TestPerformance)
{
compare_f cmpF = get<0>(GetParam());
MatType type = get<1>(GetParam());
cv::Size sz_in = get<2>(GetParam());
cv::GCompileArgs compile_args = get<3>(GetParam());
initMatsRandU(type, sz_in, type, false);
cv::Mat add_res_ocv;
cv::add(in_mat1, in_mat2, add_res_ocv);
cv::resize(add_res_ocv, out_mat_ocv, cv::Size(), 0.5, 0.5);
cv::GMat in1, in2;
cv::GMat add_res_gapi = cv::gapi::add(in1, in2);
cv::GMat out = cv::gapi::resize(add_res_gapi, cv::Size(), 0.5, 0.5, INTER_LINEAR);
cv::GComputation ac(GIn(in1, in2), GOut(out));
auto cc = ac.compile(descr_of(gin(in_mat1, in_mat2)),
std::move(compile_args));
cc(gin(in_mat1, in_mat2), gout(out_mat_gapi));
TEST_CYCLE()
{
cc(gin(in_mat1, in_mat2), gout(out_mat_gapi));
}
// Comparison ////////////////////////////////////////////////////////////
{
......
......@@ -321,16 +321,28 @@ INSTANTIATE_TEST_CASE_P(TransposePerfTestCPU, TransposePerfTest,
INSTANTIATE_TEST_CASE_P(ResizePerfTestCPU, ResizePerfTest,
Combine(Values(AbsExact().to_compare_f()),
Values(CV_8UC1, CV_16UC1, CV_16SC1),
Values(CV_8UC1, CV_8UC3, CV_16UC1, CV_16SC1),
Values(cv::INTER_NEAREST, cv::INTER_LINEAR, cv::INTER_AREA),
Values(szSmall128, szVGA, sz720p, sz1080p),
Values(cv::Size(64, 64),
cv::Size(30, 30)),
cv::Size(32, 32)),
Values(cv::compile_args(CORE_CPU))));
INSTANTIATE_TEST_CASE_P(BottleneckKernelsPerfTestCPU, BottleneckKernelsConstInputPerfTest,
Combine(Values(AbsExact().to_compare_f()),
Values("cv/optflow/frames/1080p_00.png", "cv/optflow/frames/720p_00.png",
"cv/optflow/frames/VGA_00.png", "cv/dnn_face/recognition/Aaron_Tippin_0001.jpg"),
Values(cv::compile_args(CORE_CPU))));
INSTANTIATE_TEST_CASE_P(ResizeInSimpleGraphPerfTestCPU, ResizeInSimpleGraphPerfTest,
Combine(Values(AbsExact().to_compare_f()),
Values(CV_8UC3),
Values(szSmall128, szVGA, sz720p, sz1080p),
Values(cv::compile_args(CORE_CPU))));
INSTANTIATE_TEST_CASE_P(ResizeFxFyPerfTestCPU, ResizeFxFyPerfTest,
Combine(Values(AbsExact().to_compare_f()),
Values(CV_8UC1, CV_16UC1, CV_16SC1),
Values(CV_8UC1, CV_8UC3, CV_16UC1, CV_16SC1),
Values(cv::INTER_NEAREST, cv::INTER_LINEAR, cv::INTER_AREA),
Values(szSmall128, szVGA, sz720p, sz1080p),
Values(0.5, 0.1),
......
......@@ -277,18 +277,31 @@ INSTANTIATE_TEST_CASE_P(ConvertToPerfTestFluid, ConvertToPerfTest,
Values(cv::compile_args(CORE_FLUID))));
INSTANTIATE_TEST_CASE_P(ResizePerfTestFluid, ResizePerfTest,
Combine(Values(AbsExact().to_compare_f()),
Values(CV_8UC3/*CV_8UC1, CV_16UC1, CV_16SC1*/),
Values(/*cv::INTER_NEAREST,*/ cv::INTER_LINEAR/*, cv::INTER_AREA*/),
Combine(Values(Tolerance_FloatRel_IntAbs(1e-5, 1).to_compare_f()),
Values(CV_8UC3),
Values(cv::INTER_LINEAR),
Values(szSmall128, szVGA, sz720p, sz1080p),
Values(cv::Size(64, 64),
cv::Size(30, 30)),
Values(cv::compile_args(CORE_FLUID))));
#define IMGPROC_FLUID cv::gapi::imgproc::fluid::kernels()
INSTANTIATE_TEST_CASE_P(BottleneckKernelsPerfTestFluid, BottleneckKernelsConstInputPerfTest,
Combine(Values(AbsSimilarPoints(0, 1).to_compare_f()),
Values("cv/optflow/frames/1080p_00.png", "cv/optflow/frames/720p_00.png",
"cv/optflow/frames/VGA_00.png", "cv/dnn_face/recognition/Aaron_Tippin_0001.jpg"),
Values(cv::compile_args(CORE_FLUID, IMGPROC_FLUID))));
INSTANTIATE_TEST_CASE_P(ResizeInSimpleGraphPerfTestFluid, ResizeInSimpleGraphPerfTest,
Combine(Values(Tolerance_FloatRel_IntAbs(1e-5, 1).to_compare_f()),
Values(CV_8UC3),
Values(szSmall128, szVGA, sz720p, sz1080p),
Values(cv::compile_args(CORE_FLUID, IMGPROC_FLUID))));
INSTANTIATE_TEST_CASE_P(ResizeFxFyPerfTestFluid, ResizeFxFyPerfTest,
Combine(Values(AbsExact().to_compare_f()),
Values(CV_8UC3/*CV_8UC1, CV_16UC1, CV_16SC1*/),
Values(/*cv::INTER_NEAREST,*/ cv::INTER_LINEAR/*, cv::INTER_AREA*/),
Combine(Values(Tolerance_FloatRel_IntAbs(1e-5, 1).to_compare_f()),
Values(CV_8UC3),
Values(cv::INTER_LINEAR),
Values(szSmall128, szVGA, sz720p, sz1080p),
Values(0.5, 0.1),
Values(0.5, 0.1),
......
......@@ -19,6 +19,10 @@
#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"
......@@ -2949,109 +2953,295 @@ GAPI_FLUID_KERNEL(GFluidPhase, cv::gapi::core::GPhase, false)
}
};
GAPI_FLUID_KERNEL(GFluidResize, cv::gapi::core::GResize, true)
{
static const int Window = 1;
static const auto Kind = GFluidKernel::Kind::Resize;
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--;
}
}
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;
alpha[x] = alpha0;
index[x] = index0;
struct ResizeUnit
{
short alpha0;
short alpha1;
int s0;
int s1;
};
for (int l = 0; l < 4; l++) {
clone[4*x + l] = alpha0;
}
}
static ResizeUnit map(double ratio, int start, int max, int outCoord)
{
float f = static_cast<float>((outCoord + 0.5f) * ratio - 0.5f);
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;
ResizeUnit ru;
Unit u;
ru.s0 = std::max(s - start, 0);
ru.s1 = ((f == 0.0) || s + 1 >= max) ? s - start : s - start + 1;
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);
ru.alpha0 = saturate_cast<short>((1.0f - f) * INTER_RESIZE_COEF_SCALE);
ru.alpha1 = saturate_cast<short>((f) * INTER_RESIZE_COEF_SCALE);
u.alpha0 = saturate_cast<short>(ONE * (1.0f - f));
u.alpha1 = saturate_cast<short>(ONE * f);
return ru;
return u;
}
};
static void initScratch(const cv::GMatDesc& in,
cv::Size outSz, double fx, double fy, int /*interp*/,
cv::gapi::fluid::Buffer &scratch)
{
GAPI_Assert(in.depth == CV_8U && in.chan == 3);
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;
if (outSz.area() == 0)
{
outSz.width = static_cast<int>(round(in.size.width * fx));
outSz.height = static_cast<int>(round(in.size.height * fy));
}
auto inSz = in.meta().size;
auto outSz = out.meta().size;
cv::Size scratch_size{static_cast<int>(outSz.width * sizeof(ResizeUnit)), 1};
auto inY = in.y();
int outY = out.y();
int lpi = out.lpi();
cv::GMatDesc desc;
desc.chan = 1;
desc.depth = CV_8UC1;
desc.size = scratch_size;
GAPI_DbgAssert(outY + lpi <= outSz.height);
GAPI_DbgAssert(lpi <= 4);
cv::gapi::fluid::Buffer buffer(desc);
scratch = std::move(buffer);
LinearScratchDesc<T, Mapper, numChan> scr(inSz.width, inSz.height, outSz.width, outSz.height, scratch.OutLineB());
ResizeUnit* mapX = scratch.OutLine<ResizeUnit>();
double hRatio = (double)in.size.width / outSz.width;
const auto *alpha = scr.alpha;
const auto *mapsx = scr.mapsx;
const auto *beta_0 = scr.beta;
const auto *mapsy = scr.mapsy;
for (int x = 0, w = outSz.width; x < w; x++)
{
mapX[x] = map(hRatio, 0, in.size.width, x);
}
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);
}
static void resetScratch(cv::gapi::fluid::Buffer& /*scratch*/)
{}
#if CV_SSE4_1
const auto* clone = scr.clone;
auto* tmp = scr.tmp;
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)
if (inSz.width >= 16 && outSz.width >= 16)
{
double vRatio = (double)in.meta().size.height / out.meta().size.height;
auto mapY = map(vRatio, in.y(), in.meta().size.height, out.y());
auto beta0 = mapY.alpha0;
auto beta1 = mapY.alpha1;
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);
const auto src0 = in.InLine <unsigned char>(mapY.s0);
const auto src1 = in.InLine <unsigned char>(mapY.s1);
auto dst = out.OutLine<unsigned char>();
return;
}
#endif // CV_SSE4_1
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);
}
}
}
}
ResizeUnit* mapX = scratch.OutLine<ResizeUnit>();
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;
for (int x = 0; x < out.length(); x++)
{
short alpha0 = mapX[x].alpha0;
short alpha1 = mapX[x].alpha1;
int sx0 = mapX[x].s0;
int sx1 = mapX[x].s1;
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;
int res00 = src0[3*sx0 ]*alpha0 + src0[3*(sx1) ]*alpha1;
int res10 = src1[3*sx0 ]*alpha0 + src1[3*(sx1) ]*alpha1;
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);
}
}
int res01 = src0[3*sx0 + 1]*alpha0 + src0[3*(sx1) + 1]*alpha1;
int res11 = src1[3*sx0 + 1]*alpha0 + src1[3*(sx1) + 1]*alpha1;
static void resetScratch(cv::gapi::fluid::Buffer& /*scratch*/)
{}
int res02 = src0[3*sx0 + 2]*alpha0 + src0[3*(sx1) + 2]*alpha1;
int res12 = src1[3*sx0 + 2]*alpha0 + src1[3*(sx1) + 2]*alpha1;
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));
dst[3*x ] = uchar(( ((beta0 * (res00 >> 4)) >> 16) + ((beta1 * (res10 >> 4)) >> 16) + 2)>>2);
dst[3*x + 1] = uchar(( ((beta0 * (res01 >> 4)) >> 16) + ((beta1 * (res11 >> 4)) >> 16) + 2)>>2);
dst[3*x + 2] = uchar(( ((beta0 * (res02 >> 4)) >> 16) + ((beta1 * (res12 >> 4)) >> 16) + 2)>>2);
if (channels == 3)
{
calcRowLinearC<uint8_t, Mapper, 3>(in, out, scratch);
}
else if (channels == 4)
{
calcRowLinearC<uint8_t, Mapper, 4>(in, out, scratch);
}
}
};
......
......@@ -393,7 +393,7 @@ INSTANTIATE_TEST_CASE_P(ResizeTestFluid, ResizeTest,
cv::Size(30, 30)),
Values(-1),
Values(CORE_FLUID),
Values(AbsExact().to_compare_obj()),
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),
......@@ -410,7 +410,7 @@ INSTANTIATE_TEST_CASE_P(ResizeTestFxFyFluid, ResizeTestFxFy,
cv::Size(30, 30)),
Values(-1),
Values(CORE_FLUID),
Values(AbsExact().to_compare_obj()),
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)));
......
......@@ -8,6 +8,7 @@
#include "test_precomp.hpp"
#include "gapi_fluid_test_kernels.hpp"
#include "common/gapi_tests_common.hpp"
namespace opencv_test
{
......@@ -749,8 +750,7 @@ TEST_P(NV12PlusResizeTest, Test)
cv::Mat rgb_mat;
cv::cvtColor(in_mat, rgb_mat, cv::COLOR_YUV2RGB_NV12);
cv::resize(rgb_mat, out_mat_ocv, out_sz, 0, 0, interp);
EXPECT_EQ(0, cvtest::norm(out_mat(roi), out_mat_ocv(roi), NORM_INF));
EXPECT_TRUE(Tolerance_FloatRel_IntAbs(1e-5, 1).to_compare_f()(out_mat(roi), out_mat_ocv(roi)));
}
INSTANTIATE_TEST_CASE_P(Fluid, NV12PlusResizeTest,
......
......@@ -6,6 +6,7 @@
#include "../test_precomp.hpp"
#include "../common/gapi_tests_common.hpp"
#include "api/gcomputation_priv.hpp"
#include <opencv2/gapi/fluid/gfluidkernel.hpp>
......@@ -115,9 +116,10 @@ TEST(GComputationCompile, FluidReshapeResizeDownScale)
cv::Mat cv_out_mat1, cv_out_mat2;
cv::resize(in_mat1, cv_out_mat1, szOut);
cv::resize(in_mat2, cv_out_mat2, szOut);
EXPECT_EQ(0, cvtest::norm(out_mat1, cv_out_mat1, NORM_INF));
EXPECT_EQ(0, cvtest::norm(out_mat2, cv_out_mat2, NORM_INF));
// Fluid's and OpenCV's resizes aren't bit exact.
// So 1 is here because it is max difference between them.
EXPECT_TRUE(Tolerance_FloatRel_IntAbs(1e-5, 1).to_compare_f()(out_mat1, cv_out_mat1));
EXPECT_TRUE(Tolerance_FloatRel_IntAbs(1e-5, 1).to_compare_f()(out_mat2, cv_out_mat2));
}
TEST(GComputationCompile, FluidReshapeSwitchToUpscaleFromDownscale)
......@@ -150,10 +152,11 @@ TEST(GComputationCompile, FluidReshapeSwitchToUpscaleFromDownscale)
cv::resize(in_mat1, cv_out_mat1, szOut);
cv::resize(in_mat2, cv_out_mat2, szOut);
cv::resize(in_mat3, cv_out_mat3, szOut);
EXPECT_EQ(0, cvtest::norm(out_mat1, cv_out_mat1, NORM_INF));
EXPECT_EQ(0, cvtest::norm(out_mat2, cv_out_mat2, NORM_INF));
EXPECT_EQ(0, cvtest::norm(out_mat3, cv_out_mat3, NORM_INF));
// Fluid's and OpenCV's Resizes aren't bit exact.
// So 1 is here because it is max difference between them.
EXPECT_TRUE(Tolerance_FloatRel_IntAbs(1e-5, 1).to_compare_f()(out_mat1, cv_out_mat1));
EXPECT_TRUE(Tolerance_FloatRel_IntAbs(1e-5, 1).to_compare_f()(out_mat2, cv_out_mat2));
EXPECT_TRUE(Tolerance_FloatRel_IntAbs(1e-5, 1).to_compare_f()(out_mat3, cv_out_mat3));
}
TEST(GComputationCompile, ReshapeBlur)
......@@ -224,8 +227,9 @@ TEST(GComputationCompile, ReshapeRois)
cv::Mat blur_mat, cv_out_mat;
cv::blur(in_mat, blur_mat, kernelSize);
cv::resize(blur_mat, cv_out_mat, szOut);
EXPECT_EQ(0, cvtest::norm(out_mat(roi), cv_out_mat(roi), NORM_INF));
// Fluid's and OpenCV's resizes aren't bit exact.
// So 1 is here because it is max difference between them.
EXPECT_TRUE(Tolerance_FloatRel_IntAbs(1e-5, 1).to_compare_f()(out_mat(roi), cv_out_mat(roi)));
}
}
......
......@@ -353,7 +353,9 @@ TEST_P(GAPI_Streaming, SmokeTest_ConstInput_GMat)
// With constant inputs, the stream is endless so
// the blocking pull() should never return `false`.
EXPECT_TRUE(ccomp.pull(cv::gout(out_mat_gapi)));
EXPECT_EQ(0, cvtest::norm(out_mat_gapi, out_mat_ocv, NORM_INF));
// Fluid's and OpenCV's Resizes aren't bit exact.
// So 1% is here because it is max difference between them.
EXPECT_TRUE(AbsSimilarPoints(0, 1).to_compare_f()(out_mat_gapi, out_mat_ocv));
}
EXPECT_TRUE(ccomp.running());
......@@ -405,7 +407,9 @@ TEST_P(GAPI_Streaming, SmokeTest_VideoInput_GMat)
frames++;
cv::Mat out_mat_ocv;
opencv_ref(in_mat_gapi, out_mat_ocv);
EXPECT_EQ(0, cvtest::norm(out_mat_gapi, out_mat_ocv, NORM_INF));
// Fluid's and OpenCV's Resizes aren't bit exact.
// So 1% is here because it is max difference between them.
EXPECT_TRUE(AbsSimilarPoints(0, 1).to_compare_f()(out_mat_gapi, out_mat_ocv));
}
EXPECT_LT(0u, frames);
EXPECT_FALSE(ccomp.running());
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册