nareshmlx/opencv-pr huggingface dataset:
**File:** modules/dnn/test/test_onnx_importer.cpp
**Change Type:** modified
**Context:** PR #23897: dnn: add gemm_layer in place of fully_connected_layer for onnx models

**Code Changes:**
```diff
@@ -2597,6 +2597,40 @@ TEST_P(Test_ONNX_layers, where_node)
     testONNXModels("where_layer");
 }
 
+TEST_P(Test_ONNX_layers, Conformance_Gemm_all_attributes) {
+    testONNXModels("test_gemm_all_attributes", pb, 0, 0, false, true, 2);
+}
+TEST_P(Test_ONNX_layers, Conformance_Gemm_alpha) {
+    testONNXModels("test_gemm_alpha", pb, 0, 0, false, true, 2);
+}
```

Review comment:
Why not to use GEMM implementation inside InnerProduct in case `batch_size=1`? Like `fastConvImpl` from Convolution layer? Call GEMM when it's supported and InnerProduct if not. https://github.com/opencv/opencv/blob/1794cdc03c9505bb46f33a5cde5e210c1c7f65a4/modules/dnn/src/layers/convolution_layer.cpp#L260
**File:** modules/dnn/test/test_onnx_importer.cpp
**Change Type:** modified
**Context:** PR #23897: dnn: add gemm_layer in place of fully_connected_layer for onnx models

**Code Changes:**
```diff
@@ -2597,6 +2597,40 @@ TEST_P(Test_ONNX_layers, where_node)
     testONNXModels("where_layer");
 }
 
+TEST_P(Test_ONNX_layers, Conformance_Gemm_all_attributes) {
+    testONNXModels("test_gemm_all_attributes", pb, 0, 0, false, true, 2);
+}
+TEST_P(Test_ONNX_layers, Conformance_Gemm_alpha) {
+    testONNXModels("test_gemm_alpha", pb, 0, 0, false, true, 2);
+}
```

Review comment:
The idea was to use this refactor to replace InnerProduct in the end. Code in InnerProduct is a mess and not maintainable.
**File:** modules/dnn/test/test_onnx_importer.cpp
**Change Type:** modified
**Context:** PR #23897: dnn: add gemm_layer in place of fully_connected_layer for onnx models

**Code Changes:**
```diff
@@ -2597,6 +2597,40 @@ TEST_P(Test_ONNX_layers, where_node)
     testONNXModels("where_layer");
 }
 
+TEST_P(Test_ONNX_layers, Conformance_Gemm_all_attributes) {
+    testONNXModels("test_gemm_all_attributes", pb, 0, 0, false, true, 2);
+}
+TEST_P(Test_ONNX_layers, Conformance_Gemm_alpha) {
+    testONNXModels("test_gemm_alpha", pb, 0, 0, false, true, 2);
+}
```

Review comment:
> No backends support in GEMM. This pull request is still in draft. I would try adding existing backends from InnerProduct before this patch is merged. > We will need to replace InnerProduct to GEMM everywhere, not only in ONNX importer Yes, but this PR focus on replacement in ONNX importer for now. I think replacement for other importers should be follow-up PRs. Replacing `googlenet.onnx` does not harm anything from my perspective. Current implementation which works with hardcoded 1xn Reshape with input of batch size >= 2 should be considered as a bug not a feature. > Which implementation of FC layer has been benchmarked? Does GEMM shows better performance on other CPUs? Test result I presented is case `CV_SIMD128` since it is on M1 macOS (ARM-based). More perf tests will be done in the following week. Another thing worth noted is current implementation can call BLAS if there is no bias. I will also add back this feture in follow-up PRs.
**File:** modules/dnn/include/opencv2/dnn/all_layers.hpp
**Change Type:** modified
**Context:** PR #23897: dnn: add gemm_layer in place of fully_connected_layer for onnx models
**Review Line:** 1109

**Code Changes:**
```diff
+    class CV_EXPORTS GemmLayer : public Layer {
+    public:
+        bool trans_a;
+        bool trans_b;
+        float alpha;
+        float beta;
+
+        static Ptr<GemmLayer> create(const LayerParams& params);
+    };
+
 //! @}
```

Review comment:
As OpenCV initializes all the parameters from `LayerParams`, these fields can be moved to the Impl class and became private.
**File:** modules/dnn/src/layers/gemm_layer.cpp
**Change Type:** added
**Context:** PR #23897: dnn: add gemm_layer in place of fully_connected_layer for onnx models

**Code Changes:**
```diff
@@ -0,0 +1,361 @@
+// 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.
+
+#include "../precomp.hpp"
+#include "layers_common.hpp"
+// backends
+#include "../op_cuda.hpp"
+#ifdef HAVE_CUDA
```

Review comment:
Am I right that `C` is a bias? Can you please put a formula `A * B + C` from https://github.com/opencv/opencv/pull/23897/files#diff-f9fc55b2657f441025bc0adfeb683491b1e3d8275702e159efcb368a1b2c0dd5L1950-L1951 somewhere?
**File:** modules/dnn/include/opencv2/dnn/all_layers.hpp
**Change Type:** modified
**Context:** PR #23897: dnn: add gemm_layer in place of fully_connected_layer for onnx models
**Review Line:** 1109

**Code Changes:**
```diff
+    class CV_EXPORTS GemmLayer : public Layer {
+    public:
+        bool trans_a;
+        bool trans_b;
+        float alpha;
+        float beta;
+
+        static Ptr<GemmLayer> create(const LayerParams& params);
+    };
+
 //! @}
```

Review comment:
My thoughts are parameters in classes in `all_layers.hpp` are from standard layer definitions, which are most probably the same across different frameworks (ONNX, TF, ...). And parameters in impl classes are implementation specific. It is more semantic and meanful to me and I want to keep it in this way.
**File:** modules/dnn/src/layers/gemm_layer.cpp
**Change Type:** added
**Context:** PR #23897: dnn: add gemm_layer in place of fully_connected_layer for onnx models

**Code Changes:**
```diff
@@ -0,0 +1,361 @@
+// 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.
+
+#include "../precomp.hpp"
+#include "layers_common.hpp"
+// backends
+#include "../op_cuda.hpp"
+#ifdef HAVE_CUDA
```

Review comment:
> Am I right that C is a bias? Yes. > Can you please put a formula A * B + C I put`Y = A * B + C` above `forward()` in the latest commit.
**File:** modules/dnn/test/test_onnx_importer.cpp
**Change Type:** modified
**Context:** PR #23897: dnn: add gemm_layer in place of fully_connected_layer for onnx models

**Code Changes:**
```diff
@@ -2597,6 +2597,40 @@ TEST_P(Test_ONNX_layers, where_node)
     testONNXModels("where_layer");
 }
 
+TEST_P(Test_ONNX_layers, Conformance_Gemm_all_attributes) {
+    testONNXModels("test_gemm_all_attributes", pb, 0, 0, false, true, 2);
+}
+TEST_P(Test_ONNX_layers, Conformance_Gemm_alpha) {
+    testONNXModels("test_gemm_alpha", pb, 0, 0, false, true, 2);
+}
```

Review comment:
As PR is ready, let's discuss one more time why replacement of the official ONNX model is required? If possible, let's keep the origin one.
**File:** modules/dnn/CMakeLists.txt
**Change Type:** modified
**Context:** PR #23897: dnn: add gemm_layer in place of fully_connected_layer for onnx models

**Code Changes:**
```diff
@@ -9,6 +9,7 @@ ocv_add_dispatched_file_force_all("int8layers/layers_common" AVX2 AVX512_SKX LAS
 ocv_add_dispatched_file_force_all("layers/cpu_kernels/conv_block" AVX AVX2)
 ocv_add_dispatched_file_force_all("layers/cpu_kernels/conv_depthwise" AVX AVX2 RVV LASX)
 ocv_add_dispatched_file_force_all("layers/cpu_kernels/conv_winograd_f63" AVX AVX2)
+ocv_add_dispatched_file_force_all("layers/cpu_kernels/fast_gemm_kernels" AVX AVX2 NEON LASX)
 
 ocv_add_module(dnn opencv_core opencv_imgproc WRAP python java objc js)
 
```

Review comment:
Do we have a comparison of GEMM vs. InnerProduct on AVX512, RVV and LASX?
**File:** modules/dnn/CMakeLists.txt
**Change Type:** modified
**Context:** PR #23897: dnn: add gemm_layer in place of fully_connected_layer for onnx models

**Code Changes:**
```diff
@@ -9,6 +9,7 @@ ocv_add_dispatched_file_force_all("int8layers/layers_common" AVX2 AVX512_SKX LAS
 ocv_add_dispatched_file_force_all("layers/cpu_kernels/conv_block" AVX AVX2)
 ocv_add_dispatched_file_force_all("layers/cpu_kernels/conv_depthwise" AVX AVX2 RVV LASX)
 ocv_add_dispatched_file_force_all("layers/cpu_kernels/conv_winograd_f63" AVX AVX2)
+ocv_add_dispatched_file_force_all("layers/cpu_kernels/fast_gemm_kernels" AVX AVX2 NEON LASX)
 
 ocv_add_module(dnn opencv_core opencv_imgproc WRAP python java objc js)
 
```

Review comment:
No. Optimization for AVX512, RVV and LASX will be the next patch I believe.
**File:** modules/dnn/test/test_onnx_importer.cpp
**Change Type:** modified
**Context:** PR #23897: dnn: add gemm_layer in place of fully_connected_layer for onnx models

**Code Changes:**
```diff
@@ -2597,6 +2597,40 @@ TEST_P(Test_ONNX_layers, where_node)
     testONNXModels("where_layer");
 }
 
+TEST_P(Test_ONNX_layers, Conformance_Gemm_all_attributes) {
+    testONNXModels("test_gemm_all_attributes", pb, 0, 0, false, true, 2);
+}
+TEST_P(Test_ONNX_layers, Conformance_Gemm_alpha) {
+    testONNXModels("test_gemm_alpha", pb, 0, 0, false, true, 2);
+}
```

Review comment:
Details in https://github.com/opencv/opencv_extra/pull/1073. Short version: the original one has a `Reshape` operator which forces batch size to be 1, while in the test we want it to run with batch size 2. This is just wrong.
**File:** modules/dnn/CMakeLists.txt
**Change Type:** modified
**Context:** PR #23897: dnn: add gemm_layer in place of fully_connected_layer for onnx models

**Code Changes:**
```diff
@@ -9,6 +9,7 @@ ocv_add_dispatched_file_force_all("int8layers/layers_common" AVX2 AVX512_SKX LAS
 ocv_add_dispatched_file_force_all("layers/cpu_kernels/conv_block" AVX AVX2)
 ocv_add_dispatched_file_force_all("layers/cpu_kernels/conv_depthwise" AVX AVX2 RVV LASX)
 ocv_add_dispatched_file_force_all("layers/cpu_kernels/conv_winograd_f63" AVX AVX2)
+ocv_add_dispatched_file_force_all("layers/cpu_kernels/fast_gemm_kernels" AVX AVX2 NEON LASX)
 
 ocv_add_module(dnn opencv_core opencv_imgproc WRAP python java objc js)
 
```

Review comment:
Shall we make a switch to InnerProduct in such case at ONNX importer? ```cpp #if CV_TRY_AVX512_SKX || CV_TRY_RVV || CV_TRY_LASX // Create InnerProduct #else // Create GEMM #endif ```
**File:** modules/dnn/test/test_onnx_importer.cpp
**Change Type:** modified
**Context:** PR #23897: dnn: add gemm_layer in place of fully_connected_layer for onnx models

**Code Changes:**
```diff
@@ -2597,6 +2597,40 @@ TEST_P(Test_ONNX_layers, where_node)
     testONNXModels("where_layer");
 }
 
+TEST_P(Test_ONNX_layers, Conformance_Gemm_all_attributes) {
+    testONNXModels("test_gemm_all_attributes", pb, 0, 0, false, true, 2);
+}
+TEST_P(Test_ONNX_layers, Conformance_Gemm_alpha) {
+    testONNXModels("test_gemm_alpha", pb, 0, 0, false, true, 2);
+}
```

Review comment:
Hold on. Although I am not fully agree all the opinions here, I am working on adding back this feature, which needs only two additional transposition.
**File:** modules/dnn/CMakeLists.txt
**Change Type:** modified
**Context:** PR #23897: dnn: add gemm_layer in place of fully_connected_layer for onnx models

**Code Changes:**
```diff
@@ -9,6 +9,7 @@ ocv_add_dispatched_file_force_all("int8layers/layers_common" AVX2 AVX512_SKX LAS
 ocv_add_dispatched_file_force_all("layers/cpu_kernels/conv_block" AVX AVX2)
 ocv_add_dispatched_file_force_all("layers/cpu_kernels/conv_depthwise" AVX AVX2 RVV LASX)
 ocv_add_dispatched_file_force_all("layers/cpu_kernels/conv_winograd_f63" AVX AVX2)
+ocv_add_dispatched_file_force_all("layers/cpu_kernels/fast_gemm_kernels" AVX AVX2 NEON LASX)
 
 ocv_add_module(dnn opencv_core opencv_imgproc WRAP python java objc js)
 
```

Review comment:
Done. IIRC, Gemm introduced in this pr with AVX2 acceleration is even faster than the existing implementation with AVX512 acceleration. Let me collect the results if all tests are green.
**File:** modules/dnn/test/test_onnx_importer.cpp
**Change Type:** modified
**Context:** PR #23897: dnn: add gemm_layer in place of fully_connected_layer for onnx models

**Code Changes:**
```diff
@@ -2597,6 +2597,40 @@ TEST_P(Test_ONNX_layers, where_node)
     testONNXModels("where_layer");
 }
 
+TEST_P(Test_ONNX_layers, Conformance_Gemm_all_attributes) {
+    testONNXModels("test_gemm_all_attributes", pb, 0, 0, false, true, 2);
+}
+TEST_P(Test_ONNX_layers, Conformance_Gemm_alpha) {
+    testONNXModels("test_gemm_alpha", pb, 0, 0, false, true, 2);
+}
```

Review comment:
Man, I found if batch is allowed here, it is even much more broken. I found in `TEST_P(Test_ONNX_nets, Googlenet)`, the shape of `ref` is `2x1000` instead of `2x1x1000`, meaning the shape of output of the last Gemm layer in Googlenet is `2x1000` also. Note that the input of this Gemm layer is `2 x 1 x 1024` (2 is the batch added by `blobsFromImages` in the source input). This is a broken shape inference with batch in the test. It may break some axis-sensitive layers, **also it affects other backends with their own graph engines and shape inference.** Also I can see The forced-batch feature is going to cause some troubles in vision transformer models. Following is an example. <img width="1333" alt="image" src="https://github.com/opencv/opencv/assets/17219438/0745fd59-6910-4a93-9c37-5173cabf43c7"> Above is the an attention block in ONNX. The batch dimension can be blended into other dimensions; In the 2nd last Reshape, the original batch size `1` is blended into `8`. If the forced batch feature brings a `batch=2`, the Gemm layer won't work because the inner dimension will not match.
**File:** modules/dnn/test/test_onnx_importer.cpp
**Change Type:** modified
**Context:** PR #23897: dnn: add gemm_layer in place of fully_connected_layer for onnx models

**Code Changes:**
```diff
@@ -2597,6 +2597,40 @@ TEST_P(Test_ONNX_layers, where_node)
     testONNXModels("where_layer");
 }
 
+TEST_P(Test_ONNX_layers, Conformance_Gemm_all_attributes) {
+    testONNXModels("test_gemm_all_attributes", pb, 0, 0, false, true, 2);
+}
+TEST_P(Test_ONNX_layers, Conformance_Gemm_alpha) {
+    testONNXModels("test_gemm_alpha", pb, 0, 0, false, true, 2);
+}
```

Review comment:
It should fix the googlenet problem but it messes the dimensions in attention block. `Transpose` operators in the attention block transposes the batch dimension to axis 1. Could we just simply follow the standards instead of going futher in a wrong way? The forced-batch feature assumes the batch dimension is at axis 0, which may work for most of the conv nets but not for vit.
**File:** modules/dnn/perf/perf_gemm.cpp
**Change Type:** added
**Context:** PR #23897: dnn: add gemm_layer in place of fully_connected_layer for onnx models

**Code Changes:**
```diff
@@ -0,0 +1,251 @@
+// 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.
+
+#include "perf_precomp.hpp"
+#include <opencv2/dnn/shape_utils.hpp>
+
+namespace opencv_test {
+
```

Review comment:
Will be able Gemm run without such optimizations? To avoid conditional compilation
**File:** modules/dnn/src/layers/cpu_kernels/fast_gemm.cpp
**Change Type:** added
**Context:** PR #23897: dnn: add gemm_layer in place of fully_connected_layer for onnx models

**Code Changes:**
```diff
@@ -0,0 +1,262 @@
+// 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.
+
+// This file is modified from the ficus (https://github.com/vpisarev/ficus/blob/master/runtime/ficus/impl/gemm.impl.h).
+// Here is the original license:
+/*
+    This file is a part of ficus language project.
+    See ficus/LICENSE for the licensing terms
```

Review comment:
`CV_LOG_DEBUG`
**File:** modules/dnn/src/layers/cpu_kernels/fast_gemm.cpp
**Change Type:** added
**Context:** PR #23897: dnn: add gemm_layer in place of fully_connected_layer for onnx models

**Code Changes:**
```diff
@@ -0,0 +1,262 @@
+// 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.
+
+// This file is modified from the ficus (https://github.com/vpisarev/ficus/blob/master/runtime/ficus/impl/gemm.impl.h).
+// Here is the original license:
+/*
+    This file is a part of ficus language project.
+    See ficus/LICENSE for the licensing terms
```

Review comment:
Is commented code still required or covered by the checks above?
**File:** modules/dnn/src/layers/gemm_layer.cpp
**Change Type:** added
**Context:** PR #23897: dnn: add gemm_layer in place of fully_connected_layer for onnx models

**Code Changes:**
```diff
@@ -0,0 +1,361 @@
+// 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.
+
+#include "../precomp.hpp"
+#include "layers_common.hpp"
+// backends
+#include "../op_cuda.hpp"
+#ifdef HAVE_CUDA
```

Review comment:
Please correct alignment
**File:** modules/dnn/src/layers/gemm_layer.cpp
**Change Type:** added
**Context:** PR #23897: dnn: add gemm_layer in place of fully_connected_layer for onnx models
**Review Line:** 104

**Code Changes:**
```diff
+        MatShape shape_y{M * batches, N};
+        outputs.assign(1, shape_y);
+        return false;
+    }
+
+    // TODO: replace with cv::broadcast() once 1d mat is supported
+    // FIXME: fix if conditions if 1d mat is supported properly
+    void broadcastCWtihBeta(int M, int N, const Mat &C) {
+        if (beta != 0 && !C.empty()) {
+            broadcast_C.clear();
+            broadcast_C.resize(M * N, 0.f);
```

Review comment:
https://github.com/opencv/opencv/pull/23965 merged
**File:** modules/dnn/src/layers/cpu_kernels/fast_gemm.cpp
**Change Type:** added
**Context:** PR #23897: dnn: add gemm_layer in place of fully_connected_layer for onnx models

**Code Changes:**
```diff
@@ -0,0 +1,262 @@
+// 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.
+
+// This file is modified from the ficus (https://github.com/vpisarev/ficus/blob/master/runtime/ficus/impl/gemm.impl.h).
+// Here is the original license:
+/*
+    This file is a part of ficus language project.
+    See ficus/LICENSE for the licensing terms
```

Review comment:
I wrote this because in the beginning I thought if A has extra batch, e.g. 2 x 1 x 1024, then the output Y should carry the batch, e.g. 2 x 1 x 1000. However, the googlenet unit test shows the output should be 2 x 1000 instead. So these lines are commented out.
**File:** modules/dnn/test/test_onnx_importer.cpp
**Change Type:** modified
**Context:** PR #23897: dnn: add gemm_layer in place of fully_connected_layer for onnx models
**Review Line:** 2600

**Code Changes:**
```diff
@@ -2597,6 +2597,40 @@ TEST_P(Test_ONNX_layers, where_node)
     testONNXModels("where_layer");
 }
 
+TEST_P(Test_ONNX_layers, Conformance_Gemm_all_attributes) {
+    testONNXModels("test_gemm_all_attributes", pb, 0, 0, false, true, 2);
+}
+TEST_P(Test_ONNX_layers, Conformance_Gemm_alpha) {
+    testONNXModels("test_gemm_alpha", pb, 0, 0, false, true, 2);
+}
```

Review comment:
I would like suggest to create a common class with `SetUp` and skip the tests if no CPU feature detected in runtime by `cv::checkHardwareSupport`
**File:** modules/dnn/src/onnx/onnx_importer.cpp
**Change Type:** modified
**Context:** PR #23897: dnn: add gemm_layer in place of fully_connected_layer for onnx models

**Code Changes:**
```diff
@@ -1947,73 +1947,45 @@ void ONNXImporter::parseBatchNormalization(LayerParams& layerParams, const openc
     addLayer(layerParams, node_proto);
 }
 
-// A * B + C = Y, we require that the dimension of A is [m, k], and the dimension of B is [n, k].
-// And the dim of output Y is [m, n]
-void ONNXImporter::parseGemm(LayerParams& layerParams, const opencv_onnx::NodeProto& node_proto)
+void ONNXImporter::parseGemm(LayerParams& layerParams, const opencv_onnx::NodeProto& node_proto_)
 {
-    CV_Assert(node_proto.input_size() >= 2);
```

Review comment:
Please try with `cv::checkHardwareSupport`
**File:** modules/dnn/src/layers/gemm_layer.cpp
**Change Type:** added
**Context:** PR #23897: dnn: add gemm_layer in place of fully_connected_layer for onnx models
**Review Line:** 104

**Code Changes:**
```diff
+        MatShape shape_y{M * batches, N};
+        outputs.assign(1, shape_y);
+        return false;
+    }
+
+    // TODO: replace with cv::broadcast() once 1d mat is supported
+    // FIXME: fix if conditions if 1d mat is supported properly
+    void broadcastCWtihBeta(int M, int N, const Mat &C) {
+        if (beta != 0 && !C.empty()) {
+            broadcast_C.clear();
+            broadcast_C.resize(M * N, 0.f);
```

Review comment:
Yes, but broadcasting from a 1d tensor (which is 2d mat in opencv, for example a 1d tensor of shape [2] is loaded into a mat of shape [2, 1]; The appended 1 breaks the broadcast rule) to nd may have problems.
**File:** modules/dnn/perf/perf_gemm.cpp
**Change Type:** added
**Context:** PR #23897: dnn: add gemm_layer in place of fully_connected_layer for onnx models

**Code Changes:**
```diff
@@ -0,0 +1,251 @@
+// 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.
+
+#include "perf_precomp.hpp"
+#include <opencv2/dnn/shape_utils.hpp>
+
+namespace opencv_test {
+
```

Review comment:
I plan to make a default kernel to avoid this.
**File:** modules/dnn/src/onnx/onnx_importer.cpp
**Change Type:** modified
**Context:** PR #23897: dnn: add gemm_layer in place of fully_connected_layer for onnx models
**Review Line:** 1950

**Code Changes:**
```diff
 }
 
-// A * B + C = Y, we require that the dimension of A is [m, k], and the dimension of B is [n, k].
-// And the dim of output Y is [m, n]
-void ONNXImporter::parseGemm(LayerParams& layerParams, const opencv_onnx::NodeProto& node_proto)
+void ONNXImporter::parseGemm(LayerParams& layerParams, const opencv_onnx::NodeProto& node_proto_)
 {
-    CV_Assert(node_proto.input_size() >= 2);
-    layerParams.type = "InnerProduct";
-    int transA = layerParams.get<int>("transA", 0);
-    layerParams.set("transA", transA == 1);
```

Review comment:
Yes, but in the next patch. Lets keep this patch simple enough.
**File:** modules/dnn/src/layers/cpu_kernels/fast_gemm.cpp
**Change Type:** added
**Context:** PR #23897: dnn: add gemm_layer in place of fully_connected_layer for onnx models

**Code Changes:**
```diff
@@ -0,0 +1,262 @@
+// 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.
+
+// This file is modified from the ficus (https://github.com/vpisarev/ficus/blob/master/runtime/ficus/impl/gemm.impl.h).
+// Here is the original license:
+/*
+    This file is a part of ficus language project.
+    See ficus/LICENSE for the licensing terms
```

Review comment:
Removed this line
**File:** modules/dnn/src/layers/cpu_kernels/fast_gemm.cpp
**Change Type:** added
**Context:** PR #23897: dnn: add gemm_layer in place of fully_connected_layer for onnx models

**Code Changes:**
```diff
@@ -0,0 +1,262 @@
+// 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.
+
+// This file is modified from the ficus (https://github.com/vpisarev/ficus/blob/master/runtime/ficus/impl/gemm.impl.h).
+// Here is the original license:
+/*
+    This file is a part of ficus language project.
+    See ficus/LICENSE for the licensing terms
```

Review comment:
Removed these lines