diff --git a/modules/imgproc/src/opencl/resize.cl b/modules/imgproc/src/opencl/resize.cl
index 67603e4f17..a28c59296e 100644
--- a/modules/imgproc/src/opencl/resize.cl
+++ b/modules/imgproc/src/opencl/resize.cl
@@ -51,8 +51,6 @@
 #endif
 #endif
 
-#define INTER_RESIZE_COEF_SCALE (1 << INTER_RESIZE_COEF_BITS)
-#define CAST_BITS (INTER_RESIZE_COEF_BITS << 1)
 #define INC(x,l) min(x+1,l-1)
 
 #define noconvert
@@ -188,7 +186,9 @@ __kernel void resizeLN(__global const uchar * srcptr, int src_step, int src_offs
         int y_ = INC(y, src_rows);
         int x_ = INC(x, src_cols);
 
-#if depth <= 4
+#if depth <= 1  // 8U/8S only, 16U+ cause integer overflows
+#define INTER_RESIZE_COEF_SCALE (1 << INTER_RESIZE_COEF_BITS)
+#define CAST_BITS (INTER_RESIZE_COEF_BITS << 1)
         u = u * INTER_RESIZE_COEF_SCALE;
         v = v * INTER_RESIZE_COEF_SCALE;
 
@@ -214,7 +214,7 @@ __kernel void resizeLN(__global const uchar * srcptr, int src_step, int src_offs
         WT data2 = convertToWT(loadpix(srcptr + mad24(y_, src_step, mad24(x, TSIZE, src_offset))));
         WT data3 = convertToWT(loadpix(srcptr + mad24(y_, src_step, mad24(x_, TSIZE, src_offset))));
 
-        T uval = u1 * v1 * data0 + u * v1 * data1 + u1 * v *data2 + u * v *data3;
+        T uval = convertToDT((u1 * v1) * data0 + (u * v1) * data1 + (u1 * v) * data2 + (u * v) * data3);
 #endif
         storepix(uval, dstptr + mad24(dy, dst_step, mad24(dx, TSIZE, dst_offset)));
     }
diff --git a/modules/imgproc/src/resize.cpp b/modules/imgproc/src/resize.cpp
index 4f1a4576ce..90a05085e3 100644
--- a/modules/imgproc/src/resize.cpp
+++ b/modules/imgproc/src/resize.cpp
@@ -3376,7 +3376,8 @@ static bool ocl_resize( InputArray _src, OutputArray _dst, Size dsize,
         }
         else
         {
-            int wdepth = std::max(depth, CV_32S), wtype = CV_MAKETYPE(wdepth, cn);
+            int wdepth = depth <= CV_8S ? CV_32S : std::max(depth, CV_32F);
+            int wtype = CV_MAKETYPE(wdepth, cn);
             k.create("resizeLN", ocl::imgproc::resize_oclsrc,
                      format("-D INTER_LINEAR -D depth=%d -D T=%s -D T1=%s "
                             "-D WT=%s -D convertToWT=%s -D convertToDT=%s -D cn=%d "
diff --git a/modules/imgproc/test/ocl/test_warp.cpp b/modules/imgproc/test/ocl/test_warp.cpp
index 15e024a140..b43c9b6732 100644
--- a/modules/imgproc/test/ocl/test_warp.cpp
+++ b/modules/imgproc/test/ocl/test_warp.cpp
@@ -327,6 +327,20 @@ OCL_TEST_P(Resize, Mat)
     }
 }
 
+OCL_TEST(Resize, overflow_21198)
+{
+    Mat src(Size(600, 600), CV_16UC3, Scalar::all(32768));
+    UMat src_u;
+    src.copyTo(src_u);
+
+    Mat dst;
+    cv::resize(src, dst, Size(1024, 1024), 0, 0, INTER_LINEAR);
+    UMat dst_u;
+    cv::resize(src_u, dst_u, Size(1024, 1024), 0, 0, INTER_LINEAR);
+    EXPECT_LE(cv::norm(dst_u, dst, NORM_INF), 1.0f);
+}
+
+
 /////////////////////////////////////////////////////////////////////////////////////////////////
 // remap