1
0
mirror of https://github.com/opencv/opencv.git synced 2026-07-30 07:43:03 +04:00

Merge branch 4.x

This commit is contained in:
Alexander Alekhin
2021-12-30 16:23:27 +00:00
951 changed files with 158314 additions and 152668 deletions
+18 -6
View File
@@ -24,8 +24,17 @@ namespace gimpl {
inline cv::Mat asMat(RMat::View& v) {
#if !defined(GAPI_STANDALONE)
return v.dims().empty() ? cv::Mat(v.rows(), v.cols(), v.type(), v.ptr(), v.step())
: cv::Mat(v.dims(), v.type(), v.ptr(), v.steps().data());
if (v.dims().empty()) {
return cv::Mat(v.rows(), v.cols(), v.type(), v.ptr(), v.step());
} else {
cv::Mat m(v.dims(), v.type(), v.ptr(), v.steps().data());
if (v.dims().size() == 1) {
// FIXME: cv::Mat() constructor will set m.dims to 2;
// To obtain 1D Mat, we have to set m.dims back to 1 manually
m.dims = 1;
}
return m;
}
#else
// FIXME: add a check that steps are default
return v.dims().empty() ? cv::Mat(v.rows(), v.cols(), v.type(), v.ptr(), v.step())
@@ -41,15 +50,18 @@ namespace gimpl {
}
return RMat::View(cv::descr_of(m), m.data, steps, std::move(cb));
#else
return RMat::View(cv::descr_of(m), m.data, m.step, std::move(cb));
return m.dims.empty()
? RMat::View(cv::descr_of(m), m.data, m.step, std::move(cb))
// Own Mat doesn't support n-dimensional steps so default ones are used in this case
: RMat::View(cv::descr_of(m), m.data, RMat::View::stepsT{}, std::move(cb));
#endif
}
class RMatAdapter : public RMat::Adapter {
class RMatOnMat : public RMat::IAdapter {
cv::Mat m_mat;
public:
const void* data() const { return m_mat.data; }
RMatAdapter(cv::Mat m) : m_mat(m) {}
RMatOnMat(cv::Mat m) : m_mat(m) {}
virtual RMat::View access(RMat::Access) override { return asView(m_mat); }
virtual cv::GMatDesc desc() const override { return cv::descr_of(m_mat); }
};
@@ -58,7 +70,7 @@ namespace gimpl {
struct Data;
struct RcDesc;
struct GAPI_EXPORTS RMatMediaFrameAdapter final: public cv::RMat::Adapter
struct GAPI_EXPORTS RMatMediaFrameAdapter final: public cv::RMat::IAdapter
{
using MapDescF = std::function<cv::GMatDesc(const GFrameDesc&)>;
using MapDataF = std::function<cv::Mat(const GFrameDesc&, const cv::MediaFrame::View&)>;
@@ -113,6 +113,6 @@ struct InGraphMetaKernel final: public cv::detail::KernelTag {
} // anonymous namespace
cv::gapi::GKernelPackage cv::gimpl::meta::kernels() {
cv::GKernelPackage cv::gimpl::meta::kernels() {
return cv::gapi::kernels<InGraphMetaKernel>();
}
@@ -7,7 +7,7 @@ namespace cv {
namespace gimpl {
namespace meta {
cv::gapi::GKernelPackage kernels();
cv::GKernelPackage kernels();
} // namespace meta
} // namespace gimpl
@@ -928,7 +928,7 @@ IIStream& ByteMemoryInStream::operator>> (std::string& str) {
if (sz == 0u) {
str.clear();
} else {
str.resize(sz);
str.resize(static_cast<std::size_t>(sz));
for (auto &&i : ade::util::iota(sz)) { *this >> str[i]; }
}
return *this;
+1 -27
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)
@@ -720,7 +696,7 @@ GAPI_OCV_KERNEL(GCPUSizeMF, cv::gapi::streaming::GSizeMF)
}
};
cv::gapi::GKernelPackage cv::gapi::core::cpu::kernels()
cv::GKernelPackage cv::gapi::core::cpu::kernels()
{
static auto pkg = cv::gapi::kernels
< GCPUAdd
@@ -775,8 +751,6 @@ cv::gapi::GKernelPackage cv::gapi::core::cpu::kernels()
, GCPUInRange
, GCPUSplit3
, GCPUSplit4
, GCPUResize
, GCPUResizeP
, GCPUMerge3
, GCPUMerge4
, GCPURemap
+27 -1
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,
@@ -613,10 +637,12 @@ GAPI_OCV_KERNEL(GCPUNV12toBGRp, cv::gapi::imgproc::GNV12toBGRp)
}
};
cv::gapi::GKernelPackage cv::gapi::imgproc::cpu::kernels()
cv::GKernelPackage cv::gapi::imgproc::cpu::kernels()
{
static auto pkg = cv::gapi::kernels
< GCPUFilter2D
, GCPUResize
, GCPUResizeP
, GCPUSepFilter
, GCPUBoxFilter
, GCPUBlur
+2 -2
View File
@@ -70,14 +70,14 @@ GAPI_OCV_KERNEL_ST(GCPUStereo, cv::gapi::calib3d::GStereo, StereoSetup)
}
};
cv::gapi::GKernelPackage cv::gapi::calib3d::cpu::kernels() {
cv::GKernelPackage cv::gapi::calib3d::cpu::kernels() {
static auto pkg = cv::gapi::kernels<GCPUStereo>();
return pkg;
}
#else
cv::gapi::GKernelPackage cv::gapi::calib3d::cpu::kernels()
cv::GKernelPackage cv::gapi::calib3d::cpu::kernels()
{
return GKernelPackage();
}
+2 -2
View File
@@ -174,7 +174,7 @@ GAPI_OCV_KERNEL_ST(GCPUKalmanFilterNoControl, cv::gapi::video::GKalmanFilterNoCo
}
};
cv::gapi::GKernelPackage cv::gapi::video::cpu::kernels()
cv::GKernelPackage cv::gapi::video::cpu::kernels()
{
static auto pkg = cv::gapi::kernels
< GCPUBuildOptFlowPyramid
@@ -189,7 +189,7 @@ cv::gapi::GKernelPackage cv::gapi::video::cpu::kernels()
#else
cv::gapi::GKernelPackage cv::gapi::video::cpu::kernels()
cv::GKernelPackage cv::gapi::video::cpu::kernels()
{
return GKernelPackage();
}
File diff suppressed because it is too large Load Diff
@@ -0,0 +1,214 @@
// 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) 2021 Intel Corporation
#if !defined(GAPI_STANDALONE)
#include "gfluidcore_func.hpp"
#include "gfluidcore_func.simd.hpp"
#include "backends/fluid/gfluidcore_func.simd_declarations.hpp"
#include "gfluidutils.hpp"
#include <opencv2/core/cvdef.h>
#include <opencv2/core/hal/intrin.hpp>
#include <cmath>
#include <cstdlib>
#ifdef __GNUC__
# pragma GCC diagnostic push
# pragma GCC diagnostic ignored "-Wstrict-overflow"
#endif
namespace cv {
namespace gapi {
namespace fluid {
#define DIV_SIMD(SRC, DST) \
int div_simd(const SRC in1[], const SRC in2[], DST out[], \
const int length, double _scale) \
{ \
CV_CPU_DISPATCH(div_simd, (in1, in2, out, length, _scale), \
CV_CPU_DISPATCH_MODES_ALL); \
}
DIV_SIMD(uchar, uchar)
DIV_SIMD(ushort, uchar)
DIV_SIMD(short, uchar)
DIV_SIMD(float, uchar)
DIV_SIMD(short, short)
DIV_SIMD(ushort, short)
DIV_SIMD(uchar, short)
DIV_SIMD(float, short)
DIV_SIMD(ushort, ushort)
DIV_SIMD(uchar, ushort)
DIV_SIMD(short, ushort)
DIV_SIMD(float, ushort)
DIV_SIMD(uchar, float)
DIV_SIMD(ushort, float)
DIV_SIMD(short, float)
DIV_SIMD(float, float)
#undef DIV_SIMD
#define MUL_SIMD(SRC, DST) \
int mul_simd(const SRC in1[], const SRC in2[], DST out[], \
const int length, double _scale) \
{ \
CV_CPU_DISPATCH(mul_simd, (in1, in2, out, length, _scale), \
CV_CPU_DISPATCH_MODES_ALL); \
}
MUL_SIMD(uchar, uchar)
MUL_SIMD(ushort, uchar)
MUL_SIMD(short, uchar)
MUL_SIMD(float, uchar)
MUL_SIMD(short, short)
MUL_SIMD(ushort, short)
MUL_SIMD(uchar, short)
MUL_SIMD(float, short)
MUL_SIMD(ushort, ushort)
MUL_SIMD(uchar, ushort)
MUL_SIMD(short, ushort)
MUL_SIMD(float, ushort)
MUL_SIMD(uchar, float)
MUL_SIMD(ushort, float)
MUL_SIMD(short, float)
MUL_SIMD(float, float)
#undef MUL_SIMD
#define ADDC_SIMD(SRC, DST) \
int addc_simd(const SRC in[], const float scalar[], DST out[], \
const int length, const int chan) \
{ \
CV_CPU_DISPATCH(addc_simd, (in, scalar, out, length, chan), \
CV_CPU_DISPATCH_MODES_ALL); \
}
ADDC_SIMD(uchar, uchar)
ADDC_SIMD(ushort, uchar)
ADDC_SIMD(short, uchar)
ADDC_SIMD(float, uchar)
ADDC_SIMD(short, short)
ADDC_SIMD(ushort, short)
ADDC_SIMD(uchar, short)
ADDC_SIMD(float, short)
ADDC_SIMD(ushort, ushort)
ADDC_SIMD(uchar, ushort)
ADDC_SIMD(short, ushort)
ADDC_SIMD(float, ushort)
ADDC_SIMD(uchar, float)
ADDC_SIMD(ushort, float)
ADDC_SIMD(short, float)
ADDC_SIMD(float, float)
#undef ADDC_SIMD
#define SUBC_SIMD(SRC, DST) \
int subc_simd(const SRC in[], const float scalar[], DST out[], \
const int length, const int chan) \
{ \
CV_CPU_DISPATCH(subc_simd, (in, scalar, out, length, chan), \
CV_CPU_DISPATCH_MODES_ALL); \
}
SUBC_SIMD(uchar, uchar)
SUBC_SIMD(ushort, uchar)
SUBC_SIMD(short, uchar)
SUBC_SIMD(float, uchar)
SUBC_SIMD(short, short)
SUBC_SIMD(ushort, short)
SUBC_SIMD(uchar, short)
SUBC_SIMD(float, short)
SUBC_SIMD(ushort, ushort)
SUBC_SIMD(uchar, ushort)
SUBC_SIMD(short, ushort)
SUBC_SIMD(float, ushort)
SUBC_SIMD(uchar, float)
SUBC_SIMD(ushort, float)
SUBC_SIMD(short, float)
SUBC_SIMD(float, float)
#undef SUBC_SIMD
#define SUBRC_SIMD(SRC, DST) \
int subrc_simd(const float scalar[], const SRC in[], DST out[], \
const int length, const int chan) \
{ \
CV_CPU_DISPATCH(subrc_simd, (scalar, in, out, length, chan), \
CV_CPU_DISPATCH_MODES_ALL); \
}
SUBRC_SIMD(uchar, uchar)
SUBRC_SIMD(ushort, uchar)
SUBRC_SIMD(short, uchar)
SUBRC_SIMD(float, uchar)
SUBRC_SIMD(short, short)
SUBRC_SIMD(ushort, short)
SUBRC_SIMD(uchar, short)
SUBRC_SIMD(float, short)
SUBRC_SIMD(ushort, ushort)
SUBRC_SIMD(uchar, ushort)
SUBRC_SIMD(short, ushort)
SUBRC_SIMD(float, ushort)
SUBRC_SIMD(uchar, float)
SUBRC_SIMD(ushort, float)
SUBRC_SIMD(short, float)
SUBRC_SIMD(float, float)
#undef SUBRC_SIMD
#define MULC_SIMD(SRC, DST) \
int mulc_simd(const SRC in[], const float scalar[], DST out[], \
const int length, const int chan, const float scale) \
{ \
CV_CPU_DISPATCH(mulc_simd, (in, scalar, out, length, chan, scale), \
CV_CPU_DISPATCH_MODES_ALL); \
}
MULC_SIMD(uchar, uchar)
MULC_SIMD(ushort, uchar)
MULC_SIMD(short, uchar)
MULC_SIMD(float, uchar)
MULC_SIMD(short, short)
MULC_SIMD(ushort, short)
MULC_SIMD(uchar, short)
MULC_SIMD(float, short)
MULC_SIMD(ushort, ushort)
MULC_SIMD(uchar, ushort)
MULC_SIMD(short, ushort)
MULC_SIMD(float, ushort)
MULC_SIMD(uchar, float)
MULC_SIMD(ushort, float)
MULC_SIMD(short, float)
MULC_SIMD(float, float)
#undef MULC_SIMD
#define ABSDIFFC_SIMD(SRC) \
int absdiffc_simd(const SRC in[], const float scalar[], SRC out[], \
const int length, const int chan) \
{ \
CV_CPU_DISPATCH(absdiffc_simd, (in, scalar, out, length, chan), \
CV_CPU_DISPATCH_MODES_ALL); \
}
ABSDIFFC_SIMD(uchar)
ABSDIFFC_SIMD(short)
ABSDIFFC_SIMD(ushort)
ABSDIFFC_SIMD(float)
#undef ABSDIFFC_SIMD
} // namespace fluid
} // namespace gapi
} // namespace cv
#endif // !defined(GAPI_STANDALONE)
@@ -0,0 +1,170 @@
// 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) 2021 Intel Corporation
#pragma once
#if !defined(GAPI_STANDALONE)
#include <opencv2/core.hpp>
namespace cv {
namespace gapi {
namespace fluid {
#define DIV_SIMD(SRC, DST) \
int div_simd(const SRC in1[], const SRC in2[], DST out[], \
const int length, double _scale);
DIV_SIMD(uchar, uchar)
DIV_SIMD(ushort, uchar)
DIV_SIMD(short, uchar)
DIV_SIMD(float, uchar)
DIV_SIMD(short, short)
DIV_SIMD(ushort, short)
DIV_SIMD(uchar, short)
DIV_SIMD(float, short)
DIV_SIMD(ushort, ushort)
DIV_SIMD(uchar, ushort)
DIV_SIMD(short, ushort)
DIV_SIMD(float, ushort)
DIV_SIMD(uchar, float)
DIV_SIMD(ushort, float)
DIV_SIMD(short, float)
DIV_SIMD(float, float)
#undef DIV_SIMD
#define MUL_SIMD(SRC, DST) \
int mul_simd(const SRC in1[], const SRC in2[], DST out[], \
const int length, double _scale);
MUL_SIMD(uchar, uchar)
MUL_SIMD(ushort, uchar)
MUL_SIMD(short, uchar)
MUL_SIMD(float, uchar)
MUL_SIMD(short, short)
MUL_SIMD(ushort, short)
MUL_SIMD(uchar, short)
MUL_SIMD(float, short)
MUL_SIMD(ushort, ushort)
MUL_SIMD(uchar, ushort)
MUL_SIMD(short, ushort)
MUL_SIMD(float, ushort)
MUL_SIMD(uchar, float)
MUL_SIMD(ushort, float)
MUL_SIMD(short, float)
MUL_SIMD(float, float)
#undef MUL_SIMD
#define ADDC_SIMD(SRC, DST) \
int addc_simd(const SRC in[], const float scalar[], DST out[], \
const int length, const int chan);
ADDC_SIMD(uchar, uchar)
ADDC_SIMD(ushort, uchar)
ADDC_SIMD(short, uchar)
ADDC_SIMD(float, uchar)
ADDC_SIMD(short, short)
ADDC_SIMD(ushort, short)
ADDC_SIMD(uchar, short)
ADDC_SIMD(float, short)
ADDC_SIMD(ushort, ushort)
ADDC_SIMD(uchar, ushort)
ADDC_SIMD(short, ushort)
ADDC_SIMD(float, ushort)
ADDC_SIMD(uchar, float)
ADDC_SIMD(ushort, float)
ADDC_SIMD(short, float)
ADDC_SIMD(float, float)
#undef ADDC_SIMD
#define SUBC_SIMD(SRC, DST) \
int subc_simd(const SRC in[], const float scalar[], DST out[], \
const int length, const int chan);
SUBC_SIMD(uchar, uchar)
SUBC_SIMD(ushort, uchar)
SUBC_SIMD(short, uchar)
SUBC_SIMD(float, uchar)
SUBC_SIMD(short, short)
SUBC_SIMD(ushort, short)
SUBC_SIMD(uchar, short)
SUBC_SIMD(float, short)
SUBC_SIMD(ushort, ushort)
SUBC_SIMD(uchar, ushort)
SUBC_SIMD(short, ushort)
SUBC_SIMD(float, ushort)
SUBC_SIMD(uchar, float)
SUBC_SIMD(ushort, float)
SUBC_SIMD(short, float)
SUBC_SIMD(float, float)
#undef SUBC_SIMD
#define SUBRC_SIMD(SRC, DST) \
int subrc_simd(const float scalar[], const SRC in[], DST out[], \
const int length, const int chan);
SUBRC_SIMD(uchar, uchar)
SUBRC_SIMD(ushort, uchar)
SUBRC_SIMD(short, uchar)
SUBRC_SIMD(float, uchar)
SUBRC_SIMD(short, short)
SUBRC_SIMD(ushort, short)
SUBRC_SIMD(uchar, short)
SUBRC_SIMD(float, short)
SUBRC_SIMD(ushort, ushort)
SUBRC_SIMD(uchar, ushort)
SUBRC_SIMD(short, ushort)
SUBRC_SIMD(float, ushort)
SUBRC_SIMD(uchar, float)
SUBRC_SIMD(ushort, float)
SUBRC_SIMD(short, float)
SUBRC_SIMD(float, float)
#undef SUBRC_SIMD
#define MULC_SIMD(SRC, DST) \
int mulc_simd(const SRC in[], const float scalar[], DST out[], \
const int length, const int chan, const float scale);
MULC_SIMD(uchar, uchar)
MULC_SIMD(ushort, uchar)
MULC_SIMD(short, uchar)
MULC_SIMD(float, uchar)
MULC_SIMD(short, short)
MULC_SIMD(ushort, short)
MULC_SIMD(uchar, short)
MULC_SIMD(float, short)
MULC_SIMD(ushort, ushort)
MULC_SIMD(uchar, ushort)
MULC_SIMD(short, ushort)
MULC_SIMD(float, ushort)
MULC_SIMD(uchar, float)
MULC_SIMD(ushort, float)
MULC_SIMD(short, float)
MULC_SIMD(float, float)
#undef MULC_SIMD
#define ABSDIFFC_SIMD(T) \
int absdiffc_simd(const T in[], const float scalar[], T out[], \
const int length, const int chan);
ABSDIFFC_SIMD(uchar)
ABSDIFFC_SIMD(short)
ABSDIFFC_SIMD(ushort)
ABSDIFFC_SIMD(float)
#undef ABSDIFFC_SIMD
} // namespace fluid
} // namespace gapi
} // namespace cv
#endif // !defined(GAPI_STANDALONE)
File diff suppressed because it is too large Load Diff
@@ -0,0 +1,733 @@
// 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) 2021 Intel Corporation
#if !defined(GAPI_STANDALONE)
#include "opencv2/gapi/own/saturate.hpp"
#include <smmintrin.h>
#include "opencv2/core.hpp"
#include <opencv2/core/hal/intrin.hpp>
#include <cstdint>
#include <cstring>
#include <algorithm>
#include <limits>
#include <vector>
#if defined __GNUC__
# pragma GCC diagnostic push
# pragma GCC diagnostic ignored "-Wstrict-overflow"
#endif
namespace cv {
namespace gapi {
namespace fluid {
namespace sse42 {
CV_ALWAYS_INLINE void v_gather_pixel_map(v_uint8x16& vec, const uchar src[], const short* index, const int pos)
{
const int chanNum = 4;
// pixel_1 (rgbx)
vec.val = _mm_insert_epi32(vec.val, *reinterpret_cast<const int*>(&src[chanNum * (*index + pos)]), 0);
// pixel_2 (rgbx)
vec.val = _mm_insert_epi32(vec.val, *reinterpret_cast<const int*>(&src[chanNum * (*(index + 1) + pos)]), 1);
// pixel_3
vec.val = _mm_insert_epi32(vec.val, *reinterpret_cast<const int*>(&src[chanNum * (*(index + 2) + pos)]), 2);
// pixel_4
vec.val = _mm_insert_epi32(vec.val, *reinterpret_cast<const int*>(&src[chanNum * (*(index + 3) + pos)]), 3);
}
CV_ALWAYS_INLINE void resize_vertical_anyLPI(const uchar* src0, const uchar* src1,
uchar* dst, const int inLength,
const short beta) {
constexpr int nlanes = 16;
__m128i zero = _mm_setzero_si128();
__m128i b = _mm_set1_epi16(beta);
for (int w = 0; inLength >= nlanes;)
{
for (; w <= inLength - nlanes; w += nlanes)
{
__m128i s0 = _mm_lddqu_si128(reinterpret_cast<const __m128i*>(&src0[w]));
__m128i s1 = _mm_lddqu_si128(reinterpret_cast<const __m128i*>(&src1[w]));
__m128i a1 = _mm_unpacklo_epi8(s0, zero);
__m128i b1 = _mm_unpacklo_epi8(s1, zero);
__m128i a2 = _mm_unpackhi_epi8(s0, zero);
__m128i b2 = _mm_unpackhi_epi8(s1, zero);
__m128i r1 = _mm_mulhrs_epi16(_mm_sub_epi16(a1, b1), b);
__m128i r2 = _mm_mulhrs_epi16(_mm_sub_epi16(a2, b2), b);
__m128i res1 = _mm_add_epi16(r1, b1);
__m128i res2 = _mm_add_epi16(r2, b2);
_mm_storeu_si128(reinterpret_cast<__m128i*>(dst + w), _mm_packus_epi16(res1, res2));
}
if (w < inLength) {
w = inLength - nlanes;
continue;
}
break;
}
}
CV_ALWAYS_INLINE void resize_horizontal_anyLPI(uint8_t* dst,
const uchar* src, const short mapsx[],
const short alpha[], const int width)
{
constexpr int nlanes = 16;
constexpr int chanNum = 3;
__m128i zero = _mm_setzero_si128();
for (int x = 0; width >= nlanes;)
{
for (; x <= width - nlanes; x += nlanes)
{
__m128i a012 = _mm_setr_epi16(alpha[x], alpha[x], alpha[x], alpha[x + 1],
alpha[x + 1], alpha[x + 1], alpha[x + 2], alpha[x + 2]);
__m128i a2345 = _mm_setr_epi16(alpha[x + 2], alpha[x + 3], alpha[x + 3], alpha[x + 3],
alpha[x + 4], alpha[x + 4], alpha[x + 4], alpha[x + 5]);
__m128i a567 = _mm_setr_epi16(alpha[x + 5], alpha[x + 5], alpha[x + 6], alpha[x + 6],
alpha[x + 6], alpha[x + 7], alpha[x + 7], alpha[x + 7]);
__m128i a8910 = _mm_setr_epi16(alpha[x + 8], alpha[x + 8], alpha[x + 8], alpha[x + 9],
alpha[x + 9], alpha[x + 9], alpha[x + 10], alpha[x + 10]);
__m128i a10111213 = _mm_setr_epi16(alpha[x + 10], alpha[x + 11], alpha[x + 11], alpha[x + 11],
alpha[x + 12], alpha[x + 12], alpha[x + 12], alpha[x + 13]);
__m128i a131415 = _mm_setr_epi16(alpha[x + 13], alpha[x + 13], alpha[x + 14], alpha[x + 14],
alpha[x + 14], alpha[x + 15], alpha[x + 15], alpha[x + 15]);
__m128i a1 = _mm_setr_epi8(src[chanNum * (mapsx[x] + 0)], src[chanNum * (mapsx[x] + 0) + 1], src[chanNum * (mapsx[x] + 0) + 2],
src[chanNum * (mapsx[x + 1] + 0)], src[chanNum * (mapsx[x + 1] + 0) + 1], src[chanNum * (mapsx[x + 1] + 0) + 2],
src[chanNum * (mapsx[x + 2] + 0)], src[chanNum * (mapsx[x + 2] + 0) + 1], src[chanNum * (mapsx[x + 2] + 0) + 2],
src[chanNum * (mapsx[x + 3] + 0)], src[chanNum * (mapsx[x + 3] + 0) + 1], src[chanNum * (mapsx[x + 3] + 0) + 2],
src[chanNum * (mapsx[x + 4] + 0)], src[chanNum * (mapsx[x + 4] + 0) + 1], src[chanNum * (mapsx[x + 4] + 0) + 2],
src[chanNum * (mapsx[x + 5] + 0)]);
__m128i b1 = _mm_setr_epi8(src[chanNum * (mapsx[x] + 1)], src[chanNum * (mapsx[x] + 1) + 1], src[chanNum * (mapsx[x] + 1) + 2],
src[chanNum * (mapsx[x + 1] + 1)], src[chanNum * (mapsx[x + 1] + 1) + 1], src[chanNum * (mapsx[x + 1] + 1) + 2],
src[chanNum * (mapsx[x + 2] + 1)], src[chanNum * (mapsx[x + 2] + 1) + 1], src[chanNum * (mapsx[x + 2] + 1) + 2],
src[chanNum * (mapsx[x + 3] + 1)], src[chanNum * (mapsx[x + 3] + 1) + 1], src[chanNum * (mapsx[x + 3] + 1) + 2],
src[chanNum * (mapsx[x + 4] + 1)], src[chanNum * (mapsx[x + 4] + 1) + 1], src[chanNum * (mapsx[x + 4] + 1) + 2],
src[chanNum * (mapsx[x + 5] + 1)]);
__m128i a2 = _mm_setr_epi8(src[chanNum * (mapsx[x + 5] + 0) + 1], src[chanNum * (mapsx[x + 5] + 0) + 2], src[chanNum * (mapsx[x + 6] + 0)],
src[chanNum * (mapsx[x + 6] + 0) + 1], src[chanNum * (mapsx[x + 6] + 0) + 2], src[chanNum * (mapsx[x + 7] + 0)],
src[chanNum * (mapsx[x + 7] + 0) + 1], src[chanNum * (mapsx[x + 7] + 0) + 2], src[chanNum * (mapsx[x + 8] + 0)],
src[chanNum * (mapsx[x + 8] + 0) + 1], src[chanNum * (mapsx[x + 8] + 0) + 2], src[chanNum * (mapsx[x + 9] + 0)],
src[chanNum * (mapsx[x + 9] + 0) + 1], src[chanNum * (mapsx[x + 9] + 0) + 2], src[chanNum * (mapsx[x + 10] + 0)],
src[chanNum * (mapsx[x + 10] + 0) + 1]);
__m128i b2 = _mm_setr_epi8(src[chanNum * (mapsx[x + 5] + 1) + 1], src[chanNum * (mapsx[x + 5] + 1) + 2], src[chanNum * (mapsx[x + 6] + 1)],
src[chanNum * (mapsx[x + 6] + 1) + 1], src[chanNum * (mapsx[x + 6] + 1) + 2], src[chanNum * (mapsx[x + 7] + 1)],
src[chanNum * (mapsx[x + 7] + 1) + 1], src[chanNum * (mapsx[x + 7] + 1) + 2], src[chanNum * (mapsx[x + 8] + 1)],
src[chanNum * (mapsx[x + 8] + 1) + 1], src[chanNum * (mapsx[x + 8] + 1) + 2], src[chanNum * (mapsx[x + 9] + 1)],
src[chanNum * (mapsx[x + 9] + 1) + 1], src[chanNum * (mapsx[x + 9] + 1) + 2], src[chanNum * (mapsx[x + 10] + 1)],
src[chanNum * (mapsx[x + 10] + 1) + 1]);
__m128i a3 = _mm_setr_epi8(src[chanNum * (mapsx[x + 10] + 0) + 2], src[chanNum * (mapsx[x + 11] + 0)], src[chanNum * (mapsx[x + 11] + 0) + 1],
src[chanNum * (mapsx[x + 11] + 0) + 2], src[chanNum * (mapsx[x + 12] + 0)], src[chanNum * (mapsx[x + 12] + 0) + 1],
src[chanNum * (mapsx[x + 12] + 0) + 2], src[chanNum * (mapsx[x + 13] + 0)], src[chanNum * (mapsx[x + 13] + 0) + 1],
src[chanNum * (mapsx[x + 13] + 0) + 2], src[chanNum * (mapsx[x + 14] + 0)], src[chanNum * (mapsx[x + 14] + 0) + 1],
src[chanNum * (mapsx[x + 14] + 0) + 2], src[chanNum * (mapsx[x + 15] + 0)], src[chanNum * (mapsx[x + 15] + 0) + 1],
src[chanNum * (mapsx[x + 15] + 0) + 2]);
__m128i b3 = _mm_setr_epi8(src[chanNum * (mapsx[x + 10] + 1) + 2], src[chanNum * (mapsx[x + 11] + 1)], src[chanNum * (mapsx[x + 11] + 1) + 1],
src[chanNum * (mapsx[x + 11] + 1) + 2], src[chanNum * (mapsx[x + 12] + 1)], src[chanNum * (mapsx[x + 12] + 1) + 1],
src[chanNum * (mapsx[x + 12] + 1) + 2], src[chanNum * (mapsx[x + 13] + 1)], src[chanNum * (mapsx[x + 13] + 1) + 1],
src[chanNum * (mapsx[x + 13] + 1) + 2], src[chanNum * (mapsx[x + 14] + 1)], src[chanNum * (mapsx[x + 14] + 1) + 1],
src[chanNum * (mapsx[x + 14] + 1) + 2], src[chanNum * (mapsx[x + 15] + 1)], src[chanNum * (mapsx[x + 15] + 1) + 1],
src[chanNum * (mapsx[x + 15] + 1) + 2]);
__m128i a11 = _mm_unpacklo_epi8(a1, zero);
__m128i a12 = _mm_unpackhi_epi8(a1, zero);
__m128i a21 = _mm_unpacklo_epi8(a2, zero);
__m128i a22 = _mm_unpackhi_epi8(a2, zero);
__m128i a31 = _mm_unpacklo_epi8(a3, zero);
__m128i a32 = _mm_unpackhi_epi8(a3, zero);
__m128i b11 = _mm_unpacklo_epi8(b1, zero);
__m128i b12 = _mm_unpackhi_epi8(b1, zero);
__m128i b21 = _mm_unpacklo_epi8(b2, zero);
__m128i b22 = _mm_unpackhi_epi8(b2, zero);
__m128i b31 = _mm_unpacklo_epi8(b3, zero);
__m128i b32 = _mm_unpackhi_epi8(b3, zero);
__m128i r1 = _mm_mulhrs_epi16(_mm_sub_epi16(a11, b11), a012);
__m128i r2 = _mm_mulhrs_epi16(_mm_sub_epi16(a12, b12), a2345);
__m128i r3 = _mm_mulhrs_epi16(_mm_sub_epi16(a21, b21), a567);
__m128i r4 = _mm_mulhrs_epi16(_mm_sub_epi16(a22, b22), a8910);
__m128i r5 = _mm_mulhrs_epi16(_mm_sub_epi16(a31, b31), a10111213);
__m128i r6 = _mm_mulhrs_epi16(_mm_sub_epi16(a32, b32), a131415);
__m128i r_1 = _mm_add_epi16(b11, r1);
__m128i r_2 = _mm_add_epi16(b12, r2);
__m128i r_3 = _mm_add_epi16(b21, r3);
__m128i r_4 = _mm_add_epi16(b22, r4);
__m128i r_5 = _mm_add_epi16(b31, r5);
__m128i r_6 = _mm_add_epi16(b32, r6);
__m128i res1 = _mm_packus_epi16(r_1, r_2);
__m128i res2 = _mm_packus_epi16(r_3, r_4);
__m128i res3 = _mm_packus_epi16(r_5, r_6);
_mm_storeu_si128(reinterpret_cast<__m128i*>(&dst[chanNum * x]), res1);
_mm_storeu_si128(reinterpret_cast<__m128i*>(&dst[chanNum * x + 16]), res2);
_mm_storeu_si128(reinterpret_cast<__m128i*>(&dst[chanNum * x + 32]), res3);
}
if (x < width) {
x = width - nlanes;
continue;
}
break;
}
}
template<int chanNum>
CV_ALWAYS_INLINE void calcRowLinear_8UC_Impl_(uint8_t**,
const uint8_t**,
const uint8_t**,
const short* ,
const short* ,
const short*,
const short* ,
uint8_t*,
const Size& ,
const Size& ,
const int )
{
static_assert(chanNum != 3, "Unsupported number of channel");
}
template<>
CV_ALWAYS_INLINE void calcRowLinear_8UC_Impl_<3>(uint8_t* dst[],
const uint8_t* src0[],
const uint8_t* src1[],
const short alpha[],
const short* clone, // 4 clones of alpha
const short mapsx[],
const short beta[],
uint8_t tmp[],
const Size& inSz,
const Size& outSz,
const int lpi) {
bool xRatioEq = inSz.width == outSz.width;
bool yRatioEq = inSz.height == outSz.height;
constexpr int nlanes = 16;
constexpr int half_nlanes = 16 / 2;
constexpr int chanNum = 3;
if (!xRatioEq && !yRatioEq) {
int inLength = inSz.width * chanNum;
if (lpi == 4)
{
// vertical pass
__m128i b0 = _mm_set1_epi16(beta[0]);
__m128i b1 = _mm_set1_epi16(beta[1]);
__m128i b2 = _mm_set1_epi16(beta[2]);
__m128i b3 = _mm_set1_epi16(beta[3]);
__m128i zero = _mm_setzero_si128();
__m128i vertical_shuf_mask = _mm_setr_epi8(0, 8, 4, 12, 1, 9, 5, 13, 2, 10, 6, 14, 3, 11, 7, 15);
for (int w = 0; w < inSz.width * chanNum; ) {
for (; w <= inSz.width * chanNum - half_nlanes && w >= 0; w += half_nlanes) {
#ifdef __i386__
__m128i val0lo = _mm_castpd_si128(_mm_loadh_pd(
_mm_load_sd(reinterpret_cast<const double*>(&src0[0][w])),
reinterpret_cast<const double*>(&src0[1][w])));
__m128i val0hi = _mm_castpd_si128(_mm_loadh_pd(
_mm_load_sd(reinterpret_cast<const double*>(&src0[2][w])),
reinterpret_cast<const double*>(&src0[3][w])));
__m128i val1lo = _mm_castpd_si128(_mm_loadh_pd(
_mm_load_sd(reinterpret_cast<const double*>(&src1[0][w])),
reinterpret_cast<const double*>(&src1[1][w])));
__m128i val1hi = _mm_castpd_si128(_mm_loadh_pd(
_mm_load_sd(reinterpret_cast<const double*>(&src1[2][w])),
reinterpret_cast<const double*>(&src1[3][w])));
#else
__m128i val0lo = _mm_insert_epi64(_mm_loadl_epi64(reinterpret_cast<const __m128i*>(&src0[0][w])),
*reinterpret_cast<const int64_t*>(&src0[1][w]), 1);
__m128i val0hi = _mm_insert_epi64(_mm_loadl_epi64(reinterpret_cast<const __m128i*>(&src0[2][w])),
*reinterpret_cast<const int64_t*>(&src0[3][w]), 1);
__m128i val1lo = _mm_insert_epi64(_mm_loadl_epi64(reinterpret_cast<const __m128i*>(&src1[0][w])),
*reinterpret_cast<const int64_t*>(&src1[1][w]), 1);
__m128i val1hi = _mm_insert_epi64(_mm_loadl_epi64(reinterpret_cast<const __m128i*>(&src1[2][w])),
*reinterpret_cast<const int64_t*>(&src1[3][w]), 1);
#endif
__m128i val0_0 = _mm_cvtepu8_epi16(val0lo);
__m128i val0_2 = _mm_cvtepu8_epi16(val0hi);
__m128i val1_0 = _mm_cvtepu8_epi16(val1lo);
__m128i val1_2 = _mm_cvtepu8_epi16(val1hi);
__m128i val0_1 = _mm_unpackhi_epi8(val0lo, zero);
__m128i val0_3 = _mm_unpackhi_epi8(val0hi, zero);
__m128i val1_1 = _mm_unpackhi_epi8(val1lo, zero);
__m128i val1_3 = _mm_unpackhi_epi8(val1hi, zero);
__m128i t0 = _mm_mulhrs_epi16(_mm_sub_epi16(val0_0, val1_0), b0);
__m128i t1 = _mm_mulhrs_epi16(_mm_sub_epi16(val0_1, val1_1), b1);
__m128i t2 = _mm_mulhrs_epi16(_mm_sub_epi16(val0_2, val1_2), b2);
__m128i t3 = _mm_mulhrs_epi16(_mm_sub_epi16(val0_3, val1_3), b3);
__m128i r0 = _mm_add_epi16(val1_0, t0);
__m128i r1 = _mm_add_epi16(val1_1, t1);
__m128i r2 = _mm_add_epi16(val1_2, t2);
__m128i r3 = _mm_add_epi16(val1_3, t3);
__m128i q0 = _mm_packus_epi16(r0, r1);
__m128i q1 = _mm_packus_epi16(r2, r3);
__m128i q2 = _mm_blend_epi16(q0, _mm_slli_si128(q1, 4), 0xCC /*0b11001100*/);
__m128i q3 = _mm_blend_epi16(_mm_srli_si128(q0, 4), q1, 0xCC /*0b11001100*/);
__m128i q4 = _mm_shuffle_epi8(q2, vertical_shuf_mask);
__m128i q5 = _mm_shuffle_epi8(q3, vertical_shuf_mask);
_mm_storeu_si128(reinterpret_cast<__m128i*>(&tmp[4 * w + 0]), q4);
_mm_storeu_si128(reinterpret_cast<__m128i*>(&tmp[4 * w + 16]), q5);
}
if (w < inSz.width * chanNum) {
w = inSz.width * chanNum - half_nlanes;
}
}
// horizontal pass
__m128i horizontal_shuf_mask = _mm_setr_epi8(0, 4, 8, 12, 1, 5, 9, 13, 2, 6, 10, 14, 3, 7, 11, 15);
for (int x = 0; outSz.width >= nlanes; )
{
for (; x <= outSz.width - nlanes; x += nlanes)
{
#ifdef _WIN64
__m128i a00 = _mm_setr_epi64x(*reinterpret_cast<const int64_t*>(&clone[4 * x]), *reinterpret_cast<const int64_t*>(&clone[4 * x]));
__m128i a01 = _mm_setr_epi64x(*reinterpret_cast<const int64_t*>(&clone[4 * x]), *reinterpret_cast<const int64_t*>(&clone[4 * (x + 1)]));
__m128i a11 = _mm_setr_epi64x(*reinterpret_cast<const int64_t*>(&clone[4 * (x + 1)]), *reinterpret_cast<const int64_t*>(&clone[4 * (x + 1)]));
__m128i a22 = _mm_setr_epi64x(*reinterpret_cast<const int64_t*>(&clone[4 * (x + 2)]), *reinterpret_cast<const int64_t*>(&clone[4 * (x + 2)]));
__m128i a23 = _mm_setr_epi64x(*reinterpret_cast<const int64_t*>(&clone[4 * (x + 2)]), *reinterpret_cast<const int64_t*>(&clone[4 * (x + 3)]));
__m128i a33 = _mm_setr_epi64x(*reinterpret_cast<const int64_t*>(&clone[4 * (x + 3)]), *reinterpret_cast<const int64_t*>(&clone[4 * (x + 3)]));
__m128i a44 = _mm_setr_epi64x(*reinterpret_cast<const int64_t*>(&clone[4 * (x + 4)]), *reinterpret_cast<const int64_t*>(&clone[4 * (x + 4)]));
__m128i a45 = _mm_setr_epi64x(*reinterpret_cast<const int64_t*>(&clone[4 * (x + 4)]), *reinterpret_cast<const int64_t*>(&clone[4 * (x + 5)]));
__m128i a55 = _mm_setr_epi64x(*reinterpret_cast<const int64_t*>(&clone[4 * (x + 5)]), *reinterpret_cast<const int64_t*>(&clone[4 * (x + 5)]));
__m128i a66 = _mm_setr_epi64x(*reinterpret_cast<const int64_t*>(&clone[4 * (x + 6)]), *reinterpret_cast<const int64_t*>(&clone[4 * (x + 6)]));
__m128i a67 = _mm_setr_epi64x(*reinterpret_cast<const int64_t*>(&clone[4 * (x + 6)]), *reinterpret_cast<const int64_t*>(&clone[4 * (x + 7)]));
__m128i a77 = _mm_setr_epi64x(*reinterpret_cast<const int64_t*>(&clone[4 * (x + 7)]), *reinterpret_cast<const int64_t*>(&clone[4 * (x + 7)]));
__m128i a88 = _mm_setr_epi64x(*reinterpret_cast<const int64_t*>(&clone[4 * (x + 8)]), *reinterpret_cast<const int64_t*>(&clone[4 * (x + 8)]));
__m128i a89 = _mm_setr_epi64x(*reinterpret_cast<const int64_t*>(&clone[4 * (x + 8)]), *reinterpret_cast<const int64_t*>(&clone[4 * (x + 9)]));
__m128i a99 = _mm_setr_epi64x(*reinterpret_cast<const int64_t*>(&clone[4 * (x + 9)]), *reinterpret_cast<const int64_t*>(&clone[4 * (x + 9)]));
__m128i a1010 = _mm_setr_epi64x(*reinterpret_cast<const int64_t*>(&clone[4 * (x + 10)]), *reinterpret_cast<const int64_t*>(&clone[4 * (x + 10)]));
__m128i a1011 = _mm_setr_epi64x(*reinterpret_cast<const int64_t*>(&clone[4 * (x + 10)]), *reinterpret_cast<const int64_t*>(&clone[4 * (x + 11)]));
__m128i a1111 = _mm_setr_epi64x(*reinterpret_cast<const int64_t*>(&clone[4 * (x + 11)]), *reinterpret_cast<const int64_t*>(&clone[4 * (x + 11)]));
__m128i a1212 = _mm_setr_epi64x(*reinterpret_cast<const int64_t*>(&clone[4 * (x + 12)]), *reinterpret_cast<const int64_t*>(&clone[4 * (x + 12)]));
__m128i a1213 = _mm_setr_epi64x(*reinterpret_cast<const int64_t*>(&clone[4 * (x + 12)]), *reinterpret_cast<const int64_t*>(&clone[4 * (x + 13)]));
__m128i a1313 = _mm_setr_epi64x(*reinterpret_cast<const int64_t*>(&clone[4 * (x + 13)]), *reinterpret_cast<const int64_t*>(&clone[4 * (x + 13)]));
__m128i a1414 = _mm_setr_epi64x(*reinterpret_cast<const int64_t*>(&clone[4 * (x + 14)]), *reinterpret_cast<const int64_t*>(&clone[4 * (x + 14)]));
__m128i a1415 = _mm_setr_epi64x(*reinterpret_cast<const int64_t*>(&clone[4 * (x + 14)]), *reinterpret_cast<const int64_t*>(&clone[4 * (x + 15)]));
__m128i a1515 = _mm_setr_epi64x(*reinterpret_cast<const int64_t*>(&clone[4 * (x + 15)]), *reinterpret_cast<const int64_t*>(&clone[4 * (x + 15)]));
#else
__m128i a00 = _mm_setr_epi64(*reinterpret_cast<const __m64*>(&clone[4 * x]), *reinterpret_cast<const __m64*>(&clone[4 * x]));
__m128i a01 = _mm_setr_epi64(*reinterpret_cast<const __m64*>(&clone[4 * x]), *reinterpret_cast<const __m64*>(&clone[4 * (x + 1)]));
__m128i a11 = _mm_setr_epi64(*reinterpret_cast<const __m64*>(&clone[4 * (x + 1)]), *reinterpret_cast<const __m64*>(&clone[4 * (x + 1)]));
__m128i a22 = _mm_setr_epi64(*reinterpret_cast<const __m64*>(&clone[4 * (x + 2)]), *reinterpret_cast<const __m64*>(&clone[4 * (x + 2)]));
__m128i a23 = _mm_setr_epi64(*reinterpret_cast<const __m64*>(&clone[4 * (x + 2)]), *reinterpret_cast<const __m64*>(&clone[4 * (x + 3)]));
__m128i a33 = _mm_setr_epi64(*reinterpret_cast<const __m64*>(&clone[4 * (x + 3)]), *reinterpret_cast<const __m64*>(&clone[4 * (x + 3)]));
__m128i a44 = _mm_setr_epi64(*reinterpret_cast<const __m64*>(&clone[4 * (x + 4)]), *reinterpret_cast<const __m64*>(&clone[4 * (x + 4)]));
__m128i a45 = _mm_setr_epi64(*reinterpret_cast<const __m64*>(&clone[4 * (x + 4)]), *reinterpret_cast<const __m64*>(&clone[4 * (x + 5)]));
__m128i a55 = _mm_setr_epi64(*reinterpret_cast<const __m64*>(&clone[4 * (x + 5)]), *reinterpret_cast<const __m64*>(&clone[4 * (x + 5)]));
__m128i a66 = _mm_setr_epi64(*reinterpret_cast<const __m64*>(&clone[4 * (x + 6)]), *reinterpret_cast<const __m64*>(&clone[4 * (x + 6)]));
__m128i a67 = _mm_setr_epi64(*reinterpret_cast<const __m64*>(&clone[4 * (x + 6)]), *reinterpret_cast<const __m64*>(&clone[4 * (x + 7)]));
__m128i a77 = _mm_setr_epi64(*reinterpret_cast<const __m64*>(&clone[4 * (x + 7)]), *reinterpret_cast<const __m64*>(&clone[4 * (x + 7)]));
__m128i a88 = _mm_setr_epi64(*reinterpret_cast<const __m64*>(&clone[4 * (x + 8)]), *reinterpret_cast<const __m64*>(&clone[4 * (x + 8)]));
__m128i a89 = _mm_setr_epi64(*reinterpret_cast<const __m64*>(&clone[4 * (x + 8)]), *reinterpret_cast<const __m64*>(&clone[4 * (x + 9)]));
__m128i a99 = _mm_setr_epi64(*reinterpret_cast<const __m64*>(&clone[4 * (x + 9)]), *reinterpret_cast<const __m64*>(&clone[4 * (x + 9)]));
__m128i a1010 = _mm_setr_epi64(*reinterpret_cast<const __m64*>(&clone[4 * (x + 10)]), *reinterpret_cast<const __m64*>(&clone[4 * (x + 10)]));
__m128i a1011 = _mm_setr_epi64(*reinterpret_cast<const __m64*>(&clone[4 * (x + 10)]), *reinterpret_cast<const __m64*>(&clone[4 * (x + 11)]));
__m128i a1111 = _mm_setr_epi64(*reinterpret_cast<const __m64*>(&clone[4 * (x + 11)]), *reinterpret_cast<const __m64*>(&clone[4 * (x + 11)]));
__m128i a1212 = _mm_setr_epi64(*reinterpret_cast<const __m64*>(&clone[4 * (x + 12)]), *reinterpret_cast<const __m64*>(&clone[4 * (x + 12)]));
__m128i a1213 = _mm_setr_epi64(*reinterpret_cast<const __m64*>(&clone[4 * (x + 12)]), *reinterpret_cast<const __m64*>(&clone[4 * (x + 13)]));
__m128i a1313 = _mm_setr_epi64(*reinterpret_cast<const __m64*>(&clone[4 * (x + 13)]), *reinterpret_cast<const __m64*>(&clone[4 * (x + 13)]));
__m128i a1414 = _mm_setr_epi64(*reinterpret_cast<const __m64*>(&clone[4 * (x + 14)]), *reinterpret_cast<const __m64*>(&clone[4 * (x + 14)]));
__m128i a1415 = _mm_setr_epi64(*reinterpret_cast<const __m64*>(&clone[4 * (x + 14)]), *reinterpret_cast<const __m64*>(&clone[4 * (x + 15)]));
__m128i a1515 = _mm_setr_epi64(*reinterpret_cast<const __m64*>(&clone[4 * (x + 15)]), *reinterpret_cast<const __m64*>(&clone[4 * (x + 15)]));
#endif
// load 3 channels of first pixel from first pair of 4-couple scope
__m128i pix1 = _mm_lddqu_si128(reinterpret_cast<const __m128i*>(&tmp[4 * (chanNum * mapsx[x])]));
// insert first channel from next couple of pixels to completely fill the simd vector
pix1 = _mm_insert_epi32(pix1, *reinterpret_cast<const int*>(&tmp[4 * (chanNum * mapsx[x + 1])]), 3);
// load 3 channels of neighbor pixel from first pair of 4-couple scope
__m128i pix2 = _mm_lddqu_si128(reinterpret_cast<const __m128i*>(&tmp[4 * (chanNum * (mapsx[x] + 1))]));
// insert first channel from next couple of pixels to completely fill the simd vector
pix2 = _mm_insert_epi32(pix2, *reinterpret_cast<const int*>(&tmp[4 * (chanNum * (mapsx[x + 1] + 1))]), 3);
// expand 8-bit data to 16-bit
__m128i val_0 = _mm_unpacklo_epi8(pix1, zero);
__m128i val_1 = _mm_unpacklo_epi8(pix2, zero);
// expand 8-bit data to 16-bit
__m128i val_2 = _mm_unpackhi_epi8(pix1, zero);
__m128i val_3 = _mm_unpackhi_epi8(pix2, zero);
// the main calculations
__m128i t0_0 = _mm_mulhrs_epi16(_mm_sub_epi16(val_0, val_1), a00);
__m128i t1_0 = _mm_mulhrs_epi16(_mm_sub_epi16(val_2, val_3), a01);
__m128i r0_0 = _mm_add_epi16(val_1, t0_0);
__m128i r1_0 = _mm_add_epi16(val_3, t1_0);
// pack 16-bit data to 8-bit
__m128i q0_0 = _mm_packus_epi16(r0_0, r1_0);
// gather data from the same lines together
__m128i res1 = _mm_shuffle_epi8(q0_0, horizontal_shuf_mask);
val_0 = _mm_unpacklo_epi8(_mm_insert_epi64(val_0, *reinterpret_cast<const int64_t*>(&tmp[4 * (chanNum * mapsx[x + 1] + 1)]), 0), zero);
val_1 = _mm_unpacklo_epi8(_mm_insert_epi64(val_1, *reinterpret_cast<const int64_t*>(&tmp[4 * (chanNum * (mapsx[x + 1] + 1) + 1)]), 0), zero);
val_2 = _mm_insert_epi64(val_2, *reinterpret_cast<const int64_t*>(&tmp[4 * (chanNum * mapsx[x + 2])]), 0);
val_3 = _mm_insert_epi64(val_3, *reinterpret_cast<const int64_t*>(&tmp[4 * (chanNum * (mapsx[x + 2] + 1))]), 0);
val_2 = _mm_unpacklo_epi8(val_2, zero);
val_3 = _mm_unpacklo_epi8(val_3, zero);
__m128i t0_1 = _mm_mulhrs_epi16(_mm_sub_epi16(val_0, val_1), a11);
__m128i t1_1 = _mm_mulhrs_epi16(_mm_sub_epi16(val_2, val_3), a22);
__m128i r0_1 = _mm_add_epi16(val_1, t0_1);
__m128i r1_1 = _mm_add_epi16(val_3, t1_1);
__m128i q0_1 = _mm_packus_epi16(r0_1, r1_1);
__m128i res2 = _mm_shuffle_epi8(q0_1, horizontal_shuf_mask);
__m128i pix7 = _mm_lddqu_si128(reinterpret_cast<const __m128i*>(&tmp[4 * (chanNum * (mapsx[x + 3] - 1) + 2)]));
pix7 = _mm_insert_epi32(pix7, *reinterpret_cast<const int*>(&tmp[4 * (chanNum * mapsx[x + 2] + 2)]), 0);
__m128i pix8 = _mm_lddqu_si128(reinterpret_cast<const __m128i*>(&tmp[4 * (chanNum * mapsx[x + 3] + 2)]));
pix8 = _mm_insert_epi32(pix8, *reinterpret_cast<const int*>(&tmp[4 * (chanNum * (mapsx[x + 2] + 1) + 2)]), 0);
val_0 = _mm_unpacklo_epi8(pix7, zero);
val_1 = _mm_unpacklo_epi8(pix8, zero);
val_2 = _mm_unpackhi_epi8(pix7, zero);
val_3 = _mm_unpackhi_epi8(pix8, zero);
// the main calculations
__m128i t0_2 = _mm_mulhrs_epi16(_mm_sub_epi16(val_0, val_1), a23);
__m128i t1_2 = _mm_mulhrs_epi16(_mm_sub_epi16(val_2, val_3), a33);
__m128i r0_2 = _mm_add_epi16(val_1, t0_2);
__m128i r1_2 = _mm_add_epi16(val_3, t1_2);
// pack 16-bit data to 8-bit
__m128i q0_2 = _mm_packus_epi16(r0_2, r1_2);
__m128i res3 = _mm_shuffle_epi8(q0_2, horizontal_shuf_mask);
__m128i pix9 = _mm_lddqu_si128(reinterpret_cast<const __m128i*>(&tmp[4 * (chanNum * mapsx[x + 4])]));
// insert first channel from next couple of pixels to completely fill the simd vector
pix9 = _mm_insert_epi32(pix9, *reinterpret_cast<const int*>(&tmp[4 * (chanNum * mapsx[x + 5])]), 3);
// load 3 channels of neighbor pixel from first pair of 4-couple scope
__m128i pix10 = _mm_lddqu_si128(reinterpret_cast<const __m128i*>(&tmp[4 * (chanNum * (mapsx[x + 4] + 1))]));
// insert first channel from next couple of pixels to completely fill the simd vector
pix10 = _mm_insert_epi32(pix10, *reinterpret_cast<const int*>(&tmp[4 * (chanNum * (mapsx[x + 5] + 1))]), 3);
// expand 8-bit data to 16-bit
val_0 = _mm_unpacklo_epi8(pix9, zero);
val_1 = _mm_unpacklo_epi8(pix10, zero);
// expand 8-bit data to 16-bit
val_2 = _mm_unpackhi_epi8(pix9, zero);
val_3 = _mm_unpackhi_epi8(pix10, zero);
// the main calculations
__m128i t0_3 = _mm_mulhrs_epi16(_mm_sub_epi16(val_0, val_1), a44);
__m128i t1_3 = _mm_mulhrs_epi16(_mm_sub_epi16(val_2, val_3), a45);
__m128i r0_3 = _mm_add_epi16(val_1, t0_3);
__m128i r1_3 = _mm_add_epi16(val_3, t1_3);
// pack 16-bit data to 8-bit
__m128i q0_3 = _mm_packus_epi16(r0_3, r1_3);
// gather data from the same lines together
__m128i res4 = _mm_shuffle_epi8(q0_3, horizontal_shuf_mask);
val_0 = _mm_unpacklo_epi8(_mm_insert_epi64(val_0, *reinterpret_cast<const int64_t*>(&tmp[4 * (chanNum * mapsx[x + 5] + 1)]), 0), zero);
val_1 = _mm_unpacklo_epi8(_mm_insert_epi64(val_1, *reinterpret_cast<const int64_t*>(&tmp[4 * (chanNum * (mapsx[x + 5] + 1) + 1)]), 0), zero);
val_2 = _mm_insert_epi64(val_2, *reinterpret_cast<const int64_t*>(&tmp[4 * (chanNum * mapsx[x + 6])]), 0);
val_3 = _mm_insert_epi64(val_3, *reinterpret_cast<const int64_t*>(&tmp[4 * (chanNum * (mapsx[x + 6] + 1))]), 0);
val_2 = _mm_unpacklo_epi8(val_2, zero);
val_3 = _mm_unpacklo_epi8(val_3, zero);
__m128i t0_4 = _mm_mulhrs_epi16(_mm_sub_epi16(val_0, val_1), a55);
__m128i t1_4 = _mm_mulhrs_epi16(_mm_sub_epi16(val_2, val_3), a66);
__m128i r0_4 = _mm_add_epi16(val_1, t0_4);
__m128i r1_4 = _mm_add_epi16(val_3, t1_4);
__m128i q0_4 = _mm_packus_epi16(r0_4, r1_4);
__m128i res5 = _mm_shuffle_epi8(q0_4, horizontal_shuf_mask);
__m128i pix15 = _mm_lddqu_si128(reinterpret_cast<const __m128i*>(&tmp[4 * (chanNum * (mapsx[x + 7] - 1) + 2)]));
pix15 = _mm_insert_epi32(pix15, *reinterpret_cast<const int*>(&tmp[4 * (chanNum * mapsx[x + 6] + 2)]), 0);
__m128i pix16 = _mm_lddqu_si128(reinterpret_cast<const __m128i*>(&tmp[4 * (chanNum * mapsx[x + 7] + 2)]));
pix16 = _mm_insert_epi32(pix16, *reinterpret_cast<const int*>(&tmp[4 * (chanNum * (mapsx[x + 6] + 1) + 2)]), 0);
val_0 = _mm_unpacklo_epi8(pix15, zero);
val_1 = _mm_unpacklo_epi8(pix16, zero);
val_2 = _mm_unpackhi_epi8(pix15, zero);
val_3 = _mm_unpackhi_epi8(pix16, zero);
// the main calculations
__m128i t0_5 = _mm_mulhrs_epi16(_mm_sub_epi16(val_0, val_1), a67);
__m128i t1_5 = _mm_mulhrs_epi16(_mm_sub_epi16(val_2, val_3), a77);
__m128i r0_5 = _mm_add_epi16(val_1, t0_5);
__m128i r1_5 = _mm_add_epi16(val_3, t1_5);
// pack 16-bit data to 8-bit
__m128i q0_5 = _mm_packus_epi16(r0_5, r1_5);
__m128i res6 = _mm_shuffle_epi8(q0_5, horizontal_shuf_mask);
__m128i bl1 = _mm_blend_epi16(res1, _mm_slli_si128(res2, 4), 0xCC /*0b11001100*/);
__m128i bl2 = _mm_blend_epi16(_mm_srli_si128(res1, 4), res2, 0xCC /*0b11001100*/);
__m128i bl3 = _mm_blend_epi16(res3, _mm_slli_si128(res4, 4), 0xCC /*0b11001100*/);
__m128i bl4 = _mm_blend_epi16(_mm_srli_si128(res3, 4), res4, 0xCC /*0b11001100*/);
__m128i bl5 = _mm_blend_epi16(res5, _mm_slli_si128(res6, 4), 0xCC /*0b11001100*/);
__m128i bl6 = _mm_blend_epi16(_mm_srli_si128(res5, 4), res6, 0xCC /*0b11001100*/);
__m128i bl13 = _mm_blend_epi16(bl1, _mm_slli_si128(bl3, 8), 0xF0 /*0b11110000*/);
__m128i bl31 = _mm_blend_epi16(_mm_srli_si128(bl1, 8), bl3, 0xF0 /*0b11110000*/);
__m128i bl24 = _mm_blend_epi16(bl2, _mm_slli_si128(bl4, 8), 0xF0 /*0b11110000*/);
__m128i bl42 = _mm_blend_epi16(_mm_srli_si128(bl2, 8), bl4, 0xF0 /*0b11110000*/);
// load 3 channels of first pixel from first pair of 4-couple scope
__m128i pix17 = _mm_lddqu_si128(reinterpret_cast<const __m128i*>(&tmp[4 * (chanNum * mapsx[x + 8])]));
// insert first channel from next couple of pixels to completely fill the simd vector
pix17 = _mm_insert_epi32(pix17, *reinterpret_cast<const int*>(&tmp[4 * (chanNum * mapsx[x + 9])]), 3);
// load 3 channels of neighbor pixel from first pair of 4-couple scope
__m128i pix18 = _mm_lddqu_si128(reinterpret_cast<const __m128i*>(&tmp[4 * (chanNum * (mapsx[x + 8] + 1))]));
// insert first channel from next couple of pixels to completely fill the simd vector
pix18 = _mm_insert_epi32(pix18, *reinterpret_cast<const int*>(&tmp[4 * (chanNum * (mapsx[x + 9] + 1))]), 3);
// expand 8-bit data to 16-bit
val_0 = _mm_unpacklo_epi8(pix17, zero);
val_1 = _mm_unpacklo_epi8(pix18, zero);
// expand 8-bit data to 16-bit
val_2 = _mm_unpackhi_epi8(pix17, zero);
val_3 = _mm_unpackhi_epi8(pix18, zero);
// the main calculations
__m128i t0_6 = _mm_mulhrs_epi16(_mm_sub_epi16(val_0, val_1), a88);
__m128i t1_6 = _mm_mulhrs_epi16(_mm_sub_epi16(val_2, val_3), a89);
__m128i r0_6 = _mm_add_epi16(val_1, t0_6);
__m128i r1_6 = _mm_add_epi16(val_3, t1_6);
// pack 16-bit data to 8-bit
__m128i q0_6 = _mm_packus_epi16(r0_6, r1_6);
// gather data from the same lines together
__m128i res7 = _mm_shuffle_epi8(q0_6, horizontal_shuf_mask);
val_0 = _mm_unpacklo_epi8(_mm_insert_epi64(val_0, *reinterpret_cast<const int64_t*>(&tmp[4 * (chanNum * mapsx[x + 9] + 1)]), 0), zero);
val_1 = _mm_unpacklo_epi8(_mm_insert_epi64(val_1, *reinterpret_cast<const int64_t*>(&tmp[4 * (chanNum * (mapsx[x + 9] + 1) + 1)]), 0), zero);
val_2 = _mm_insert_epi64(val_2, *reinterpret_cast<const int64_t*>(&tmp[4 * (chanNum * mapsx[x + 10])]), 0);
val_3 = _mm_insert_epi64(val_3, *reinterpret_cast<const int64_t*>(&tmp[4 * (chanNum * (mapsx[x + 10] + 1))]), 0);
val_2 = _mm_unpacklo_epi8(val_2, zero);
val_3 = _mm_unpacklo_epi8(val_3, zero);
__m128i t0_7 = _mm_mulhrs_epi16(_mm_sub_epi16(val_0, val_1), a99);
__m128i t1_7 = _mm_mulhrs_epi16(_mm_sub_epi16(val_2, val_3), a1010);
__m128i r0_7 = _mm_add_epi16(val_1, t0_7);
__m128i r1_7 = _mm_add_epi16(val_3, t1_7);
__m128i q0_7 = _mm_packus_epi16(r0_7, r1_7);
__m128i res8 = _mm_shuffle_epi8(q0_7, horizontal_shuf_mask);
__m128i pix21 = _mm_lddqu_si128(reinterpret_cast<const __m128i*>(&tmp[4 * (chanNum * (mapsx[x + 11] - 1) + 2)]));
pix21 = _mm_insert_epi32(pix21, *reinterpret_cast<const int*>(&tmp[4 * (chanNum * mapsx[x + 10] + 2)]), 0);
__m128i pix22 = _mm_lddqu_si128(reinterpret_cast<const __m128i*>(&tmp[4 * (chanNum * mapsx[x + 11] + 2)]));
pix22 = _mm_insert_epi32(pix22, *reinterpret_cast<const int*>(&tmp[4 * (chanNum * (mapsx[x + 10] + 1) + 2)]), 0);
val_0 = _mm_unpacklo_epi8(pix21, zero);
val_1 = _mm_unpacklo_epi8(pix22, zero);
val_2 = _mm_unpackhi_epi8(pix21, zero);
val_3 = _mm_unpackhi_epi8(pix22, zero);
// the main calculations
__m128i t0_8 = _mm_mulhrs_epi16(_mm_sub_epi16(val_0, val_1), a1011);
__m128i t1_8 = _mm_mulhrs_epi16(_mm_sub_epi16(val_2, val_3), a1111);
__m128i r0_8 = _mm_add_epi16(val_1, t0_8);
__m128i r1_8 = _mm_add_epi16(val_3, t1_8);
// pack 16-bit data to 8-bit
__m128i q0_8 = _mm_packus_epi16(r0_8, r1_8);
__m128i res9 = _mm_shuffle_epi8(q0_8, horizontal_shuf_mask);
__m128i pix23 = _mm_lddqu_si128(reinterpret_cast<const __m128i*>(&tmp[4 * (chanNum * mapsx[x + 12])]));
// insert first channel from next couple of pixels to completely fill the simd vector
pix23 = _mm_insert_epi32(pix23, *reinterpret_cast<const int*>(&tmp[4 * (chanNum * mapsx[x + 13])]), 3);
// load 3 channels of neighbor pixel from first pair of 4-couple scope
__m128i pix24 = _mm_lddqu_si128(reinterpret_cast<const __m128i*>(&tmp[4 * (chanNum * (mapsx[x + 12] + 1))]));
// insert first channel from next couple of pixels to completely fill the simd vector
pix24 = _mm_insert_epi32(pix24, *reinterpret_cast<const int*>(&tmp[4 * (chanNum * (mapsx[x + 13] + 1))]), 3);
// expand 8-bit data to 16-bit
val_0 = _mm_unpacklo_epi8(pix23, zero);
val_1 = _mm_unpacklo_epi8(pix24, zero);
// expand 8-bit data to 16-bit
val_2 = _mm_unpackhi_epi8(pix23, zero);
val_3 = _mm_unpackhi_epi8(pix24, zero);
// the main calculations
__m128i t0_9 = _mm_mulhrs_epi16(_mm_sub_epi16(val_0, val_1), a1212);
__m128i t1_9 = _mm_mulhrs_epi16(_mm_sub_epi16(val_2, val_3), a1213);
__m128i r0_9 = _mm_add_epi16(val_1, t0_9);
__m128i r1_9 = _mm_add_epi16(val_3, t1_9);
// pack 16-bit data to 8-bit
__m128i q0_9 = _mm_packus_epi16(r0_9, r1_9);
// gather data from the same lines together
__m128i res10 = _mm_shuffle_epi8(q0_9, horizontal_shuf_mask);
val_0 = _mm_unpacklo_epi8(_mm_insert_epi64(val_0, *reinterpret_cast<const int64_t*>(&tmp[4 * (chanNum * mapsx[x + 13] + 1)]), 0), zero);
val_1 = _mm_unpacklo_epi8(_mm_insert_epi64(val_1, *reinterpret_cast<const int64_t*>(&tmp[4 * (chanNum * (mapsx[x + 13] + 1) + 1)]), 0), zero);
val_2 = _mm_insert_epi64(val_2, *reinterpret_cast<const int64_t*>(&tmp[4 * (chanNum * mapsx[x + 14])]), 0);
val_3 = _mm_insert_epi64(val_3, *reinterpret_cast<const int64_t*>(&tmp[4 * (chanNum * (mapsx[x + 14] + 1))]), 0);
val_2 = _mm_unpacklo_epi8(val_2, zero);
val_3 = _mm_unpacklo_epi8(val_3, zero);
__m128i t0_10 = _mm_mulhrs_epi16(_mm_sub_epi16(val_0, val_1), a1313);
__m128i t1_10 = _mm_mulhrs_epi16(_mm_sub_epi16(val_2, val_3), a1414);
__m128i r0_10 = _mm_add_epi16(val_1, t0_10);
__m128i r1_10 = _mm_add_epi16(val_3, t1_10);
__m128i q0_10 = _mm_packus_epi16(r0_10, r1_10);
__m128i res11 = _mm_shuffle_epi8(q0_10, horizontal_shuf_mask);
__m128i pix27 = _mm_lddqu_si128(reinterpret_cast<const __m128i*>(&tmp[4 * (chanNum * (mapsx[x + 15] - 1) + 2)]));
pix27 = _mm_insert_epi32(pix27, *reinterpret_cast<const int*>(&tmp[4 * (chanNum * mapsx[x + 14] + 2)]), 0);
__m128i pix28 = _mm_lddqu_si128(reinterpret_cast<const __m128i*>(&tmp[4 * (chanNum * mapsx[x + 15] + 2)]));
pix28 = _mm_insert_epi32(pix28, *reinterpret_cast<const int*>(&tmp[4 * (chanNum * (mapsx[x + 14] + 1) + 2)]), 0);
val_0 = _mm_unpacklo_epi8(pix27, zero);
val_1 = _mm_unpacklo_epi8(pix28, zero);
val_2 = _mm_unpackhi_epi8(pix27, zero);
val_3 = _mm_unpackhi_epi8(pix28, zero);
// the main calculations
__m128i t0_11 = _mm_mulhrs_epi16(_mm_sub_epi16(val_0, val_1), a1415);
__m128i t1_11 = _mm_mulhrs_epi16(_mm_sub_epi16(val_2, val_3), a1515);
__m128i r0_11 = _mm_add_epi16(val_1, t0_11);
__m128i r1_11 = _mm_add_epi16(val_3, t1_11);
// pack 16-bit data to 8-bit
__m128i q0_11 = _mm_packus_epi16(r0_11, r1_11);
__m128i res12 = _mm_shuffle_epi8(q0_11, horizontal_shuf_mask);
__m128i bl7 = _mm_blend_epi16(res7, _mm_slli_si128(res8, 4), 0xCC /*0b11001100*/);
__m128i bl8 = _mm_blend_epi16(_mm_srli_si128(res7, 4), res8, 0xCC /*0b11001100*/);
__m128i bl9 = _mm_blend_epi16(res9, _mm_slli_si128(res10, 4), 0xCC /*0b11001100*/);
__m128i bl10 = _mm_blend_epi16(_mm_srli_si128(res9, 4), res10, 0xCC /*0b11001100*/);
__m128i bl11 = _mm_blend_epi16(res11, _mm_slli_si128(res12, 4), 0xCC /*0b11001100*/);
__m128i bl12 = _mm_blend_epi16(_mm_srli_si128(res11, 4), res12, 0xCC /*0b11001100*/);
__m128i bl57 = _mm_blend_epi16(bl5, _mm_slli_si128(bl7, 8), 0xF0 /*0b11110000*/);
__m128i bl75 = _mm_blend_epi16(_mm_srli_si128(bl5, 8), bl7, 0xF0 /*0b11110000*/);
__m128i bl68 = _mm_blend_epi16(bl6, _mm_slli_si128(bl8, 8), 0xF0 /*0b11110000*/);
__m128i bl86 = _mm_blend_epi16(_mm_srli_si128(bl6, 8), bl8, 0xF0 /*0b11110000*/);
__m128i bl911 = _mm_blend_epi16(bl9, _mm_slli_si128(bl11, 8), 0xF0 /*0b11110000*/);
__m128i bl119 = _mm_blend_epi16(_mm_srli_si128(bl9, 8), bl11, 0xF0 /*0b11110000*/);
__m128i bl1012 = _mm_blend_epi16(bl10, _mm_slli_si128(bl12, 8), 0xF0 /*0b11110000*/);
__m128i bl1210 = _mm_blend_epi16(_mm_srli_si128(bl10, 8), bl12, 0xF0 /*0b11110000*/);
_mm_storeu_si128(reinterpret_cast<__m128i*>(&dst[0][3 * x]), bl13);
_mm_storeu_si128(reinterpret_cast<__m128i*>(&dst[1][3 * x]), bl24);
_mm_storeu_si128(reinterpret_cast<__m128i*>(&dst[2][3 * x]), bl31);
_mm_storeu_si128(reinterpret_cast<__m128i*>(&dst[3][3 * x]), bl42);
_mm_storeu_si128(reinterpret_cast<__m128i*>(&dst[0][3 * x + 16]), bl57);
_mm_storeu_si128(reinterpret_cast<__m128i*>(&dst[1][3 * x + 16]), bl68);
_mm_storeu_si128(reinterpret_cast<__m128i*>(&dst[2][3 * x + 16]), bl75);
_mm_storeu_si128(reinterpret_cast<__m128i*>(&dst[3][3 * x + 16]), bl86);
_mm_storeu_si128(reinterpret_cast<__m128i*>(&dst[0][3 * x + 32]), bl911);
_mm_storeu_si128(reinterpret_cast<__m128i*>(&dst[1][3 * x + 32]), bl1012);
_mm_storeu_si128(reinterpret_cast<__m128i*>(&dst[2][3 * x + 32]), bl119);
_mm_storeu_si128(reinterpret_cast<__m128i*>(&dst[3][3 * x + 32]), bl1210);
}
if (x < outSz.width) {
x = outSz.width - nlanes;
continue;
}
break;
}
}
else
{ // if any lpi
for (int l = 0; l < lpi; ++l) {
short beta0 = beta[l];
const uchar* s0 = src0[l];
const uchar* s1 = src1[l];
// vertical pass
resize_vertical_anyLPI(s0, s1, tmp, inLength, beta0);
// horizontal pass
resize_horizontal_anyLPI(dst[l], tmp, mapsx, alpha, outSz.width);
}
}
} else if (!xRatioEq) {
GAPI_DbgAssert(yRatioEq);
for (int l = 0; l < lpi; ++l) {
const uchar* src = src0[l];
// horizontal pass
resize_horizontal_anyLPI(dst[l], src, mapsx, alpha, outSz.width);
}
} else if (!yRatioEq) {
GAPI_DbgAssert(xRatioEq);
int inLength = inSz.width*chanNum; // == outSz.width
for (int l = 0; l < lpi; ++l) {
short beta0 = beta[l];
const uchar* s0 = src0[l];
const uchar* s1 = src1[l];
// vertical pass
resize_vertical_anyLPI(s0, s1, dst[l], inLength, beta0);
}
} else {
GAPI_DbgAssert(xRatioEq && yRatioEq);
int length = inSz.width *chanNum;
for (int l = 0; l < lpi; ++l) {
memcpy(dst[l], src0[l], length);
}
}
}
} // namespace sse42
} // namespace fliud
} // namespace gapi
} // namespace cv
#endif // !defined(GAPI_STANDALONE)
@@ -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,16 +1825,312 @@ 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
cv::gapi::GKernelPackage cv::gapi::imgproc::fluid::kernels()
cv::GKernelPackage cv::gapi::imgproc::fluid::kernels()
{
using namespace cv::gapi::fluid;
return cv::gapi::kernels
< GFluidBGR2Gray
, GFluidResize
, GFluidRGB2Gray
, GFluidRGB2GrayCustom
, GFluidRGB2YUV
@@ -49,3 +49,9 @@ cv::gapi::ie::PyParams& cv::gapi::ie::PyParams::cfgNumRequests(size_t nireq) {
m_priv->cfgNumRequests(nireq);
return *this;
}
cv::gapi::ie::PyParams&
cv::gapi::ie::PyParams::cfgBatchSize(const size_t size) {
m_priv->cfgBatchSize(size);
return *this;
}
+151 -70
View File
@@ -127,7 +127,6 @@ inline int toCV(IE::Precision prec) {
inline IE::TensorDesc toIE(const cv::Mat &mat, cv::gapi::ie::TraitAs hint) {
const auto &sz = mat.size;
// NB: For some reason RGB image is 2D image
// (since channel component is not counted here).
// Note: regular 2D vectors also fall into this category
@@ -148,7 +147,6 @@ inline IE::TensorDesc toIE(const cv::Mat &mat, cv::gapi::ie::TraitAs hint) {
return IE::TensorDesc(toIE(mat.depth()),
IE::SizeVector{1, channels, height, width}, bdesc);
}
return IE::TensorDesc(toIE(mat.depth()), toIE(sz), toIELayout(sz.dims()));
}
@@ -218,14 +216,18 @@ struct IEUnit {
cv::gapi::ie::detail::ParamDesc params;
IE::CNNNetwork net;
IE::InputsDataMap inputs;
IE::OutputsDataMap outputs;
IE::ExecutableNetwork this_network;
cv::gimpl::ie::wrap::Plugin this_plugin;
InferenceEngine::RemoteContext::Ptr rctx = nullptr;
// FIXME: Unlike loadNetwork case, importNetwork requires that preprocessing
// should be passed as ExecutableNetwork::SetBlob method, so need to collect
// and store this information at the graph compilation stage (outMeta) and use in runtime.
using PreProcMap = std::unordered_map<std::string, IE::PreProcessInfo>;
PreProcMap preproc_map;
explicit IEUnit(const cv::gapi::ie::detail::ParamDesc &pp)
: params(pp) {
InferenceEngine::ParamMap* ctx_params =
@@ -237,11 +239,12 @@ struct IEUnit {
if (params.kind == cv::gapi::ie::detail::ParamDesc::Kind::Load) {
net = cv::gimpl::ie::wrap::readNetwork(params);
inputs = net.getInputsInfo();
outputs = net.getOutputsInfo();
// NB: Set batch size only if user asked. (don't set by default)
if (params.batch_size.has_value()) {
net.setBatchSize(params.batch_size.value());
}
} else if (params.kind == cv::gapi::ie::detail::ParamDesc::Kind::Import) {
this_plugin = cv::gimpl::ie::wrap::getPlugin(params);
this_plugin.SetConfig(params.config);
this_network = cv::gimpl::ie::wrap::importNetwork(this_plugin, params, rctx);
if (!params.reshape_table.empty() || !params.layer_names_to_reshape.empty()) {
GAPI_LOG_WARNING(NULL, "Reshape isn't supported for imported network");
@@ -267,14 +270,14 @@ struct IEUnit {
}
if (params.num_in == 1u && params.input_names.empty()) {
if (params.kind == cv::gapi::ie::detail::ParamDesc::Kind::Load) {
params.input_names = { inputs.begin()->first };
params.input_names = { net.getInputsInfo().begin()->first };
} else {
params.input_names = { this_network.GetInputsInfo().begin()->first };
}
}
if (params.num_out == 1u && params.output_names.empty()) {
if (params.kind == cv::gapi::ie::detail::ParamDesc::Kind::Load) {
params.output_names = { outputs.begin()->first };
params.output_names = { net.getOutputsInfo().begin()->first };
} else {
params.output_names = { this_network.GetOutputsInfo().begin()->first };
}
@@ -289,11 +292,11 @@ struct IEUnit {
// This method is [supposed to be] called at Island compilation stage
cv::gimpl::ie::IECompiled compile() const {
IEUnit* non_const_this = const_cast<IEUnit*>(this);
// FIXME: LoadNetwork must be called only after all necessary model
// inputs information is set, since it's done in outMeta and compile called after that,
// this place seems to be suitable, but consider another place not to break const agreements.
if (params.kind == cv::gapi::ie::detail::ParamDesc::Kind::Load) {
// FIXME: In case importNetwork for fill inputs/outputs need to obtain ExecutableNetwork, but
// for loadNetwork they can be obtained by using readNetwork
non_const_this->this_plugin = cv::gimpl::ie::wrap::getPlugin(params);
non_const_this->this_plugin.SetConfig(params.config);
non_const_this->this_network = cv::gimpl::ie::wrap::loadNetwork(non_const_this->this_plugin,
net, params, rctx);
}
@@ -518,7 +521,9 @@ inline IE::Blob::Ptr extractRemoteBlob(IECallContext& ctx, std::size_t i) {
blob_params->second);
}
inline IE::Blob::Ptr extractBlob(IECallContext& ctx, std::size_t i) {
inline IE::Blob::Ptr extractBlob(IECallContext& ctx,
std::size_t i,
cv::gapi::ie::TraitAs hint) {
if (ctx.uu.rctx != nullptr) {
return extractRemoteBlob(ctx, i);
}
@@ -530,7 +535,7 @@ inline IE::Blob::Ptr extractBlob(IECallContext& ctx, std::size_t i) {
return wrapIE(*(ctx.views.back()), frame.desc());
}
case cv::GShape::GMAT: {
return wrapIE(ctx.inMat(i), cv::gapi::ie::TraitAs::IMAGE);
return wrapIE(ctx.inMat(i), hint);
}
default:
GAPI_Assert("Unsupported input shape for IE backend");
@@ -539,19 +544,19 @@ inline IE::Blob::Ptr extractBlob(IECallContext& ctx, std::size_t i) {
}
static void setBlob(InferenceEngine::InferRequest& req,
cv::gapi::ie::detail::ParamDesc::Kind kind,
const std::string& layer_name,
IE::Blob::Ptr blob) {
// NB: In case importNetwork preprocessing must be
// passed as SetBlob argument.
if (kind == cv::gapi::ie::detail::ParamDesc::Kind::Load) {
static void setBlob(InferenceEngine::InferRequest& req,
const std::string& layer_name,
const IE::Blob::Ptr& blob,
const IECallContext& ctx) {
// TODO: Ideally we shouldn't do SetBlob() but GetBlob() instead,
// and redirect our data producers to this memory
// (A memory dialog comes to the picture again)
using namespace cv::gapi::ie::detail;
if (ctx.uu.params.kind == ParamDesc::Kind::Load) {
req.SetBlob(layer_name, blob);
} else {
GAPI_Assert(kind == cv::gapi::ie::detail::ParamDesc::Kind::Import);
IE::PreProcessInfo info;
info.setResizeAlgorithm(IE::RESIZE_BILINEAR);
req.SetBlob(layer_name, blob, info);
GAPI_Assert(ctx.uu.params.kind == ParamDesc::Kind::Import);
req.SetBlob(layer_name, blob, ctx.uu.preproc_map.at(layer_name));
}
}
@@ -821,6 +826,23 @@ static void configureInputInfo(const IE::InputInfo::Ptr& ii, const cv::GMetaArg
}
}
static IE::PreProcessInfo configurePreProcInfo(const IE::InputInfo::CPtr& ii,
const cv::GMetaArg& mm) {
IE::PreProcessInfo info;
if (cv::util::holds_alternative<cv::GFrameDesc>(mm)) {
auto desc = cv::util::get<cv::GFrameDesc>(mm);
if (desc.fmt == cv::MediaFormat::NV12) {
info.setColorFormat(IE::ColorFormat::NV12);
}
}
const auto layout = ii->getTensorDesc().getLayout();
if (layout == IE::Layout::NCHW ||
layout == IE::Layout::NHWC) {
info.setResizeAlgorithm(IE::RESIZE_BILINEAR);
}
return info;
}
// NB: This is a callback used by async infer
// to post outputs blobs (cv::GMat's).
static void PostOutputs(InferenceEngine::InferRequest &request,
@@ -920,11 +942,13 @@ struct Infer: public cv::detail::KernelTag {
// NB: Configuring input precision and network reshape must be done
// only in the loadNetwork case.
if (uu.params.kind == cv::gapi::ie::detail::ParamDesc::Kind::Load) {
using namespace cv::gapi::ie::detail;
if (uu.params.kind == ParamDesc::Kind::Load) {
auto inputs = uu.net.getInputsInfo();
for (auto &&it : ade::util::zip(ade::util::toRange(uu.params.input_names),
ade::util::toRange(in_metas))) {
const auto &input_name = std::get<0>(it);
auto &&ii = uu.inputs.at(input_name);
auto ii = inputs.at(input_name);
const auto & mm = std::get<1>(it);
configureInputInfo(ii, mm);
@@ -932,7 +956,14 @@ struct Infer: public cv::detail::KernelTag {
uu.params.layer_names_to_reshape.end()) {
configureInputReshapeByImage(ii, mm, input_reshape_table);
}
ii->getPreProcess().setResizeAlgorithm(IE::RESIZE_BILINEAR);
// NB: Configure resize only for NCHW/NHWC layout,
// since it isn't supposed to work with others.
auto layout = ii->getTensorDesc().getLayout();
if (layout == IE::Layout::NCHW ||
layout == IE::Layout::NHWC) {
ii->getPreProcess().setResizeAlgorithm(IE::RESIZE_BILINEAR);
}
}
// FIXME: This isn't the best place to call reshape function.
@@ -941,6 +972,18 @@ struct Infer: public cv::detail::KernelTag {
if (!input_reshape_table.empty()) {
const_cast<IE::CNNNetwork *>(&uu.net)->reshape(input_reshape_table);
}
} else {
GAPI_Assert(uu.params.kind == ParamDesc::Kind::Import);
auto inputs = uu.this_network.GetInputsInfo();
// FIXME: This isn't the best place to collect PreProcMap.
auto* non_const_prepm = const_cast<IEUnit::PreProcMap*>(&uu.preproc_map);
for (auto &&it : ade::util::zip(ade::util::toRange(uu.params.input_names),
ade::util::toRange(in_metas))) {
const auto &input_name = std::get<0>(it);
auto ii = inputs.at(input_name);
const auto & mm = std::get<1>(it);
non_const_prepm->emplace(input_name, configurePreProcInfo(ii, mm));
}
}
// FIXME: It would be nice here to have an exact number of network's
@@ -949,11 +992,13 @@ struct Infer: public cv::detail::KernelTag {
for (const auto &out_name : uu.params.output_names) {
// NOTE: our output_names vector follows the API order
// of this operation's outputs
const IE::DataPtr& ie_out = uu.outputs.at(out_name);
const IE::SizeVector dims = ie_out->getTensorDesc().getDims();
const auto& desc =
uu.params.kind == cv::gapi::ie::detail::ParamDesc::Kind::Load
? uu.net.getOutputsInfo().at(out_name)->getTensorDesc()
: uu.this_network.GetOutputsInfo().at(out_name)->getTensorDesc();
cv::GMatDesc outm(toCV(ie_out->getPrecision()),
toCV(ie_out->getTensorDesc().getDims()));
cv::GMatDesc outm(toCV(desc.getPrecision()),
toCV(desc.getDims()));
result.emplace_back(outm);
}
return result;
@@ -968,14 +1013,16 @@ struct Infer: public cv::detail::KernelTag {
// non-generic version for now:
// - assumes all inputs/outputs are always Mats
for (auto i : ade::util::iota(ctx->uu.params.num_in)) {
// TODO: Ideally we shouldn't do SetBlob() but GetBlob() instead,
// and redirect our data producers to this memory
// (A memory dialog comes to the picture again)
IE::Blob::Ptr this_blob = extractBlob(*ctx, i);
setBlob(req,
ctx->uu.params.kind,
ctx->uu.params.input_names[i],
this_blob);
const auto& layer_name = ctx->uu.params.input_names[i];
auto layout =
ctx->uu.this_network.GetInputsInfo().
at(layer_name)->getTensorDesc().getLayout();
auto hint =
(layout == IE::Layout::NCHW || layout == IE::Layout::NHWC)
? cv::gapi::ie::TraitAs::IMAGE : cv::gapi::ie::TraitAs::TENSOR;
IE::Blob::Ptr this_blob = extractBlob(*ctx, i, hint);
setBlob(req, layer_name, this_blob, *ctx);
}
// FIXME: Should it be done by kernel ?
// What about to do that in RequestPool ?
@@ -1007,13 +1054,13 @@ struct InferROI: public cv::detail::KernelTag {
GAPI_Assert(1u == uu.params.input_names.size());
GAPI_Assert(2u == in_metas.size());
const auto &input_name = uu.params.input_names.at(0);
auto &&mm = in_metas.at(1u);
// NB: Configuring input precision and network reshape must be done
// only in the loadNetwork case.
if (uu.params.kind == cv::gapi::ie::detail::ParamDesc::Kind::Load) {
// 0th is ROI, 1st is input image
const auto &input_name = uu.params.input_names.at(0);
auto &&ii = uu.inputs.at(input_name);
auto &&mm = in_metas.at(1u);
auto ii = uu.net.getInputsInfo().at(input_name);
configureInputInfo(ii, mm);
if (uu.params.layer_names_to_reshape.find(input_name) !=
uu.params.layer_names_to_reshape.end()) {
@@ -1027,6 +1074,13 @@ struct InferROI: public cv::detail::KernelTag {
if (!input_reshape_table.empty()) {
const_cast<IE::CNNNetwork *>(&uu.net)->reshape(input_reshape_table);
}
} else {
GAPI_Assert(uu.params.kind == cv::gapi::ie::detail::ParamDesc::Kind::Import);
auto inputs = uu.this_network.GetInputsInfo();
// FIXME: This isn't the best place to collect PreProcMap.
auto* non_const_prepm = const_cast<IEUnit::PreProcMap*>(&uu.preproc_map);
auto ii = inputs.at(input_name);
non_const_prepm->emplace(input_name, configurePreProcInfo(ii, mm));
}
// FIXME: It would be nice here to have an exact number of network's
@@ -1035,11 +1089,13 @@ struct InferROI: public cv::detail::KernelTag {
for (const auto &out_name : uu.params.output_names) {
// NOTE: our output_names vector follows the API order
// of this operation's outputs
const IE::DataPtr& ie_out = uu.outputs.at(out_name);
const IE::SizeVector dims = ie_out->getTensorDesc().getDims();
const auto& desc =
uu.params.kind == cv::gapi::ie::detail::ParamDesc::Kind::Load
? uu.net.getOutputsInfo().at(out_name)->getTensorDesc()
: uu.this_network.GetOutputsInfo().at(out_name)->getTensorDesc();
cv::GMatDesc outm(toCV(ie_out->getPrecision()),
toCV(ie_out->getTensorDesc().getDims()));
cv::GMatDesc outm(toCV(desc.getPrecision()),
toCV(desc.getDims()));
result.emplace_back(outm);
}
return result;
@@ -1054,12 +1110,14 @@ struct InferROI: public cv::detail::KernelTag {
GAPI_Assert(ctx->uu.params.num_in == 1);
auto&& this_roi = ctx->inArg<cv::detail::OpaqueRef>(0).rref<cv::Rect>();
IE::Blob::Ptr this_blob = extractBlob(*ctx, 1);
// NB: This blob will be used to make roi from its, so
// it should be treated as image
IE::Blob::Ptr this_blob =
extractBlob(*ctx, 1, cv::gapi::ie::TraitAs::IMAGE);
setBlob(req,
ctx->uu.params.kind,
*(ctx->uu.params.input_names.begin()),
IE::make_shared_blob(this_blob,
toIE(this_roi)));
IE::make_shared_blob(this_blob, toIE(this_roi)),
*ctx);
// FIXME: Should it be done by kernel ?
// What about to do that in RequestPool ?
req.StartAsync();
@@ -1098,8 +1156,9 @@ struct InferList: public cv::detail::KernelTag {
// only in the loadNetwork case.
if (uu.params.kind == cv::gapi::ie::detail::ParamDesc::Kind::Load) {
std::size_t idx = 1u;
auto inputs = uu.net.getInputsInfo();
for (auto &&input_name : uu.params.input_names) {
auto &&ii = uu.inputs.at(input_name);
auto ii = inputs.at(input_name);
const auto & mm = in_metas[idx++];
configureInputInfo(ii, mm);
if (uu.params.layer_names_to_reshape.find(input_name) !=
@@ -1115,6 +1174,16 @@ struct InferList: public cv::detail::KernelTag {
if (!input_reshape_table.empty()) {
const_cast<IE::CNNNetwork *>(&uu.net)->reshape(input_reshape_table);
}
} else {
GAPI_Assert(uu.params.kind == cv::gapi::ie::detail::ParamDesc::Kind::Import);
std::size_t idx = 1u;
auto inputs = uu.this_network.GetInputsInfo();
auto* non_const_prepm = const_cast<IEUnit::PreProcMap*>(&uu.preproc_map);
for (auto &&input_name : uu.params.input_names) {
auto ii = inputs.at(input_name);
const auto & mm = in_metas[idx++];
non_const_prepm->emplace(input_name, configurePreProcInfo(ii, mm));
}
}
// roi-list version is much easier at the moment.
@@ -1139,12 +1208,18 @@ struct InferList: public cv::detail::KernelTag {
return;
}
IE::Blob::Ptr this_blob = extractBlob(*ctx, 1);
// NB: This blob will be used to make roi from its, so
// it should be treated as image
IE::Blob::Ptr this_blob = extractBlob(*ctx, 1, cv::gapi::ie::TraitAs::IMAGE);
std::vector<std::vector<int>> cached_dims(ctx->uu.params.num_out);
for (auto i : ade::util::iota(ctx->uu.params.num_out)) {
const IE::DataPtr& ie_out = ctx->uu.outputs.at(ctx->uu.params.output_names[i]);
cached_dims[i] = toCV(ie_out->getTensorDesc().getDims());
const auto& out_name = ctx->uu.params.output_names[i];
const auto& desc =
ctx->uu.params.kind == cv::gapi::ie::detail::ParamDesc::Kind::Load
? ctx->uu.net.getOutputsInfo().at(out_name)->getTensorDesc()
: ctx->uu.this_network.GetOutputsInfo().at(out_name)->getTensorDesc();
cached_dims[i] = toCV(desc.getDims());
// FIXME: Isn't this should be done automatically
// by some resetInternalData(), etc? (Probably at the GExecutor level)
auto& out_vec = ctx->outVecR<cv::Mat>(i);
@@ -1160,10 +1235,7 @@ struct InferList: public cv::detail::KernelTag {
cv::gimpl::ie::RequestPool::Task {
[ctx, rc, this_blob](InferenceEngine::InferRequest &req) {
IE::Blob::Ptr roi_blob = IE::make_shared_blob(this_blob, toIE(rc));
setBlob(req,
ctx->uu.params.kind,
ctx->uu.params.input_names[0u],
roi_blob);
setBlob(req, ctx->uu.params.input_names[0u], roi_blob, *ctx);
req.StartAsync();
},
std::bind(callback, std::placeholders::_1, pos)
@@ -1231,7 +1303,6 @@ struct InferList2: public cv::detail::KernelTag {
std::size_t idx = 1u;
for (auto &&input_name : uu.params.input_names) {
auto &ii = uu.inputs.at(input_name);
const auto &mm = in_metas[idx];
GAPI_Assert(util::holds_alternative<cv::GArrayDesc>(mm)
&& "Non-array inputs are not supported");
@@ -1241,6 +1312,7 @@ struct InferList2: public cv::detail::KernelTag {
// only in the loadNetwork case.
if (uu.params.kind == cv::gapi::ie::detail::ParamDesc::Kind::Load) {
// This is a cv::Rect -- configure the IE preprocessing
auto ii = uu.net.getInputsInfo().at(input_name);
configureInputInfo(ii, mm_0);
if (uu.params.layer_names_to_reshape.find(input_name) !=
uu.params.layer_names_to_reshape.end()) {
@@ -1254,6 +1326,12 @@ struct InferList2: public cv::detail::KernelTag {
if (!input_reshape_table.empty()) {
const_cast<IE::CNNNetwork *>(&uu.net)->reshape(input_reshape_table);
}
} else {
GAPI_Assert(uu.params.kind == cv::gapi::ie::detail::ParamDesc::Kind::Import);
auto inputs = uu.this_network.GetInputsInfo();
auto* non_const_prepm = const_cast<IEUnit::PreProcMap*>(&uu.preproc_map);
auto ii = inputs.at(input_name);
non_const_prepm->emplace(input_name, configurePreProcInfo(ii, mm_0));
}
} else {
// This is a cv::GMat (equals to: cv::Mat)
@@ -1276,7 +1354,9 @@ struct InferList2: public cv::detail::KernelTag {
cv::gimpl::ie::RequestPool &reqPool) {
GAPI_Assert(ctx->inArgs().size() > 1u
&& "This operation must have at least two arguments");
IE::Blob::Ptr blob_0 = extractBlob(*ctx, 0);
// NB: This blob will be used to make roi from its, so
// it should be treated as image
IE::Blob::Ptr blob_0 = extractBlob(*ctx, 0, cv::gapi::ie::TraitAs::IMAGE);
const auto list_size = ctx->inArg<cv::detail::VectorRef>(1u).size();
if (list_size == 0u) {
for (auto i : ade::util::iota(ctx->uu.params.num_out)) {
@@ -1289,8 +1369,12 @@ struct InferList2: public cv::detail::KernelTag {
// FIXME: This could be done ONCE at graph compile stage!
std::vector< std::vector<int> > cached_dims(ctx->uu.params.num_out);
for (auto i : ade::util::iota(ctx->uu.params.num_out)) {
const IE::DataPtr& ie_out = ctx->uu.outputs.at(ctx->uu.params.output_names[i]);
cached_dims[i] = toCV(ie_out->getTensorDesc().getDims());
const auto& out_name = ctx->uu.params.output_names[i];
const auto& desc =
ctx->uu.params.kind == cv::gapi::ie::detail::ParamDesc::Kind::Load
? ctx->uu.net.getOutputsInfo().at(out_name)->getTensorDesc()
: ctx->uu.this_network.GetOutputsInfo().at(out_name)->getTensorDesc();
cached_dims[i] = toCV(desc.getDims());
// FIXME: Isn't this should be done automatically
// by some resetInternalData(), etc? (Probably at the GExecutor level)
auto& out_vec = ctx->outVecR<cv::Mat>(i);
@@ -1318,10 +1402,7 @@ struct InferList2: public cv::detail::KernelTag {
GAPI_Assert(false &&
"Only Rect and Mat types are supported for infer list 2!");
}
setBlob(req,
ctx->uu.params.kind,
ctx->uu.params.input_names[in_idx],
this_blob);
setBlob(req, ctx->uu.params.input_names[in_idx], this_blob, *ctx);
}
req.StartAsync();
},
@@ -1375,7 +1456,7 @@ namespace {
return EPtr{new cv::gimpl::ie::GIEExecutable(graph, nodes)};
}
virtual cv::gapi::GKernelPackage auxiliaryKernels() const override {
virtual cv::GKernelPackage auxiliaryKernels() const override {
return cv::gapi::kernels< cv::gimpl::ie::Infer
, cv::gimpl::ie::InferROI
, cv::gimpl::ie::InferList
@@ -1412,11 +1493,11 @@ std::vector<int> cv::gapi::ie::util::to_ocv(const IE::SizeVector &dims) {
return toCV(dims);
}
IE::Blob::Ptr cv::gapi::ie::util::to_ie(cv::Mat &blob) {
IE::Blob::Ptr cv::gapi::ie::util::to_ie(const cv::Mat &blob) {
return wrapIE(blob, cv::gapi::ie::TraitAs::IMAGE);
}
IE::Blob::Ptr cv::gapi::ie::util::to_ie(cv::Mat &y_plane, cv::Mat &uv_plane) {
IE::Blob::Ptr cv::gapi::ie::util::to_ie(const cv::Mat &y_plane, const cv::Mat &uv_plane) {
auto y_blob = wrapIE(y_plane, cv::gapi::ie::TraitAs::IMAGE);
auto uv_blob = wrapIE(uv_plane, cv::gapi::ie::TraitAs::IMAGE);
#if INF_ENGINE_RELEASE >= 2021010000
@@ -18,6 +18,8 @@
#include <opencv2/core/utility.hpp>
#include <opencv2/core/utils/logger.hpp>
#include <opencv2/core/utils/configuration.private.hpp>
namespace IE = InferenceEngine;
namespace giewrap = cv::gimpl::ie::wrap;
using GIEParam = cv::gapi::ie::detail::ParamDesc;
@@ -93,11 +95,38 @@ IE::InferencePlugin giewrap::getPlugin(const GIEParam& params) {
return plugin;
}
#else // >= 2019.R2
IE::Core giewrap::getCore() {
// NB: Some of IE plugins fail during IE::Core destroying in specific cases.
// Solution is allocate IE::Core in heap and doesn't destroy it, which cause
// leak, but fixes tests on CI. This behaviour is configurable by using
// OPENCV_GAPI_INFERENCE_ENGINE_CORE_LIFETIME_WORKAROUND=0
static IE::Core create_IE_Core_pointer() {
// NB: 'delete' is never called
static IE::Core* core = new IE::Core();
return *core;
}
static IE::Core create_IE_Core_instance() {
static IE::Core core;
return core;
}
IE::Core giewrap::getCore() {
// NB: to make happy memory leak tools use:
// - OPENCV_GAPI_INFERENCE_ENGINE_CORE_LIFETIME_WORKAROUND=0
static bool param_GAPI_INFERENCE_ENGINE_CORE_LIFETIME_WORKAROUND =
utils::getConfigurationParameterBool(
"OPENCV_GAPI_INFERENCE_ENGINE_CORE_LIFETIME_WORKAROUND",
#if defined(_WIN32) || defined(__APPLE__)
true
#else
false
#endif
);
return param_GAPI_INFERENCE_ENGINE_CORE_LIFETIME_WORKAROUND
? create_IE_Core_pointer() : create_IE_Core_instance();
}
IE::Core giewrap::getPlugin(const GIEParam& params) {
auto plugin = giewrap::getCore();
if (params.device_id == "CPU" || params.device_id == "FPGA")
@@ -34,13 +34,12 @@ using Plugin = IE::InferencePlugin;
GAPI_EXPORTS IE::InferencePlugin getPlugin(const GIEParam& params);
GAPI_EXPORTS inline IE::ExecutableNetwork loadNetwork( IE::InferencePlugin& plugin,
const IE::CNNNetwork& net,
const GIEParam&) {
return plugin.LoadNetwork(net, {}); // FIXME: 2nd parameter to be
// configurable via the API
const GIEParam& params) {
return plugin.LoadNetwork(net, params.config);
}
GAPI_EXPORTS inline IE::ExecutableNetwork importNetwork( IE::CNNNetwork& plugin,
const GIEParam& param) {
return plugin.ImportNetwork(param.model_path, param.device_id, {});
const GIEParam& params) {
return plugin.ImportNetwork(param.model_path, param.device_id, params.config);
}
#else // >= 2019.R2
using Plugin = IE::Core;
@@ -51,9 +50,9 @@ GAPI_EXPORTS inline IE::ExecutableNetwork loadNetwork( IE::Core& core
const GIEParam& params,
IE::RemoteContext::Ptr rctx = nullptr) {
if (rctx != nullptr) {
return core.LoadNetwork(net, rctx);
return core.LoadNetwork(net, rctx, params.config);
} else {
return core.LoadNetwork(net, params.device_id);
return core.LoadNetwork(net, params.device_id, params.config);
}
}
GAPI_EXPORTS inline IE::ExecutableNetwork importNetwork( IE::Core& core,
@@ -67,9 +66,9 @@ GAPI_EXPORTS inline IE::ExecutableNetwork importNetwork( IE::Core& core,
throw std::runtime_error("Could not open file");
}
std::istream graphBlob(&blobFile);
return core.ImportNetwork(graphBlob, rctx);
return core.ImportNetwork(graphBlob, rctx, params.config);
} else {
return core.ImportNetwork(params.model_path, params.device_id, {});
return core.ImportNetwork(params.model_path, params.device_id, params.config);
}
}
#endif // INF_ENGINE_RELEASE < 2019020000
+2 -2
View File
@@ -27,8 +27,8 @@ namespace util {
// test suite only.
GAPI_EXPORTS std::vector<int> to_ocv(const InferenceEngine::SizeVector &dims);
GAPI_EXPORTS cv::Mat to_ocv(InferenceEngine::Blob::Ptr blob);
GAPI_EXPORTS InferenceEngine::Blob::Ptr to_ie(cv::Mat &blob);
GAPI_EXPORTS InferenceEngine::Blob::Ptr to_ie(cv::Mat &y_plane, cv::Mat &uv_plane);
GAPI_EXPORTS InferenceEngine::Blob::Ptr to_ie(const cv::Mat &blob);
GAPI_EXPORTS InferenceEngine::Blob::Ptr to_ie(const cv::Mat &y_plane, const cv::Mat &uv_plane);
}}}}
+1 -10
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)
@@ -531,7 +523,7 @@ GAPI_OCL_KERNEL(GOCLTranspose, cv::gapi::core::GTranspose)
}
};
cv::gapi::GKernelPackage cv::gapi::core::ocl::kernels()
cv::GKernelPackage cv::gapi::core::ocl::kernels()
{
static auto pkg = cv::gapi::kernels
< GOCLAdd
@@ -585,7 +577,6 @@ cv::gapi::GKernelPackage cv::gapi::core::ocl::kernels()
, GOCLInRange
, GOCLSplit3
, GOCLSplit4
, GOCLResize
, GOCLMerge3
, GOCLMerge4
, GOCLRemap
@@ -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)
{
@@ -266,10 +273,11 @@ GAPI_OCL_KERNEL(GOCLRGB2GrayCustom, cv::gapi::imgproc::GRGB2GrayCustom)
};
cv::gapi::GKernelPackage cv::gapi::imgproc::ocl::kernels()
cv::GKernelPackage cv::gapi::imgproc::ocl::kernels()
{
static auto pkg = cv::gapi::kernels
< GOCLFilter2D
, GOCLResize
, GOCLSepFilter
, GOCLBoxFilter
, GOCLBlur
@@ -1147,7 +1147,7 @@ namespace {
return EPtr{new cv::gimpl::onnx::GONNXExecutable(graph, nodes)};
}
virtual cv::gapi::GKernelPackage auxiliaryKernels() const override {
virtual cv::GKernelPackage auxiliaryKernels() const override {
return cv::gapi::kernels< cv::gimpl::onnx::Infer
, cv::gimpl::onnx::InferROI
, cv::gimpl::onnx::InferList
@@ -47,7 +47,7 @@ GAPI_PLAIDML_LOGICAL_OP(GPlaidMLOr , cv::gapi::core::GOr , |)
GAPI_PLAIDML_ARITHMETIC_OP(GPlaidMLAdd, cv::gapi::core::GAdd, +);
GAPI_PLAIDML_ARITHMETIC_OP(GPlaidMLSub, cv::gapi::core::GSub, -);
cv::gapi::GKernelPackage cv::gapi::core::plaidml::kernels()
cv::GKernelPackage cv::gapi::core::plaidml::kernels()
{
static auto pkg = cv::gapi::kernels<GPlaidMLAdd, GPlaidMLSub, GPlaidMLAnd, GPlaidMLXor, GPlaidMLOr>();
return pkg;
@@ -55,7 +55,7 @@ cv::gapi::GKernelPackage cv::gapi::core::plaidml::kernels()
#else // HAVE_PLAIDML
cv::gapi::GKernelPackage cv::gapi::core::plaidml::kernels()
cv::GKernelPackage cv::gapi::core::plaidml::kernels()
{
// Still provide this symbol to avoid linking issues
util::throw_error(std::runtime_error("G-API has been compiled without PlaidML2 support"));
@@ -128,7 +128,7 @@ static void writeBack(cv::GRunArg& arg, cv::GRunArgP& out)
case cv::GRunArg::index_of<cv::Mat>():
{
auto& rmat = *cv::util::get<cv::RMat*>(out);
rmat = cv::make_rmat<cv::gimpl::RMatAdapter>(cv::util::get<cv::Mat>(arg));
rmat = cv::make_rmat<cv::gimpl::RMatOnMat>(cv::util::get<cv::Mat>(arg));
break;
}
case cv::GRunArg::index_of<cv::Scalar>():
+22 -18
View File
@@ -128,15 +128,12 @@ GAPI_OCV_KERNEL_ST(RenderFrameOCVImpl, cv::gapi::wip::draw::GRenderFrame, Render
out = in;
auto desc = out.desc();
auto w_out = out.access(cv::MediaFrame::Access::W);
cv::Mat upsample_uv, yuv;
{
auto r_in = in.access(cv::MediaFrame::Access::R);
auto out_y = cv::Mat(desc.size, CV_8UC1, w_out.ptr[0], w_out.stride[0]);
auto out_uv = cv::Mat(desc.size / 2, CV_8UC2, w_out.ptr[1], w_out.stride[1]);
auto r_in = in.access(cv::MediaFrame::Access::R);
auto in_y = cv::Mat(desc.size, CV_8UC1, r_in.ptr[0], r_in.stride[0]);
auto in_uv = cv::Mat(desc.size / 2, CV_8UC2, r_in.ptr[1], r_in.stride[1]);
auto in_y = cv::Mat(desc.size, CV_8UC1, r_in.ptr[0], r_in.stride[0]);
auto in_uv = cv::Mat(desc.size / 2, CV_8UC2, r_in.ptr[1], r_in.stride[1]);
/* FIXME How to render correctly on NV12 format ?
*
@@ -157,19 +154,26 @@ GAPI_OCV_KERNEL_ST(RenderFrameOCVImpl, cv::gapi::wip::draw::GRenderFrame, Render
*
*/
// NV12 -> YUV
cv::Mat upsample_uv, yuv;
cv::resize(in_uv, upsample_uv, in_uv.size() * 2, cv::INTER_LINEAR);
cv::merge(std::vector<cv::Mat>{in_y, upsample_uv}, yuv);
// NV12 -> YUV
cv::resize(in_uv, upsample_uv, in_uv.size() * 2, cv::INTER_LINEAR);
cv::merge(std::vector<cv::Mat>{in_y, upsample_uv}, yuv);
}
cv::gapi::wip::draw::drawPrimitivesOCVYUV(yuv, prims, state.ftpr);
// YUV -> NV12
cv::Mat out_u, out_v, uv_plane;
std::vector<cv::Mat> chs = { out_y, out_u, out_v };
cv::split(yuv, chs);
cv::merge(std::vector<cv::Mat>{chs[1], chs[2]}, uv_plane);
cv::resize(uv_plane, out_uv, uv_plane.size() / 2, cv::INTER_LINEAR);
{
auto w_out = out.access(cv::MediaFrame::Access::W);
auto out_y = cv::Mat(desc.size, CV_8UC1, w_out.ptr[0], w_out.stride[0]);
auto out_uv = cv::Mat(desc.size / 2, CV_8UC2, w_out.ptr[1], w_out.stride[1]);
cv::Mat out_u, out_v, uv_plane;
std::vector<cv::Mat> chs = { out_y, out_u, out_v };
cv::split(yuv, chs);
cv::merge(std::vector<cv::Mat>{chs[1], chs[2]}, uv_plane);
cv::resize(uv_plane, out_uv, uv_plane.size() / 2, cv::INTER_LINEAR);
}
}
static void setup(const cv::GFrameDesc& /* in_nv12 */,
@@ -189,7 +193,7 @@ GAPI_OCV_KERNEL_ST(RenderFrameOCVImpl, cv::gapi::wip::draw::GRenderFrame, Render
};
cv::gapi::GKernelPackage cv::gapi::render::ocv::kernels()
cv::GKernelPackage cv::gapi::render::ocv::kernels()
{
const static auto pkg = cv::gapi::kernels<RenderBGROCVImpl, RenderNV12OCVImpl, RenderFrameOCVImpl>();
return pkg;
@@ -193,7 +193,7 @@ void Copy::Actor::run(cv::gimpl::GIslandExecutable::IInput &in,
out.post(std::move(out_arg));
}
cv::gapi::GKernelPackage cv::gimpl::streaming::kernels()
cv::GKernelPackage cv::gimpl::streaming::kernels()
{
return cv::gapi::kernels<Copy>();
}
@@ -279,7 +279,7 @@ void GOCVBGR::Actor::extractRMat(const cv::MediaFrame& frame, cv::RMat& rmat)
cv::Mat y_plane (desc.size, CV_8UC1, view.ptr[0], view.stride[0]);
cv::Mat uv_plane(desc.size / 2, CV_8UC2, view.ptr[1], view.stride[1]);
cv::cvtColorTwoPlane(y_plane, uv_plane, bgr, cv::COLOR_YUV2BGR_NV12);
rmat = cv::make_rmat<cv::gimpl::RMatAdapter>(bgr);
rmat = cv::make_rmat<cv::gimpl::RMatOnMat>(bgr);
break;
}
default:
@@ -327,7 +327,7 @@ void GOCVY::Actor::extractRMat(const cv::MediaFrame& frame, cv::RMat& rmat)
cv::Mat tmp_bgr(desc.size, CV_8UC3, view.ptr[0], view.stride[0]);
cv::Mat yuv;
cvtColor(tmp_bgr, yuv, cv::COLOR_BGR2YUV_I420);
rmat = cv::make_rmat<cv::gimpl::RMatAdapter>(yuv.rowRange(0, desc.size.height));
rmat = cv::make_rmat<cv::gimpl::RMatOnMat>(yuv.rowRange(0, desc.size.height));
break;
}
case cv::MediaFormat::NV12:
@@ -396,7 +396,7 @@ void GOCVUV::Actor::extractRMat(const cv::MediaFrame& frame, cv::RMat& rmat)
yuv.rowRange(start + range_h, start + range_h * 2).reshape(0, dims)
};
cv::merge(uv_planes, uv);
rmat = cv::make_rmat<cv::gimpl::RMatAdapter>(uv);
rmat = cv::make_rmat<cv::gimpl::RMatOnMat>(uv);
break;
}
case cv::MediaFormat::NV12:
@@ -414,14 +414,14 @@ void GOCVUV::Actor::extractRMat(const cv::MediaFrame& frame, cv::RMat& rmat)
}
}
cv::gapi::GKernelPackage cv::gapi::streaming::kernels()
cv::GKernelPackage cv::gapi::streaming::kernels()
{
return cv::gapi::kernels<GOCVBGR, GOCVY, GOCVUV>();
}
#else
cv::gapi::GKernelPackage cv::gapi::streaming::kernels()
cv::GKernelPackage cv::gapi::streaming::kernels()
{
// Still provide this symbol to avoid linking issues
util::throw_error(std::runtime_error("cv::gapi::streaming::kernels() isn't supported in standalone"));
@@ -15,7 +15,7 @@ namespace cv {
namespace gimpl {
namespace streaming {
cv::gapi::GKernelPackage kernels();
cv::GKernelPackage kernels();
struct GCopy final : public cv::detail::NoTag
{