mirror of
https://github.com/opencv/opencv.git
synced 2026-07-29 15:23:05 +04:00
Merge pull request #27658 from abhishek-gola:det_layer_add
Added Determinant (Det) layer to new DNN engine #27658 ### 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:
@@ -1263,6 +1263,12 @@ CV__DNN_INLINE_NS_BEGIN
|
||||
static Ptr<SizeLayer> create(const LayerParams ¶ms);
|
||||
};
|
||||
|
||||
class CV_EXPORTS DetLayer : public Layer
|
||||
{
|
||||
public:
|
||||
static Ptr<DetLayer> create(const LayerParams ¶ms);
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief Bilinear resize layer from https://github.com/cdmh/deeplab-public-ver2
|
||||
*
|
||||
|
||||
@@ -111,6 +111,7 @@ void initializeLayerFactory()
|
||||
CV_DNN_REGISTER_LAYER_CLASS(Unsqueeze, UnsqueezeLayer);
|
||||
CV_DNN_REGISTER_LAYER_CLASS(IsNaN, IsNaNLayer);
|
||||
CV_DNN_REGISTER_LAYER_CLASS(IsInf, IsInfLayer);
|
||||
CV_DNN_REGISTER_LAYER_CLASS(Det, DetLayer);
|
||||
|
||||
CV_DNN_REGISTER_LAYER_CLASS(Convolution, ConvolutionLayer);
|
||||
CV_DNN_REGISTER_LAYER_CLASS(Deconvolution, DeconvolutionLayer);
|
||||
|
||||
@@ -0,0 +1,143 @@
|
||||
// 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/dnn/shape_utils.hpp>
|
||||
|
||||
namespace cv {
|
||||
namespace dnn {
|
||||
|
||||
// ONNX Det operator
|
||||
// Spec: https://onnx.ai/onnx/operators/onnx__Det.html
|
||||
// Supported opsets: 11-22
|
||||
|
||||
class DetLayerImpl CV_FINAL : public DetLayer
|
||||
{
|
||||
public:
|
||||
DetLayerImpl(const LayerParams& params)
|
||||
{
|
||||
setParamsFrom(params);
|
||||
}
|
||||
|
||||
bool supportBackend(int backendId) CV_OVERRIDE
|
||||
{
|
||||
return backendId == DNN_BACKEND_OPENCV;
|
||||
}
|
||||
|
||||
bool getMemoryShapes(const std::vector<MatShape>& inputs,
|
||||
const int /*requiredOutputs*/,
|
||||
std::vector<MatShape>& outputs,
|
||||
std::vector<MatShape>& /*internals*/) const CV_OVERRIDE
|
||||
{
|
||||
CV_Assert(inputs.size() == 1);
|
||||
const MatShape& in = inputs[0];
|
||||
CV_Assert(in.size() >= 2);
|
||||
|
||||
int n0 = in[in.size() - 2];
|
||||
int n1 = in[in.size() - 1];
|
||||
CV_Assert(n0 == -1 || n1 == -1 || n0 == n1);
|
||||
|
||||
MatShape out;
|
||||
if (in.size() > 2)
|
||||
out.assign(in.begin(), in.end() - 2);
|
||||
else
|
||||
out = MatShape({1});
|
||||
|
||||
outputs.assign(1, out);
|
||||
return false;
|
||||
}
|
||||
|
||||
void getTypes(const std::vector<MatType>& inputs,
|
||||
const int requiredOutputs,
|
||||
const int requiredInternals,
|
||||
std::vector<MatType>& outputs,
|
||||
std::vector<MatType>& internals) const CV_OVERRIDE
|
||||
{
|
||||
CV_Assert(!inputs.empty());
|
||||
int t = inputs[0];
|
||||
|
||||
CV_Assert(t == CV_32F || t == CV_64F || t == CV_16F || t == CV_16BF);
|
||||
outputs.assign(requiredOutputs, MatType(t));
|
||||
internals.assign(requiredInternals, MatType(t));
|
||||
}
|
||||
|
||||
void forward(InputArrayOfArrays inputs_arr,
|
||||
OutputArrayOfArrays outputs_arr,
|
||||
OutputArrayOfArrays /*internals_arr*/) CV_OVERRIDE
|
||||
{
|
||||
std::vector<Mat> inputs, outputs;
|
||||
inputs_arr.getMatVector(inputs);
|
||||
outputs_arr.getMatVector(outputs);
|
||||
|
||||
CV_Assert(inputs.size() == 1);
|
||||
const Mat& X = inputs[0];
|
||||
|
||||
CV_Assert(X.dims >= 2);
|
||||
int n = X.size[X.dims - 1];
|
||||
int m = X.size[X.dims - 2];
|
||||
CV_Assert(n == m);
|
||||
|
||||
size_t batch = X.total() / (X.size[X.dims - 2] * X.size[X.dims - 1]);
|
||||
|
||||
int outDims;
|
||||
std::vector<int> outSizes;
|
||||
if (X.dims > 2)
|
||||
{
|
||||
outDims = X.dims - 2;
|
||||
outSizes.assign(X.size.p, X.size.p + outDims);
|
||||
}
|
||||
else
|
||||
{
|
||||
outDims = 1;
|
||||
outSizes = {1};
|
||||
}
|
||||
outputs[0].create(outDims, outSizes.data(), X.type());
|
||||
|
||||
const int type = X.type();
|
||||
const size_t elemSz = X.elemSize();
|
||||
const size_t matStrideBytes = (size_t)n * (size_t)m * elemSz;
|
||||
|
||||
const uchar* base = X.data;
|
||||
uchar* outp = outputs[0].ptr();
|
||||
|
||||
parallel_for_(Range(0, static_cast<int>(batch)), [&](const Range& r){
|
||||
Mat temp;
|
||||
for (int bi = r.start; bi < r.end; ++bi)
|
||||
{
|
||||
size_t b = static_cast<size_t>(bi);
|
||||
const uchar* p = base + b * matStrideBytes;
|
||||
Mat A(m, n, type, const_cast<uchar*>(p));
|
||||
|
||||
double det;
|
||||
if (type == CV_32F || type == CV_64F) {
|
||||
det = determinant(A);
|
||||
} else {
|
||||
A.convertTo(temp, CV_32F);
|
||||
det = determinant(temp);
|
||||
}
|
||||
|
||||
if (type == CV_32F)
|
||||
reinterpret_cast<float*>(outp)[b] = static_cast<float>(det);
|
||||
else if (type == CV_64F)
|
||||
reinterpret_cast<double*>(outp)[b] = det;
|
||||
else if (type == CV_16F)
|
||||
reinterpret_cast<hfloat*>(outp)[b] = saturate_cast<hfloat>(det);
|
||||
else if (type == CV_16BF)
|
||||
reinterpret_cast<bfloat*>(outp)[b] = saturate_cast<bfloat>(det);
|
||||
else
|
||||
CV_Error(Error::BadDepth, "Unsupported input/output depth for DetLayer");
|
||||
}
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
Ptr<DetLayer> DetLayer::create(const LayerParams& params)
|
||||
{
|
||||
return Ptr<DetLayer>(new DetLayerImpl(params));
|
||||
}
|
||||
|
||||
}}
|
||||
@@ -212,6 +212,7 @@ protected:
|
||||
void parseTrilu (LayerParams& layerParams, const opencv_onnx::NodeProto& node_proto);
|
||||
void parseIsNaN (LayerParams& layerParams, const opencv_onnx::NodeProto& node_proto);
|
||||
void parseIsInf (LayerParams& layerParams, const opencv_onnx::NodeProto& node_proto);
|
||||
void parseDet (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);
|
||||
@@ -1624,6 +1625,12 @@ void ONNXImporter2::parseIsInf(LayerParams& layerParams, const opencv_onnx::Node
|
||||
addLayer(layerParams, node_proto);
|
||||
}
|
||||
|
||||
void ONNXImporter2::parseDet(LayerParams& layerParams, const opencv_onnx::NodeProto& node_proto)
|
||||
{
|
||||
layerParams.type = "Det";
|
||||
addLayer(layerParams, node_proto);
|
||||
}
|
||||
|
||||
void ONNXImporter2::parseUpsample(LayerParams& layerParams, const opencv_onnx::NodeProto& node_proto)
|
||||
{
|
||||
int n_inputs = node_proto.input_size();
|
||||
@@ -2456,6 +2463,7 @@ void ONNXImporter2::buildDispatchMap_ONNX_AI(int opset_version)
|
||||
dispatch["Trilu"] = &ONNXImporter2::parseTrilu;
|
||||
dispatch["IsNaN"] = &ONNXImporter2::parseIsNaN;
|
||||
dispatch["IsInf"] = &ONNXImporter2::parseIsInf;
|
||||
dispatch["Det"] = &ONNXImporter2::parseDet;
|
||||
dispatch["Upsample"] = &ONNXImporter2::parseUpsample;
|
||||
dispatch["SoftMax"] = dispatch["Softmax"] = dispatch["LogSoftmax"] = &ONNXImporter2::parseSoftMax;
|
||||
dispatch["DetectionOutput"] = &ONNXImporter2::parseDetectionOutput;
|
||||
|
||||
@@ -507,9 +507,9 @@ CASE(test_dequantizelinear_axis)
|
||||
CASE(test_dequantizelinear_blocked)
|
||||
SKIP;
|
||||
CASE(test_det_2d)
|
||||
// no filter
|
||||
SKIP;
|
||||
CASE(test_det_nd)
|
||||
// no filter
|
||||
SKIP;
|
||||
CASE(test_div)
|
||||
// no filter
|
||||
CASE(test_div_bcast)
|
||||
|
||||
@@ -91,3 +91,5 @@
|
||||
"test_triu_pos",
|
||||
"test_triu_square",
|
||||
"test_triu_square_neg",
|
||||
"test_det_2d",
|
||||
"test_det_nd",
|
||||
|
||||
@@ -69,8 +69,6 @@
|
||||
"test_convtranspose_pad", // Issue::Parser::Weights are required as inputs
|
||||
"test_convtranspose_pads", // Issue::Parser::Weights are required as inputs
|
||||
"test_convtranspose_with_kernel", // Issue::Parser::Weights are required as inputs
|
||||
"test_det_2d", // Issue:: Unkonwn error
|
||||
"test_det_nd", // Issue:: Unkonwn error
|
||||
"test_dropout_default_mask", // Issue::cvtest::norm::wrong data type
|
||||
"test_dropout_default_mask_ratio", // ---- same as above ---
|
||||
"test_dynamicquantizelinear", // Issue:: Unkonwn error
|
||||
|
||||
Reference in New Issue
Block a user