mirror of
https://github.com/opencv/opencv.git
synced 2025-08-06 14:36:36 +08:00
Merge pull request #21678 from anna-khakimova:ak/resize_f32c1_scalar
GAPI Fluid: Resize F32C1 scalar version. * GAPI Fluid: Resize F32C1 scalar. * Final version * Applied comments
This commit is contained in:
parent
685797f403
commit
48cd2d190f
@ -43,7 +43,6 @@ namespace detail
|
||||
#define GAPI_Assert(expr) \
|
||||
{ if (!(expr)) ::detail::assert_abort(#expr, __LINE__, __FILE__, __func__); }
|
||||
|
||||
|
||||
#ifdef NDEBUG
|
||||
# define GAPI_DbgAssert(expr) GAPI_DbgAssertNoOp(expr)
|
||||
#else
|
||||
|
@ -201,7 +201,7 @@ INSTANTIATE_TEST_CASE_P(RGB2LabPerfTestFluid, RGB2LabPerfTest,
|
||||
|
||||
INSTANTIATE_TEST_CASE_P(ResizePerfTestFluid, ResizePerfTest,
|
||||
Combine(Values(Tolerance_FloatRel_IntAbs(1e-5, 1).to_compare_f()),
|
||||
Values(CV_8UC3),
|
||||
Values(CV_8UC3, CV_32FC1),
|
||||
Values(cv::INTER_LINEAR),
|
||||
Values(szSmall128, szVGA, sz720p, sz1080p),
|
||||
Values(cv::Size(64, 64),
|
||||
@ -217,7 +217,7 @@ INSTANTIATE_TEST_CASE_P(BottleneckKernelsPerfTestFluid, BottleneckKernelsConstIn
|
||||
|
||||
INSTANTIATE_TEST_CASE_P(ResizeInSimpleGraphPerfTestFluid, ResizeInSimpleGraphPerfTest,
|
||||
Combine(Values(Tolerance_FloatRel_IntAbs(1e-5, 1).to_compare_f()),
|
||||
Values(CV_8UC3),
|
||||
Values(CV_8UC3, CV_32FC1),
|
||||
Values(szSmall128, szVGA, sz720p, sz1080p),
|
||||
Values(0.5),
|
||||
Values(0.5),
|
||||
@ -225,7 +225,7 @@ INSTANTIATE_TEST_CASE_P(ResizeInSimpleGraphPerfTestFluid, ResizeInSimpleGraphPer
|
||||
|
||||
INSTANTIATE_TEST_CASE_P(ResizeFxFyPerfTestFluid, ResizeFxFyPerfTest,
|
||||
Combine(Values(Tolerance_FloatRel_IntAbs(1e-5, 1).to_compare_f()),
|
||||
Values(CV_8UC3),
|
||||
Values(CV_8UC3, CV_32FC1),
|
||||
Values(cv::INTER_LINEAR),
|
||||
Values(szSmall128, szVGA, sz720p, sz1080p),
|
||||
Values(0.5, 0.25, 2),
|
||||
|
@ -1866,10 +1866,11 @@ static inline double ratio(int inSz, int outSz) {
|
||||
}
|
||||
|
||||
template<typename T, typename Mapper, int chanNum = 1>
|
||||
static inline void initScratchLinear(const cv::GMatDesc& in,
|
||||
CV_ALWAYS_INLINE void initScratchLinear(const cv::GMatDesc& in,
|
||||
const Size& outSz,
|
||||
cv::gapi::fluid::Buffer& scratch,
|
||||
int lpi) {
|
||||
int lpi)
|
||||
{
|
||||
using alpha_type = typename Mapper::alpha_type;
|
||||
static const auto unity = Mapper::unity;
|
||||
|
||||
@ -1895,7 +1896,8 @@ static inline void initScratchLinear(const cv::GMatDesc& in,
|
||||
auto *clone = scr.clone;
|
||||
auto *index = scr.mapsx;
|
||||
|
||||
for (int x = 0; x < outSz.width; x++) {
|
||||
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;
|
||||
@ -1930,7 +1932,7 @@ static inline void initScratchLinear(const cv::GMatDesc& in,
|
||||
alpha[x] = alpha0;
|
||||
index[x] = index0;
|
||||
|
||||
for (int l = 0; l < 4; l++) {
|
||||
for (int l = 0; l < 4; ++l) {
|
||||
clone[4*x + l] = alpha0;
|
||||
}
|
||||
}
|
||||
@ -1952,10 +1954,18 @@ struct MapperUnit {
|
||||
I index0, index1;
|
||||
};
|
||||
|
||||
inline static uint8_t calc(short alpha0, uint8_t src0, short alpha1, uint8_t src1) {
|
||||
CV_ALWAYS_INLINE uint8_t resize_calc_revert_fixedpoint(short alpha0, uint8_t src0, short alpha1, uint8_t src1)
|
||||
{
|
||||
constexpr static const int half = 1 << 14;
|
||||
return (src0 * alpha0 + src1 * alpha1 + half) >> 15;
|
||||
}
|
||||
|
||||
CV_ALWAYS_INLINE float resize_main_calculation(float alpha0, float src0, float alpha1, float src1)
|
||||
{
|
||||
return src0 * alpha0 + src1 * alpha1;
|
||||
}
|
||||
|
||||
namespace linear {
|
||||
struct Mapper {
|
||||
constexpr static const int ONE = 1 << 15;
|
||||
typedef short alpha_type;
|
||||
@ -1980,9 +1990,36 @@ struct Mapper {
|
||||
return u;
|
||||
}
|
||||
};
|
||||
} // namespace linear
|
||||
|
||||
namespace linear32f {
|
||||
struct Mapper {
|
||||
typedef float alpha_type;
|
||||
typedef int index_type;
|
||||
constexpr static const float unity = 1;
|
||||
|
||||
typedef MapperUnit<float, int> 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 = std::max(s - start, 0);
|
||||
u.index1 = ((std::fabs(f) <= FLT_EPSILON) || s + 1 >= max) ? s - start : s - start + 1;
|
||||
|
||||
u.alpha0 = 1.f - f;
|
||||
u.alpha1 = f;
|
||||
|
||||
return u;
|
||||
}
|
||||
};
|
||||
} // namespace linear32f
|
||||
|
||||
template<typename T, class Mapper, int numChan>
|
||||
static void calcRowLinearC(const cv::gapi::fluid::View & in,
|
||||
CV_ALWAYS_INLINE 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;
|
||||
@ -2052,14 +2089,74 @@ static void calcRowLinearC(const cv::gapi::fluid::View & in,
|
||||
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);
|
||||
T tmp0 = resize_calc_revert_fixedpoint(beta0, src0[l][idx0], beta1, src1[l][idx0]);
|
||||
T tmp1 = resize_calc_revert_fixedpoint(beta0, src0[l][idx1], beta1, src1[l][idx1]);
|
||||
dst[l][numChan * x + c] = resize_calc_revert_fixedpoint(alpha0, tmp0, alpha1, tmp1);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
template<class Mapper>
|
||||
CV_ALWAYS_INLINE void calcRowLinear(const cv::gapi::fluid::View& in,
|
||||
cv::gapi::fluid::Buffer& out,
|
||||
cv::gapi::fluid::Buffer& scratch)
|
||||
{
|
||||
GAPI_DbgAssert((out.meta().depth == CV_32F) && (out.meta().chan == 1));
|
||||
|
||||
auto inSz = in.meta().size;
|
||||
auto outSz = out.meta().size;
|
||||
|
||||
auto inY = in.y();
|
||||
int length = out.length();
|
||||
int outY = out.y();
|
||||
int lpi = out.lpi();
|
||||
GAPI_DbgAssert(outY + lpi <= outSz.height);
|
||||
|
||||
GAPI_DbgAssert(lpi <= 4);
|
||||
|
||||
LinearScratchDesc<float, Mapper, 1> scr(inSz.width, inSz.height, outSz.width,
|
||||
outSz.height, scratch.OutLineB());
|
||||
|
||||
const auto* alpha = scr.alpha;
|
||||
const auto* mapsx = scr.mapsx;
|
||||
const auto* beta0 = scr.beta;
|
||||
const auto* mapsy = scr.mapsy;
|
||||
|
||||
const auto* beta = beta0 + outY;
|
||||
const float* src0[4];
|
||||
const float* src1[4];
|
||||
float* 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 float>(index0);
|
||||
src1[l] = in.InLine<const float>(index1);
|
||||
dst[l] = out.OutLine<float>(l);
|
||||
}
|
||||
|
||||
using alpha_type = typename Mapper::alpha_type;
|
||||
for (int l = 0; l < lpi; ++l)
|
||||
{
|
||||
constexpr static const auto unity = Mapper::unity;
|
||||
|
||||
auto b0 = beta[l];
|
||||
auto b1 = 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;
|
||||
float tmp0 = resize_main_calculation(b0, src0[l][sx0], b1, src1[l][sx0]);
|
||||
float tmp1 = resize_main_calculation(b0, src0[l][sx1], b1, src1[l][sx1]);
|
||||
dst[l][x] = resize_main_calculation(alpha0, tmp0, alpha1, tmp1);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
GAPI_FLUID_KERNEL(GFluidResize, cv::gapi::imgproc::GResize, true)
|
||||
{
|
||||
static const int Window = 1;
|
||||
@ -2071,9 +2168,12 @@ GAPI_FLUID_KERNEL(GFluidResize, cv::gapi::imgproc::GResize, true)
|
||||
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::Size outSz, double fx, double fy, int interp,
|
||||
cv::gapi::fluid::Buffer &scratch)
|
||||
{
|
||||
GAPI_Assert((in.depth == CV_8U && in.chan == 3) ||
|
||||
(in.depth == CV_32F && in.chan == 1));
|
||||
GAPI_Assert(interp == cv::INTER_LINEAR);
|
||||
int outSz_w;
|
||||
int outSz_h;
|
||||
if (outSz.width == 0 || outSz.height == 0)
|
||||
@ -2088,32 +2188,44 @@ GAPI_FLUID_KERNEL(GFluidResize, cv::gapi::imgproc::GResize, true)
|
||||
}
|
||||
cv::Size outSize(outSz_w, outSz_h);
|
||||
|
||||
if (in.chan == 3)
|
||||
if (in.depth == CV_8U && in.chan == 3)
|
||||
{
|
||||
initScratchLinear<uchar, Mapper, 3>(in, outSize, scratch, LPI);
|
||||
initScratchLinear<uchar, linear::Mapper, 3>(in, outSize, scratch, LPI);
|
||||
}
|
||||
else if (in.chan == 4)
|
||||
else if (in.depth == CV_32F && in.chan == 1)
|
||||
{
|
||||
initScratchLinear<uchar, Mapper, 4>(in, outSize, scratch, LPI);
|
||||
initScratchLinear<float, linear32f::Mapper, 1>(in, outSize, scratch, LPI);
|
||||
}
|
||||
else
|
||||
{
|
||||
CV_Error(cv::Error::StsBadArg, "unsupported combination of type and number of channel");
|
||||
}
|
||||
}
|
||||
|
||||
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) {
|
||||
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)
|
||||
{
|
||||
GAPI_Assert((in.meta().depth == CV_8U && in.meta().chan == 3) ||
|
||||
(in.meta().depth == CV_32F && in.meta().chan == 1));
|
||||
GAPI_Assert(interp == cv::INTER_LINEAR);
|
||||
const int channels = in.meta().chan;
|
||||
GAPI_Assert((channels == 3 || channels == 4) && (interp == cv::INTER_LINEAR));
|
||||
const int depth = in.meta().depth;
|
||||
|
||||
if (channels == 3)
|
||||
if (depth == CV_8U && channels == 3)
|
||||
{
|
||||
calcRowLinearC<uint8_t, Mapper, 3>(in, out, scratch);
|
||||
calcRowLinearC<uint8_t, linear::Mapper, 3>(in, out, scratch);
|
||||
}
|
||||
else if (channels == 4)
|
||||
else if (depth == CV_32F && channels == 1)
|
||||
{
|
||||
calcRowLinearC<uint8_t, Mapper, 4>(in, out, scratch);
|
||||
calcRowLinear<linear32f::Mapper>(in, out, scratch);
|
||||
}
|
||||
else
|
||||
{
|
||||
CV_Error(cv::Error::StsBadArg, "unsupported combination of type and number of channel");
|
||||
}
|
||||
}
|
||||
};
|
||||
|
Loading…
Reference in New Issue
Block a user