// 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 #include #include "gapi_fluid_test_kernels.hpp" #include #include 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(0); const uint8_t* in2 = b.InLine(0); uint8_t* out = o.OutLine(); // 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 (l); uint8_t* out_row = out.OutLine(l); //std::cout << "l=" << l << ": "; for (int i = 0, w = in.length(); i < w; i++) { //std::cout << std::setw(4) << int(in_row[i]); //FIXME: it seems that over kernels might need it as well out_row[i] = cv::gapi::own::saturate(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 (l); uint8_t* out_row = out.OutLine(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(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 (l); uint8_t* out_row = out.OutLine(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(in_row[i] + cval[0]); } std::cout << std::endl; } } }; template 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(i - borderSize + l); } auto out = dst.OutLine(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(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(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(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(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(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(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(-1), a.InLine( 0), a.InLine(+1) }; uint8_t* out = o.OutLine(); // 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(-3 + l), a.InLine(-2 + l), a.InLine(-1 + l), a.InLine( 0 + l), a.InLine(+1 + l), a.InLine(+2 + l), a.InLine(+3 + l), }; uint8_t* out = o.OutLine(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(); 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 (0); uint8_t* out_row = out .OutLine(); uint8_t* tmp_row = scratch.OutLine(); 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(l); uint8_t* out_r = o1.OutLine(l); uint8_t* out_g = o2.OutLine(l); uint8_t* out_b = o3.OutLine(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 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 (l); const uint8_t* in_row2 = b .InLine (l); uint8_t* out_row = out.OutLine(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(in_row1[i] + in_row2[i] + cval[0]); } std::cout << std::endl; } } }; GAPI_FLUID_KERNEL(FEqualizeHist, TEqualizeHist, false) { static const int Window = 1; static const int LPI = 2; static void run(const cv::gapi::fluid::View &mat, const std::vector &arr, cv::gapi::fluid::Buffer &out) { for (int l = 0, lpi = out.lpi(); l < lpi; l++) { const uint8_t* in_row = mat.InLine (l); uint8_t* out_row = out.OutLine(l); for (int i = 0, w = mat.length(); i < w; i++) { out_row[i] = static_cast(arr[in_row[i]]); } } } }; GAPI_OCV_KERNEL(OCVCalcHist, TCalcHist) { static void run(const cv::Mat& in, std::vector& out) { out = std::vector(256, 0); // Calculate normalized accumulated integral transformation array for gapi for(int i = 0; i < in.rows; ++i) for(int j = 0; j < in.cols; ++j) ++out[in.at(i, j)]; for(unsigned int i = 1; i < out.size(); ++i) out[i] += out[i-1]; int size = in.size().width * in.size().height; int min = size; for(unsigned int i = 0; i < out.size(); ++i) if(out[i] != 0 && out[i] < min) min = out[i]; for(auto & el : out) { // General histogram equalization formula el = cvRound(((float)(el - min) / (float)(size - min))*255); } } }; 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((y + ruv) >> ITUR_BT_601_SHIFT); g = saturate_cast((y + guv) >> ITUR_BT_601_SHIFT); b = saturate_cast((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(l); const auto *in2 = src2.InLine(l); const auto *in3 = src3.InLine(l); auto *out = dst.OutLine(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 (); } // namespace gapi_test_kernels } // namespace cv