diff --git a/README.md b/README.md
index 86c4c3190e703e8ba35ee8e441c7d66aaf4003d0..305c3a0c0db2e441b053ebe12cdc505cf3492b3b 100644
--- a/README.md
+++ b/README.md
@@ -45,9 +45,12 @@ Run the image processing benchmark:
 *ii. Please replace `<kernel name>` with name of the kernel which is to be used for*
 *benchmarking as specifed in `include/ImageProcessing/Kernels.h`.*
 
+*ii. Please replace `<kernelmorph name>` with name of the unsigned int kernel which is to be used for*
+*benchmarking as specifed in `include/ImageProcessing/Kernels.h`.*
+
 *iii. Please replace `<Boundary Option>` with `CONSTANT_PADDING` or `REPLICATE_PADDING`.*
 
-Ex. `./image-processing-benchmark ../../benchmarks/ImageProcessing/Images/YuTu.png laplacianKernelAlign CONSTANT_PADDING`
+Ex. `./image-processing-benchmark ../../benchmarks/ImageProcessing/Images/YuTu.png random3x3KernelAlign random3x3KernelAlignInt CONSTANT_PADDING`
 ```
 $ cd buddy-benchmark
 $ mkdir build && cd build
@@ -57,7 +60,7 @@ $ cmake -G Ninja .. \
     -DEIGEN_DIR=/PATH/TO/EIGEN/SOURCE/CODE \
     -DBUDDY_OPT_BUILD_DIR=/PATH/TO/BUDDY-MLIR/BUILD/
 $ ninja image-processing-benchmark
-$ cd bin && ./image-processing-benchmark <image path> <kernel name> <Boundary Option>
+$ cd bin && ./image-processing-benchmark <image path> <kernel name> <kernelmorph name> <Boundary Option>
 ```
 
 ## Deep Learning Benchmark
diff --git a/benchmarks/ImageProcessing/BuddyMorph2D.mlir b/benchmarks/ImageProcessing/BuddyMorph2D.mlir
new file mode 100644
index 0000000000000000000000000000000000000000..d1d9b7f7dc71a053a2ae74eb1669edaae3337762
--- /dev/null
+++ b/benchmarks/ImageProcessing/BuddyMorph2D.mlir
@@ -0,0 +1,103 @@
+//===- BuddyMorph2D.mlir ---------------------------------------------------===//
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//     http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file provides Buddy Morpholgical operations.
+//
+//===----------------------------------------------------------------------===//
+
+func.func @erosion_2d_constant_padding(%inputImage : memref<?x?xf32>, %kernel : memref<?x?xf32>, %outputImage : memref<?x?xf32>, %copymemref : memref<?x?xf32>, %centerX : index, %centerY : index, %iterations : index, %constantValue: f32)
+{
+  dip.erosion_2d <CONSTANT_PADDING> %inputImage, %kernel, %outputImage, %copymemref, %centerX, %centerY, %iterations, %constantValue: memref<?x?xf32>, memref<?x?xf32>, memref<?x?xf32>, memref<?x?xf32>, index, index, index, f32
+  return
+}
+
+func.func @erosion_2d_replicate_padding(%inputImage : memref<?x?xf32>, %kernel : memref<?x?xf32>, %outputImage : memref<?x?xf32>, %copymemref : memref<?x?xf32>, %centerX : index, %centerY : index, %iterations : index, %constantValue : f32)
+{
+  dip.erosion_2d <REPLICATE_PADDING> %inputImage, %kernel, %outputImage, %copymemref, %centerX, %centerY, %iterations, %constantValue : memref<?x?xf32>, memref<?x?xf32>, memref<?x?xf32>, memref<?x?xf32>, index, index, index, f32
+  return
+}
+
+func.func @dilation_2d_constant_padding(%inputImage : memref<?x?xf32>, %kernel : memref<?x?xf32>, %outputImage : memref<?x?xf32>, %copymemref : memref<?x?xf32>, %centerX : index, %centerY : index, %iterations : index, %constantValue: f32)
+{
+  dip.dilation_2d <CONSTANT_PADDING> %inputImage,  %kernel, %outputImage, %copymemref, %centerX, %centerY, %iterations, %constantValue : memref<?x?xf32>, memref<?x?xf32>, memref<?x?xf32>, memref<?x?xf32>, index, index, index, f32
+  return
+}
+
+func.func @dilation_2d_replicate_padding(%inputImage : memref<?x?xf32>, %kernel : memref<?x?xf32>, %outputImage : memref<?x?xf32>, %copymemref : memref<?x?xf32>, %centerX : index, %centerY : index, %iterations : index, %constantValue : f32)
+{
+  dip.dilation_2d <REPLICATE_PADDING> %inputImage, %kernel, %outputImage, %copymemref, %centerX, %centerY, %iterations, %constantValue : memref<?x?xf32>, memref<?x?xf32>, memref<?x?xf32>, memref<?x?xf32>, index, index, index, f32
+  return
+}
+
+func.func @opening_2d_constant_padding(%inputImage : memref<?x?xf32>, %kernel : memref<?x?xf32>, %outputImage : memref<?x?xf32>, %outputImage1 : memref<?x?xf32>, %copymemref : memref<?x?xf32>, %copymemref1 : memref<?x?xf32>, %centerX : index, %centerY : index, %iterations : index, %constantValue: f32)
+{
+  dip.opening_2d <CONSTANT_PADDING> %inputImage, %kernel, %outputImage, %outputImage1, %copymemref, %copymemref1, %centerX, %centerY, %iterations, %constantValue : memref<?x?xf32>, memref<?x?xf32>, memref<?x?xf32>, memref<?x?xf32>, memref<?x?xf32>, memref<?x?xf32>, index, index, index, f32
+  return
+}
+
+func.func @opening_2d_replicate_padding(%inputImage : memref<?x?xf32>, %kernel : memref<?x?xf32>, %outputImage : memref<?x?xf32>, %outputImage1 : memref<?x?xf32>, %copymemref : memref<?x?xf32>, %copymemref1 : memref<?x?xf32>, %centerX : index, %centerY : index, %iterations : index, %constantValue : f32)
+{
+  dip.opening_2d <REPLICATE_PADDING> %inputImage, %kernel, %outputImage, %outputImage1, %copymemref, %copymemref1, %centerX, %centerY, %iterations, %constantValue : memref<?x?xf32>, memref<?x?xf32>, memref<?x?xf32>, memref<?x?xf32>, memref<?x?xf32>, memref<?x?xf32>, index, index, index, f32
+  return
+}
+
+func.func @closing_2d_constant_padding(%inputImage : memref<?x?xf32>, %kernel : memref<?x?xf32>, %outputImage : memref<?x?xf32>, %outputImage1 : memref<?x?xf32>, %copymemref : memref<?x?xf32>, %copymemref1 : memref<?x?xf32>, %centerX : index, %centerY : index, %iterations : index, %constantValue: f32)
+{
+  dip.closing_2d <CONSTANT_PADDING> %inputImage, %kernel, %outputImage, %outputImage1, %copymemref, %copymemref1, %centerX, %centerY, %iterations, %constantValue : memref<?x?xf32>, memref<?x?xf32>, memref<?x?xf32>, memref<?x?xf32>, memref<?x?xf32>, memref<?x?xf32>, index, index, index, f32
+  return
+}
+
+func.func @closing_2d_replicate_padding(%inputImage : memref<?x?xf32>, %kernel : memref<?x?xf32>, %outputImage : memref<?x?xf32>, %outputImage1 : memref<?x?xf32>, %copymemref : memref<?x?xf32>, %copymemref1 : memref<?x?xf32>, %centerX : index, %centerY : index, %iterations : index, %constantValue : f32)
+{
+  dip.closing_2d <REPLICATE_PADDING> %inputImage,  %kernel, %outputImage, %outputImage1, %copymemref, %copymemref1, %centerX, %centerY, %iterations, %constantValue : memref<?x?xf32>, memref<?x?xf32>, memref<?x?xf32>,memref<?x?xf32>, memref<?x?xf32>, memref<?x?xf32>, index, index, index, f32
+  return
+}
+
+func.func @tophat_2d_constant_padding(%inputImage : memref<?x?xf32>, %kernel : memref<?x?xf32>, %outputImage : memref<?x?xf32>, %outputImage1 : memref<?x?xf32>,%outputImage2 : memref<?x?xf32>, %inputImage1 : memref<?x?xf32>, %copymemref : memref<?x?xf32>, %copymemref1 : memref<?x?xf32>, %centerX : index, %centerY : index, %iterations : index, %constantValue: f32)
+{
+  dip.tophat_2d <CONSTANT_PADDING> %inputImage, %kernel, %outputImage, %outputImage1, %outputImage2, %inputImage1, %copymemref, %copymemref1, %centerX, %centerY, %iterations, %constantValue : memref<?x?xf32>, memref<?x?xf32>, memref<?x?xf32>, memref<?x?xf32>, memref<?x?xf32>, memref<?x?xf32>, memref<?x?xf32>, memref<?x?xf32>, index, index, index, f32
+  return
+}
+
+func.func @tophat_2d_replicate_padding(%inputImage : memref<?x?xf32>, %kernel : memref<?x?xf32>, %outputImage : memref<?x?xf32>, %outputImage1 : memref<?x?xf32>, %outputImage2 : memref<?x?xf32>, %inputImage1 : memref<?x?xf32>, %copymemref : memref<?x?xf32>, %copymemref1 : memref<?x?xf32>, %centerX : index, %centerY : index, %iterations : index, %constantValue : f32)
+{
+  dip.tophat_2d <REPLICATE_PADDING> %inputImage, %kernel, %outputImage, %outputImage1, %outputImage2, %inputImage1, %copymemref, %copymemref1, %centerX, %centerY, %iterations, %constantValue : memref<?x?xf32>, memref<?x?xf32>, memref<?x?xf32>, memref<?x?xf32>, memref<?x?xf32>, memref<?x?xf32>, memref<?x?xf32>, memref<?x?xf32>, index, index, index, f32
+  return
+}
+
+func.func @bottomhat_2d_constant_padding(%inputImage : memref<?x?xf32>, %kernel : memref<?x?xf32>, %outputImage : memref<?x?xf32>, %outputImage1 : memref<?x?xf32>, %outputImage2 : memref<?x?xf32>, %inputImage1 : memref<?x?xf32>, %copymemref : memref<?x?xf32>, %copymemref1 : memref<?x?xf32>, %centerX : index, %centerY : index, %iterations : index, %constantValue: f32)
+{
+  dip.bottomhat_2d <CONSTANT_PADDING> %inputImage, %kernel, %outputImage, %outputImage1, %outputImage2, %inputImage1, %copymemref, %copymemref1, %centerX, %centerY, %iterations, %constantValue : memref<?x?xf32>, memref<?x?xf32>, memref<?x?xf32>, memref<?x?xf32>, memref<?x?xf32>, memref<?x?xf32>, memref<?x?xf32>, memref<?x?xf32>, index, index, index, f32
+  return
+}
+
+func.func @bottomhat_2d_replicate_padding(%inputImage : memref<?x?xf32>, %kernel : memref<?x?xf32>, %outputImage : memref<?x?xf32>, %outputImage1 : memref<?x?xf32>, %outputImage2 : memref<?x?xf32>, %inputImage1 : memref<?x?xf32>, %copymemref : memref<?x?xf32>, %copymemref1 : memref<?x?xf32>, %centerX : index, %centerY : index, %iterations : index, %constantValue : f32)
+{
+  dip.bottomhat_2d <REPLICATE_PADDING> %inputImage, %kernel, %outputImage, %outputImage1, %outputImage2, %inputImage1, %copymemref, %copymemref1, %centerX, %centerY, %iterations, %constantValue : memref<?x?xf32>, memref<?x?xf32>, memref<?x?xf32>, memref<?x?xf32>, memref<?x?xf32>, memref<?x?xf32>, memref<?x?xf32>, memref<?x?xf32>, index, index, index, f32
+  return
+}
+
+func.func @morphgrad_2d_constant_padding(%inputImage : memref<?x?xf32>, %kernel : memref<?x?xf32>, %outputImage : memref<?x?xf32>, %outputImage1 : memref<?x?xf32>,%outputImage2 : memref<?x?xf32>, %inputImage1 : memref<?x?xf32>, %copymemref : memref<?x?xf32>, %copymemref1 : memref<?x?xf32>, %centerX : index, %centerY : index,%iterations : index, %constantValue: f32)
+{
+  dip.morphgrad_2d <CONSTANT_PADDING> %inputImage, %kernel, %outputImage, %outputImage1, %outputImage2,  %inputImage1, %copymemref, %copymemref1, %centerX, %centerY, %iterations, %constantValue : memref<?x?xf32>, memref<?x?xf32>, memref<?x?xf32>, memref<?x?xf32>, memref<?x?xf32>, memref<?x?xf32>, memref<?x?xf32>, memref<?x?xf32>, index, index,index, f32
+  return
+}
+
+func.func @morphgrad_2d_replicate_padding(%inputImage : memref<?x?xf32>, %kernel : memref<?x?xf32>, %outputImage : memref<?x?xf32>, %outputImage1 : memref<?x?xf32>,%outputImage2 : memref<?x?xf32>, %inputImage1 : memref<?x?xf32>, %copymemref : memref<?x?xf32>, %copymemref1 : memref<?x?xf32>, %centerX : index, %centerY : index, %iterations : index, %constantValue : f32)
+{
+  dip.morphgrad_2d <REPLICATE_PADDING> %inputImage, %kernel, %outputImage, %outputImage1,%outputImage2, %inputImage1, %copymemref, %copymemref1, %centerX, %centerY, %iterations, %constantValue : memref<?x?xf32>, memref<?x?xf32>, memref<?x?xf32>, memref<?x?xf32>, memref<?x?xf32>, memref<?x?xf32>, memref<?x?xf32>, memref<?x?xf32>, index, index, index, f32
+  return
+}
diff --git a/benchmarks/ImageProcessing/BuddyMorph2DBenchmark.cpp b/benchmarks/ImageProcessing/BuddyMorph2DBenchmark.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..62f1d1affc3b3ac1bff53416169c5b0fa570a1ae
--- /dev/null
+++ b/benchmarks/ImageProcessing/BuddyMorph2DBenchmark.cpp
@@ -0,0 +1,832 @@
+//===- BuddyMorph2DBenchmark.cpp -------------------------------------------===//
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//     http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file implements the benchmark for Morph2D operation.
+//
+//===----------------------------------------------------------------------===//
+
+#include "ImageProcessing/Kernels.h"
+#include "Utils/Container.h"
+#include <benchmark/benchmark.h>
+#include <opencv2/opencv.hpp>
+
+using namespace cv;
+using namespace std;
+
+// Declare the C interface
+
+extern "C" {
+void _mlir_ciface_erosion_2d_constant_padding(
+    MemRef<float, 2> inputBuddyMorph2D, MemRef<float, 2> *kernelBuddyMorph2D,
+    MemRef<float, 2> *outputBuddyErosion2D,
+    MemRef<float, 2> *copyMemRefErosion2D, unsigned int centerX,
+    unsigned int centerY, unsigned int iterations, float constantValue);
+
+void _mlir_ciface_erosion_2d_replicate_padding(
+    MemRef<float, 2> inputBuddyMorph2D, MemRef<float, 2> *kernelBuddyMorph2D,
+    MemRef<float, 2> *outputBuddyErosion2D,
+    MemRef<float, 2> *copyMemRefErosion2D, unsigned int centerX,
+    unsigned int centerY, unsigned int iterations, float constantValue);
+
+void _mlir_ciface_dilation_2d_constant_padding(
+    MemRef<float, 2> inputBuddyMorph2D, MemRef<float, 2> *kernelBuddyMorph2D,
+    MemRef<float, 2> *outputBuddyDilation2D,
+    MemRef<float, 2> *copyMemRefDilation2D, unsigned int centerX,
+    unsigned int centerY, unsigned int iterations, float constantValue);
+
+void _mlir_ciface_dilation_2d_replicate_padding(
+    MemRef<float, 2> inputBuddyMorph2D, MemRef<float, 2> *kernelBuddyMorph2D,
+    MemRef<float, 2> *outputBuddyDilation2D,
+    MemRef<float, 2> *copyMemRefDilation2D, unsigned int centerX,
+    unsigned int centerY, unsigned int iterations, float constantValue);
+
+void _mlir_ciface_opening_2d_constant_padding(
+    MemRef<float, 2> inputBuddyMorph2D, MemRef<float, 2> *kernelBuddyMorph2D,
+    MemRef<float, 2> *outputBuddyOpening2D,
+    MemRef<float, 2> *outputBuddyOpening2D1,
+    MemRef<float, 2> *copyMemRefOpening2D,
+    MemRef<float, 2> *copyMemRefOpening2D1, unsigned int centerX,
+    unsigned int centerY, unsigned int iterations, float constantValue);
+
+void _mlir_ciface_opening_2d_replicate_padding(
+    MemRef<float, 2> inputBuddyMorph2D, MemRef<float, 2> *kernelBuddyMorph2D,
+    MemRef<float, 2> *outputBuddyOpening2D,
+    MemRef<float, 2> *outputBuuddyOpening2D1,
+    MemRef<float, 2> *copyMemRefOpening2D,
+    MemRef<float, 2> *copyMemRefOpening2D1, unsigned int centerX,
+    unsigned int centerY, unsigned int iterations, float constantValue);
+
+void _mlir_ciface_closing_2d_constant_padding(
+    MemRef<float, 2> inputBuddyMorph2D, MemRef<float, 2> *kernelBuddyMorph2D,
+    MemRef<float, 2> *outputBuddyClosing2D,
+    MemRef<float, 2> *outputBuddyClosing2D1,
+    MemRef<float, 2> *copyMemRefClosing2D,
+    MemRef<float, 2> *copyMemRefClosing2D1, unsigned int centerX,
+    unsigned int centerY, unsigned int iterations, float constantValue);
+
+void _mlir_ciface_closing_2d_replicate_padding(
+    MemRef<float, 2> inputBuddyMorph2D, MemRef<float, 2> *kernelBuddyMorph2D,
+    MemRef<float, 2> *outputBuddyClosing2D,
+    MemRef<float, 2> *outputBuuddyClosing2D1,
+    MemRef<float, 2> *copyMemRefClosing2D,
+    MemRef<float, 2> *copyMemRefClosing2D1, unsigned int centerX,
+    unsigned int centerY, unsigned int iterations, float constantValue);
+
+void _mlir_ciface_tophat_2d_constant_padding(
+    MemRef<float, 2> inputBuddyMorph2D, MemRef<float, 2> *kernelBuddyMorph2D,
+    MemRef<float, 2> *outputBuddyTopHat2D,
+    MemRef<float, 2> *outputBuddyTopHat2D1,
+    MemRef<float, 2> *outputBuddyTopHat2D2,
+    MemRef<float, 2> *inputBuddyTopHat2D1, MemRef<float, 2> *copyMemRefTopHat2D,
+    MemRef<float, 2> *copyMemRefTopHat2D1, unsigned int centerX,
+    unsigned int centerY, unsigned int iterations, float constantValue);
+
+void _mlir_ciface_tophat_2d_replicate_padding(
+    MemRef<float, 2> inputBuddyMorph2D, MemRef<float, 2> *kernelBuddyMorph2D,
+    MemRef<float, 2> *outputBuddyTopHat2D,
+    MemRef<float, 2> *outputBuddyTopHat2D1,
+    MemRef<float, 2> *outputBuddyTopHat2D2,
+    MemRef<float, 2> *inputBuddyTopHat2D1, MemRef<float, 2> *copyMemRefTopHat2D,
+    MemRef<float, 2> *copyMemRefTopHat2D1, unsigned int centerX,
+    unsigned int centerY, unsigned int iterations, float constantValue);
+
+void _mlir_ciface_bottomhat_2d_constant_padding(
+    MemRef<float, 2> inputBuddyMorph2D, MemRef<float, 2> *kernelBuddyMorph2D,
+    MemRef<float, 2> *outputBuddyBottomHat2D,
+    MemRef<float, 2> *outputBuddyBottomHat2D1,
+    MemRef<float, 2> *outputBuddyBottomHat2D2,
+    MemRef<float, 2> *inputBuddyBottomHat2D1,
+    MemRef<float, 2> *copyMemRefBottomHat2D,
+    MemRef<float, 2> *copyMemRefBottomHat2D1, unsigned int centerX,
+    unsigned int centerY, unsigned int iterations, float constantValue);
+
+void _mlir_ciface_bottomhat_2d_replicate_padding(
+    MemRef<float, 2> inputBuddyMorph2D, MemRef<float, 2> *kernelBuddyMorph2D,
+    MemRef<float, 2> *outputBuddyBottomHat2D,
+    MemRef<float, 2> *outputBuddyBottomHat2D1,
+    MemRef<float, 2> *outputBuddyBottomHat2D2,
+    MemRef<float, 2> *inputBuddyBottomHat2D1,
+    MemRef<float, 2> *copyMemRefBottomHat2D,
+    MemRef<float, 2> *copyMemRefBottomHat2D1, unsigned int centerX,
+    unsigned int centerY, unsigned int iterations, float constantValue);
+
+void _mlir_ciface_morphgrad_2d_constant_padding(
+    MemRef<float, 2> inputBuddyMorph2D, MemRef<float, 2> *kernelBuddyMorph2D,
+    MemRef<float, 2> *outputBuddyMorphGrad2D,
+    MemRef<float, 2> *outputBuddyMorphGrad2D1,
+    MemRef<float, 2> *outputBuddyMorphGrad2D2,
+    MemRef<float, 2> *inputBuddyMorphGrad2D1,
+    MemRef<float, 2> *copyMemRefMorphGrad2D,
+    MemRef<float, 2> *copyMemRefMorphGrad2D1, unsigned int centerX,
+    unsigned int centerY, unsigned int iterations, float constantValue);
+
+void _mlir_ciface_morphgrad_2d_replicate_padding(
+    MemRef<float, 2> inputBuddyMorph2D, MemRef<float, 2> *kernelBuddyMorph2D,
+    MemRef<float, 2> *outputBuddyMorphGrad2D,
+    MemRef<float, 2> *outputBuddyMorphGrad2D1,
+    MemRef<float, 2> *outputBuddyMorphGrad2D2,
+    MemRef<float, 2> *inputBuddyMorphGrad2D1,
+    MemRef<float, 2> *copyMemRefMorphGrad2D,
+    MemRef<float, 2> *copyMemRefMorphGrad2D1, unsigned int centerX,
+    unsigned int centerY, unsigned int iterations, float constantValue);
+}
+
+// Declare input image and kernel.
+Mat inputImageBuddyMorph2D, kernelBuddyMorph2DMat;
+
+// Define the kernel size.
+int kernelRowsBuddyMorph2D, kernelColsBuddyMorph2D;
+
+// Define the output size.
+int outputRowsBuddyMorph2D, outputColsBuddyMorph2D;
+
+// Define sizes of input, kernel, and output.
+intptr_t sizesInputBuddyMorph2D[2];
+intptr_t sizesKernelBuddyMorph2D[2];
+intptr_t sizesOutputBuddyMorph2D[2];
+
+// Declare Boundary Options supported.
+enum BoundaryOption { constant_padding, replicate_padding };
+
+// Define Boundary option selected.
+BoundaryOption BoundaryType1;
+
+void initializeBuddyMorph2D(char **argv) {
+  inputImageBuddyMorph2D = imread(argv[1], IMREAD_GRAYSCALE);
+  kernelBuddyMorph2DMat =
+      Mat(get<1>(kernelMap[argv[2]]), get<2>(kernelMap[argv[2]]), CV_32FC1,
+          get<0>(kernelMap[argv[2]]));
+
+  kernelRowsBuddyMorph2D = kernelBuddyMorph2DMat.rows;
+  kernelColsBuddyMorph2D = kernelBuddyMorph2DMat.cols;
+
+  outputRowsBuddyMorph2D = inputImageBuddyMorph2D.rows;
+  outputColsBuddyMorph2D = inputImageBuddyMorph2D.cols;
+
+  sizesInputBuddyMorph2D[0] = inputImageBuddyMorph2D.rows;
+  sizesInputBuddyMorph2D[1] = inputImageBuddyMorph2D.cols;
+
+  sizesKernelBuddyMorph2D[0] = kernelRowsBuddyMorph2D;
+  sizesKernelBuddyMorph2D[1] = kernelColsBuddyMorph2D;
+
+  sizesOutputBuddyMorph2D[0] = outputRowsBuddyMorph2D;
+  sizesOutputBuddyMorph2D[1] = outputColsBuddyMorph2D;
+
+  if (static_cast<string>(argv[3]) == "REPLICATE_PADDING") {
+    BoundaryType1 = replicate_padding;
+  } else {
+    BoundaryType1 = constant_padding;
+  }
+}
+MemRef<float, 2> inputBuddyMorph2D(inputImageBuddyMorph2D,
+                                   sizesInputBuddyMorph2D);
+MemRef<float, 2> kernelBuddyMorph2D(kernelBuddyMorph2DMat,
+                                    sizesKernelBuddyMorph2D);
+static void Buddy_Erosion2D_Constant_Padding(benchmark::State &state) {
+  // Define the MemRef descriptor for input, kernel, and output.
+
+  MemRef<float, 2> outputBuddyErosion2D(sizesOutputBuddyMorph2D);
+  MemRef<float, 2> copyMemRefErosion2D(sizesOutputBuddyMorph2D, 256.f);
+
+  for (auto _ : state) {
+    for (int i = 0; i < state.range(0); ++i) {
+      _mlir_ciface_erosion_2d_constant_padding(
+          inputBuddyMorph2D, &kernelBuddyMorph2D, &outputBuddyErosion2D,
+          &copyMemRefErosion2D, 1 /* Center X */, 1 /* Center Y */, 1,
+          0.0f /* Constant Value */);
+    }
+  }
+}
+
+static void Buddy_Erosion2D_Replicate_Padding(benchmark::State &state) {
+  // Define the MemRef descriptor for input, kernel, and output.
+  MemRef<float, 2> outputBuddyErosion2D(sizesOutputBuddyMorph2D);
+  MemRef<float, 2> copyMemRefErosion2D(sizesOutputBuddyMorph2D, 256.f);
+
+  for (auto _ : state) {
+    for (int i = 0; i < state.range(0); ++i) {
+      _mlir_ciface_erosion_2d_replicate_padding(
+          inputBuddyMorph2D, &kernelBuddyMorph2D, &outputBuddyErosion2D,
+          &copyMemRefErosion2D, 1 /* Center X */, 1 /* Center Y */, 1,
+          0.0f /* Constant Value */);
+    }
+  }
+}
+
+static void Buddy_Dilation2D_Constant_Padding(benchmark::State &state) {
+  // Define the MemRef descriptor for input, kernel, and output.
+  MemRef<float, 2> outputBuddyDilation2D(sizesOutputBuddyMorph2D);
+  MemRef<float, 2> copyMemRefDilation2D(sizesOutputBuddyMorph2D, -1.f);
+
+  for (auto _ : state) {
+    for (int i = 0; i < state.range(0); ++i) {
+      _mlir_ciface_dilation_2d_constant_padding(
+          inputBuddyMorph2D, &kernelBuddyMorph2D, &outputBuddyDilation2D,
+          &copyMemRefDilation2D, 1 /* Center X */, 1 /* Center Y */, 1,
+          0.0f /* Constant Value */);
+    }
+  }
+}
+
+static void Buddy_Dilation2D_Replicate_Padding(benchmark::State &state) {
+  // Define the MemRef descriptor for input, kernel, and output.
+  MemRef<float, 2> outputBuddyDilation2D(sizesOutputBuddyMorph2D);
+  MemRef<float, 2> copyMemRefDilation2D(sizesOutputBuddyMorph2D, -1.f);
+
+  for (auto _ : state) {
+    for (int i = 0; i < state.range(0); ++i) {
+      _mlir_ciface_dilation_2d_replicate_padding(
+          inputBuddyMorph2D, &kernelBuddyMorph2D, &outputBuddyDilation2D,
+          &copyMemRefDilation2D, 1 /* Center X */, 1 /* Center Y */, 1,
+          0.0f /* Constant Value */);
+    }
+  }
+}
+
+static void Buddy_Opening2D_Constant_Padding(benchmark::State &state) {
+  // Define the MemRef descriptor for input, kernel, and output.
+
+  MemRef<float, 2> outputBuddyOpening2D(sizesOutputBuddyMorph2D);
+  MemRef<float, 2> outputBuddyOpening2D1(sizesOutputBuddyMorph2D);
+  MemRef<float, 2> copyMemRefOpening2D(sizesOutputBuddyMorph2D, -1.f);
+  MemRef<float, 2> copyMemRefOpening2D1(sizesOutputBuddyMorph2D, 256.f);
+
+  for (auto _ : state) {
+    for (int i = 0; i < state.range(0); ++i) {
+      _mlir_ciface_opening_2d_constant_padding(
+          inputBuddyMorph2D, &kernelBuddyMorph2D, &outputBuddyOpening2D,
+          &outputBuddyOpening2D1, &copyMemRefOpening2D, &copyMemRefOpening2D1,
+          1 /* Center X */, 1 /* Center Y */, 1, 0.0f /* Constant Value */);
+    }
+  }
+}
+
+static void Buddy_Opening2D_Replicate_Padding(benchmark::State &state) {
+  // Define the MemRef descriptor for input, kernel, and output.
+
+  MemRef<float, 2> outputBuddyOpening2D(sizesOutputBuddyMorph2D);
+  MemRef<float, 2> outputBuddyOpening2D1(sizesOutputBuddyMorph2D);
+  MemRef<float, 2> copyMemRefOpening2D(sizesOutputBuddyMorph2D, -1.f);
+  MemRef<float, 2> copyMemRefOpening2D1(sizesOutputBuddyMorph2D, 256.f);
+
+  for (auto _ : state) {
+    for (int i = 0; i < state.range(0); ++i) {
+      _mlir_ciface_opening_2d_replicate_padding(
+          inputBuddyMorph2D, &kernelBuddyMorph2D, &outputBuddyOpening2D,
+          &outputBuddyOpening2D1, &copyMemRefOpening2D, &copyMemRefOpening2D1,
+          1 /* Center X */, 1 /* Center Y */, 1, 0.0f /* Constant Value */);
+    }
+  }
+}
+
+static void Buddy_Closing2D_Constant_Padding(benchmark::State &state) {
+  // Define the MemRef descriptor for input, kernel, and output.
+
+  MemRef<float, 2> outputBuddyClosing2D(sizesOutputBuddyMorph2D);
+  MemRef<float, 2> outputBuddyClosing2D1(sizesOutputBuddyMorph2D);
+  MemRef<float, 2> copyMemRefClosing2D(sizesOutputBuddyMorph2D, -1.f);
+  MemRef<float, 2> copyMemRefClosing2D1(sizesOutputBuddyMorph2D, 256.f);
+
+  for (auto _ : state) {
+    for (int i = 0; i < state.range(0); ++i) {
+      _mlir_ciface_closing_2d_constant_padding(
+          inputBuddyMorph2D, &kernelBuddyMorph2D, &outputBuddyClosing2D,
+          &outputBuddyClosing2D1, &copyMemRefClosing2D, &copyMemRefClosing2D1,
+          1 /* Center X */, 1 /* Center Y */, 1, 0.0f /* Constant Value */);
+    }
+  }
+}
+
+static void Buddy_Closing2D_Replicate_Padding(benchmark::State &state) {
+  // Define the MemRef descriptor for input, kernel, and output.
+
+  MemRef<float, 2> outputBuddyClosing2D(sizesOutputBuddyMorph2D);
+  MemRef<float, 2> outputBuddyClosing2D1(sizesOutputBuddyMorph2D);
+  MemRef<float, 2> copyMemRefClosing2D(sizesOutputBuddyMorph2D, -1.f);
+  MemRef<float, 2> copyMemRefClosing2D1(sizesOutputBuddyMorph2D, 256.f);
+
+  for (auto _ : state) {
+    for (int i = 0; i < state.range(0); ++i) {
+      _mlir_ciface_closing_2d_replicate_padding(
+          inputBuddyMorph2D, &kernelBuddyMorph2D, &outputBuddyClosing2D,
+          &outputBuddyClosing2D1, &copyMemRefClosing2D, &copyMemRefClosing2D1,
+          1 /* Center X */, 1 /* Center Y */, 1, 0.0f /* Constant Value */);
+    }
+  }
+}
+
+static void Buddy_TopHat2D_Constant_Padding(benchmark::State &state) {
+  // Define the MemRef descriptor for input, kernel, and output.
+
+  MemRef<float, 2> inputBuddyTopHat2D1(sizesInputBuddyMorph2D);
+  MemRef<float, 2> outputBuddyTopHat2D(sizesOutputBuddyMorph2D);
+  MemRef<float, 2> outputBuddyTopHat2D1(sizesOutputBuddyMorph2D);
+  MemRef<float, 2> outputBuddyTopHat2D2(sizesOutputBuddyMorph2D);
+  MemRef<float, 2> copyMemRefTopHat2D(sizesOutputBuddyMorph2D, 256.f);
+  MemRef<float, 2> copyMemRefTopHat2D1(sizesOutputBuddyMorph2D, -1.f);
+
+  for (auto _ : state) {
+    for (int i = 0; i < state.range(0); ++i) {
+      _mlir_ciface_tophat_2d_constant_padding(
+          inputBuddyMorph2D, &kernelBuddyMorph2D, &outputBuddyTopHat2D,
+          &outputBuddyTopHat2D1, &outputBuddyTopHat2D2, &inputBuddyTopHat2D1,
+          &copyMemRefTopHat2D, &copyMemRefTopHat2D1, 1 /* Center X */,
+          1 /* Center Y */, 1, 0.0f /* Constant Value */);
+    }
+  }
+}
+
+static void Buddy_TopHat2D_Replicate_Padding(benchmark::State &state) {
+  // Define the MemRef descriptor for input, kernel, and output.
+  MemRef<float, 2> inputBuddyTopHat2D1(sizesInputBuddyMorph2D);
+  MemRef<float, 2> outputBuddyTopHat2D(sizesOutputBuddyMorph2D);
+  MemRef<float, 2> outputBuddyTopHat2D1(sizesOutputBuddyMorph2D);
+  MemRef<float, 2> outputBuddyTopHat2D2(sizesOutputBuddyMorph2D);
+  MemRef<float, 2> copyMemRefTopHat2D(sizesOutputBuddyMorph2D, 256.f);
+  MemRef<float, 2> copyMemRefTopHat2D1(sizesOutputBuddyMorph2D, -1.f);
+
+  for (auto _ : state) {
+    for (int i = 0; i < state.range(0); ++i) {
+      _mlir_ciface_tophat_2d_replicate_padding(
+          inputBuddyMorph2D, &kernelBuddyMorph2D, &outputBuddyTopHat2D,
+          &outputBuddyTopHat2D1, &outputBuddyTopHat2D2, &inputBuddyTopHat2D1,
+          &copyMemRefTopHat2D, &copyMemRefTopHat2D1, 1 /* Center X */,
+          1 /* Center Y */, 1, 0.0f /* Constant Value */);
+    }
+  }
+}
+
+static void Buddy_BottomHat2D_Constant_Padding(benchmark::State &state) {
+  // Define the MemRef descriptor for input, kernel, and output.
+  MemRef<float, 2> inputBuddyBottomHat2D1(sizesInputBuddyMorph2D);
+  MemRef<float, 2> outputBuddyBottomHat2D(sizesOutputBuddyMorph2D);
+  MemRef<float, 2> outputBuddyBottomHat2D1(sizesOutputBuddyMorph2D);
+  MemRef<float, 2> outputBuddyBottomHat2D2(sizesOutputBuddyMorph2D);
+  MemRef<float, 2> copyMemRefBottomHat2D(sizesOutputBuddyMorph2D, 256.f);
+  MemRef<float, 2> copyMemRefBottomHat2D1(sizesOutputBuddyMorph2D, -1.f);
+
+  for (auto _ : state) {
+    for (int i = 0; i < state.range(0); ++i) {
+      _mlir_ciface_bottomhat_2d_constant_padding(
+          inputBuddyMorph2D, &kernelBuddyMorph2D, &outputBuddyBottomHat2D,
+          &outputBuddyBottomHat2D1, &outputBuddyBottomHat2D2,
+          &inputBuddyBottomHat2D1, &copyMemRefBottomHat2D,
+          &copyMemRefBottomHat2D1, 1 /* Center X */, 1 /* Center Y */, 1,
+          0.0f /* Constant Value */);
+    }
+  }
+}
+
+static void Buddy_BottomHat2D_Replicate_Padding(benchmark::State &state) {
+  // Define the MemRef descriptor for input, kernel, and output.
+  MemRef<float, 2> inputBuddyBottomHat2D1(sizesInputBuddyMorph2D);
+  MemRef<float, 2> outputBuddyBottomHat2D(sizesOutputBuddyMorph2D);
+  MemRef<float, 2> outputBuddyBottomHat2D1(sizesOutputBuddyMorph2D);
+  MemRef<float, 2> outputBuddyBottomHat2D2(sizesOutputBuddyMorph2D);
+  MemRef<float, 2> copyMemRefBottomHat2D(sizesOutputBuddyMorph2D, 256.f);
+  MemRef<float, 2> copyMemRefBottomHat2D1(sizesOutputBuddyMorph2D, -1.f);
+
+  for (auto _ : state) {
+    for (int i = 0; i < state.range(0); ++i) {
+      _mlir_ciface_bottomhat_2d_replicate_padding(
+          inputBuddyMorph2D, &kernelBuddyMorph2D, &outputBuddyBottomHat2D,
+          &outputBuddyBottomHat2D1, &outputBuddyBottomHat2D2,
+          &inputBuddyBottomHat2D1, &copyMemRefBottomHat2D,
+          &copyMemRefBottomHat2D1, 1 /* Center X */, 1 /* Center Y */, 1,
+          0.0f /* Constant Value */);
+    }
+  }
+}
+
+static void Buddy_MorphGrad2D_Constant_Padding(benchmark::State &state) {
+  // Define the MemRef descriptor for input, kernel, and output.
+  MemRef<float, 2> inputBuddyMorphGrad2D1(sizesInputBuddyMorph2D);
+  MemRef<float, 2> outputBuddyMorphGrad2D(sizesOutputBuddyMorph2D);
+  MemRef<float, 2> outputBuddyMorphGrad2D1(sizesOutputBuddyMorph2D);
+  MemRef<float, 2> outputBuddyMorphGrad2D2(sizesOutputBuddyMorph2D);
+  MemRef<float, 2> copyMemRefMorphGrad2D(sizesOutputBuddyMorph2D, 256.f);
+  MemRef<float, 2> copyMemRefMorphGrad2D1(sizesOutputBuddyMorph2D, -1.f);
+
+  for (auto _ : state) {
+    for (int i = 0; i < state.range(0); ++i) {
+      _mlir_ciface_morphgrad_2d_constant_padding(
+          inputBuddyMorph2D, &kernelBuddyMorph2D, &outputBuddyMorphGrad2D,
+          &outputBuddyMorphGrad2D1, &outputBuddyMorphGrad2D2,
+          &inputBuddyMorphGrad2D1, &copyMemRefMorphGrad2D,
+          &copyMemRefMorphGrad2D1, 1 /* Center X */, 1 /* Center Y */, 1,
+          0.0f /* Constant Value */);
+    }
+  }
+}
+
+static void Buddy_MorphGrad2D_Replicate_Padding(benchmark::State &state) {
+  // Define the MemRef descriptor for input, kernel, and output.
+  MemRef<float, 2> inputBuddyMorphGrad2D1(sizesInputBuddyMorph2D);
+  MemRef<float, 2> outputBuddyMorphGrad2D(sizesOutputBuddyMorph2D);
+  MemRef<float, 2> outputBuddyMorphGrad2D1(sizesOutputBuddyMorph2D);
+  MemRef<float, 2> outputBuddyMorphGrad2D2(sizesOutputBuddyMorph2D);
+  MemRef<float, 2> copyMemRefMorphGrad2D(sizesOutputBuddyMorph2D, 256.f);
+  MemRef<float, 2> copyMemRefMorphGrad2D1(sizesOutputBuddyMorph2D, -1.f);
+
+  for (auto _ : state) {
+    for (int i = 0; i < state.range(0); ++i) {
+      _mlir_ciface_morphgrad_2d_replicate_padding(
+          inputBuddyMorph2D, &kernelBuddyMorph2D, &outputBuddyMorphGrad2D,
+          &outputBuddyMorphGrad2D1, &outputBuddyMorphGrad2D2,
+          &inputBuddyMorphGrad2D1, &copyMemRefMorphGrad2D,
+          &copyMemRefMorphGrad2D1, 1 /* Center X */, 1 /* Center Y */, 1,
+          0.0f /* Constant Value */);
+    }
+  }
+}
+
+// Register benchmarking function.
+void registerBenchmarkBuddyErosion2D() {
+  if (BoundaryType1 == replicate_padding) {
+    BENCHMARK(Buddy_Erosion2D_Replicate_Padding)->Arg(1);
+  } else {
+    BENCHMARK(Buddy_Erosion2D_Constant_Padding)->Arg(1);
+  }
+}
+
+// Register benchmarking function.
+void registerBenchmarkBuddyDilation2D() {
+  if (BoundaryType1 == replicate_padding) {
+    BENCHMARK(Buddy_Dilation2D_Replicate_Padding)->Arg(1);
+  } else {
+    BENCHMARK(Buddy_Dilation2D_Constant_Padding)->Arg(1);
+  }
+}
+
+// Register benchmarking function.
+void registerBenchmarkBuddyOpening2D() {
+  if (BoundaryType1 == replicate_padding) {
+    BENCHMARK(Buddy_Opening2D_Replicate_Padding)->Arg(1);
+  } else {
+    BENCHMARK(Buddy_Opening2D_Constant_Padding)->Arg(1);
+  }
+}
+
+// Register benchmarking function.
+void registerBenchmarkBuddyClosing2D() {
+  if (BoundaryType1 == replicate_padding) {
+    BENCHMARK(Buddy_Closing2D_Replicate_Padding)->Arg(1);
+  } else {
+    BENCHMARK(Buddy_Closing2D_Constant_Padding)->Arg(1);
+  }
+}
+
+// Register benchmarking function.
+void registerBenchmarkBuddyTopHat2D() {
+  if (BoundaryType1 == replicate_padding) {
+    BENCHMARK(Buddy_TopHat2D_Replicate_Padding)->Arg(1);
+  } else {
+    BENCHMARK(Buddy_TopHat2D_Constant_Padding)->Arg(1);
+  }
+}
+
+// Register benchmarking function.
+void registerBenchmarkBuddyBottomHat2D() {
+  if (BoundaryType1 == replicate_padding) {
+    BENCHMARK(Buddy_BottomHat2D_Replicate_Padding)->Arg(1);
+  } else {
+    BENCHMARK(Buddy_BottomHat2D_Constant_Padding)->Arg(1);
+  }
+}
+
+// Register benchmarking function.
+void registerBenchmarkBuddyMorphGrad2D() {
+  if (BoundaryType1 == replicate_padding) {
+    BENCHMARK(Buddy_MorphGrad2D_Replicate_Padding)->Arg(1);
+  } else {
+    BENCHMARK(Buddy_MorphGrad2D_Constant_Padding)->Arg(1);
+  }
+}
+
+// Generate result image.
+void generateResultBuddyErosion2D(char **argv) {
+  // Define the MemRef descriptor for input, kernel, and output.
+  MemRef<float, 2> input = inputBuddyMorph2D;
+  MemRef<float, 2> kernel = kernelBuddyMorph2D;
+  MemRef<float, 2> output(sizesOutputBuddyMorph2D);
+  MemRef<float, 2> copyMemRef(sizesOutputBuddyMorph2D, 256.f);
+  // Run the 2D Erosionelation.
+  if (static_cast<string>(argv[3]) == "REPLICATE_PADDING") {
+    _mlir_ciface_erosion_2d_replicate_padding(
+        input, &kernel, &output, &copyMemRef, 1 /* Center X */,
+        1 /* Center Y */, 1, 0.0f /* Constant Value */);
+  } else {
+    _mlir_ciface_erosion_2d_constant_padding(
+        input, &kernel, &output, &copyMemRef, 1 /* Center X */,
+        1 /* Center Y */, 1, 0.0f /* Constant Value */);
+  }
+
+  // Define a cv::Mat with the output of the Erosionelation.
+  Mat outputImage(outputRowsBuddyMorph2D, outputColsBuddyMorph2D, CV_32FC1,
+                  output.getData());
+
+  // Choose a PNG compression level
+  vector<int> compressionParams;
+  compressionParams.push_back(IMWRITE_PNG_COMPRESSION);
+  compressionParams.push_back(9);
+
+  // Write output to PNG.
+  bool result = false;
+  try {
+    result =
+        imwrite("ResultBuddyErosion2D.png", outputImage, compressionParams);
+  } catch (const cv::Exception &ex) {
+    fprintf(stderr, "Exception converting image to PNG format: %s\n",
+            ex.what());
+  }
+  if (result)
+    cout << "Saved PNG file." << endl;
+  else
+    cout << "ERROR: Can't save PNG file." << endl;
+}
+
+// Generate result image.
+void generateResultBuddyDilation2D(char **argv) {
+  // Define the MemRef descriptor for input, kernel, and output.
+  MemRef<float, 2> input = inputBuddyMorph2D;
+  MemRef<float, 2> kernel = kernelBuddyMorph2D;
+  MemRef<float, 2> output(sizesOutputBuddyMorph2D);
+  MemRef<float, 2> copymemref(sizesOutputBuddyMorph2D, -1.f);
+  // Run the 2D Dilationelation.
+  if (static_cast<string>(argv[3]) == "REPLICATE_PADDING") {
+    _mlir_ciface_dilation_2d_replicate_padding(
+        input, &kernel, &output, &copymemref, 1 /* Center X */,
+        1 /* Center Y */, 1, 0.0f /* Constant Value */);
+  } else {
+    _mlir_ciface_dilation_2d_constant_padding(
+        input, &kernel, &output, &copymemref, 1 /* Center X */,
+        1 /* Center Y */, 1, 0.0f /* Constant Value */);
+  }
+
+  // Define a cv::Mat with the output of the Dilationelation.
+  Mat outputImage(outputRowsBuddyMorph2D, outputColsBuddyMorph2D, CV_32FC1,
+                  output.getData());
+
+  // Choose a PNG compression level
+  vector<int> compressionParams;
+  compressionParams.push_back(IMWRITE_PNG_COMPRESSION);
+  compressionParams.push_back(9);
+
+  // Write output to PNG.
+  bool result = false;
+  try {
+    result =
+        imwrite("ResultBuddyDilation2D.png", outputImage, compressionParams);
+  } catch (const cv::Exception &ex) {
+    fprintf(stderr, "Exception converting image to PNG format: %s\n",
+            ex.what());
+  }
+  if (result)
+    cout << "Saved PNG file." << endl;
+  else
+    cout << "ERROR: Can't save PNG file." << endl;
+}
+
+// Generate result image.
+void generateResultBuddyOpening2D(char **argv) {
+  // Define the MemRef descriptor for input, kernel, and output.
+  MemRef<float, 2> input = inputBuddyMorph2D;
+  MemRef<float, 2> kernel = kernelBuddyMorph2D;
+  MemRef<float, 2> output(sizesOutputBuddyMorph2D);
+  MemRef<float, 2> output1(sizesOutputBuddyMorph2D);
+  MemRef<float, 2> copymemref(sizesOutputBuddyMorph2D, -1.f);
+  MemRef<float, 2> copymemref1(sizesOutputBuddyMorph2D, 256.f);
+  // Run the 2D Opening operation
+  if (static_cast<string>(argv[3]) == "REPLICATE_PADDING") {
+    _mlir_ciface_opening_2d_replicate_padding(
+        input, &kernel, &output, &output1, &copymemref, &copymemref1,
+        1 /* Center X */, 1 /* Center Y */, 1, 0.0f /* Constant Value */);
+  } else {
+    _mlir_ciface_opening_2d_constant_padding(
+        input, &kernel, &output, &output1, &copymemref, &copymemref1,
+        1 /* Center X */, 1 /* Center Y */, 1, 0.0f /* Constant Value */);
+  }
+
+  // Define a cv::Mat with the output of the Opening
+  Mat outputImage(outputRowsBuddyMorph2D, outputColsBuddyMorph2D, CV_32FC1,
+                  output.getData());
+
+  // Choose a PNG compression level
+  vector<int> compressionParams;
+  compressionParams.push_back(IMWRITE_PNG_COMPRESSION);
+  compressionParams.push_back(9);
+
+  // Write output to PNG.
+  bool result = false;
+  try {
+    result =
+        imwrite("ResultBuddyOpening2D.png", outputImage, compressionParams);
+  } catch (const cv::Exception &ex) {
+    fprintf(stderr, "Exception converting image to PNG format: %s\n",
+            ex.what());
+  }
+  if (result)
+    cout << "Saved PNG file." << endl;
+  else
+    cout << "ERROR: Can't save PNG file." << endl;
+}
+
+// Generate result image.
+void generateResultBuddyClosing2D(char **argv) {
+  // Define the MemRef descriptor for input, kernel, and output.
+  MemRef<float, 2> input = inputBuddyMorph2D;
+  MemRef<float, 2> kernel = kernelBuddyMorph2D;
+  MemRef<float, 2> output(sizesOutputBuddyMorph2D);
+  MemRef<float, 2> output1(sizesOutputBuddyMorph2D);
+  MemRef<float, 2> copymemref(sizesOutputBuddyMorph2D, -1.f);
+  MemRef<float, 2> copymemref1(sizesOutputBuddyMorph2D, 256.f);
+  // Run the 2D Closing operation
+  if (static_cast<string>(argv[3]) == "REPLICATE_PADDING") {
+    _mlir_ciface_closing_2d_replicate_padding(
+        input, &kernel, &output, &output1, &copymemref, &copymemref1,
+        1 /* Center X */, 1 /* Center Y */, 1, 0.0f /* Constant Value */);
+  } else {
+    _mlir_ciface_closing_2d_constant_padding(
+        input, &kernel, &output, &output1, &copymemref, &copymemref1,
+        1 /* Center X */, 1 /* Center Y */, 1, 0.0f /* Constant Value */);
+  }
+
+  // Define a cv::Mat with the output of the Closing
+  Mat outputImage(outputRowsBuddyMorph2D, outputColsBuddyMorph2D, CV_32FC1,
+                  output.getData());
+
+  // Choose a PNG compression level
+  vector<int> compressionParams;
+  compressionParams.push_back(IMWRITE_PNG_COMPRESSION);
+  compressionParams.push_back(9);
+
+  // Write output to PNG.
+  bool result = false;
+  try {
+    result =
+        imwrite("ResultBuddyClosing2D.png", outputImage, compressionParams);
+  } catch (const cv::Exception &ex) {
+    fprintf(stderr, "Exception converting image to PNG format: %s\n",
+            ex.what());
+  }
+  if (result)
+    cout << "Saved PNG file." << endl;
+  else
+    cout << "ERROR: Can't save PNG file." << endl;
+}
+
+// Generate result image.
+void generateResultBuddyTopHat2D(char **argv) {
+  // Define the MemRef descriptor for input, kernel, and output.
+  MemRef<float, 2> input = inputBuddyMorph2D;
+  MemRef<float, 2> kernel = kernelBuddyMorph2D;
+  MemRef<float, 2> output(sizesOutputBuddyMorph2D);
+  MemRef<float, 2> output1(sizesOutputBuddyMorph2D);
+  MemRef<float, 2> output2(sizesOutputBuddyMorph2D);
+  MemRef<float, 2> input1(sizesOutputBuddyMorph2D);
+  MemRef<float, 2> copymemref(sizesOutputBuddyMorph2D, 256.f);
+  MemRef<float, 2> copymemref1(sizesOutputBuddyMorph2D, -1.f);
+  // Run the 2D TopHat operation
+  if (static_cast<string>(argv[3]) == "REPLICATE_PADDING") {
+    _mlir_ciface_tophat_2d_replicate_padding(
+        input, &kernel, &output, &output1, &output2, &input1, &copymemref,
+        &copymemref1, 1 /* Center X */, 1 /* Center Y */, 1,
+        0.0f /* Constant Value */);
+  } else {
+    _mlir_ciface_tophat_2d_constant_padding(
+        input, &kernel, &output, &output1, &output2, &input1, &copymemref,
+        &copymemref1, 1 /* Center X */, 1 /* Center Y */, 1,
+        0.0f /* Constant Value */);
+  }
+
+  // Define a cv::Mat with the output of the TopHat
+  Mat outputImage(outputRowsBuddyMorph2D, outputColsBuddyMorph2D, CV_32FC1,
+                  output.getData());
+
+  // Choose a PNG compression level
+  vector<int> compressionParams;
+  compressionParams.push_back(IMWRITE_PNG_COMPRESSION);
+  compressionParams.push_back(9);
+
+  // Write output to PNG.
+  bool result = false;
+  try {
+    result = imwrite("ResultBuddyTopHat2D.png", outputImage, compressionParams);
+  } catch (const cv::Exception &ex) {
+    fprintf(stderr, "Exception converting image to PNG format: %s\n",
+            ex.what());
+  }
+  if (result)
+    cout << "Saved PNG file." << endl;
+  else
+    cout << "ERROR: Can't save PNG file." << endl;
+}
+
+// Generate result image.
+void generateResultBuddyBottomHat2D(char **argv) {
+  // Define the MemRef descriptor for input, kernel, and output.
+  MemRef<float, 2> input = inputBuddyMorph2D;
+  MemRef<float, 2> kernel = kernelBuddyMorph2D;
+  MemRef<float, 2> output(sizesOutputBuddyMorph2D);
+  MemRef<float, 2> output1(sizesOutputBuddyMorph2D);
+  MemRef<float, 2> output2(sizesOutputBuddyMorph2D);
+  MemRef<float, 2> input1(sizesOutputBuddyMorph2D);
+  MemRef<float, 2> copymemref(sizesOutputBuddyMorph2D, 256.f);
+  MemRef<float, 2> copymemref1(sizesOutputBuddyMorph2D, -1.f);
+  // Run the 2D BottomHat operation
+  if (static_cast<string>(argv[3]) == "REPLICATE_PADDING") {
+    _mlir_ciface_bottomhat_2d_replicate_padding(
+        input, &kernel, &output, &output1, &output2, &input1, &copymemref,
+        &copymemref1, 1 /* Center X */, 1 /* Center Y */, 1,
+        0.0f /* Constant Value */);
+  } else {
+    _mlir_ciface_bottomhat_2d_constant_padding(
+        input, &kernel, &output, &output1, &output2, &input1, &copymemref,
+        &copymemref1, 1 /* Center X */, 1 /* Center Y */, 1,
+        0.0f /* Constant Value */);
+  }
+
+  // Define a cv::Mat with the output of the BottomHat
+  Mat outputImage(outputRowsBuddyMorph2D, outputColsBuddyMorph2D, CV_32FC1,
+                  output.getData());
+
+  // Choose a PNG compression level
+  vector<int> compressionParams;
+  compressionParams.push_back(IMWRITE_PNG_COMPRESSION);
+  compressionParams.push_back(9);
+
+  // Write output to PNG.
+  bool result = false;
+  try {
+    result =
+        imwrite("ResultBuddyBottomHat2D.png", outputImage, compressionParams);
+  } catch (const cv::Exception &ex) {
+    fprintf(stderr, "Exception converting image to PNG format: %s\n",
+            ex.what());
+  }
+  if (result)
+    cout << "Saved PNG file." << endl;
+  else
+    cout << "ERROR: Can't save PNG file." << endl;
+}
+
+// Generate result image.
+void generateResultBuddyMorphGrad2D(char **argv) {
+  // Define the MemRef descriptor for input, kernel, and output.
+  MemRef<float, 2> input = inputBuddyMorph2D;
+  MemRef<float, 2> kernel = kernelBuddyMorph2D;
+  MemRef<float, 2> output(sizesOutputBuddyMorph2D);
+  MemRef<float, 2> output1(sizesOutputBuddyMorph2D);
+  MemRef<float, 2> output2(sizesOutputBuddyMorph2D);
+  MemRef<float, 2> input1(sizesOutputBuddyMorph2D);
+  MemRef<float, 2> copymemref(sizesOutputBuddyMorph2D, 256.f);
+  MemRef<float, 2> copymemref1(sizesOutputBuddyMorph2D, -1.f);
+  // Run the 2D MorphGrad operation
+  if (static_cast<string>(argv[3]) == "REPLICATE_PADDING") {
+    _mlir_ciface_morphgrad_2d_replicate_padding(
+        input, &kernel, &output, &output1, &output2, &input1, &copymemref,
+        &copymemref1, 1 /* Center X */, 1 /* Center Y */, 1,
+        0.0f /* Constant Value */);
+  } else {
+    _mlir_ciface_morphgrad_2d_constant_padding(
+        input, &kernel, &output, &output1, &output2, &input1, &copymemref,
+        &copymemref1, 1 /* Center X */, 1 /* Center Y */, 1,
+        0.0f /* Constant Value */);
+  }
+
+  // Define a cv::Mat with the output of the MorphGrad
+  Mat outputImage(outputRowsBuddyMorph2D, outputRowsBuddyMorph2D, CV_32FC1,
+                  output.getData());
+
+  // Choose a PNG compression level
+  vector<int> compressionParams;
+  compressionParams.push_back(IMWRITE_PNG_COMPRESSION);
+  compressionParams.push_back(9);
+
+  // Write output to PNG.
+  bool result = false;
+  try {
+    result =
+        imwrite("ResultBuddyMorphGrad2D.png", outputImage, compressionParams);
+  } catch (const cv::Exception &ex) {
+    fprintf(stderr, "Exception converting image to PNG format: %s\n",
+            ex.what());
+  }
+  if (result)
+    cout << "Saved PNG file." << endl;
+  else
+    cout << "ERROR: Can't save PNG file." << endl;
+}
diff --git a/benchmarks/ImageProcessing/CMakeLists.txt b/benchmarks/ImageProcessing/CMakeLists.txt
index 5d8125b7a92fb34c5303d49b48bab44f701268d9..286c01bf3498ce0f2034fd8ebede9fc44f8189e8 100644
--- a/benchmarks/ImageProcessing/CMakeLists.txt
+++ b/benchmarks/ImageProcessing/CMakeLists.txt
@@ -102,6 +102,22 @@ add_custom_command(OUTPUT buddy-corr2d.o
 add_library(BuddyCorr2D STATIC buddy-corr2d.o)
 set_target_properties(BuddyCorr2D PROPERTIES LINKER_LANGUAGE CXX)
 
+add_custom_command(OUTPUT buddy-morph2d.o
+  COMMAND ${BUDDY_OPT_BUILD_DIR}/bin/buddy-opt 
+          ${BUDDY_SOURCE_DIR}/benchmarks/ImageProcessing/BuddyMorph2D.mlir 
+            -lower-dip="DIP-strip-mining=${SPLITING_SIZE}" 
+            -lower-affine -convert-scf-to-cf -convert-vector-to-llvm 
+            --llvm-request-c-wrappers
+            -convert-memref-to-llvm -convert-func-to-llvm 
+            -reconcile-unrealized-casts | 
+          ${LLVM_MLIR_BINARY_DIR}/mlir-translate --mlir-to-llvmir |
+          ${LLVM_MLIR_BINARY_DIR}/llc -mtriple=${BUDDY_OPT_TRIPLE} 
+            -mattr=${BUDDY_OPT_ATTR} --filetype=obj 
+            -o ${BUDDY_BINARY_DIR}/../benchmarks/ImageProcessing/buddy-morph2d.o
+)
+add_library(BuddyMorph2D STATIC buddy-morph2d.o)
+set_target_properties(BuddyMorph2D PROPERTIES LINKER_LANGUAGE CXX)
+
 #-------------------------------------------------------------------------------
 # Image Processing Benchmark Target
 #-------------------------------------------------------------------------------
@@ -113,6 +129,8 @@ add_executable(image-processing-benchmark
   MLIRConv2DBenchmark.cpp
   BuddyConv2DBenchmark.cpp
   BuddyCorr2DBenchmark.cpp
+  BuddyMorph2DBenchmark.cpp
+  OpenCVMorph2DBenchmark.cpp
   )
 
 target_include_directories(image-processing-benchmark 
@@ -127,6 +145,7 @@ target_link_libraries(image-processing-benchmark
   MLIRConv2D
   BuddyConv2D
   BuddyCorr2D
+  BuddyMorph2D
   Container
   PNGImage
   )
diff --git a/benchmarks/ImageProcessing/Main.cpp b/benchmarks/ImageProcessing/Main.cpp
index 787bd75a2bb38f0ea281efebfc640b677396d4e2..83d949841582cceaf1070de3574e848014e543b6 100644
--- a/benchmarks/ImageProcessing/Main.cpp
+++ b/benchmarks/ImageProcessing/Main.cpp
@@ -24,27 +24,58 @@
 void initializeMLIRConv2D(char **);
 void initializeBuddyConv2D(char **);
 void initializeBuddyCorr2D(char **);
+void initializeBuddyMorph2D(char **);
+void initializeOpenCVMorph2D(char **);
 void initializeOpenCVFilter2D(char **);
 void initializeEigenConvolve2D(char **);
 
 void generateResultBuddyConv2D(char **);
 void generateResultBuddyCorr2D(char **);
+void generateResultBuddyErosion2D(char **);
+void generateResultBuddyOpening2D(char **);
+void generateResultBuddyClosing2D(char **);
+void generateResultBuddyTopHat2D(char **);
+void generateResultBuddyBottomHat2D(char **);
+void generateResultBuddyMorphGrad2D(char **);
+void generateResultBuddyDilation2D(char **);
+void generateResultOpenCVErode2D();
+void generateResultOpenCVDilate2D();
 void generateResultOpenCVFilter2D();
+void generateResultOpenCVOpening2D();
+void generateResultOpenCVClosing2D();
+void generateResultOpenCVTopHat2D();
+void generateResultOpenCVBottomHat2D();
+void generateResultOpenCVMorphGrad2D();
 void generateResultEigenConvolve2D();
 
 void registerBenchmarkBuddyCorr2D();
+void registerBenchmarkBuddyErosion2D();
+void registerBenchmarkBuddyDilation2D();
+void registerBenchmarkBuddyOpening2D();
+void registerBenchmarkBuddyClosing2D();
+void registerBenchmarkBuddyTopHat2D();
+void registerBenchmarkBuddyBottomHat2D();
+void registerBenchmarkBuddyMorphGrad2D();
+void registerBenchmarkOpenCVErode2D();
+void registerBenchmarkOpenCVDilate2D();
+void registerBenchmarkOpenCVOpening2D();
+void registerBenchmarkOpenCVClosing2D();
+void registerBenchmarkOpenCVTopHat2D();
+void registerBenchmarkOpenCVBottomHat2D();
+void registerBenchmarkOpenCVMorphGrad2D();
 void registerBenchmarkOpenCVFilter2D();
 
 // Run benchmarks.
 int main(int argc, char **argv) {
-  if (argc != 4) {
+  if (argc != 5) {
     throw std::invalid_argument(
         "Wrong format of command line arguments.\n"
         "Correct format is ./image-processing-benchmark <image path> <kernel "
-        "name> <Boundary Option>\n where "
+        "name> <kernelmorph> <Boundary Option>\n where "
         "image path provides path of the image to be processed, kernel name "
         "denotes the name "
         "of desired kernel as specified in "
+        "kernelmorph denotes the kernel to be used for morphological operations"
         "include/ImageProcessing/Kernels.h and Boundary options available "
         "are CONSTANT_PADDING, REPLICATE_PADDING.\n");
   }
@@ -52,11 +83,26 @@ int main(int argc, char **argv) {
   initializeMLIRConv2D(argv);
   initializeBuddyConv2D(argv);
   initializeBuddyCorr2D(argv);
+  initializeBuddyMorph2D(argv);
+  initializeOpenCVMorph2D(argv);
   initializeOpenCVFilter2D(argv);
   initializeEigenConvolve2D(argv);
 
   registerBenchmarkBuddyCorr2D();
   registerBenchmarkOpenCVFilter2D();
+  registerBenchmarkBuddyErosion2D();
+  registerBenchmarkBuddyDilation2D();
+  registerBenchmarkBuddyOpening2D();
+  registerBenchmarkBuddyClosing2D();
+  registerBenchmarkBuddyTopHat2D();
+  registerBenchmarkBuddyBottomHat2D();
+  registerBenchmarkOpenCVErode2D();
+  registerBenchmarkOpenCVOpening2D();
+  registerBenchmarkOpenCVClosing2D();
+  registerBenchmarkOpenCVTopHat2D();
+  registerBenchmarkOpenCVBottomHat2D();
+  registerBenchmarkOpenCVMorphGrad2D();
+  registerBenchmarkOpenCVDilate2D();
 
   ::benchmark::Initialize(&argc, argv);
   ::benchmark::RunSpecifiedBenchmarks();
@@ -65,6 +111,20 @@ int main(int argc, char **argv) {
   generateResultOpenCVFilter2D();
   generateResultBuddyConv2D(argv);
   generateResultBuddyCorr2D(argv);
+  generateResultBuddyErosion2D(argv);
+  generateResultBuddyDilation2D(argv);
+  generateResultBuddyOpening2D(argv);
+  generateResultBuddyClosing2D(argv);
+  generateResultBuddyTopHat2D(argv);
+  generateResultBuddyBottomHat2D(argv);
+  generateResultBuddyMorphGrad2D(argv);
+  generateResultOpenCVTopHat2D();
+  generateResultOpenCVBottomHat2D();
+  generateResultOpenCVMorphGrad2D();
+  generateResultOpenCVErode2D();
+  generateResultOpenCVDilate2D();
+  generateResultOpenCVOpening2D();
+  generateResultOpenCVClosing2D();
   generateResultEigenConvolve2D();
 
   return 0;
diff --git a/benchmarks/ImageProcessing/OpenCVMorph2DBenchmark.cpp b/benchmarks/ImageProcessing/OpenCVMorph2DBenchmark.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..49169468f36272dd750677d20980da3634dc467a
--- /dev/null
+++ b/benchmarks/ImageProcessing/OpenCVMorph2DBenchmark.cpp
@@ -0,0 +1,455 @@
+//===- OpenCVMorph2DBenchmark.cpp ----------------------------------------===//
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//     http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file implements the benchmark for OpenCV's Morphological Operations.
+//
+//===----------------------------------------------------------------------===//
+
+#include "ImageProcessing/Kernels.h"
+#include <benchmark/benchmark.h>
+#include <opencv2/opencv.hpp>
+
+using namespace cv;
+using namespace std;
+
+// Declare input image, kernel and output image.
+Mat inputImageMorph2D, kernelMorph2D, outputErode2D, outputDilate2D,
+    outputOpening2D, outputClosing2D, outputTopHat2D, outputBottomHat2D,
+    outputMorphGrad2D;
+
+// Declare Boundary Options supported.
+enum BoundaryOption { constant_padding, replicate_padding };
+
+BoundaryOption OpenCVBoundaryType1;
+
+void initializeOpenCVMorph2D(char **argv) {
+  inputImageMorph2D = imread(argv[1], IMREAD_GRAYSCALE);
+
+  kernelMorph2D = Mat(get<1>(kernelMap1[argv[4]]), get<2>(kernelMap1[argv[4]]),
+                      CV_8UC1, get<0>(kernelMap1[argv[4]]));
+
+  if (static_cast<string>(argv[3]) == "REPLICATE_PADDING") {
+    OpenCVBoundaryType1 = replicate_padding;
+  } else {
+    OpenCVBoundaryType1 = constant_padding;
+  }
+}
+
+// Benchmarking function.
+static void OpenCV_Erode2D_Constant_Padding(benchmark::State &state) {
+  for (auto _ : state) {
+    for (int i = 0; i < state.range(0); ++i) {
+      erode(inputImageMorph2D, outputErode2D, kernelMorph2D, cv::Point(1, 1), 5,
+            cv::BORDER_CONSTANT, 0.0);
+    }
+  }
+}
+
+static void OpenCV_Erode2D_Replicate_Padding(benchmark::State &state) {
+  for (auto _ : state) {
+    for (int i = 0; i < state.range(0); ++i) {
+      erode(inputImageMorph2D, outputErode2D, kernelMorph2D, cv::Point(1, 1), 5,
+            cv::BORDER_REPLICATE, 0.0);
+    }
+  }
+}
+
+// Benchmarking function.
+static void OpenCV_Dilate2D_Constant_Padding(benchmark::State &state) {
+  for (auto _ : state) {
+    for (int i = 0; i < state.range(0); ++i) {
+      dilate(inputImageMorph2D, outputDilate2D, kernelMorph2D, cv::Point(1, 1),
+             5, cv::BORDER_CONSTANT, 0.0);
+    }
+  }
+}
+
+static void OpenCV_Dilate2D_Replicate_Padding(benchmark::State &state) {
+  for (auto _ : state) {
+    for (int i = 0; i < state.range(0); ++i) {
+      dilate(inputImageMorph2D, outputDilate2D, kernelMorph2D, cv::Point(1, 1),
+             5, cv::BORDER_REPLICATE, 0.0);
+    }
+  }
+}
+
+// Benchmarking function.
+static void OpenCV_Opening2D_Constant_Padding(benchmark::State &state) {
+  for (auto _ : state) {
+    for (int i = 0; i < state.range(0); ++i) {
+      cv::morphologyEx(inputImageMorph2D, outputOpening2D, 2, kernelMorph2D,
+                       cv::Point(1, 1), 3, cv::BORDER_CONSTANT, 0.0);
+    }
+  }
+}
+
+static void OpenCV_Opening2D_Replicate_Padding(benchmark::State &state) {
+  for (auto _ : state) {
+    for (int i = 0; i < state.range(0); ++i) {
+      cv::morphologyEx(inputImageMorph2D, outputOpening2D, 2, kernelMorph2D,
+                       cv::Point(1, 1), 3, cv::BORDER_REPLICATE, 0.0);
+    }
+  }
+}
+
+// Benchmarking function.
+static void OpenCV_Closing2D_Constant_Padding(benchmark::State &state) {
+  for (auto _ : state) {
+    for (int i = 0; i < state.range(0); ++i) {
+      cv::morphologyEx(inputImageMorph2D, outputClosing2D, 2, kernelMorph2D,
+                       cv::Point(1, 1), 3, cv::BORDER_CONSTANT, 0.0);
+    }
+  }
+}
+
+static void OpenCV_Closing2D_Replicate_Padding(benchmark::State &state) {
+  for (auto _ : state) {
+    for (int i = 0; i < state.range(0); ++i) {
+      cv::morphologyEx(inputImageMorph2D, outputClosing2D, 2, kernelMorph2D,
+                       cv::Point(1, 1), 3, cv::BORDER_REPLICATE, 0.0);
+    }
+  }
+}
+
+// Benchmarking function.
+static void OpenCV_TopHat2D_Constant_Padding(benchmark::State &state) {
+  for (auto _ : state) {
+    for (int i = 0; i < state.range(0); ++i) {
+      cv::morphologyEx(inputImageMorph2D, outputTopHat2D, 5, kernelMorph2D,
+                       cv::Point(1, 1), 3, cv::BORDER_CONSTANT, 0.0);
+    }
+  }
+}
+
+static void OpenCV_TopHat2D_Replicate_Padding(benchmark::State &state) {
+  for (auto _ : state) {
+    for (int i = 0; i < state.range(0); ++i) {
+      cv::morphologyEx(inputImageMorph2D, outputTopHat2D, 5, kernelMorph2D,
+                       cv::Point(1, 1), 3, cv::BORDER_REPLICATE, 0.0);
+    }
+  }
+}
+
+// Benchmarking function.
+static void OpenCV_BottomHat2D_Constant_Padding(benchmark::State &state) {
+  for (auto _ : state) {
+    for (int i = 0; i < state.range(0); ++i) {
+      cv::morphologyEx(inputImageMorph2D, outputBottomHat2D, 6, kernelMorph2D,
+                       cv::Point(1, 1), 3, cv::BORDER_CONSTANT, 0.0);
+    }
+  }
+}
+
+static void OpenCV_BottomHat2D_Replicate_Padding(benchmark::State &state) {
+  for (auto _ : state) {
+    for (int i = 0; i < state.range(0); ++i) {
+      cv::morphologyEx(inputImageMorph2D, outputBottomHat2D, 6, kernelMorph2D,
+                       cv::Point(1, 1), 3, cv::BORDER_REPLICATE, 0.0);
+    }
+  }
+}
+
+// Benchmarking function.
+static void OpenCV_MorphGrad2D_Constant_Padding(benchmark::State &state) {
+  for (auto _ : state) {
+    for (int i = 0; i < state.range(0); ++i) {
+      cv::morphologyEx(inputImageMorph2D, outputMorphGrad2D, 4, kernelMorph2D,
+                       cv::Point(1, 1), 3, cv::BORDER_CONSTANT, 0.0);
+    }
+  }
+}
+
+static void OpenCV_MorphGrad2D_Replicate_Padding(benchmark::State &state) {
+  for (auto _ : state) {
+    for (int i = 0; i < state.range(0); ++i) {
+      cv::morphologyEx(inputImageMorph2D, outputMorphGrad2D, 4, kernelMorph2D,
+                       cv::Point(1, 1), 3, cv::BORDER_REPLICATE, 0.0);
+    }
+  }
+}
+
+// Register benchmarking function.
+void registerBenchmarkOpenCVErode2D() {
+  if (OpenCVBoundaryType1 == replicate_padding) {
+    BENCHMARK(OpenCV_Erode2D_Replicate_Padding)->Arg(1);
+  } else {
+    BENCHMARK(OpenCV_Erode2D_Constant_Padding)->Arg(1);
+  }
+}
+
+// Register benchmarking function.
+void registerBenchmarkOpenCVDilate2D() {
+  if (OpenCVBoundaryType1 == replicate_padding) {
+    BENCHMARK(OpenCV_Dilate2D_Replicate_Padding)->Arg(1);
+  } else {
+    BENCHMARK(OpenCV_Dilate2D_Constant_Padding)->Arg(1);
+  }
+}
+
+// Register benchmarking function.
+void registerBenchmarkOpenCVOpening2D() {
+  if (OpenCVBoundaryType1 == replicate_padding) {
+    BENCHMARK(OpenCV_Opening2D_Replicate_Padding)->Arg(1);
+  } else {
+    BENCHMARK(OpenCV_Opening2D_Constant_Padding)->Arg(1);
+  }
+}
+
+// Register benchmarking function.
+void registerBenchmarkOpenCVClosing2D() {
+  if (OpenCVBoundaryType1 == replicate_padding) {
+    BENCHMARK(OpenCV_Closing2D_Replicate_Padding)->Arg(1);
+  } else {
+    BENCHMARK(OpenCV_Closing2D_Constant_Padding)->Arg(1);
+  }
+}
+
+// Register benchmarking function.
+void registerBenchmarkOpenCVTopHat2D() {
+  if (OpenCVBoundaryType1 == replicate_padding) {
+    BENCHMARK(OpenCV_TopHat2D_Replicate_Padding)->Arg(1);
+  } else {
+    BENCHMARK(OpenCV_TopHat2D_Constant_Padding)->Arg(1);
+  }
+}
+
+// Register benchmarking function.
+void registerBenchmarkOpenCVBottomHat2D() {
+  if (OpenCVBoundaryType1 == replicate_padding) {
+    BENCHMARK(OpenCV_BottomHat2D_Replicate_Padding)->Arg(1);
+  } else {
+    BENCHMARK(OpenCV_BottomHat2D_Constant_Padding)->Arg(1);
+  }
+}
+
+// Register benchmarking function.
+void registerBenchmarkOpenCVMorphGrad2D() {
+  if (OpenCVBoundaryType1 == replicate_padding) {
+    BENCHMARK(OpenCV_MorphGrad2D_Replicate_Padding)->Arg(1);
+  } else {
+    BENCHMARK(OpenCV_MorphGrad2D_Constant_Padding)->Arg(1);
+  }
+}
+
+// Generate result image.
+void generateResultOpenCVErode2D() {
+  if (OpenCVBoundaryType1 == replicate_padding) {
+    erode(inputImageMorph2D, outputErode2D, kernelMorph2D, cv::Point(1, 1), 5,
+          cv::BORDER_REPLICATE, 0.0);
+  } else {
+    erode(inputImageMorph2D, outputErode2D, kernelMorph2D, cv::Point(1, 1), 5,
+          cv::BORDER_CONSTANT, 0.0);
+  }
+
+  // Choose a PNG compression level
+  vector<int> compressionParams;
+  compressionParams.push_back(IMWRITE_PNG_COMPRESSION);
+  compressionParams.push_back(9);
+
+  // Write output to PNG.
+  bool result = false;
+  try {
+    result =
+        imwrite("ResultOpenCVErode2D.png", outputErode2D, compressionParams);
+  } catch (const cv::Exception &ex) {
+    fprintf(stderr, "Exception converting image to PNG format: %s\n",
+            ex.what());
+  }
+  if (result)
+    cout << "Saved PNG file." << endl;
+  else
+    cout << "ERROR: Can't save PNG file." << endl;
+}
+
+// Generate result image.
+void generateResultOpenCVDilate2D() {
+  if (OpenCVBoundaryType1 == replicate_padding) {
+    dilate(inputImageMorph2D, outputDilate2D, kernelMorph2D, cv::Point(1, 1), 5,
+           cv::BORDER_REPLICATE, 0.0);
+  } else {
+    dilate(inputImageMorph2D, outputDilate2D, kernelMorph2D, cv::Point(1, 1), 5,
+           cv::BORDER_CONSTANT, 0.0);
+  }
+
+  // Choose a PNG compression level
+  vector<int> compressionParams;
+  compressionParams.push_back(IMWRITE_PNG_COMPRESSION);
+  compressionParams.push_back(9);
+
+  // Write output to PNG.
+  bool result = false;
+  try {
+    result =
+        imwrite("ResultOpenCVDilate2D.png", outputDilate2D, compressionParams);
+  } catch (const cv::Exception &ex) {
+    fprintf(stderr, "Exception converting image to PNG format: %s\n",
+            ex.what());
+  }
+  if (result)
+    cout << "Saved PNG file." << endl;
+  else
+    cout << "ERROR: Can't save PNG file." << endl;
+}
+
+// Generate result image.
+void generateResultOpenCVOpening2D() {
+  if (OpenCVBoundaryType1 == replicate_padding) {
+    cv::morphologyEx(inputImageMorph2D, outputOpening2D, 2, kernelMorph2D,
+                     cv::Point(1, 1), 3, cv::BORDER_REPLICATE, 0.0);
+  } else {
+    cv::morphologyEx(inputImageMorph2D, outputOpening2D, 2, kernelMorph2D,
+                     cv::Point(1, 1), 3, cv::BORDER_CONSTANT, 0.0);
+  }
+
+  // Choose a PNG compression level
+  vector<int> compressionParams;
+  compressionParams.push_back(IMWRITE_PNG_COMPRESSION);
+  compressionParams.push_back(9);
+
+  // Write output to PNG.
+  bool result = false;
+  try {
+    result = imwrite("ResultOpenCVOpening2D.png", outputOpening2D,
+                     compressionParams);
+  } catch (const cv::Exception &ex) {
+    fprintf(stderr, "Exception converting image to PNG format: %s\n",
+            ex.what());
+  }
+  if (result)
+    cout << "Saved PNG file." << endl;
+  else
+    cout << "ERROR: Can't save PNG file." << endl;
+}
+
+// Generate result image.
+void generateResultOpenCVClosing2D() {
+  if (OpenCVBoundaryType1 == replicate_padding) {
+    cv::morphologyEx(inputImageMorph2D, outputClosing2D, 2, kernelMorph2D,
+                     cv::Point(1, 1), 3, cv::BORDER_REPLICATE, 0.0);
+  } else {
+    cv::morphologyEx(inputImageMorph2D, outputClosing2D, 2, kernelMorph2D,
+                     cv::Point(1, 1), 3, cv::BORDER_CONSTANT, 0.0);
+  }
+
+  // Choose a PNG compression level
+  vector<int> compressionParams;
+  compressionParams.push_back(IMWRITE_PNG_COMPRESSION);
+  compressionParams.push_back(9);
+
+  // Write output to PNG.
+  bool result = false;
+  try {
+    result = imwrite("ResultOpenCVClosing2D.png", outputClosing2D,
+                     compressionParams);
+  } catch (const cv::Exception &ex) {
+    fprintf(stderr, "Exception converting image to PNG format: %s\n",
+            ex.what());
+  }
+  if (result)
+    cout << "Saved PNG file." << endl;
+  else
+    cout << "ERROR: Can't save PNG file." << endl;
+}
+
+// Generate result image.
+void generateResultOpenCVTopHat2D() {
+  if (OpenCVBoundaryType1 == replicate_padding) {
+    cv::morphologyEx(inputImageMorph2D, outputTopHat2D, 5, kernelMorph2D,
+                     cv::Point(1, 1), 3, cv::BORDER_REPLICATE, 0.0);
+  } else {
+    cv::morphologyEx(inputImageMorph2D, outputTopHat2D, 5, kernelMorph2D,
+                     cv::Point(1, 1), 3, cv::BORDER_CONSTANT, 0.0);
+  }
+
+  // Choose a PNG compression level
+  vector<int> compressionParams;
+  compressionParams.push_back(IMWRITE_PNG_COMPRESSION);
+  compressionParams.push_back(9);
+
+  // Write output to PNG.
+  bool result = false;
+  try {
+    result =
+        imwrite("ResultOpenCVTopHat2D.png", outputTopHat2D, compressionParams);
+  } catch (const cv::Exception &ex) {
+    fprintf(stderr, "Exception converting image to PNG format: %s\n",
+            ex.what());
+  }
+  if (result)
+    cout << "Saved PNG file." << endl;
+  else
+    cout << "ERROR: Can't save PNG file." << endl;
+}
+
+// Generate result image.
+void generateResultOpenCVBottomHat2D() {
+  if (OpenCVBoundaryType1 == replicate_padding) {
+    cv::morphologyEx(inputImageMorph2D, outputBottomHat2D, 6, kernelMorph2D,
+                     cv::Point(1, 1), 3, cv::BORDER_REPLICATE, 0.0);
+  } else {
+    cv::morphologyEx(inputImageMorph2D, outputBottomHat2D, 6, kernelMorph2D,
+                     cv::Point(1, 1), 3, cv::BORDER_CONSTANT, 0.0);
+  }
+
+  // Choose a PNG compression level
+  vector<int> compressionParams;
+  compressionParams.push_back(IMWRITE_PNG_COMPRESSION);
+  compressionParams.push_back(9);
+
+  // Write output to PNG.
+  bool result = false;
+  try {
+    result = imwrite("ResultOpenCVBottomHat2D.png", outputBottomHat2D,
+                     compressionParams);
+  } catch (const cv::Exception &ex) {
+    fprintf(stderr, "Exception converting image to PNG format: %s\n",
+            ex.what());
+  }
+  if (result)
+    cout << "Saved PNG file." << endl;
+  else
+    cout << "ERROR: Can't save PNG file." << endl;
+}
+
+// Generate result image.
+void generateResultOpenCVMorphGrad2D() {
+  if (OpenCVBoundaryType1 == replicate_padding) {
+    cv::morphologyEx(inputImageMorph2D, outputMorphGrad2D, 4, kernelMorph2D,
+                     cv::Point(1, 1), 3, cv::BORDER_REPLICATE, 0.0);
+  } else {
+    cv::morphologyEx(inputImageMorph2D, outputMorphGrad2D, 4, kernelMorph2D,
+                     cv::Point(1, 1), 3, cv::BORDER_CONSTANT, 0.0);
+  }
+
+  // Choose a PNG compression level
+  vector<int> compressionParams;
+  compressionParams.push_back(IMWRITE_PNG_COMPRESSION);
+  compressionParams.push_back(9);
+
+  // Write output to PNG.
+  bool result = false;
+  try {
+    result = imwrite("ResultOpenCVMorphGrad2D.png", outputMorphGrad2D,
+                     compressionParams);
+  } catch (const cv::Exception &ex) {
+    fprintf(stderr, "Exception converting image to PNG format: %s\n",
+            ex.what());
+  }
+  if (result)
+    cout << "Saved PNG file." << endl;
+  else
+    cout << "ERROR: Can't save PNG file." << endl;
+}
diff --git a/include/ImageProcessing/Kernels.h b/include/ImageProcessing/Kernels.h
index ac159f348de44feb1d35c265d598ea9ea78eb98d..afa3109ef3680186e83aa5f0ccc9074925ee6dd7 100644
--- a/include/ImageProcessing/Kernels.h
+++ b/include/ImageProcessing/Kernels.h
@@ -78,6 +78,10 @@ static int logKernelCols = 5;
 static float random3x3KernelAlign[9] = {0, 4, 1, 
                                         3, 3, 8, 
                                         9, 6, 3};
+
+static uint8_t random3x3KernelAlignInt[9] = {0, 4, 1, 
+                                        3, 3, 8, 
+                                        9, 6, 3};                                        
 static int random3x3KernelRows = 3;
 static int random3x3KernelCols = 3;
 
@@ -85,7 +89,7 @@ static float random5x5KernelAlign[25] = {1, 9, 8, 8, 1,
                                          6, 6, 3, 3, 7, 
                                          1, 9, 5, 5, 7, 
                                          4, 5, 4, 3, 2, 
-                                         9, 8, 3, 8, 9};
+                                         9, 8, 3, 8, 9};                                       
 static int random5x5KernelRows = 5;
 static int random5x5KernelCols = 5;
 
@@ -95,7 +99,7 @@ static float random7x7KernelAlign[49] = {6, 3, 1, 5, 1, 9, 4,
                                         4, 5, 2, 6, 3, 9, 1, 
                                         7, 7, 2, 6, 7, 8, 6, 
                                         2, 8, 9, 2, 2, 7, 8, 
-                                        8, 9, 2, 3, 5, 3, 5};
+                                        8, 9, 2, 3, 5, 3, 5};                                      
 static int random7x7KernelRows = 7;
 static int random7x7KernelCols = 7;
 
@@ -107,7 +111,7 @@ static float random9x9KernelAlign[81] = {7, 9, 5, 0, 9, 8, 4, 9, 9,
                                          7, 2, 9, 8, 1, 4, 5, 7, 7, 
                                          7, 3, 4, 4, 3, 3, 4, 0, 7, 
                                          2, 7, 3, 5, 2, 3, 4, 2, 3, 
-                                         9, 5, 2, 7, 7, 4, 8, 7, 2};
+                                         9, 5, 2, 7, 7, 4, 8, 7, 2};                                       
 static int random9x9KernelRows = 9;
 static int random9x9KernelCols = 9;
 
@@ -121,7 +125,7 @@ static float random11x11KernelAlign[121] = {4, 5, 7, 6, 3, 6, 6, 6, 1, 9, 8,
                                             0, 6, 7, 9, 7, 5, 6, 6, 1, 8, 0,
                                             0, 7, 8, 3, 3, 8, 3, 2, 6, 9, 2,
                                             6, 5, 8, 1, 0, 7, 5, 8, 9, 7, 5,
-                                            6, 8, 4, 3, 7, 0, 6, 5, 1, 6, 5};
+                                            6, 8, 4, 3, 7, 0, 6, 5, 1, 6, 5};                                           
 static int random11x11KernelRows = 11;
 static int random11x11KernelCols = 11;
 
@@ -137,7 +141,7 @@ static float random13x13KernelAlign[169] = {8, 0, 6, 6, 7, 3, 4, 0, 6, 1, 5, 4,
                                             3, 1, 5, 4, 0, 7, 9, 4, 0, 2, 9, 3, 2,
                                             0, 4, 4, 1, 4, 6, 2, 8, 9, 7, 6, 8, 2,
                                             8, 2, 0, 6, 6, 3, 0, 1, 8, 0, 8, 9, 6,
-                                            9, 1, 5, 2, 6, 8, 8, 2, 1, 4, 9, 3, 2};
+                                            9, 1, 5, 2, 6, 8, 8, 2, 1, 4, 9, 3, 2};                                          
 static int random13x13KernelRows = 13;
 static int random13x13KernelCols = 13;
 
@@ -173,7 +177,11 @@ static std::map<std::string, std::tuple<float*, int, int>> kernelMap = {
     {"random9x9KernelAlign", {random9x9KernelAlign, random9x9KernelRows, random9x9KernelCols}},
     {"random11x11KernelAlign", {random11x11KernelAlign, random11x11KernelRows, random11x11KernelCols}},
     {"random13x13KernelAlign", {random13x13KernelAlign, random13x13KernelRows, random13x13KernelCols}},
-    {"random15x15KernelAlign", {random15x15KernelAlign, random15x15KernelRows, random15x15KernelCols}}
+    {"random15x15KernelAlign", {random15x15KernelAlign, random15x15KernelRows, random15x15KernelCols}}    
+};
+
+static std::map<std::string, std::tuple<uint8_t*, int, int>> kernelMap1 = {
+    {"random3x3KernelAlignInt", {random3x3KernelAlignInt, random3x3KernelRows, random3x3KernelCols}}
 };
 
 // clang-format on