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

Merge pull request #28807 from abhishek-gola:eyelike_layer_add

Added EyeLike layer support
This commit is contained in:
Alexander Smorkalov
2026-04-14 11:20:53 +03:00
committed by GitHub
7 changed files with 143 additions and 6 deletions
@@ -1557,6 +1557,12 @@ CV__DNN_INLINE_NS_BEGIN
static Ptr<DetLayer> create(const LayerParams &params);
};
class CV_EXPORTS EyeLikeLayer : public Layer
{
public:
static Ptr<EyeLikeLayer> create(const LayerParams &params);
};
class CV_EXPORTS CenterCropPadLayer : public Layer
{
public:
+1
View File
@@ -120,6 +120,7 @@ void initializeLayerFactory()
CV_DNN_REGISTER_LAYER_CLASS(IsInf, IsInfLayer);
CV_DNN_REGISTER_LAYER_CLASS(OneHot, OneHotLayer);
CV_DNN_REGISTER_LAYER_CLASS(Det, DetLayer);
CV_DNN_REGISTER_LAYER_CLASS(EyeLike, EyeLikeLayer);
CV_DNN_REGISTER_LAYER_CLASS(BlackmanWindow, BlackmanWindowLayer);
CV_DNN_REGISTER_LAYER_CLASS(HannWindow, HannWindowLayer);
CV_DNN_REGISTER_LAYER_CLASS(HammingWindow, HammingWindowLayer);
+117
View File
@@ -0,0 +1,117 @@
// 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) 2026, 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 EyeLike operator
// Spec: https://onnx.ai/onnx/operators/onnx__EyeLike.html
// Supported opsets: 9-22
class EyeLikeLayerImpl CV_FINAL : public EyeLikeLayer
{
public:
int k; // diagonal offset
int outputDtype; // -1 means use input dtype
EyeLikeLayerImpl(const LayerParams& params)
{
setParamsFrom(params);
k = params.get<int>("k", 0);
outputDtype = params.get<int>("dtype", -1);
}
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);
outputs.assign(1, in);
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 = (outputDtype >= 0) ? outputDtype : inputs[0];
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 rows = X.size[0];
int cols = X.size[1];
int outType = (outputDtype >= 0) ? outputDtype : X.type();
outputs[0].create(rows, cols, outType);
Mat& Y = outputs[0];
Y.setTo(Scalar::all(0));
// Set ones on the k-th diagonal: Y[i, i+k] = 1
int iStart = (k >= 0) ? 0 : -k;
int jStart = (k >= 0) ? k : 0;
int diagLen = std::min(rows - iStart, cols - jStart);
switch (outType)
{
case CV_32F: fillDiag<float> (Y, iStart, jStart, diagLen, 1.0f); break;
case CV_64F: fillDiag<double> (Y, iStart, jStart, diagLen, 1.0); break;
case CV_32S: fillDiag<int32_t> (Y, iStart, jStart, diagLen, 1); break;
case CV_64S: fillDiag<int64_t> (Y, iStart, jStart, diagLen, 1); break;
case CV_8U: fillDiag<uint8_t> (Y, iStart, jStart, diagLen, 1); break;
case CV_8S: fillDiag<int8_t> (Y, iStart, jStart, diagLen, 1); break;
case CV_16U: fillDiag<uint16_t>(Y, iStart, jStart, diagLen, 1); break;
case CV_16S: fillDiag<int16_t> (Y, iStart, jStart, diagLen, 1); break;
case CV_16F: fillDiag<hfloat> (Y, iStart, jStart, diagLen, hfloat(1.0f)); break;
case CV_16BF: fillDiag<bfloat> (Y, iStart, jStart, diagLen, bfloat(1.0f)); break;
case CV_Bool: fillDiag<bool> (Y, iStart, jStart, diagLen, true); break;
default:
CV_Error(Error::BadDepth, "Unsupported output depth for EyeLikeLayer");
}
}
private:
template<typename T>
static void fillDiag(Mat& Y, int iStart, int jStart, int diagLen, T one)
{
for (int d = 0; d < diagLen; ++d)
Y.at<T>(iStart + d, jStart + d) = one;
}
};
Ptr<EyeLikeLayer> EyeLikeLayer::create(const LayerParams& params)
{
return Ptr<EyeLikeLayer>(new EyeLikeLayerImpl(params));
}
}}
+13
View File
@@ -221,6 +221,7 @@ protected:
void parseOneHot (LayerParams& layerParams, const opencv_onnx::NodeProto& node_proto);
void parseDFT (LayerParams& layerParams, const opencv_onnx::NodeProto& node_proto);
void parseDet (LayerParams& layerParams, const opencv_onnx::NodeProto& node_proto);
void parseEyeLike (LayerParams& layerParams, const opencv_onnx::NodeProto& node_proto);
void parseBlackmanWindow (LayerParams& layerParams, const opencv_onnx::NodeProto& node_proto);
void parseHannWindow (LayerParams& layerParams, const opencv_onnx::NodeProto& node_proto);
void parseHammingWindow (LayerParams& layerParams, const opencv_onnx::NodeProto& node_proto);
@@ -1764,6 +1765,17 @@ void ONNXImporter2::parseDet(LayerParams& layerParams, const opencv_onnx::NodePr
addLayer(layerParams, node_proto);
}
void ONNXImporter2::parseEyeLike(LayerParams& layerParams, const opencv_onnx::NodeProto& node_proto)
{
layerParams.type = "EyeLike";
if (layerParams.has("dtype"))
{
int onnxDtype = layerParams.get<int>("dtype");
layerParams.set("dtype", dataType2cv((opencv_onnx::TensorProto_DataType)onnxDtype));
}
addLayer(layerParams, node_proto);
}
void ONNXImporter2::parseBlackmanWindow(LayerParams& layerParams, const opencv_onnx::NodeProto& node_proto)
{
layerParams.type = "BlackmanWindow";
@@ -2731,6 +2743,7 @@ void ONNXImporter2::buildDispatchMap_ONNX_AI()
dispatch["OneHot"] = &ONNXImporter2::parseOneHot;
dispatch["DFT"] = &ONNXImporter2::parseDFT;
dispatch["Det"] = &ONNXImporter2::parseDet;
dispatch["EyeLike"] = &ONNXImporter2::parseEyeLike;
dispatch["BlackmanWindow"] = &ONNXImporter2::parseBlackmanWindow;
dispatch["HannWindow"] = &ONNXImporter2::parseHannWindow;
dispatch["HammingWindow"] = &ONNXImporter2::parseHammingWindow;
@@ -717,11 +717,11 @@ CASE(test_expand_dim_changed)
CASE(test_expand_dim_unchanged)
SKIP;
CASE(test_eyelike_populate_off_main_diagonal)
// no filter
SKIP;
CASE(test_eyelike_with_dtype)
// no filter
SKIP;
CASE(test_eyelike_without_dtype)
// no filter
SKIP;
CASE(test_flatten_axis0)
// no filter
CASE(test_flatten_axis1)
@@ -735,3 +735,6 @@
"test_reduce_sum_square_empty_set_expanded",
"test_reduce_log_sum_exp_empty_set_expanded",
"test_loop11",
"test_eyelike_populate_off_main_diagonal",
"test_eyelike_with_dtype",
"test_eyelike_without_dtype",
@@ -305,9 +305,6 @@
"test_einsum_scalar",
"test_equal_string",
"test_equal_string_broadcast",
"test_eyelike_populate_off_main_diagonal", // Issues::Layer::Can't create layer::Can't create layer "onnx_node_output_0!y" of type "EyeLike" in function 'getLayerInstance'
"test_eyelike_with_dtype", // ---- same as above ---
"test_eyelike_without_dtype", // ---- same as above ---
"test_gridsample_bicubic", // ---- same as above ---
"test_gridsample_bicubic_align_corners_0_additional_1",
"test_gridsample_bicubic_align_corners_1_additional_1",