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

Merge pull request #27661 from abhishek-gola:isNan_layer_add

Added IsNan layer to new DNN engine #27661

### Pull Request Readiness Checklist

See details at https://github.com/opencv/opencv/wiki/How_to_contribute#making-a-good-pull-request

- [x] I agree to contribute to the project under Apache 2 License.
- [x] To the best of my knowledge, the proposed patch is not based on a code under GPL or another license that is incompatible with OpenCV
- [x] The PR is proposed to the proper branch
- [x] There is a reference to the original bug report and related work
- [x] There is accuracy test, performance test and test data in opencv_extra repository, if applicable
      Patch to opencv_extra has the same branch name.
- [x] The feature is well documented and sample code can be built with the project CMake
This commit is contained in:
Abhishek Gola
2025-08-13 23:38:53 +05:30
committed by GitHub
parent 87320416ce
commit d5f054cd43
7 changed files with 108 additions and 2 deletions
@@ -514,6 +514,12 @@ CV__DNN_INLINE_NS_BEGIN
static Ptr<Reshape2Layer> create(const LayerParams& params);
};
class CV_EXPORTS IsNaNLayer : public Layer
{
public:
static Ptr<IsNaNLayer> create(const LayerParams& params);
};
class CV_EXPORTS FlattenLayer : public Layer
{
public:
+1
View File
@@ -109,6 +109,7 @@ void initializeLayerFactory()
CV_DNN_REGISTER_LAYER_CLASS(Tile2, Tile2Layer);
CV_DNN_REGISTER_LAYER_CLASS(Transpose, TransposeLayer);
CV_DNN_REGISTER_LAYER_CLASS(Unsqueeze, UnsqueezeLayer);
CV_DNN_REGISTER_LAYER_CLASS(IsNaN, IsNaNLayer);
CV_DNN_REGISTER_LAYER_CLASS(Convolution, ConvolutionLayer);
CV_DNN_REGISTER_LAYER_CLASS(Deconvolution, DeconvolutionLayer);
+91
View File
@@ -0,0 +1,91 @@
// 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) 2025, BigVision LLC, all rights reserved.
// Third party copyrights are property of their respective owners.
#include "../precomp.hpp"
#include "layers_common.hpp"
#include "opencv2/core/fast_math.hpp" // for cvIsNaN
namespace cv {
namespace dnn {
/*
IsNaN layer, as defined in ONNX specification:
https://onnx.ai/onnx/operators/onnx__IsNaN.html
Opset's 9 to 20 are covered.
*/
template <typename T, typename WT = T>
static inline void computeIsNaNMask(const T* src, uchar* dst, const size_t count)
{
parallel_for_(Range(0, (int)count), [&](const Range& r){
for (int i = r.start; i < r.end; ++i)
{
WT v = (WT)src[i];
dst[i] = static_cast<uchar>(cvIsNaN(v));
}
});
}
class IsNaNLayerImpl CV_FINAL : public IsNaNLayer
{
public:
IsNaNLayerImpl(const LayerParams& params)
{
setParamsFrom(params);
}
bool supportBackend(int backendId) CV_OVERRIDE
{
return backendId == DNN_BACKEND_OPENCV;
}
bool getMemoryShapes(const std::vector<MatShape>& inputs, int,
std::vector<MatShape>& outputs,
std::vector<MatShape>&) const CV_OVERRIDE
{
CV_Assert(inputs.size() == 1);
outputs.assign(1, inputs[0]);
return false;
}
void getTypes(const std::vector<MatType>&, const int requiredOutputs,
const int requiredInternals, std::vector<MatType>& outputs,
std::vector<MatType>& internals) const CV_OVERRIDE
{
outputs.assign(requiredOutputs, CV_Bool);
internals.assign(requiredInternals, MatType(-1));
}
void forward(InputArrayOfArrays in, OutputArrayOfArrays out, OutputArrayOfArrays) CV_OVERRIDE
{
std::vector<Mat> inputs, outputs; in.getMatVector(inputs); out.getMatVector(outputs);
CV_Assert(inputs.size() == 1 && outputs.size() == 1);
const Mat& X = inputs[0];
Mat& Y = outputs[0];
const int defaultOutType = CV_BoolC1;
const int outType = (Y.empty() || Y.type() < 0) ? defaultOutType : Y.type();
Y.create(X.dims, X.size.p, outType);
const int depth = CV_MAT_DEPTH(X.type());
const size_t total = X.total();
uchar* dst = Y.ptr<uchar>();
switch (depth) {
case CV_32F: computeIsNaNMask<float>(X.ptr<float>(), dst, total); break;
case CV_64F: computeIsNaNMask<double>(X.ptr<double>(), dst, total); break;
case CV_16F: computeIsNaNMask<hfloat, float>(X.ptr<hfloat>(), dst, total); break;
case CV_16BF: computeIsNaNMask<bfloat, float>(X.ptr<bfloat>(), dst, total); break;
default: CV_Error_(Error::StsError, ("IsNaN: Unsupported type depth=%d", depth));
}
}
};
Ptr<IsNaNLayer> IsNaNLayer::create(const LayerParams& p) { return makePtr<IsNaNLayerImpl>(p); }
}} // namespace cv::dnn
+8
View File
@@ -210,6 +210,7 @@ protected:
void parseReduce (LayerParams& layerParams, const opencv_onnx::NodeProto& node_proto);
void parseRelu (LayerParams& layerParams, const opencv_onnx::NodeProto& node_proto);
void parseTrilu (LayerParams& layerParams, const opencv_onnx::NodeProto& node_proto);
void parseIsNaN (LayerParams& layerParams, const opencv_onnx::NodeProto& node_proto);
void parseResize (LayerParams& layerParams, const opencv_onnx::NodeProto& node_proto);
void parseSize (LayerParams& layerParams, const opencv_onnx::NodeProto& node_proto);
void parseReshape (LayerParams& layerParams, const opencv_onnx::NodeProto& node_proto);
@@ -1610,6 +1611,12 @@ void ONNXImporter2::parseTrilu(LayerParams& layerParams, const opencv_onnx::Node
}
void ONNXImporter2::parseIsNaN(LayerParams& layerParams, const opencv_onnx::NodeProto& node_proto)
{
layerParams.type = "IsNaN";
addLayer(layerParams, node_proto);
}
void ONNXImporter2::parseUpsample(LayerParams& layerParams, const opencv_onnx::NodeProto& node_proto)
{
int n_inputs = node_proto.input_size();
@@ -2440,6 +2447,7 @@ void ONNXImporter2::buildDispatchMap_ONNX_AI(int opset_version)
dispatch["Resize"] = &ONNXImporter2::parseResize;
dispatch["Size"] = &ONNXImporter2::parseSize;
dispatch["Trilu"] = &ONNXImporter2::parseTrilu;
dispatch["IsNaN"] = &ONNXImporter2::parseIsNaN;
dispatch["Upsample"] = &ONNXImporter2::parseUpsample;
dispatch["SoftMax"] = dispatch["Softmax"] = dispatch["LogSoftmax"] = &ONNXImporter2::parseSoftMax;
dispatch["DetectionOutput"] = &ONNXImporter2::parseDetectionOutput;
@@ -797,7 +797,7 @@ CASE(test_isinf_negative)
CASE(test_isinf_positive)
// no filter
CASE(test_isnan)
// no filter
SKIP;
CASE(test_layer_normalization_2d_axis0)
// no filter
CASE(test_layer_normalization_2d_axis1)
@@ -71,3 +71,4 @@
"test_mean_example",
"test_mean_one_input",
"test_mean_two_inputs",
"test_isnan",
@@ -110,7 +110,6 @@
"test_isinf", // Issue::Can't create layer "onnx_node_output_0!y" of type "IsInf" in function 'getLayerInstance'
"test_isinf_negative", //-- same as above ---
"test_isinf_positive", //-- same as above ---
"test_isnan", // -- same as above ---
"test_loop11", // Issue::'Graph' is not supported in function 'getLayerParams'
"test_loop13_seq", // Issue::typeProto.has_tensor_type() in function 'populateNet'
"test_loop16_seq_none", // Issue::Failed to allocate 179812654996800 bytes in function 'OutOfMemoryError'