}
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) {
+CV_ALWAYS_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 *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;
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;
}
}
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;
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::gapi::fluid::Buffer& out,
- cv::gapi::fluid::Buffer& scratch) {
+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;
auto inSz = in.meta().size;
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;
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)
}
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, linear::Mapper, 3>(in, out, scratch);
+ }
+ else if (depth == CV_32F && channels == 1)
{
- calcRowLinearC<uint8_t, Mapper, 3>(in, out, scratch);
+ calcRowLinear<linear32f::Mapper>(in, out, scratch);
}
- else if (channels == 4)
+ else
{
- calcRowLinearC<uint8_t, Mapper, 4>(in, out, scratch);
+ CV_Error(cv::Error::StsBadArg, "unsupported combination of type and number of channel");
}
}
};