mirror of https://github.com/opencv/opencv.git
Open Source Computer Vision Library
https://opencv.org/
You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
572 lines
17 KiB
572 lines
17 KiB
// 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 |
|
|
|
#include "test_precomp.hpp" |
|
|
|
#include <iomanip> |
|
#include "gapi_fluid_test_kernels.hpp" |
|
#include <opencv2/gapi/core.hpp> |
|
|
|
namespace cv |
|
{ |
|
namespace gapi_test_kernels |
|
{ |
|
|
|
GAPI_FLUID_KERNEL(FAddSimple, TAddSimple, false) |
|
{ |
|
static const int Window = 1; |
|
|
|
static void run(const cv::gapi::fluid::View &a, |
|
const cv::gapi::fluid::View &b, |
|
cv::gapi::fluid::Buffer &o) |
|
{ |
|
// std::cout << "AddSimple {{{\n"; |
|
// std::cout << " a - "; a.debug(std::cout); |
|
// std::cout << " b - "; b.debug(std::cout); |
|
// std::cout << " o - "; o.debug(std::cout); |
|
|
|
const uint8_t* in1 = a.InLine<uint8_t>(0); |
|
const uint8_t* in2 = b.InLine<uint8_t>(0); |
|
uint8_t* out = o.OutLine<uint8_t>(); |
|
|
|
// std::cout << "a: "; |
|
// for (int i = 0, w = a.length(); i < w; i++) |
|
// { |
|
// std::cout << std::setw(4) << int(in1[i]); |
|
// } |
|
// std::cout << "\n"; |
|
|
|
// std::cout << "b: "; |
|
// for (int i = 0, w = a.length(); i < w; i++) |
|
// { |
|
// std::cout << std::setw(4) << int(in2[i]); |
|
// } |
|
// std::cout << "\n"; |
|
|
|
for (int i = 0, w = a.length(); i < w; i++) |
|
{ |
|
out[i] = in1[i] + in2[i]; |
|
} |
|
|
|
// std::cout << "}}} " << std::endl;; |
|
} |
|
}; |
|
|
|
GAPI_FLUID_KERNEL(FAddCSimple, TAddCSimple, false) |
|
{ |
|
static const int Window = 1; |
|
static const int LPI = 2; |
|
|
|
static void run(const cv::gapi::fluid::View &in, |
|
const int cval, |
|
cv::gapi::fluid::Buffer &out) |
|
{ |
|
for (int l = 0, lpi = out.lpi(); l < lpi; l++) |
|
{ |
|
const uint8_t* in_row = in .InLine <uint8_t>(l); |
|
uint8_t* out_row = out.OutLine<uint8_t>(l); |
|
//std::cout << "l=" << l << ": "; |
|
for (int i = 0, w = in.length(); i < w; i++) |
|
{ |
|
//std::cout << std::setw(4) << int(in_row[i]); |
|
out_row[i] = static_cast<uint8_t>(in_row[i] + cval); |
|
} |
|
//std::cout << std::endl; |
|
} |
|
} |
|
}; |
|
|
|
GAPI_FLUID_KERNEL(FAddScalar, TAddScalar, false) |
|
{ |
|
static const int Window = 1; |
|
static const int LPI = 2; |
|
|
|
static void run(const cv::gapi::fluid::View &in, |
|
const cv::Scalar &cval, |
|
cv::gapi::fluid::Buffer &out) |
|
{ |
|
for (int l = 0, lpi = out.lpi(); l < lpi; l++) |
|
{ |
|
const uint8_t* in_row = in .InLine <uint8_t>(l); |
|
uint8_t* out_row = out.OutLine<uint8_t>(l); |
|
std::cout << "l=" << l << ": "; |
|
for (int i = 0, w = in.length(); i < w; i++) |
|
{ |
|
std::cout << std::setw(4) << int(in_row[i]); |
|
out_row[i] = static_cast<uint8_t>(in_row[i] + cval[0]); |
|
} |
|
std::cout << std::endl; |
|
} |
|
} |
|
}; |
|
|
|
GAPI_FLUID_KERNEL(FAddScalarToMat, TAddScalarToMat, false) |
|
{ |
|
static const int Window = 1; |
|
static const int LPI = 2; |
|
|
|
static void run(const cv::Scalar &cval, |
|
const cv::gapi::fluid::View &in, |
|
cv::gapi::fluid::Buffer &out) |
|
{ |
|
for (int l = 0, lpi = out.lpi(); l < lpi; l++) |
|
{ |
|
const uint8_t* in_row = in .InLine <uint8_t>(l); |
|
uint8_t* out_row = out.OutLine<uint8_t>(l); |
|
std::cout << "l=" << l << ": "; |
|
for (int i = 0, w = in.length(); i < w; i++) |
|
{ |
|
std::cout << std::setw(4) << int(in_row[i]); |
|
out_row[i] = static_cast<uint8_t>(in_row[i] + cval[0]); |
|
} |
|
std::cout << std::endl; |
|
} |
|
} |
|
}; |
|
|
|
template<int kernelSize, int lpi = 1> |
|
static void runBlur(const cv::gapi::fluid::View& src, cv::gapi::fluid::Buffer& dst) |
|
{ |
|
const auto borderSize = (kernelSize - 1) / 2; |
|
const unsigned char* ins[kernelSize]; |
|
|
|
for (int l = 0; l < lpi; l++) |
|
{ |
|
for (int i = 0; i < kernelSize; i++) |
|
{ |
|
ins[i] = src.InLine<unsigned char>(i - borderSize + l); |
|
} |
|
|
|
auto out = dst.OutLine<unsigned char>(l); |
|
const auto width = dst.length(); |
|
|
|
for (int w = 0; w < width; w++) |
|
{ |
|
float res = 0.0f; |
|
for (int i = 0; i < kernelSize; i++) |
|
{ |
|
for (int j = -borderSize; j < borderSize + 1; j++) |
|
{ |
|
res += ins[i][w+j]; |
|
} |
|
} |
|
out[w] = static_cast<unsigned char>(std::rint(res / (kernelSize * kernelSize))); |
|
} |
|
} |
|
} |
|
|
|
GAPI_FLUID_KERNEL(FBlur1x1, TBlur1x1, false) |
|
{ |
|
static const int Window = 1; |
|
|
|
static void run(const cv::gapi::fluid::View &src, int /*borderType*/, |
|
cv::Scalar /*borderValue*/, cv::gapi::fluid::Buffer &dst) |
|
{ |
|
runBlur<Window>(src, dst); |
|
} |
|
}; |
|
|
|
GAPI_FLUID_KERNEL(FBlur3x3, TBlur3x3, false) |
|
{ |
|
static const int Window = 3; |
|
|
|
static void run(const cv::gapi::fluid::View &src, int /*borderType*/, |
|
cv::Scalar /*borderValue*/, cv::gapi::fluid::Buffer &dst) |
|
{ |
|
runBlur<Window>(src, dst); |
|
} |
|
|
|
static cv::gapi::fluid::Border getBorder(const cv::GMatDesc &/*src*/, int borderType, cv::Scalar borderValue) |
|
{ |
|
return { borderType, to_own(borderValue)}; |
|
} |
|
}; |
|
|
|
GAPI_FLUID_KERNEL(FBlur5x5, TBlur5x5, false) |
|
{ |
|
static const int Window = 5; |
|
|
|
static void run(const cv::gapi::fluid::View &src, int /*borderType*/, |
|
cv::Scalar /*borderValue*/, cv::gapi::fluid::Buffer &dst) |
|
{ |
|
runBlur<Window>(src, dst); |
|
} |
|
|
|
static cv::gapi::fluid::Border getBorder(const cv::GMatDesc &/*src*/, int borderType, cv::Scalar borderValue) |
|
{ |
|
return { borderType, to_own(borderValue)}; |
|
} |
|
}; |
|
|
|
GAPI_FLUID_KERNEL(FBlur3x3_2lpi, TBlur3x3_2lpi, false) |
|
{ |
|
static const int Window = 3; |
|
static const int LPI = 2; |
|
|
|
static void run(const cv::gapi::fluid::View &src, int /*borderType*/, |
|
cv::Scalar /*borderValue*/, cv::gapi::fluid::Buffer &dst) |
|
{ |
|
runBlur<Window, LPI>(src, dst); |
|
} |
|
|
|
static cv::gapi::fluid::Border getBorder(const cv::GMatDesc &/*src*/, int borderType, cv::Scalar borderValue) |
|
{ |
|
return { borderType, to_own(borderValue)}; |
|
} |
|
}; |
|
|
|
GAPI_FLUID_KERNEL(FBlur5x5_2lpi, TBlur5x5_2lpi, false) |
|
{ |
|
static const int Window = 5; |
|
static const int LPI = 2; |
|
|
|
static void run(const cv::gapi::fluid::View &src, int /*borderType*/, |
|
cv::Scalar /*borderValue*/, cv::gapi::fluid::Buffer &dst) |
|
{ |
|
runBlur<Window, LPI>(src, dst); |
|
} |
|
|
|
static cv::gapi::fluid::Border getBorder(const cv::GMatDesc &/*src*/, int borderType, cv::Scalar borderValue) |
|
{ |
|
return { borderType, to_own(borderValue )}; |
|
} |
|
}; |
|
|
|
GAPI_FLUID_KERNEL(FIdentity, TId, false) |
|
{ |
|
static const int Window = 3; |
|
|
|
static void run(const cv::gapi::fluid::View &a, |
|
cv::gapi::fluid::Buffer &o) |
|
{ |
|
const uint8_t* in[3] = { |
|
a.InLine<uint8_t>(-1), |
|
a.InLine<uint8_t>( 0), |
|
a.InLine<uint8_t>(+1) |
|
}; |
|
uint8_t* out = o.OutLine<uint8_t>(); |
|
|
|
// ReadFunction3x3(in, a.length()); |
|
for (int i = 0, w = a.length(); i < w; i++) |
|
{ |
|
out[i] = in[1][i]; |
|
} |
|
} |
|
|
|
static gapi::fluid::Border getBorder(const cv::GMatDesc &) |
|
{ |
|
return { cv::BORDER_REPLICATE, cv::gapi::own::Scalar{} }; |
|
} |
|
}; |
|
|
|
GAPI_FLUID_KERNEL(FId7x7, TId7x7, false) |
|
{ |
|
static const int Window = 7; |
|
static const int LPI = 2; |
|
|
|
static void run(const cv::gapi::fluid::View &a, |
|
cv::gapi::fluid::Buffer &o) |
|
{ |
|
for (int l = 0, lpi = o.lpi(); l < lpi; l++) |
|
{ |
|
const uint8_t* in[Window] = { |
|
a.InLine<uint8_t>(-3 + l), |
|
a.InLine<uint8_t>(-2 + l), |
|
a.InLine<uint8_t>(-1 + l), |
|
a.InLine<uint8_t>( 0 + l), |
|
a.InLine<uint8_t>(+1 + l), |
|
a.InLine<uint8_t>(+2 + l), |
|
a.InLine<uint8_t>(+3 + l), |
|
}; |
|
uint8_t* out = o.OutLine<uint8_t>(l); |
|
|
|
// std::cout << "Id7x7 " << l << " of " << lpi << " {{{\n"; |
|
// std::cout << " a - "; a.debug(std::cout); |
|
// std::cout << " o - "; o.debug(std::cout); |
|
// std::cout << "}}} " << std::endl;; |
|
|
|
// // std::cout << "Id7x7 at " << a.y() << "/L" << l << " {{{" << std::endl; |
|
// for (int j = 0; j < Window; j++) |
|
// { |
|
// // std::cout << std::setw(2) << j-(Window-1)/2 << ": "; |
|
// for (int i = 0, w = a.length(); i < w; i++) |
|
// std::cout << std::setw(4) << int(in[j][i]); |
|
// std::cout << std::endl; |
|
// } |
|
// std::cout << "}}}" << std::endl; |
|
|
|
for (int i = 0, w = a.length(); i < w; i++) |
|
out[i] = in[(Window-1)/2][i]; |
|
} |
|
} |
|
|
|
static cv::gapi::fluid::Border getBorder(const cv::GMatDesc&/* src*/) |
|
{ |
|
return { cv::BORDER_REPLICATE, cv::gapi::own::Scalar{} }; |
|
} |
|
}; |
|
|
|
GAPI_FLUID_KERNEL(FPlusRow0, TPlusRow0, true) |
|
{ |
|
static const int Window = 1; |
|
|
|
static void initScratch(const cv::GMatDesc &in, |
|
cv::gapi::fluid::Buffer &scratch) |
|
{ |
|
cv::Size scratch_size{in.size.width, 1}; |
|
cv::gapi::fluid::Buffer buffer(in.withSize(scratch_size)); |
|
scratch = std::move(buffer); |
|
} |
|
|
|
static void resetScratch(cv::gapi::fluid::Buffer &scratch) |
|
{ |
|
// FIXME: only 1 line can be used! |
|
uint8_t* out_row = scratch.OutLine<uint8_t>(); |
|
for (int i = 0, w = scratch.length(); i < w; i++) |
|
{ |
|
out_row[i] = 0; |
|
} |
|
} |
|
|
|
static void run(const cv::gapi::fluid::View &in, |
|
cv::gapi::fluid::Buffer &out, |
|
cv::gapi::fluid::Buffer &scratch) |
|
{ |
|
const uint8_t* in_row = in .InLine <uint8_t>(0); |
|
uint8_t* out_row = out .OutLine<uint8_t>(); |
|
uint8_t* tmp_row = scratch.OutLine<uint8_t>(); |
|
|
|
if (in.y() == 0) |
|
{ |
|
// Copy 1st row to scratch buffer |
|
for (int i = 0, w = in.length(); i < w; i++) |
|
{ |
|
out_row[i] = in_row[i]; |
|
tmp_row[i] = in_row[i]; |
|
} |
|
} |
|
else |
|
{ |
|
// Output is 1st row + in |
|
for (int i = 0, w = in.length(); i < w; i++) |
|
{ |
|
out_row[i] = in_row[i] + tmp_row[i]; |
|
} |
|
} |
|
} |
|
}; |
|
|
|
static void split3Row(const cv::gapi::fluid::View &in, |
|
cv::gapi::fluid::Buffer &o1, |
|
cv::gapi::fluid::Buffer &o2, |
|
cv::gapi::fluid::Buffer &o3) |
|
{ |
|
for (int l = 0; l < o1.lpi(); l++) |
|
{ |
|
// std::cout << "Split3 {{{\n"; |
|
// std::cout << " a - "; in.debug(std::cout); |
|
// std::cout << " 1 - "; o1.debug(std::cout); |
|
// std::cout << " 2 - "; o2.debug(std::cout); |
|
// std::cout << " 3 - "; o3.debug(std::cout); |
|
// std::cout << "}}} " << std::endl;; |
|
|
|
const uint8_t* in_rgb = in.InLine<uint8_t>(l); |
|
uint8_t* out_r = o1.OutLine<uint8_t>(l); |
|
uint8_t* out_g = o2.OutLine<uint8_t>(l); |
|
uint8_t* out_b = o3.OutLine<uint8_t>(l); |
|
|
|
for (int i = 0, w = in.length(); i < w; i++) |
|
{ |
|
out_r[i] = in_rgb[3*i]; |
|
out_g[i] = in_rgb[3*i+1]; |
|
out_b[i] = in_rgb[3*i+2]; |
|
} |
|
} |
|
} |
|
|
|
GAPI_FLUID_KERNEL(FTestSplit3, cv::gapi::core::GSplit3, false) |
|
{ |
|
static const int Window = 1; |
|
|
|
static void run(const cv::gapi::fluid::View &in, |
|
cv::gapi::fluid::Buffer &o1, |
|
cv::gapi::fluid::Buffer &o2, |
|
cv::gapi::fluid::Buffer &o3) |
|
{ |
|
split3Row(in, o1, o2, o3); |
|
} |
|
}; |
|
|
|
GAPI_FLUID_KERNEL(FTestSplit3_4lpi, TSplit3_4lpi, false) |
|
{ |
|
static const int Window = 1; |
|
static const int LPI = 4; |
|
|
|
static void run(const cv::gapi::fluid::View &in, |
|
cv::gapi::fluid::Buffer &o1, |
|
cv::gapi::fluid::Buffer &o2, |
|
cv::gapi::fluid::Buffer &o3) |
|
{ |
|
split3Row(in, o1, o2, o3); |
|
} |
|
}; |
|
|
|
std::tuple<GMat, GMat, GMat> split3_4lpi(const GMat& src) |
|
{ |
|
return TSplit3_4lpi::on(src); |
|
} |
|
|
|
GAPI_FLUID_KERNEL(FSum2MatsAndScalar, TSum2MatsAndScalar, false) |
|
{ |
|
static const int Window = 1; |
|
static const int LPI = 2; |
|
|
|
static void run(const cv::gapi::fluid::View &a, |
|
const cv::Scalar &cval, |
|
const cv::gapi::fluid::View &b, |
|
cv::gapi::fluid::Buffer &out) |
|
{ |
|
for (int l = 0, lpi = out.lpi(); l < lpi; l++) |
|
{ |
|
const uint8_t* in_row1 = a .InLine <uint8_t>(l); |
|
const uint8_t* in_row2 = b .InLine <uint8_t>(l); |
|
uint8_t* out_row = out.OutLine<uint8_t>(l); |
|
std::cout << "l=" << l << ": "; |
|
for (int i = 0, w = a.length(); i < w; i++) |
|
{ |
|
std::cout << std::setw(4) << int(in_row1[i]); |
|
std::cout << std::setw(4) << int(in_row2[i]); |
|
out_row[i] = static_cast<uint8_t>(in_row1[i] + in_row2[i] + cval[0]); |
|
} |
|
std::cout << std::endl; |
|
} |
|
} |
|
}; |
|
|
|
static const int ITUR_BT_601_CY = 1220542; |
|
static const int ITUR_BT_601_CUB = 2116026; |
|
static const int ITUR_BT_601_CUG = -409993; |
|
static const int ITUR_BT_601_CVG = -852492; |
|
static const int ITUR_BT_601_CVR = 1673527; |
|
static const int ITUR_BT_601_SHIFT = 20; |
|
|
|
static inline void uvToRGBuv(const uchar u, const uchar v, int& ruv, int& guv, int& buv) |
|
{ |
|
int uu, vv; |
|
uu = int(u) - 128; |
|
vv = int(v) - 128; |
|
|
|
ruv = (1 << (ITUR_BT_601_SHIFT - 1)) + ITUR_BT_601_CVR * vv; |
|
guv = (1 << (ITUR_BT_601_SHIFT - 1)) + ITUR_BT_601_CVG * vv + ITUR_BT_601_CUG * uu; |
|
buv = (1 << (ITUR_BT_601_SHIFT - 1)) + ITUR_BT_601_CUB * uu; |
|
} |
|
|
|
static inline void yRGBuvToRGB(const uchar vy, const int ruv, const int guv, const int buv, |
|
uchar& r, uchar& g, uchar& b) |
|
{ |
|
int y = std::max(0, vy - 16) * ITUR_BT_601_CY; |
|
r = saturate_cast<uchar>((y + ruv) >> ITUR_BT_601_SHIFT); |
|
g = saturate_cast<uchar>((y + guv) >> ITUR_BT_601_SHIFT); |
|
b = saturate_cast<uchar>((y + buv) >> ITUR_BT_601_SHIFT); |
|
} |
|
|
|
GAPI_FLUID_KERNEL(FNV12toRGB, cv::gapi::imgproc::GNV12toRGB, false) |
|
{ |
|
static const int Window = 1; |
|
static const int LPI = 2; |
|
static const auto Kind = GFluidKernel::Kind::NV12toRGB; |
|
|
|
static void run(const cv::gapi::fluid::View &in1, |
|
const cv::gapi::fluid::View &in2, |
|
cv::gapi::fluid::Buffer &out) |
|
{ |
|
const auto w = out.length(); |
|
|
|
GAPI_Assert(w % 2 == 0); |
|
GAPI_Assert(out.lpi() == 2); |
|
|
|
const uchar* uv_row = in2.InLineB(0); |
|
const uchar* y_rows[] = {in1. InLineB(0), in1. InLineB(1)}; |
|
uchar* out_rows[] = {out.OutLineB(0), out.OutLineB(1)}; |
|
|
|
for (int i = 0; i < w/2; i++) |
|
{ |
|
uchar u = uv_row[2*i]; |
|
uchar v = uv_row[2*i + 1]; |
|
int ruv, guv, buv; |
|
uvToRGBuv(u, v, ruv, guv, buv); |
|
|
|
for (int y = 0; y < 2; y++) |
|
{ |
|
for (int x = 0; x < 2; x++) |
|
{ |
|
uchar vy = y_rows[y][2*i + x]; |
|
uchar r, g, b; |
|
yRGBuvToRGB(vy, ruv, guv, buv, r, g, b); |
|
|
|
out_rows[y][3*(2*i + x)] = r; |
|
out_rows[y][3*(2*i + x) + 1] = g; |
|
out_rows[y][3*(2*i + x) + 2] = b; |
|
} |
|
} |
|
} |
|
} |
|
}; |
|
|
|
|
|
GAPI_FLUID_KERNEL(FMerge3_4lpi, TMerge3_4lpi, false) |
|
{ |
|
static const int Window = 1; |
|
static const int LPI = 4; |
|
|
|
static void run(const cv::gapi::fluid::View &src1, |
|
const cv::gapi::fluid::View &src2, |
|
const cv::gapi::fluid::View &src3, |
|
cv::gapi::fluid::Buffer &dst) |
|
{ |
|
for (int l = 0; l < dst.lpi(); l++) |
|
{ |
|
const auto *in1 = src1.InLine<uchar>(l); |
|
const auto *in2 = src2.InLine<uchar>(l); |
|
const auto *in3 = src3.InLine<uchar>(l); |
|
auto *out = dst.OutLine<uchar>(l); |
|
|
|
for (int w = 0; w < dst.length(); w++) |
|
{ |
|
out[3*w ] = in1[w]; |
|
out[3*w + 1] = in2[w]; |
|
out[3*w + 2] = in3[w]; |
|
} |
|
} |
|
} |
|
}; |
|
|
|
GMat merge3_4lpi(const GMat& src1, const GMat& src2, const GMat& src3) |
|
{ |
|
return TMerge3_4lpi::on(src1, src2, src3); |
|
} |
|
|
|
cv::gapi::GKernelPackage fluidTestPackage = cv::gapi::kernels |
|
<FAddSimple |
|
,FAddCSimple |
|
,FAddScalar |
|
,FAddScalarToMat |
|
,FBlur1x1 |
|
,FBlur3x3 |
|
,FBlur5x5 |
|
,FBlur3x3_2lpi |
|
,FBlur5x5_2lpi |
|
,FIdentity |
|
,FId7x7 |
|
,FMerge3_4lpi |
|
,FNV12toRGB |
|
,FPlusRow0 |
|
,FSum2MatsAndScalar |
|
,FTestSplit3 |
|
,FTestSplit3_4lpi |
|
>(); |
|
} // namespace gapi_test_kernels |
|
} // namespace cv
|
|
|