diff --git a/modules/core/src/convert.dispatch.cpp b/modules/core/src/convert.dispatch.cpp index a18d4beb85..66671804cc 100644 --- a/modules/core/src/convert.dispatch.cpp +++ b/modules/core/src/convert.dispatch.cpp @@ -140,10 +140,10 @@ void Mat::convertTo(OutputArray dst, int type_, double alpha, double beta) const const int dtype = CV_MAKETYPE(ddepth, channels()); dst.release(); - if (dims <= 2) - dst.create(size(), dtype); - else - dst.create(dims, size.p, dtype); + bool allowTransposed = dims == 1 || + dst.kind() == _InputArray::STD_VECTOR || + (dst.fixedSize() && dst.dims() == 1); + dst.create(size, dtype, -1, allowTransposed); return; } diff --git a/modules/dnn/src/layers/avgpool_layer.cpp b/modules/dnn/src/layers/avgpool_layer.cpp index 987789eb94..861baec27b 100644 --- a/modules/dnn/src/layers/avgpool_layer.cpp +++ b/modules/dnn/src/layers/avgpool_layer.cpp @@ -41,6 +41,7 @@ static void avgPool32f(const void* inp_, void* out_, int planesize = D*H*W*C0; int SZ = cs.strides[0], SY = cs.strides[1], SX = cs.strides[2]; int padZ0 = cs.pads[0], padY0 = cs.pads[1], padX0 = cs.pads[2]; + int padZ1 = cs.pads[MAX_POOL_DIMS], padY1 = cs.pads[MAX_POOL_DIMS+1], padX1 = cs.pads[MAX_POOL_DIMS+2]; int inner_z0 = cs.inner[0], inner_z1 = cs.inner[MAX_POOL_DIMS]; int inner_y0 = cs.inner[1], inner_y1 = cs.inner[MAX_POOL_DIMS + 1]; int inner_x0 = cs.inner[2], inner_x1 = cs.inner[MAX_POOL_DIMS + 2]; @@ -78,12 +79,15 @@ static void avgPool32f(const void* inp_, void* out_, for (; x0 < x1; x0++) { int xi_ = x0*SX - padX0; v_float32 s0 = z; - int nitems = 0; + int nitems = 0, npadded = 0; for (int k = 0; k < ksize; k++) { int zi = zi_ + zyxtab[k*MAX_POOL_DIMS]; int yi = yi_ + zyxtab[k*MAX_POOL_DIMS+1]; int xi = xi_ + zyxtab[k*MAX_POOL_DIMS+2]; v_float32 v0; + npadded += (zi >= -padZ0 && zi < Di + padZ1 && + yi >= -padY0 && yi < Hi + padY1 && + xi >= -padX0 && xi < Wi + padX1); if ((unsigned)zi >= (unsigned)Di || (unsigned)yi >= (unsigned)Hi || (unsigned)xi >= (unsigned)Wi) @@ -92,7 +96,7 @@ static void avgPool32f(const void* inp_, void* out_, s0 = v_add(s0, v0); nitems++; } - s0 = v_mul(s0, count_include_pad ? vscale0 : vx_setall_f32(1.f/nitems)); + s0 = v_mul(s0, vx_setall_f32(1.f/(count_include_pad ? npadded : nitems))); vx_store(out + x0*C0, s0); } } else { @@ -100,12 +104,15 @@ static void avgPool32f(const void* inp_, void* out_, int xi_ = x0*SX - padX0; for (int c = 0; c < C0; c += nlanes*2) { v_float32 s0 = z, s1 = z; - int nitems = 0; + int nitems = 0, npadded = 0; for (int k = 0; k < ksize; k++) { int zi = zi_ + zyxtab[k*MAX_POOL_DIMS]; int yi = yi_ + zyxtab[k*MAX_POOL_DIMS+1]; int xi = xi_ + zyxtab[k*MAX_POOL_DIMS+2]; v_float32 v0, v1; + npadded += (zi >= -padZ0 && zi < Di + padZ1 && + yi >= -padY0 && yi < Hi + padY1 && + xi >= -padX0 && xi < Wi + padX1); if ((unsigned)zi >= (unsigned)Di || (unsigned)yi >= (unsigned)Hi || (unsigned)xi >= (unsigned)Wi) @@ -117,7 +124,7 @@ static void avgPool32f(const void* inp_, void* out_, s1 = v_add(s1, v1); nitems++; } - v_float32 vscale = count_include_pad ? vscale0 : vx_setall_f32(1.f/nitems); + v_float32 vscale = vx_setall_f32(1.f/(count_include_pad ? npadded : nitems)); s0 = v_mul(s0, vscale); s1 = v_mul(s1, vscale); vx_store(out + x0*C0 + c, s0); @@ -128,11 +135,14 @@ static void avgPool32f(const void* inp_, void* out_, #else for (; x0 < x1; x0++) { int xi_ = x0*SX - padX0; - int nitems = 0; + int nitems = 0, npadded = 0; for (int k = 0; k < ksize; k++) { int zi = zi_ + zyxtab[k*MAX_POOL_DIMS]; int yi = yi_ + zyxtab[k*MAX_POOL_DIMS+1]; int xi = xi_ + zyxtab[k*MAX_POOL_DIMS+2]; + npadded += (zi >= -padZ0 && zi < Di + padZ1 && + yi >= -padY0 && yi < Hi + padY1 && + xi >= -padX0 && xi < Wi + padX1); if ((unsigned)zi >= (unsigned)Di || (unsigned)yi >= (unsigned)Hi || (unsigned)xi >= (unsigned)Wi) @@ -142,7 +152,7 @@ static void avgPool32f(const void* inp_, void* out_, out[x0*C0 + c] += inptr[c]; nitems++; } - float scale = count_include_pad ? iksize : 1.f/nitems; + float scale = count_include_pad ? 1.f/npadded : 1.f/nitems; for (int c = 0; c < C0; c++) out[x0*C0 + c] *= scale; } @@ -264,6 +274,7 @@ static void avgPool16xf(const _Tp* inp_, _Tp* out_, int planesize = D*H*W*C0; int SZ = cs.strides[0], SY = cs.strides[1], SX = cs.strides[2]; int padZ0 = cs.pads[0], padY0 = cs.pads[1], padX0 = cs.pads[2]; + int padZ1 = cs.pads[MAX_POOL_DIMS], padY1 = cs.pads[MAX_POOL_DIMS+1], padX1 = cs.pads[MAX_POOL_DIMS+2]; int inner_z0 = cs.inner[0], inner_z1 = cs.inner[MAX_POOL_DIMS]; int inner_y0 = cs.inner[1], inner_y1 = cs.inner[MAX_POOL_DIMS + 1]; int inner_x0 = cs.inner[2], inner_x1 = cs.inner[MAX_POOL_DIMS + 2]; diff --git a/modules/dnn/src/layers/conv2_common.cpp b/modules/dnn/src/layers/conv2_common.cpp index 6244eb618f..89d5d3b052 100644 --- a/modules/dnn/src/layers/conv2_common.cpp +++ b/modules/dnn/src/layers/conv2_common.cpp @@ -91,11 +91,16 @@ MatShape convInferShape(const MatShape& inpShape, const MatShape& wshape, int dilation = dilations.empty() ? 1 : dilations[i]; int outsz; if (autoPad == AUTO_PAD_NONE || autoPad == AUTO_PAD_VALID) { - int pad = 0; + int pad0 = 0, pad = 0; if (!pads.empty()) { + pad0 = pads[i]; pad = pads[i] + pads[i + nspatialdims]; } outsz = (inpsz + pad - 1 - dilation * (k_i - 1) + (ceilMode ? stride - 1 : 0)) / stride + 1; + // ONNX: with ceil_mode a sliding window that starts in the right/bottom + // padding region is dropped + if (ceilMode && (outsz - 1) * stride >= inpsz + pad0) + outsz--; } else { if (ceilMode) outsz = (inpsz + stride - 1)/stride; diff --git a/modules/dnn/src/layers/einsum_layer.cpp b/modules/dnn/src/layers/einsum_layer.cpp index a1aac9ceb3..de26131b09 100644 --- a/modules/dnn/src/layers/einsum_layer.cpp +++ b/modules/dnn/src/layers/einsum_layer.cpp @@ -682,14 +682,15 @@ void LayerEinsumImpl::preProcessInputs(InputArrayOfArrays& inputs_arr) // variable to hold processed version of the original input MatShape input_dims = shape(input); - if (input_dims.empty()){ + const auto& currSubscriptIndices = inputSubscriptIndices[inputIter]; + + if (input_dims.empty() || currSubscriptIndices.empty()){ + CV_CheckEQ(total(input_dims), (size_t)1, "Einsum: input with no subscript labels must be a scalar"); homogenizedInputDims[inputIter] = MatShape(numLetterIndices, 1); ++inputIter; continue; } - const auto& currSubscriptIndices = inputSubscriptIndices[inputIter]; - // There should be subscript index (subscript label) for each dim of the input CV_CheckEQ(input_dims.size(), currSubscriptIndices.size(), "Rank of the input must match number of subscript labels corresponding to the input"); diff --git a/modules/dnn/src/layers/resize2_layer.cpp b/modules/dnn/src/layers/resize2_layer.cpp index 2f85b391f4..69834f9c11 100644 --- a/modules/dnn/src/layers/resize2_layer.cpp +++ b/modules/dnn/src/layers/resize2_layer.cpp @@ -34,6 +34,7 @@ enum class CoordTransMode { PYTORCH_HALF_PIXEL, TF_HALF_PIXEL_FOR_NN, TF_CROP_AND_RESIZE, + HALF_PIXEL_SYMMETRIC, ASYMMETRIC }; @@ -43,6 +44,7 @@ static inline CoordTransMode parseCoordTransMode(const String& s) if (s == "pytorch_half_pixel") return CoordTransMode::PYTORCH_HALF_PIXEL; if (s == "tf_half_pixel_for_nn") return CoordTransMode::TF_HALF_PIXEL_FOR_NN; if (s == "tf_crop_and_resize") return CoordTransMode::TF_CROP_AND_RESIZE; + if (s == "half_pixel_symmetric") return CoordTransMode::HALF_PIXEL_SYMMETRIC; return CoordTransMode::ASYMMETRIC; } @@ -90,6 +92,13 @@ inline float computeSrcGeneric(int dst, float scale, int limit, int len, return (dst + 0.5f)*scale - 0.5f; if (coordTransMode == CoordTransMode::TF_HALF_PIXEL_FOR_NN) return (dst + 0.5f)*scale; + if (coordTransMode == CoordTransMode::HALF_PIXEL_SYMMETRIC) + { + // ONNX half_pixel_symmetric: offset = center*(1 - len_resized/(len_orig*x_scale)), + // with scale == 1/x_scale and limit == input length. + const float offset = limit*0.5f - len*scale*0.5f; + return offset + (dst + 0.5f)*scale - 0.5f; + } return dst*scale; } @@ -122,7 +131,7 @@ static inline void buildNearestIndexMap(std::vector& map, map.resize(outLen); for (int i = 0; i < outLen; ++i) { - float src = computeSrcGeneric(i, scale, inLen - 1, len, + float src = computeSrcGeneric(i, scale, inLen, len, coordTransMode, halfPixelCenters, start_coord, end_coord); if (coordTransMode == CoordTransMode::TF_CROP_AND_RESIZE) { if (src < 0.f || src >= float(inLen)) { @@ -175,9 +184,9 @@ static inline void buildBilinearIndexAndLerp(std::vector& i0, } else { - src = std::min(std::max(src, 0.f), float(inLen - 1) - 1e-6f); + src = std::min(std::max(src, 0.f), std::max(0.f, float(inLen - 1) - 1e-6f)); int base = int(std::floor(src)); - i0[o] = base; + i0[o] = clamp(base, 0, inLen - 1); i1[o] = clamp(base + 1, 0, inLen - 1); frac[o] = src - float(base); } @@ -773,6 +782,119 @@ void resizeCubic(const Mat &inp, Mat &out, } }, nstripes); } + +// ---- ONNX antialias (PIL-style) resampling ---------------------------------- +static inline float aaTriangle(float x) +{ + x = std::abs(x); + return x < 1.f ? 1.f - x : 0.f; +} + +static inline float aaCubic(float x, float a) +{ + x = std::abs(x); + if (x < 1.f) return ((a + 2.f)*x - (a + 3.f))*x*x + 1.f; + if (x < 2.f) return a*(((x - 5.f)*x + 8.f)*x - 4.f); + return 0.f; +} + +// Per-output filter taps for one axis. After clamping out-of-bound samples to +// the edge (exclude_outside == false), the contributing indices are contiguous, +// so each output stores a start index 'lo', a 'cnt' and an offset into 'w'. +struct AAWeights +{ + std::vector lo, cnt, ofs; + std::vector w; +}; + +static void buildAAWeights(AAWeights& p, int inS, int outS, float xscale, + bool cubic, float cubicA, CoordTransMode coordMode) +{ + const float scaleC = 1.f / xscale; // input/output direction + const float radius = cubic ? 2.f : 1.f; + const float support = scaleC >= 1.f ? radius*scaleC : radius; + const float inv = scaleC >= 1.f ? 1.f/scaleC : 1.f; + + p.lo.resize(outS); p.cnt.resize(outS); p.ofs.resize(outS); + p.w.clear(); + std::vector tmp; + for (int y = 0; y < outS; y++) + { + const float center = computeSrcGeneric(y, scaleC, inS, outS, coordMode, true); + const int xmin = (int)std::floor(center - support + 0.5f); + const int xmax = (int)std::floor(center + support + 0.5f); // inclusive + const int lo = std::min(std::max(xmin, 0), inS - 1); + const int hi = std::min(std::max(xmax, 0), inS - 1); + const int cnt = hi - lo + 1; + tmp.assign(cnt, 0.f); + float tot = 0.f; + for (int x = xmin; x <= xmax; x++) + { + const float wt = cubic ? aaCubic((x - center)*inv, cubicA) + : aaTriangle((x - center)*inv); + const int idx = std::min(std::max(x, 0), inS - 1); + tmp[idx - lo] += wt; + tot += wt; + } + p.lo[y] = lo; p.cnt[y] = cnt; p.ofs[y] = (int)p.w.size(); + for (int k = 0; k < cnt; k++) + p.w.push_back(tot != 0.f ? tmp[k] / tot : 0.f); + } +} + +template +void resizeAntialias(const Mat& inp, Mat& out, + float xscaleH, float xscaleW, + bool cubic, float cubicA, CoordTransMode coordMode) +{ + CV_Assert(inp.dims == 4 && out.dims == 4 && inp.isContinuous() && out.isContinuous()); + const int N = inp.size[0], C = inp.size[1]; + const int inH = inp.size[2], inW = inp.size[3]; + const int outH = out.size[2], outW = out.size[3]; + + AAWeights px, py; + buildAAWeights(px, inW, outW, xscaleW, cubic, cubicA, coordMode); + buildAAWeights(py, inH, outH, xscaleH, cubic, cubicA, coordMode); + + const int planes = N * C; + parallel_for_(Range(0, planes), [&](const Range& r) { + std::vector buf((size_t)inH * outW); + for (int pl = r.start; pl < r.end; pl++) + { + const T* inPlane = inp.ptr(0) + (size_t)pl * inH * inW; + T* outPlane = out.ptr(0) + (size_t)pl * outH * outW; + // Horizontal pass: inp[inH x inW] -> buf[inH x outW]. + for (int y = 0; y < inH; y++) + { + const T* inRow = inPlane + (size_t)y * inW; + float* bufRow = buf.data() + (size_t)y * outW; + for (int ox = 0; ox < outW; ox++) + { + const float* w = px.w.data() + px.ofs[ox]; + const int lo = px.lo[ox], cnt = px.cnt[ox]; + float acc = 0.f; + for (int k = 0; k < cnt; k++) + acc += w[k] * (float)inRow[lo + k]; + bufRow[ox] = acc; + } + } + // Vertical pass: buf[inH x outW] -> out[outH x outW]. + for (int oy = 0; oy < outH; oy++) + { + const float* w = py.w.data() + py.ofs[oy]; + const int lo = py.lo[oy], cnt = py.cnt[oy]; + T* outRow = outPlane + (size_t)oy * outW; + for (int ox = 0; ox < outW; ox++) + { + float acc = 0.f; + for (int k = 0; k < cnt; k++) + acc += w[k] * buf[(size_t)(lo + k) * outW + ox]; + outRow[ox] = saturate_cast(acc); + } + } + } + }); +} } class Resize2LayerImpl : public Resize2Layer @@ -811,6 +933,33 @@ public: if (interpolation == "opencv_linear") halfPixelCenters = true; + + keepAspectPolicy = params.get("keep_aspect_ratio_policy", "stretch"); + antialias = params.get("antialias", 0) != 0; + if (params.has("axes")) { + const DictValue& a = params.get("axes"); + axesAttr.resize(a.size()); + for (int i = 0; i < a.size(); i++) + axesAttr[i] = a.get(i); + } + } + + // Map the H (axis 2) and W (axis 3) entries within a 2- or 4-element + // sizes/scales vector, honoring the ONNX "axes" attribute order. + void spatialIndices(size_t nelems, int& hIdx, int& wIdx) const + { + if (nelems == 4) { hIdx = 2; wIdx = 3; } + else { hIdx = 0; wIdx = 1; } + + if (axesAttr.size() == nelems) { + int foundH = -1, foundW = -1; + for (size_t k = 0; k < nelems; k++) { + int ax = axesAttr[k] < 0 ? axesAttr[k] + 4 : axesAttr[k]; + if (ax == 2) foundH = (int)k; + else if (ax == 3) foundW = (int)k; + } + if (foundH >= 0 && foundW >= 0) { hIdx = foundH; wIdx = foundW; } + } } bool dynamicOutputShapes() const CV_OVERRIDE @@ -868,22 +1017,26 @@ public: : (sizes.size() == 4 || sizes.size() == 2))); MatShape outShape = inpShape; + const int inH = inpShape[2], inW = inpShape[3]; if (!sizes.empty()) { - if (sizes.size() == 4) { - outShape[2] = sizes[2]; - outShape[3] = sizes[3]; - } else /* sizes.size() == 2 */ { - outShape[2] = sizes[0]; - outShape[3] = sizes[1]; + int hIdx, wIdx; + spatialIndices(sizes.size(), hIdx, wIdx); + int szH = sizes[hIdx], szW = sizes[wIdx]; + if (keepAspectPolicy == "not_larger" || keepAspectPolicy == "not_smaller") { + float scH = float(szH) / inH, scW = float(szW) / inW; + float sc = keepAspectPolicy == "not_larger" ? std::min(scH, scW) + : std::max(scH, scW); + outShape[2] = int(std::round(sc * inH)); + outShape[3] = int(std::round(sc * inW)); + } else { + outShape[2] = szH; + outShape[3] = szW; } } else { - if (scales.size() == 4) { - outShape[2] = cvFloor(inpShape[2] * scales[2]); - outShape[3] = cvFloor(inpShape[3] * scales[3]); - } else /* scales.size() == 2 */ { - outShape[2] = cvFloor(inpShape[2] * scales[0]); - outShape[3] = cvFloor(inpShape[3] * scales[1]); - } + int hIdx, wIdx; + spatialIndices(scales.size(), hIdx, wIdx); + outShape[2] = cvFloor(inH * scales[hIdx]); + outShape[3] = cvFloor(inW * scales[wIdx]); } return outShape; } @@ -1016,7 +1169,20 @@ public: Mat roiTensor = inputs[1]; std::vector roi; tensorToFloatVec(roiTensor, roi); - if (roi.size() >= 4) + if (axesAttr.size() == 2 && roi.size() == 4) + { + // ROI given per "axes": [start_axes[0], start_axes[1], end_axes[0], end_axes[1]] + float start[4] = {0.f, 0.f, 0.f, 0.f}; + float end[4] = {1.f, 1.f, 1.f, 1.f}; + for (int k = 0; k < 2; k++) { + int ax = axesAttr[k] < 0 ? axesAttr[k] + 4 : axesAttr[k]; + start[ax] = roi[k]; + end[ax] = roi[2 + k]; + } + roi_start_y = start[2]; roi_start_x = start[3]; + roi_end_y = end[2]; roi_end_x = end[3]; + } + else if (roi.size() >= 4) { if (roi.size() == 4) { roi_start_y = roi[0]; @@ -1039,10 +1205,19 @@ public: if (sizes.empty() && !scales.empty() && halfPixelCenters) { - float sH = (scales.size() == 4) ? scales[2] : scales[0]; - float sW = (scales.size() == 4) ? scales[3] : scales[1]; - scaleHeight = 1.f / sH; - scaleWidth = 1.f / sW; + int hIdx, wIdx; + spatialIndices(scales.size(), hIdx, wIdx); + scaleHeight = 1.f / scales[hIdx]; + scaleWidth = 1.f / scales[wIdx]; + } + else if (sizes.empty() && !scales.empty() && alignCorners) + { + int hIdx, wIdx; + spatialIndices(scales.size(), hIdx, wIdx); + float lenH = inpShape[2] * scales[hIdx]; + float lenW = inpShape[3] * scales[wIdx]; + if (lenH > 1.f) scaleHeight = float(inpShape[2] - 1) / (lenH - 1.f); + if (lenW > 1.f) scaleWidth = float(inpShape[3] - 1) / (lenW - 1.f); } auto kind = outputs_arr.kind(); @@ -1084,7 +1259,29 @@ public: out = out_; } - if(interpolation=="nearest"){ + if (antialias && inp.dims == 4 && + (interpolation == "bilinear" || interpolation == "opencv_linear" || interpolation == "cubic")) + { + const bool cubic = (interpolation == "cubic"); + float xsH, xsW; + if (!scales.empty()) { + int hIdx, wIdx; + spatialIndices(scales.size(), hIdx, wIdx); + xsH = scales[hIdx]; xsW = scales[wIdx]; + } else { + xsH = float(outShape[2]) / inpShape[2]; + xsW = float(outShape[3]) / inpShape[3]; + } + switch (depth) { + case CV_8S: resizeAntialias(inp, out, xsH, xsW, cubic, cubicCoeffA, coordTransModeE); break; + case CV_8U: resizeAntialias(inp, out, xsH, xsW, cubic, cubicCoeffA, coordTransModeE); break; + case CV_16F: resizeAntialias(inp, out, xsH, xsW, cubic, cubicCoeffA, coordTransModeE); break; + case CV_16BF: resizeAntialias(inp, out, xsH, xsW, cubic, cubicCoeffA, coordTransModeE); break; + case CV_32F: resizeAntialias(inp, out, xsH, xsW, cubic, cubicCoeffA, coordTransModeE); break; + default: CV_Error(Error::StsUnsupportedFormat, "Unsupported depth"); + } + } + else if(interpolation=="nearest"){ switch(depth){ case CV_8S: resizeNearest(inp,out,scaleHeight,scaleWidth,length_resized_y,length_resized_x,nearestModeE,coordTransMode,halfPixelCenters,roi_start_y,roi_end_y,roi_start_x,roi_end_x,extrapolation_value); @@ -1311,6 +1508,9 @@ protected: float cubicCoeffA; float roi_start_y, roi_end_y, roi_start_x, roi_end_x; float extrapolation_value; // Extrapolation value for tf_crop_and_resize mode + std::vector axesAttr; // ONNX "axes" attribute (subset of dims that sizes/scales refer to) + String keepAspectPolicy; // ONNX "keep_aspect_ratio_policy": stretch|not_larger|not_smaller + bool antialias; // ONNX "antialias" attribute (filter stretching when downsampling) }; Ptr Resize2Layer::create(const LayerParams& params) diff --git a/modules/dnn/src/onnx/onnx_importer2.cpp b/modules/dnn/src/onnx/onnx_importer2.cpp index 7920d6ae51..dff54be46b 100644 --- a/modules/dnn/src/onnx/onnx_importer2.cpp +++ b/modules/dnn/src/onnx/onnx_importer2.cpp @@ -1740,7 +1740,7 @@ void ONNXImporter2::parseResize2(LayerParams& layerParams, const opencv_onnx::No layerParams.type = "Resize2"; String interp_mode = layerParams.get("coordinate_transformation_mode", "half_pixel"); - bool halfPixel = interp_mode == "tf_half_pixel_for_nn" || interp_mode == "half_pixel" || interp_mode == "pytorch_half_pixel"; + bool halfPixel = interp_mode == "tf_half_pixel_for_nn" || interp_mode == "half_pixel" || interp_mode == "pytorch_half_pixel" || interp_mode == "half_pixel_symmetric"; layerParams.set("align_corners", interp_mode == "align_corners"); layerParams.set("half_pixel_centers", halfPixel); diff --git a/modules/dnn/test/test_onnx_conformance.cpp b/modules/dnn/test/test_onnx_conformance.cpp index 8fd844a08a..07bd09f7ee 100644 --- a/modules/dnn/test/test_onnx_conformance.cpp +++ b/modules/dnn/test/test_onnx_conformance.cpp @@ -1897,6 +1897,12 @@ TEST_P(Test_ONNX_conformance, Layer_Test) name == "test_reduce_sum_square_default_axes_keepdims_random_expanded") { default_l1 = 2e-5; // Expected: (normL1) <= (l1), actual: 1.52588e-05 vs 1e-05 } + if (name == "test_nllloss_NCd1d2_reduction_sum_expanded") { + default_l1 = 2e-5; // Expected: (normL1) <= (l1), actual: 1.14441e-05 vs 1e-05 + } + if (name == "test_nllloss_NCd1d2d3d4d5_mean_weight_expanded") { + default_l1 = 2e-5; // Expected: (normL1) <= (l1), actual: 1.06394e-05 vs 1e-05 + } } #ifdef HAVE_HALIDE else if (backend == DNN_BACKEND_HALIDE) diff --git a/modules/dnn/test/test_onnx_conformance_layer_filter__openvino.inl.hpp b/modules/dnn/test/test_onnx_conformance_layer_filter__openvino.inl.hpp index a01a75d26a..61c64488bd 100644 --- a/modules/dnn/test/test_onnx_conformance_layer_filter__openvino.inl.hpp +++ b/modules/dnn/test/test_onnx_conformance_layer_filter__openvino.inl.hpp @@ -217,6 +217,10 @@ CASE(test_averagepool_1d_default) // no filter CASE(test_averagepool_2d_ceil) // no filter +CASE(test_averagepool_2d_ceil_last_window_starts_on_pad) + SKIP; +CASE(test_averagepool_2d_dilations) + SKIP; CASE(test_averagepool_2d_default) // no filter CASE(test_averagepool_2d_pads) @@ -250,6 +254,16 @@ CASE(test_averagepool_2d_strides) // no filter CASE(test_averagepool_3d_default) // no filter +CASE(test_averagepool_3d_dilations_large_count_include_pad_is_0_ceil_mode_is_False) + SKIP; +CASE(test_averagepool_3d_dilations_large_count_include_pad_is_0_ceil_mode_is_True) + SKIP; +CASE(test_averagepool_3d_dilations_large_count_include_pad_is_1_ceil_mode_is_False) + SKIP; +CASE(test_averagepool_3d_dilations_large_count_include_pad_is_1_ceil_mode_is_True) + SKIP; +CASE(test_averagepool_3d_dilations_small) + SKIP; CASE(test_basic_conv_with_padding) #if SKIP_SET_1 SKIP_MYRIAD; @@ -513,7 +527,7 @@ CASE(test_constant_pad) CASE(test_constantofshape_float_ones) SKIP; CASE(test_constantofshape_int_shape_zero) - // no filter + SKIP; CASE(test_constantofshape_int_zeros) SKIP; CASE(test_conv_with_autopad_same) @@ -677,11 +691,13 @@ CASE(test_einsum_batch_diagonal) CASE(test_einsum_batch_matmul) // no filter CASE(test_einsum_inner_prod) - // no filter + SKIP; CASE(test_einsum_sum) // no filter CASE(test_einsum_transpose) // no filter +CASE(test_einsum_scalar) + SKIP; CASE(test_elu) // no filter CASE(test_elu_default) @@ -1204,6 +1220,14 @@ CASE(test_isnan) SKIP; CASE(test_isnan_float16) SKIP; +CASE(test_l1normalization_axis_0) + SKIP; +CASE(test_l1normalization_axis_1) + SKIP; +CASE(test_l1normalization_axis_last) + SKIP; +CASE(test_l2normalization_axis_1) + SKIP; CASE(test_layer_normalization_2d_axis0) SKIP; CASE(test_layer_normalization_2d_axis0_expanded) @@ -2258,15 +2282,23 @@ CASE(test_resize_downsample_scales_cubic) CASE(test_resize_downsample_scales_cubic_A_n0p5_exclude_outside) SKIP; CASE(test_resize_downsample_scales_cubic_align_corners) - // no filter + SKIP; +CASE(test_resize_downsample_scales_cubic_antialias) + SKIP; CASE(test_resize_downsample_scales_linear) SKIP; CASE(test_resize_downsample_scales_linear_align_corners) - // no filter + SKIP; +CASE(test_resize_downsample_scales_linear_antialias) + SKIP; CASE(test_resize_downsample_scales_nearest) SKIP; CASE(test_resize_downsample_sizes_cubic) SKIP; +CASE(test_resize_downsample_sizes_cubic_antialias) + SKIP; +CASE(test_resize_downsample_scales_linear_half_pixel_symmetric) + SKIP; CASE(test_resize_downsample_sizes_linear_pytorch_half_pixel) SKIP; CASE(test_resize_downsample_sizes_nearest) @@ -2275,6 +2307,12 @@ CASE(test_resize_downsample_sizes_nearest_tf_half_pixel_for_nn) SKIP; CASE(test_resize_tf_crop_and_resize) SKIP; +CASE(test_resize_tf_crop_and_resize_axes_2_3) + SKIP; +CASE(test_resize_tf_crop_and_resize_axes_3_2) + SKIP; +CASE(test_resize_tf_crop_and_resize_extrapolation_value) + SKIP; CASE(test_resize_upsample_scales_cubic) SKIP; CASE(test_resize_upsample_scales_cubic_A_n0p5_exclude_outside) @@ -2283,8 +2321,24 @@ CASE(test_resize_upsample_scales_cubic_align_corners) SKIP; CASE(test_resize_upsample_scales_cubic_asymmetric) SKIP; +CASE(test_resize_upsample_scales_linear_half_pixel_symmetric) + SKIP; +CASE(test_resize_upsample_scales_nearest_axes_3_2) + SKIP; +CASE(test_resize_upsample_sizes_nearest_axes_3_2) + SKIP; +CASE(test_resize_upsample_sizes_nearest_not_larger) + SKIP; +CASE(test_resize_upsample_sizes_nearest_not_smaller) + SKIP; CASE(test_resize_upsample_scales_linear) SKIP; +CASE(test_resize_downsample_sizes_linear_antialias) + SKIP; +CASE(test_resize_downsample_sizes_nearest_not_larger) + SKIP; +CASE(test_resize_downsample_sizes_nearest_not_smaller) + SKIP; CASE(test_resize_upsample_scales_linear_align_corners) SKIP; CASE(test_resize_upsample_scales_nearest) @@ -2317,6 +2371,44 @@ CASE(test_roialign_mode_max) SKIP; CASE(test_round) // no filter +CASE(test_rms_normalization_2d_axis0_expanded) + SKIP; +CASE(test_rms_normalization_2d_axis1_expanded) + SKIP; +CASE(test_rms_normalization_2d_axis_negative_1_expanded) + SKIP; +CASE(test_rms_normalization_2d_axis_negative_2_expanded) + SKIP; +CASE(test_rms_normalization_3d_axis0_epsilon_expanded) + SKIP; +CASE(test_rms_normalization_3d_axis1_epsilon_expanded) + SKIP; +CASE(test_rms_normalization_3d_axis2_epsilon_expanded) + SKIP; +CASE(test_rms_normalization_3d_axis_negative_1_epsilon_expanded) + SKIP; +CASE(test_rms_normalization_3d_axis_negative_2_epsilon_expanded) + SKIP; +CASE(test_rms_normalization_3d_axis_negative_3_epsilon_expanded) + SKIP; +CASE(test_rms_normalization_4d_axis0_expanded) + SKIP; +CASE(test_rms_normalization_4d_axis1_expanded) + SKIP; +CASE(test_rms_normalization_4d_axis2_expanded) + SKIP; +CASE(test_rms_normalization_4d_axis3_expanded) + SKIP; +CASE(test_rms_normalization_4d_axis_negative_1_expanded) + SKIP; +CASE(test_rms_normalization_4d_axis_negative_2_expanded) + SKIP; +CASE(test_rms_normalization_4d_axis_negative_3_expanded) + SKIP; +CASE(test_rms_normalization_4d_axis_negative_4_expanded) + SKIP; +CASE(test_rms_normalization_default_axis_expanded) + SKIP; CASE(test_scan9_sum) // no filter CASE(test_scan_sum) @@ -2643,6 +2735,24 @@ CASE(test_spacetodepth) // no filter CASE(test_spacetodepth_example) // no filter +CASE(test_split_1d_uneven_split_opset18) + SKIP; +CASE(test_split_2d_uneven_split_opset18) + SKIP; +CASE(test_split_equal_parts_1d_opset13) + SKIP; +CASE(test_split_equal_parts_1d_opset18) + SKIP; +CASE(test_split_equal_parts_default_axis_opset13) + SKIP; +CASE(test_split_equal_parts_default_axis_opset18) + SKIP; +CASE(test_split_zero_size_splits) + SKIP; +CASE(test_split_zero_size_splits_opset13) + SKIP; +CASE(test_split_zero_size_splits_opset18) + SKIP; CASE(test_split_equal_parts_1d) SKIP; CASE(test_split_equal_parts_2d) @@ -2721,6 +2831,8 @@ CASE(test_sum_two_inputs) // no filter CASE(test_swish) SKIP; +CASE(test_swish_expanded) + SKIP; CASE(test_tan) // no filter CASE(test_tan_example) @@ -2816,7 +2928,7 @@ CASE(test_tril_square) CASE(test_tril_square_neg) SKIP; CASE(test_tril_zero) - // no filter + SKIP; CASE(test_triu) SKIP; CASE(test_triu_neg) @@ -2834,7 +2946,7 @@ CASE(test_triu_square) CASE(test_triu_square_neg) SKIP; CASE(test_triu_zero) - // no filter + SKIP; CASE(test_unique_not_sorted_without_axis) SKIP; CASE(test_unique_sorted_with_axis) diff --git a/modules/dnn/test/test_onnx_conformance_layer_filter_opencv_classic_denylist.inl.hpp b/modules/dnn/test/test_onnx_conformance_layer_filter_opencv_classic_denylist.inl.hpp index e06c00881a..e6ea1668dc 100644 --- a/modules/dnn/test/test_onnx_conformance_layer_filter_opencv_classic_denylist.inl.hpp +++ b/modules/dnn/test/test_onnx_conformance_layer_filter_opencv_classic_denylist.inl.hpp @@ -271,8 +271,8 @@ "test_top_k_same_values_2d", "test_top_k_same_values_largest", "test_top_k_uint64", -"test_training_dropout_zero_ratio", // ---- same as above --- -"test_wrap_pad", // type mismatch +"test_training_dropout_zero_ratio", +"test_wrap_pad", "test_div_int16", "test_div_uint8", "test_div_int8", @@ -756,3 +756,67 @@ "test_maxpool_3d_dilations", "test_maxpool_3d_dilations_use_ref_impl", "test_maxpool_3d_dilations_use_ref_impl_large", +"test_einsum_inner_prod", +"test_einsum_scalar", +"test_averagepool_2d_ceil_last_window_starts_on_pad", +"test_averagepool_2d_dilations", +"test_averagepool_3d_dilations_large_count_include_pad_is_0_ceil_mode_is_False", +"test_averagepool_3d_dilations_large_count_include_pad_is_0_ceil_mode_is_True", +"test_averagepool_3d_dilations_large_count_include_pad_is_1_ceil_mode_is_False", +"test_averagepool_3d_dilations_large_count_include_pad_is_1_ceil_mode_is_True", +"test_averagepool_3d_dilations_small", +"test_constantofshape_int_shape_zero", +"test_l1normalization_axis_0", +"test_l1normalization_axis_1", +"test_l1normalization_axis_last", +"test_l2normalization_axis_1", +"test_nllloss_NCd1d2d3d4d5_mean_weight_expanded", +"test_nllloss_NCd1d2_reduction_sum_expanded", +"test_rms_normalization_2d_axis0_expanded", +"test_rms_normalization_2d_axis1_expanded", +"test_rms_normalization_2d_axis_negative_1_expanded", +"test_rms_normalization_2d_axis_negative_2_expanded", +"test_rms_normalization_3d_axis0_epsilon_expanded", +"test_rms_normalization_3d_axis1_epsilon_expanded", +"test_rms_normalization_3d_axis2_epsilon_expanded", +"test_rms_normalization_3d_axis_negative_1_epsilon_expanded", +"test_rms_normalization_3d_axis_negative_2_epsilon_expanded", +"test_rms_normalization_3d_axis_negative_3_epsilon_expanded", +"test_rms_normalization_4d_axis0_expanded", +"test_rms_normalization_4d_axis1_expanded", +"test_rms_normalization_4d_axis2_expanded", +"test_rms_normalization_4d_axis3_expanded", +"test_rms_normalization_4d_axis_negative_1_expanded", +"test_rms_normalization_4d_axis_negative_2_expanded", +"test_rms_normalization_4d_axis_negative_3_expanded", +"test_rms_normalization_4d_axis_negative_4_expanded", +"test_rms_normalization_default_axis_expanded", +"test_split_1d_uneven_split_opset18", +"test_split_2d_uneven_split_opset18", +"test_split_equal_parts_1d_opset13", +"test_split_equal_parts_1d_opset18", +"test_split_equal_parts_default_axis_opset13", +"test_split_equal_parts_default_axis_opset18", +"test_split_zero_size_splits", +"test_split_zero_size_splits_opset13", +"test_split_zero_size_splits_opset18", +"test_swish_expanded", +"test_tril_zero", +"test_triu_zero", +"test_resize_downsample_scales_cubic_align_corners", +"test_resize_downsample_scales_cubic_antialias", +"test_resize_downsample_scales_linear_align_corners", +"test_resize_downsample_scales_linear_antialias", +"test_resize_downsample_scales_linear_half_pixel_symmetric", +"test_resize_downsample_sizes_cubic_antialias", +"test_resize_downsample_sizes_linear_antialias", +"test_resize_downsample_sizes_nearest_not_larger", +"test_resize_downsample_sizes_nearest_not_smaller", +"test_resize_tf_crop_and_resize_axes_2_3", +"test_resize_tf_crop_and_resize_axes_3_2", +"test_resize_tf_crop_and_resize_extrapolation_value", +"test_resize_upsample_scales_linear_half_pixel_symmetric", +"test_resize_upsample_scales_nearest_axes_3_2", +"test_resize_upsample_sizes_nearest_axes_3_2", +"test_resize_upsample_sizes_nearest_not_larger", +"test_resize_upsample_sizes_nearest_not_smaller", diff --git a/modules/dnn/test/test_onnx_conformance_layer_parser_denylist.inl.hpp b/modules/dnn/test/test_onnx_conformance_layer_parser_denylist.inl.hpp index 75d6133672..529ee8d146 100644 --- a/modules/dnn/test/test_onnx_conformance_layer_parser_denylist.inl.hpp +++ b/modules/dnn/test/test_onnx_conformance_layer_parser_denylist.inl.hpp @@ -114,13 +114,6 @@ "test_attention_4d_with_qk_matmul_softcap_expanded", "test_attention_4d_with_qk_matmul_softmax", "test_attention_4d_with_qk_matmul_softmax_expanded", -"test_averagepool_2d_ceil_last_window_starts_on_pad", -"test_averagepool_2d_dilations", -"test_averagepool_3d_dilations_large_count_include_pad_is_0_ceil_mode_is_False", -"test_averagepool_3d_dilations_large_count_include_pad_is_0_ceil_mode_is_True", -"test_averagepool_3d_dilations_large_count_include_pad_is_1_ceil_mode_is_False", -"test_averagepool_3d_dilations_large_count_include_pad_is_1_ceil_mode_is_True", -"test_averagepool_3d_dilations_small", "test_basic_convinteger", // Issues::Layer::Can't create layer "onnx_node_output_0!y" of type "ConvInteger" in function 'getLayerInstance' "test_basic_deform_conv_with_padding", "test_basic_deform_conv_without_padding", @@ -266,7 +259,6 @@ "test_compress_negative_axis", // ---- same as above --- "test_constant_pad_axes", //type mismatch "test_constant_pad_negative_axes", -"test_constantofshape_int_shape_zero", // Issue::Parser::Weights are required as inputs "test_convinteger_with_padding", // Issues::Layer::Can't create layer "onnx_node_output_0!y" of type "ConvInteger" in function 'getLayerInstance' "test_convinteger_without_padding", //Issues::Layer::Can't create layer "onnx_node_output_0!y" of type "ConvInteger" in function 'getLayerInstance' "test_convtranspose_autopad_same", @@ -290,8 +282,6 @@ "test_dynamicquantizelinear_max_adjusted_expanded", // ---- same as above --- "test_dynamicquantizelinear_min_adjusted", // ---- same as above --- "test_dynamicquantizelinear_min_adjusted_expanded", // ---- same as above --- -"test_einsum_inner_prod", // Issue::Output shape does not match with reference -"test_einsum_scalar", "test_equal_string", "test_equal_string_broadcast", "test_gridsample_bicubic", // ---- same as above --- @@ -312,11 +302,7 @@ "test_image_decoder_decode_pnm_rgb", "test_image_decoder_decode_tiff_rgb", "test_image_decoder_decode_webp_rgb", -"test_l1normalization_axis_0", -"test_l1normalization_axis_1", -"test_l1normalization_axis_last", -"test_l2normalization_axis_0", -"test_l2normalization_axis_1", +"test_l2normalization_axis_0", //nan "test_loop13_seq", // Loop with tensor sequences output, not yet supported in OpenCV "test_loop16_seq_none", // Loop with optional tensor sequences, not yet supported in OpenCV "test_lppool_1d_default", @@ -336,8 +322,6 @@ "test_mvn_expanded", // Issues::Wrong answer "test_mvn_expanded_ver18", "test_nesterov_momentum", // Issues::Layer does not exist (NesterovsAcceleratedGradient) Can't create layer "onnx_node_output_0!X_new" of type "ai.onnx.preview.training.Momentum" in function 'getLayerInstance' -"test_nllloss_NCd1d2_reduction_sum_expanded", -"test_nllloss_NCd1d2d3d4d5_mean_weight_expanded", "test_optional_get_element", // Issue::out of memory :: Failed to allocate 1044051907127083008 bytes in function 'OutOfMemoryError' "test_optional_get_element_optional_sequence", "test_optional_get_element_optional_tensor", @@ -377,44 +361,8 @@ "test_regex_full_match_email_domain", "test_regex_full_match_empty", "test_reshape_allowzero_reordered", // incompatible type of input tensor #0 'data': CV_8UC1 given, CV_32FC1 expected in function 'setGraphInput' -"test_resize_downsample_scales_cubic_align_corners", // ---- same as above --- -"test_resize_downsample_scales_cubic_antialias", -"test_resize_downsample_scales_linear_align_corners", // ---- same as above --- -"test_resize_downsample_scales_linear_antialias", //incorrect output -"test_resize_downsample_scales_linear_half_pixel_symmetric", -"test_resize_downsample_sizes_cubic_antialias", -"test_resize_downsample_sizes_linear_antialias", -"test_resize_downsample_sizes_nearest_not_larger", -"test_resize_downsample_sizes_nearest_not_smaller", -"test_resize_tf_crop_and_resize_axes_2_3", -"test_resize_tf_crop_and_resize_axes_3_2", -"test_resize_tf_crop_and_resize_extrapolation_value", -"test_resize_upsample_scales_linear_half_pixel_symmetric", //shape mismatch -"test_resize_upsample_scales_nearest_axes_3_2", -"test_resize_upsample_sizes_nearest_axes_3_2", -"test_resize_upsample_sizes_nearest_not_larger", -"test_resize_upsample_sizes_nearest_not_smaller", "test_reversesequence_batch", // Issue:: Parser: Can't create layer "onnx_node_output_0!y" of type "ReverseSequence" in function 'getLayerInstance' "test_reversesequence_time", // ---- same as above --- -"test_rms_normalization_2d_axis0_expanded", -"test_rms_normalization_2d_axis1_expanded", -"test_rms_normalization_2d_axis_negative_1_expanded", -"test_rms_normalization_2d_axis_negative_2_expanded", -"test_rms_normalization_3d_axis0_epsilon_expanded", -"test_rms_normalization_3d_axis1_epsilon_expanded", -"test_rms_normalization_3d_axis2_epsilon_expanded", -"test_rms_normalization_3d_axis_negative_1_epsilon_expanded", -"test_rms_normalization_3d_axis_negative_2_epsilon_expanded", -"test_rms_normalization_3d_axis_negative_3_epsilon_expanded", -"test_rms_normalization_4d_axis0_expanded", -"test_rms_normalization_4d_axis1_expanded", -"test_rms_normalization_4d_axis2_expanded", -"test_rms_normalization_4d_axis3_expanded", -"test_rms_normalization_4d_axis_negative_1_expanded", -"test_rms_normalization_4d_axis_negative_2_expanded", -"test_rms_normalization_4d_axis_negative_3_expanded", -"test_rms_normalization_4d_axis_negative_4_expanded", -"test_rms_normalization_default_axis_expanded", "test_rnn_seq_length", // Issue:: Parser: Can't create layer "onnx_node_output_1!Y_h" of type "RNN" in function 'getLayerInstance' "test_scan9_sum", // Issue:: Parser: 'Graph' is not supported in function 'getLayerParams' "test_scan_sum", // ---- same as above --- @@ -437,18 +385,9 @@ "test_simple_rnn_defaults", // ---- same as above --- "test_simple_rnn_with_initial_bias", // ---- same as above --- "test_slice_start_out_of_bounds", -"test_split_1d_uneven_split_opset18", //type mismatch -"test_split_2d_uneven_split_opset18", -"test_split_equal_parts_1d_opset13", -"test_split_equal_parts_1d_opset18", -"test_split_equal_parts_default_axis_opset13", -"test_split_equal_parts_default_axis_opset18", "test_split_to_sequence_1", "test_split_to_sequence_2", "test_split_to_sequence_nokeepdims", -"test_split_zero_size_splits", // ---- incompatible type of input tensor #0 'input': CV_8UC1 given, CV_32FC1 expected in function 'setGraphInput' --- -"test_split_zero_size_splits_opset13", // type mismatch -"test_split_zero_size_splits_opset18", // type mismatch "test_stft", "test_stft_with_window", "test_string_concat", @@ -468,7 +407,6 @@ "test_strnormalizer_export_monday_empty_output", // ---- same as above --- "test_strnormalizer_export_monday_insensintive_upper_twodim", // ---- same as above --- "test_strnormalizer_nostopwords_nochangecase", // Issue:: Parser: Can't create layer "onnx_node_output_0!y" of type "StringNormalizer" in function 'getLayerInstance' -"test_swish_expanded", "test_tensorscatter", "test_tensorscatter_3d", "test_tensorscatter_circular", @@ -484,6 +422,4 @@ "test_training_dropout_default_mask", // ---- same as above --- "test_training_dropout_mask", // ---- same as above --- "test_training_dropout_zero_ratio_mask", // ---- same as above --- -"test_tril_zero", // ---- same as above --- type mismatch -"test_triu_zero", // ---- same as above --- type mismatch "test_unique_length_1", //incorrect output