diff --git a/.gitlab/ci/build.gitlab-ci.yml b/.gitlab/ci/build.gitlab-ci.yml
index 264fefa4d0d4c34065581fafe7b66277cd6dedf7..7d806c923f25d38366b36b503ba55949632fc288 100644
--- a/.gitlab/ci/build.gitlab-ci.yml
+++ b/.gitlab/ci/build.gitlab-ci.yml
@@ -1,3 +1,6 @@
+include:
+  - remote: 'https://gitlab.eclipse.org/eclipse/aidge/gitlab_shared_files/-/raw/main/.gitlab/ci/shared_script.gitlab-ci.yml'
+
 build:ubuntu_cpp:
   stage: build
   needs: []
@@ -8,10 +11,7 @@ build:ubuntu_cpp:
     - DEPENDENCY_JOB="build:ubuntu_cpp"
     # aidge_core
     - DEPENDENCY_NAME="aidge_core" 
-    - !reference [.download_dependency, script]   
-    # aidge_backend_cpu
-    - DEPENDENCY_NAME="aidge_backend_cpu"
-    - !reference [.download_dependency, script]    
+    - !reference [.download_dependency, script]       
   
     # Build current module
     - export CMAKE_PREFIX_PATH=../install_cpp
@@ -37,9 +37,6 @@ build:ubuntu_cpp_g++10:
     # aidge_core
     - DEPENDENCY_NAME="aidge_core" 
     - !reference [.download_dependency, script]   
-    # aidge_backend_cpu
-    - DEPENDENCY_NAME="aidge_backend_cpu"
-    - !reference [.download_dependency, script]    
 
     # Build current module
     - export CMAKE_PREFIX_PATH=../install_cpp
@@ -62,10 +59,7 @@ build:ubuntu_cpp_g++12:
     - DEPENDENCY_JOB="build:ubuntu_cpp"
     # aidge_core
     - DEPENDENCY_NAME="aidge_core" 
-    - !reference [.download_dependency, script]   
-    # aidge_backend_cpu
-    - DEPENDENCY_NAME="aidge_backend_cpu"
-    - !reference [.download_dependency, script]    
+    - !reference [.download_dependency, script]      
 
     # Build current module
     - export CMAKE_PREFIX_PATH=../install_cpp
@@ -88,9 +82,6 @@ build:ubuntu_cpp_clang12:
     - DEPENDENCY_JOB="build:ubuntu_cpp"
     # aidge_core
     - DEPENDENCY_NAME="aidge_core" 
-    - !reference [.download_dependency, script]   
-    # aidge_backend_cpu
-    - DEPENDENCY_NAME="aidge_backend_cpu"
     - !reference [.download_dependency, script]    
 
     # Build current module
@@ -114,10 +105,7 @@ build:ubuntu_cpp_clang15:
     - DEPENDENCY_JOB="build:ubuntu_cpp"
     # aidge_core
     - DEPENDENCY_NAME="aidge_core" 
-    - !reference [.download_dependency, script]   
-    # aidge_backend_cpu
-    - DEPENDENCY_NAME="aidge_backend_cpu"
-    - !reference [.download_dependency, script]    
+    - !reference [.download_dependency, script]     
 
     # Build current module
     - export CMAKE_PREFIX_PATH=../install_cpp
@@ -140,9 +128,6 @@ build:ubuntu_python:
     - DEPENDENCY_JOB="build:ubuntu_python"
     # aidge_core
     - DEPENDENCY_NAME="aidge_core" 
-    - !reference [.download_dependency, script]   
-    # aidge_backend_cpu
-    - DEPENDENCY_NAME="aidge_backend_cpu"
     - !reference [.download_dependency, script]    
 
     - python3 -m pip install virtualenv
diff --git a/CMakeLists.txt b/CMakeLists.txt
index e4277ed329a17f46dd98b0b2e59281f87ddf7576..89926eaae69899c9d01874d3759e6cef52961a9c 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -31,7 +31,6 @@ endif()
 ##############################################
 # Find system dependencies
 find_package(aidge_core REQUIRED)
-find_package(aidge_backend_cpu REQUIRED)
 find_package(OpenCV REQUIRED)
 if (${OpenCV_VERSION_MAJOR} LESS 3)
     MESSAGE(FATAL_ERROR "Unsupported OpenCV version. OpenCV 3.0.0+ is required")
@@ -47,7 +46,6 @@ add_library(${module_name} ${src_files} ${inc_files})
 target_link_libraries(${module_name}
     PUBLIC
         _aidge_core # _ is added because we link the target not the project
-        _aidge_backend_cpu
 )
 
 target_link_libraries(${module_name} PUBLIC ${OpenCV_LIBS})
diff --git a/requirements.txt b/requirements.txt
new file mode 100644
index 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391
diff --git a/setup.py b/setup.py
index b6e2d45f5ce08dd1ed825ff9dd54d5884e13c0eb..168007e3367e7785054acc13c7a722339d94fea3 100644
--- a/setup.py
+++ b/setup.py
@@ -108,7 +108,7 @@ if __name__ == '__main__':
         cmdclass={
             'build_ext': CMakeBuild,
         },
-        install_requires=['aidge_core','aidge_backend_cpu'],
+        install_requires=['aidge_core'],
         zip_safe=False,
 
     )
diff --git a/unit_tests/Test_DataProvider.cpp b/unit_tests/Test_DataProvider.cpp
deleted file mode 100644
index 69f4f7b871c60cbbe074e4f8f4a700c7fa68899c..0000000000000000000000000000000000000000
--- a/unit_tests/Test_DataProvider.cpp
+++ /dev/null
@@ -1,63 +0,0 @@
-/********************************************************************************
- * Copyright (c) 2023 CEA-List
- *
- * This program and the accompanying materials are made available under the
- * terms of the Eclipse Public License 2.0 which is available at
- * http://www.eclipse.org/legal/epl-2.0.
- *
- * SPDX-License-Identifier: EPL-2.0
- *
- ********************************************************************************/
-
-#include <catch2/catch_test_macros.hpp>
-
-#include "aidge/backend/opencv/database/MNIST.hpp"
-#include "aidge/data/Tensor.hpp"
-#include "aidge/data/DataProvider.hpp"
-
-
-// #include "aidge/backend/opencv/data/TensorImpl.hpp"
-// #include "aidge/backend/cpu/data/TensorImpl.hpp"
-
-using namespace Aidge;
-
-TEST_CASE("DataProvider instanciation & test mnist","[Data][OpenCV]") {
-
-    // Create database
-    std::string path = "/data1/is156025/tb256203/dev/eclipse_aidge/aidge/user_tests/test_mnist_database";
-    bool train = false;
-    MNIST mnist(path, train);
-
-    // DataProvider settings
-    unsigned int batchSize = 256;
-    unsigned int number_batch = std::ceil(mnist.getLen() / batchSize);
-
-    // Instanciate the dataloader
-    DataProvider provider(mnist, batchSize);
-
-    // Perform the tests on the batches
-    for (unsigned int i = 0; i < number_batch; ++i){
-        auto batch = provider.readBatch(i*batchSize);
-        auto data_batch_ptr = static_cast<uint8_t*>(batch[0]->getImpl()->rawPtr());
-        auto label_batch_ptr = static_cast<int*>(batch[1]->getImpl()->rawPtr());
-
-        for (unsigned int s = 0; s < batchSize; ++s){
-            auto data = mnist.getItem(i*batchSize+s)[0];
-            auto label = mnist.getItem(i*batchSize+s)[1];
-            unsigned int size_data = data->size();
-            unsigned int size_label = label->size();
-            auto data_ptr = static_cast<uint8_t*>(data->getImpl()->rawPtr());
-            auto label_ptr = static_cast<int*>(label->getImpl()->rawPtr());
-            for (unsigned int j = 0; j < size_data; ++j){
-                auto element_data = data_ptr[j];
-                auto element_data_batch = data_batch_ptr[size_data*s+j];
-                REQUIRE(element_data == element_data_batch);
-            }
-            for (unsigned int j = 0; j < size_label; ++j){
-                auto element_label = label_ptr[j];
-                auto element_label_batch = label_batch_ptr[size_label*s+j];
-                REQUIRE(element_label == element_label_batch);
-            }
-        }
-    }
-}
\ No newline at end of file
diff --git a/unit_tests/Test_Stimulus.cpp b/unit_tests/Test_Stimulus.cpp
index 7ad5613cdaece960c08ee2d4915bf1f97b6d65f5..a02a71180e4cdb5eee1fb539a2c2083567a76cfa 100644
--- a/unit_tests/Test_Stimulus.cpp
+++ b/unit_tests/Test_Stimulus.cpp
@@ -19,17 +19,37 @@
 #include "aidge/backend/opencv/data/TensorImpl.hpp"
 #include "aidge/data/Tensor.hpp"
 
+#include "Tools.hpp"
 
 using namespace Aidge;
 
 TEST_CASE("Stimulus creation", "[Stimulus][OpenCV]") {
     SECTION("Instanciation & load an image") {
-        //  Load image with imread
-        cv::Mat true_mat = cv::imread("/data1/is156025/tb256203/dev/eclipse_aidge/aidge/user_tests/train-images-idx3-ubyte[00001].pgm", cv::IMREAD_UNCHANGED);
-        REQUIRE(true_mat.empty()==false);
+        // //  Load image with imread
+        // cv::Mat true_mat = cv::imread("/data1/is156025/tb256203/dev/eclipse_aidge/aidge/user_tests/train-images-idx3-ubyte[00001].pgm", cv::IMREAD_UNCHANGED);
+        // REQUIRE(true_mat.empty()==false);
+
+        // // Create Stimulus
+        // Stimulus stimg("/data1/is156025/tb256203/dev/eclipse_aidge/aidge/user_tests/train-images-idx3-ubyte[00001].pgm", true);
+        // stimg.setBackend("opencv");
+        
+        //  Generate random matrix and save it
+        std::vector<cv::Mat> channels;
+        cv::Mat true_mat;
+
+        for (int c = 0; c < 3; ++c){
+            // Create a random matrix
+            cv::Mat randomMat = createRandomMat<unsigned char>(224, 224);
+            // Add each random matrix to the vector
+            channels.push_back(randomMat);
+        }
+        // Merge the vector of cv mat into one cv mat
+        cv::merge(channels, true_mat);
+
+        cv::imwrite("output_image.png", true_mat);
 
         // Create Stimulus
-        Stimulus stimg("/data1/is156025/tb256203/dev/eclipse_aidge/aidge/user_tests/train-images-idx3-ubyte[00001].pgm", true);
+        Stimulus stimg("output_image.png", true);
         stimg.setBackend("opencv");
 
         // Load the image in a tensor & save it in memory
@@ -38,10 +58,21 @@ TEST_CASE("Stimulus creation", "[Stimulus][OpenCV]") {
 
         // Access the cv::Mat with the tensor
         TensorImpl_opencv_* tImpl_opencv = dynamic_cast<TensorImpl_opencv_*>(tensor_load->getImpl().get());
+        auto mat_tensor = tImpl_opencv->data();
+
+        // Check the dimensions
+        REQUIRE((mat_tensor.total() * mat_tensor.channels()) == (true_mat.total() * true_mat.channels()));
 
-        REQUIRE((tImpl_opencv->data().total() * tImpl_opencv->data().channels()) == (true_mat.total() * true_mat.channels()));
-        REQUIRE(cv::countNonZero(tImpl_opencv->data() != true_mat) == 0);
+        // Split it in channels
+        std::vector<cv::Mat> channels_tensor;
+        cv::split(mat_tensor, channels_tensor);
 
+        REQUIRE(channels_tensor.size() == channels.size());
+
+        // Check the elements
+        for (size_t i = 0; i < channels_tensor.size(); ++i) {
+            REQUIRE(cv::countNonZero(channels_tensor[i] != channels[i]) == 0);   
+        }
 
         // This time the tensor is already loaded in memory
         std::shared_ptr<Tensor> tensor_load_2;
@@ -49,9 +80,20 @@ TEST_CASE("Stimulus creation", "[Stimulus][OpenCV]") {
 
         // Access the cv::Mat with the tensor
         TensorImpl_opencv_* tImpl_opencv_2 = dynamic_cast<TensorImpl_opencv_*>(tensor_load_2->getImpl().get());
+        auto mat_tensor_2 = tImpl_opencv_2->data();
+
+        // Check the dimensions
+        REQUIRE((mat_tensor_2.total() * mat_tensor_2.channels()) == (true_mat.total() * true_mat.channels()));
+
+        // Split it in channels
+        std::vector<cv::Mat> channels_tensor_2;
+        cv::split(mat_tensor_2, channels_tensor_2);
 
-        REQUIRE((tImpl_opencv_2->data().total() * tImpl_opencv_2->data().channels()) == (true_mat.total() * true_mat.channels()));
-        REQUIRE(cv::countNonZero(tImpl_opencv_2->data() != true_mat) == 0);
+        REQUIRE(channels_tensor_2.size() == channels.size());
 
+        // Check the elements
+        for (size_t i = 0; i < channels_tensor_2.size(); ++i) {
+            REQUIRE(cv::countNonZero(channels_tensor_2[i] != channels[i]) == 0);   
+        }
     }
 }
diff --git a/unit_tests/Test_StimulusImpl_opencv_imread.cpp b/unit_tests/Test_StimulusImpl_opencv_imread.cpp
index d84e65ee8a32d06067428ba76eb5eb0aaccb0296..4fd5a994443278c1cc5dbce11e517fa6235e80b8 100644
--- a/unit_tests/Test_StimulusImpl_opencv_imread.cpp
+++ b/unit_tests/Test_StimulusImpl_opencv_imread.cpp
@@ -19,27 +19,60 @@
 #include "aidge/backend/opencv/data/TensorImpl.hpp"
 #include "aidge/data/Tensor.hpp"
 
+#include "Tools.hpp"
 
 using namespace Aidge;
 
 TEST_CASE("StimulusImpl_opencv_imread creation", "[StimulusImpl_opencv_imread][OpenCV]") {
     SECTION("Instanciation & load an image") {
-        //  Load image with imread
-        // cv::Mat true_mat = cv::imread("/data1/is156025/tb256203/dev/eclipse_aidge/aidge/user_tests/Lenna.png");
-        cv::Mat true_mat = cv::imread("/data1/is156025/tb256203/dev/eclipse_aidge/aidge/user_tests/train-images-idx3-ubyte[00001].pgm", cv::IMREAD_UNCHANGED);
-        REQUIRE(true_mat.empty()==false);
-
-        // Create StimulusImpl_opencv_imread
-        // StimulusImpl_opencv_imread stImpl("/data1/is156025/tb256203/dev/eclipse_aidge/aidge/user_tests/Lenna.png");
-        StimulusImpl_opencv_imread stImpl("/data1/is156025/tb256203/dev/eclipse_aidge/aidge/user_tests/train-images-idx3-ubyte[00001].pgm");
+        // //  Load image with imread
+        // // cv::Mat true_mat = cv::imread("/data1/is156025/tb256203/dev/eclipse_aidge/aidge/user_tests/Lenna.png");
+        // cv::Mat true_mat = cv::imread("/data1/is156025/tb256203/dev/eclipse_aidge/aidge/user_tests/train-images-idx3-ubyte[00001].pgm", cv::IMREAD_UNCHANGED);
+        // REQUIRE(true_mat.empty()==false);
+
+        // // Create StimulusImpl_opencv_imread
+        // // StimulusImpl_opencv_imread stImpl("/data1/is156025/tb256203/dev/eclipse_aidge/aidge/user_tests/Lenna.png");
+        // StimulusImpl_opencv_imread stImpl("/data1/is156025/tb256203/dev/eclipse_aidge/aidge/user_tests/train-images-idx3-ubyte[00001].pgm");
+        
+         //  Generate random matrix and save it
+        std::vector<cv::Mat> channels;
+        cv::Mat true_mat;
+
+        for (int c = 0; c < 3; ++c){
+            // Create a random matrix
+            cv::Mat randomMat = createRandomMat<unsigned char>(224, 224);
+            // Add each random matrix to the vector
+            channels.push_back(randomMat);
+        }
+        // Merge the vector of cv mat into one cv mat
+        cv::merge(channels, true_mat);
+
+        // Save image into a png file
+        cv::imwrite("output_image_stimpl.png", true_mat);
+
+        // Instanciate timulusImpl_opencv_imread
+        StimulusImpl_opencv_imread stImpl("output_image_stimpl.png");
+
+        // Load the image as a tensor
         std::shared_ptr<Tensor> tensor_load;
         tensor_load = stImpl.load();
 
         // Access the cv::Mat with the tensor
         TensorImpl_opencv_* tImpl_opencv = dynamic_cast<TensorImpl_opencv_*>(tensor_load->getImpl().get());
+        auto mat_tensor = tImpl_opencv->data();
+
+        // Check the dimensions
+        REQUIRE((mat_tensor.total() * mat_tensor.channels()) == (true_mat.total() * true_mat.channels()));
+
+        // Split it in channels
+        std::vector<cv::Mat> channels_tensor;
+        cv::split(mat_tensor, channels_tensor);
 
-        REQUIRE((tImpl_opencv->data().total() * tImpl_opencv->data().channels()) == (true_mat.total() * true_mat.channels()));
-        REQUIRE(cv::countNonZero(tImpl_opencv->data() != true_mat) == 0);
+        REQUIRE(channels_tensor.size() == channels.size());
 
+        // Check the elements
+        for (size_t i = 0; i < channels_tensor.size(); ++i) {
+            REQUIRE(cv::countNonZero(channels_tensor[i] != channels[i]) == 0);   
+        }
     }
 }
diff --git a/unit_tests/Tests_Utils.cpp b/unit_tests/Tests_Utils.cpp
index bd01df9b9f51c53e68135c554ab3497d3e5a19c1..5f6cd7103c1afaa673898d71db6c5c05fdfd1bfe 100644
--- a/unit_tests/Tests_Utils.cpp
+++ b/unit_tests/Tests_Utils.cpp
@@ -21,18 +21,10 @@
 #include "aidge/backend/opencv/data/TensorImpl.hpp"
 #include "aidge/backend/cpu/data/TensorImpl.hpp"
 
+#include "Tools.hpp"
 
 using namespace Aidge;
 
-template <typename T>
-cv::Mat createRandomMat(int rows, int cols) {
-    cv::Mat randomMat(rows, cols, cv::DataType<T>::type);
-
-    cv::randu(randomMat, cv::Scalar::all(0), cv::Scalar::all(255));
-
-    return randomMat;
-}
-
 // TEMPLATE_TEST_CASE("Opencv Utils", "[Utils][OpenCV]", char, unsigned char, short, unsigned short, int, float, double) {
 // TODO : perform test for char and double
 TEMPLATE_TEST_CASE("Opencv Utils", "[Utils][OpenCV]", signed char, unsigned char, short, unsigned short, int, float, double) {
@@ -73,21 +65,17 @@ TEMPLATE_TEST_CASE("Opencv Utils", "[Utils][OpenCV]", signed char, unsigned char
             REQUIRE(mat.cols == tensorOcv->dims()[0]);
             REQUIRE(mat.channels() == tensorOcv->dims()[2]);
 
-            // Check the matrix inside the tensor coorresponds to the matrix
+            //Get the matrix inside the tensor
             TensorImpl_opencv_* tImpl_opencv = dynamic_cast<TensorImpl_opencv_*>(tensorOcv->getImpl().get());
             auto mat_tensor = tImpl_opencv->data();
-            
-            REQUIRE(mat_tensor.size() == mat.size());
-            REQUIRE(cv::countNonZero(mat_tensor != mat) == 0);
-
-            // Convert opencv tensor to cpu tensor
-            auto tensorCpu = convertCpu(tensorOcv);
-
             // Split the mat from tensor opencv into channels
             std::vector<cv::Mat> channels_split;
             cv::split(mat_tensor, channels_split);
 
-            // Get the ptr to the std::vector<TestType> as a void * with rawPtr()
+            // Convert opencv tensor to cpu tensor
+            auto tensorCpu = convertCpu(tensorOcv);
+
+            // Get the cpu ptr of the converted tensor
             auto cpu_ptr = static_cast<TestType*>(tensorCpu->getImpl()->rawPtr());
 
             // Compare the tensor cpu values with the cv mat in an elementwise fashion
diff --git a/unit_tests/Tools.hpp b/unit_tests/Tools.hpp
new file mode 100644
index 0000000000000000000000000000000000000000..0ade0c54c11ca35ce52fbe26491e77af80fa31c4
--- /dev/null
+++ b/unit_tests/Tools.hpp
@@ -0,0 +1,26 @@
+/********************************************************************************
+ * Copyright (c) 2023 CEA-List
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License 2.0 which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ *
+ ********************************************************************************/
+
+#ifndef AIDGE_OPENCV_TOOLS_H_
+#define AIDGE_OPENCV_TOOLS_H_
+
+#include "opencv2/core.hpp"
+
+template <typename T>
+cv::Mat createRandomMat(int rows, int cols) {
+    cv::Mat randomMat(rows, cols, cv::DataType<T>::type);
+
+    cv::randu(randomMat, cv::Scalar::all(0), cv::Scalar::all(255));
+
+    return randomMat;
+}
+
+#endif // AIDGE_OPENCV_TESTS_UTILS_H_
\ No newline at end of file