diff --git a/benchmarks/ImageProcessing/BuddyRotate2DBenchmark.cpp b/benchmarks/ImageProcessing/BuddyRotate2DBenchmark.cpp new file mode 100644 index 00000000..d3fac55f --- /dev/null +++ b/benchmarks/ImageProcessing/BuddyRotate2DBenchmark.cpp @@ -0,0 +1,108 @@ +//===------------ BuddyRotate2DBenchmark.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 Rotate2D operation. +// +//===----------------------------------------------------------------------===// + +#include "Kernels.h" +#include +#include +#include +#include +#include +#include +#include + +using namespace cv; +using namespace std; + +const float angleRad = M_PI * 30.0 / 180; + +// Define the input image. +Img inputBuddyRotate2D; + +// Declare the input name. +std::string inputNameBuddyRotate2D; + +// Define sizes of input and output. +intptr_t sizesInputBuddyRotate2D[2]; +intptr_t sizesOutputBuddyRotate2D[2]; + +void initializeBuddyRotate2D(char **argv, + Img inputImageBuddyRotate2D) { + inputNameBuddyRotate2D = argv[1]; + + sizesInputBuddyRotate2D[0] = inputImageBuddyRotate2D.getSizes()[0]; + sizesInputBuddyRotate2D[1] = inputImageBuddyRotate2D.getSizes()[1]; + + float sinAngle = std::sin(angleRad); + float cosAngle = std::cos(angleRad); + + sizesOutputBuddyRotate2D[0] = + std::round(std::abs(sizesInputBuddyRotate2D[0] * cosAngle) + + std::abs(sizesInputBuddyRotate2D[1] * sinAngle)); + sizesOutputBuddyRotate2D[1] = + std::round(std::abs(sizesInputBuddyRotate2D[0] * sinAngle) + + std::abs(sizesInputBuddyRotate2D[1] * cosAngle)); + inputBuddyRotate2D = inputImageBuddyRotate2D; +} + +// Benchmarking functions. +static void Buddy_Rotate2D(benchmark::State &state) { + // Define the MemRef descriptor for input and output. + // dip::imread(inputNameBuddyRotate2D, dip::IMGRD_GRAYSCALE); + + MemRef outputBuddyRotate2D(sizesOutputBuddyRotate2D); + + for (auto _ : state) { + for (int i = 0; i < state.range(0); ++i) { + // Call the MLIR Rotate2D function. + dip::detail::_mlir_ciface_rotate_2d(&inputBuddyRotate2D, angleRad, + &outputBuddyRotate2D); + } + } +} + +// Register benchmarking function. +void registerBenchmarkBuddyRotate2D() { + BENCHMARK(Buddy_Rotate2D)->Arg(1)->Unit(benchmark::kMillisecond); +} + +// Generate result image. +void generateResultBuddyRotate2D(char **argv, Img input) { + // Define the MemRef descriptors for output. + MemRef output(sizesOutputBuddyRotate2D); + + // Run the 2D rotate function. + dip::detail::_mlir_ciface_rotate_2d(&input, angleRad, &output); + + intptr_t sizes[2] = {output.getSizes()[0], output.getSizes()[1]}; + + // Define Img containers for output images. + Img outputImage(output.getData(), sizes); + + // Write output to PNG. + bool result = dip::imwrite("ResultBuddyRotate2D.png", outputImage); + + if (!result) { + fprintf(stderr, "Exception converting image to PNG format. \n"); + } + if (result) + cout << "Saved PNG file." << endl; + else + cout << "ERROR: Can't save PNG file." << endl; +} \ No newline at end of file diff --git a/benchmarks/ImageProcessing/BuddyRotate4DBenchmark.cpp b/benchmarks/ImageProcessing/BuddyRotate4DBenchmark.cpp new file mode 100644 index 00000000..f7c8b8b8 --- /dev/null +++ b/benchmarks/ImageProcessing/BuddyRotate4DBenchmark.cpp @@ -0,0 +1,170 @@ +//===------------ BuddyRotate4DBenchmark.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 Rotate4D operation. +// +//===----------------------------------------------------------------------===// + +#include "Kernels.h" +#include +#include +#include +#include +#include +#include +#include + +using namespace cv; +using namespace std; + +const float angleRad = M_PI * 30.0 / 180; +const int inputBatch = 3; + +// Define the input image. +Img inputBuddyRotate4D_NHWC; +Img inputBuddyRotate4D_NCHW; + +// Declare the input name. +std::string inputNameBuddyRotate4D; + +// Define sizes of input and output. +intptr_t sizesInputBuddyRotate4D_NHWC[4]; +intptr_t sizesOutputBuddyRotate4D_NHWC[4]; +intptr_t sizesInputBuddyRotate4D_NCHW[4]; +intptr_t sizesOutputBuddyRotate4D_NCHW[4]; + +void initializeBuddyRotate4D(char **argv) { + inputNameBuddyRotate4D = argv[1]; + + // Read as color image in [HWC] format. + Img inputImage = dip::imread(argv[1], dip::IMGRD_COLOR); + const int inputHeight = inputImage.getSizes()[0]; + const int inputWidth = inputImage.getSizes()[1]; + const int inputChannel = inputImage.getSizes()[2]; + + sizesInputBuddyRotate4D_NHWC[0] = sizesInputBuddyRotate4D_NCHW[0] = + inputBatch; + sizesInputBuddyRotate4D_NHWC[1] = sizesInputBuddyRotate4D_NCHW[2] = + inputHeight; + sizesInputBuddyRotate4D_NHWC[2] = sizesInputBuddyRotate4D_NCHW[3] = + inputWidth; + sizesInputBuddyRotate4D_NHWC[3] = sizesInputBuddyRotate4D_NCHW[1] = + inputChannel; + + const int inputStride = inputImage.getSize(); + + Img inputImages_NHWC(sizesInputBuddyRotate4D_NHWC); + auto imagePtr = inputImages_NHWC.getData(); + memcpy(imagePtr, inputImage.getData(), inputStride * sizeof(float)); + for (int i = 1; i < inputBatch; i++) { + Img input = dip::imread(argv[1], dip::IMGRD_COLOR); + memcpy(imagePtr + i * inputStride, input.getData(), + inputStride * sizeof(float)); + } + + float sinAngle = std::sin(angleRad); + float cosAngle = std::cos(angleRad); + const int outputHeight = + std::round(std::abs(inputImage.getSizes()[0] * cosAngle) + + std::abs(inputImage.getSizes()[1] * sinAngle)); + const int outputWidth = + std::round(std::abs(inputImage.getSizes()[0] * sinAngle) + + std::abs(inputImage.getSizes()[1] * cosAngle)); + + sizesOutputBuddyRotate4D_NHWC[0] = sizesOutputBuddyRotate4D_NCHW[0] = + inputBatch; + sizesOutputBuddyRotate4D_NHWC[1] = sizesOutputBuddyRotate4D_NCHW[2] = + outputHeight; + sizesOutputBuddyRotate4D_NHWC[2] = sizesOutputBuddyRotate4D_NCHW[3] = + outputWidth; + sizesOutputBuddyRotate4D_NHWC[3] = sizesOutputBuddyRotate4D_NCHW[1] = + inputChannel; + + inputBuddyRotate4D_NHWC = inputImages_NHWC; + + Img inputImages_NCHW(sizesInputBuddyRotate4D_NCHW); + dip::detail::Transpose(&inputImages_NCHW, &inputImages_NHWC, + {0, 3, 1, 2}); + inputBuddyRotate4D_NCHW = inputImages_NCHW; +} + +// Benchmarking functions. +static void Buddy_Rotate4D_NHWC(benchmark::State &state) { + MemRef outputBuddyRotate4D(sizesOutputBuddyRotate4D_NHWC); + + for (auto _ : state) { + for (int i = 0; i < state.range(0); ++i) { + // Call the MLIR Rotate4D function. + dip::detail::_mlir_ciface_rotate_4d_nhwc(&inputBuddyRotate4D_NHWC, + angleRad, &outputBuddyRotate4D); + } + } +} + +static void Buddy_Rotate4D_NCHW(benchmark::State &state) { + MemRef outputBuddyRotate4D(sizesOutputBuddyRotate4D_NCHW); + + for (auto _ : state) { + for (int i = 0; i < state.range(0); ++i) { + // Call the MLIR Rotate4D function. + dip::detail::_mlir_ciface_rotate_4d_nchw(&inputBuddyRotate4D_NCHW, + angleRad, &outputBuddyRotate4D); + } + } +} + +// Register benchmarking function. +void registerBenchmarkBuddyRotate4D() { + BENCHMARK(Buddy_Rotate4D_NHWC)->Arg(1)->Unit(benchmark::kMillisecond); + BENCHMARK(Buddy_Rotate4D_NCHW)->Arg(1)->Unit(benchmark::kMillisecond); +} + +// Generate result image. +void generateResultBuddyRotate4D(char **argv) { + // Define the MemRef descriptors for output. + MemRef output_NHWC(sizesOutputBuddyRotate4D_NHWC); + + // Run the 4D rotate function. + dip::detail::_mlir_ciface_rotate_4d_nhwc(&inputBuddyRotate4D_NHWC, angleRad, + &output_NHWC); + + intptr_t imageSizes[3] = {output_NHWC.getSizes()[1], + output_NHWC.getSizes()[2], + output_NHWC.getSizes()[3]}; + Img image_NHWC(output_NHWC.getData(), imageSizes); + + // Write output to PNG. + bool result = dip::imwrite("ResultBuddyRotate4D_NHWC.png", image_NHWC); + + MemRef output_NCHW(sizesOutputBuddyRotate4D_NCHW); + + dip::detail::_mlir_ciface_rotate_4d_nchw(&inputBuddyRotate4D_NCHW, angleRad, + &output_NCHW); + + dip::detail::Transpose(&output_NHWC, &output_NCHW, {0, 2, 3, 1}); + + Img image_NCHW(output_NHWC.getData(), imageSizes); + + result = dip::imwrite("ResultBuddyRotate4D_NCHW.png", image_NCHW); + + if (!result) { + fprintf(stderr, "Exception converting image to PNG format. \n"); + } + if (result) + cout << "Saved PNG file." << endl; + else + cout << "ERROR: Can't save PNG file." << endl; +} \ No newline at end of file diff --git a/benchmarks/ImageProcessing/CMakeLists.txt b/benchmarks/ImageProcessing/CMakeLists.txt index a788fecb..1647c4d9 100644 --- a/benchmarks/ImageProcessing/CMakeLists.txt +++ b/benchmarks/ImageProcessing/CMakeLists.txt @@ -101,7 +101,10 @@ add_executable(image-processing-benchmark BuddyMorph2DBenchmark.cpp OpenCVMorph2DBenchmark.cpp BuddyResize2DBenchmark.cpp + BuddyRotate2DBenchmark.cpp + BuddyRotate4DBenchmark.cpp OpenCVResize2DBenchmark.cpp + OpenCVRotate2DBenchmark.cpp ) target_include_directories(image-processing-benchmark diff --git a/benchmarks/ImageProcessing/Main.cpp b/benchmarks/ImageProcessing/Main.cpp index 3f2f2eeb..b44d3912 100644 --- a/benchmarks/ImageProcessing/Main.cpp +++ b/benchmarks/ImageProcessing/Main.cpp @@ -35,12 +35,17 @@ void initializeOpenCVMorph2D(char **); void initializeOpenCVFilter2D(char **); void initializeEigenConvolve2D(char **, Img); void initializeBuddyResize2D(char **, Img); +void initializeBuddyRotate2D(char **, Img); +void initializeBuddyRotate4D(char **); void initializeOpenCVResize2D(char **); +void initializeOpenCVRotate2D(char **); void generateResultMLIRConv2D(Img); void generateResultBuddyConv2D(Img); void generateResultBuddyCorr2D(char **argv, Img); void generateResultBuddyResize2D(char **argv, Img); +void generateResultBuddyRotate2D(char **argv, Img); +void generateResultBuddyRotate4D(char **); void generateResultBuddyErosion2D(char **, Img); void generateResultBuddyOpening2D(char **, Img); void generateResultBuddyClosing2D(char **, Img); @@ -57,6 +62,7 @@ void generateResultOpenCVTopHat2D(); void generateResultOpenCVBottomHat2D(); void generateResultOpenCVMorphGrad2D(); void generateResultOpenCVResize2D(); +void generateResultOpenCVRotate2D(); void generateResultEigenConvolve2D(); void registerBenchmarkBuddyCorr2D(); @@ -76,7 +82,10 @@ void registerBenchmarkOpenCVBottomHat2D(); void registerBenchmarkOpenCVMorphGrad2D(); void registerBenchmarkOpenCVFilter2D(); void registerBenchmarkBuddyResize2D(); +void registerBenchmarkBuddyRotate2D(); +void registerBenchmarkBuddyRotate4D(); void registerBenchmarkOpenCVResize2D(); +void registerBenchmarkOpenCVRotate2D(); // Run benchmarks. int main(int argc, char **argv) { @@ -103,12 +112,18 @@ int main(int argc, char **argv) { initializeOpenCVFilter2D(argv); initializeEigenConvolve2D(argv, img); initializeBuddyResize2D(argv, img); + initializeBuddyRotate2D(argv, img); + initializeBuddyRotate4D(argv); initializeOpenCVResize2D(argv); + initializeOpenCVRotate2D(argv); registerBenchmarkBuddyCorr2D(); registerBenchmarkOpenCVFilter2D(); registerBenchmarkBuddyResize2D(); + registerBenchmarkBuddyRotate2D(); + registerBenchmarkBuddyRotate4D(); registerBenchmarkOpenCVResize2D(); + registerBenchmarkOpenCVRotate2D(); registerBenchmarkBuddyErosion2D(); registerBenchmarkBuddyDilation2D(); registerBenchmarkBuddyOpening2D(); @@ -131,6 +146,8 @@ int main(int argc, char **argv) { generateResultOpenCVFilter2D(); generateResultBuddyConv2D(img); generateResultBuddyCorr2D(argv, img); + generateResultBuddyRotate2D(argv, img); + generateResultBuddyRotate4D(argv); generateResultBuddyResize2D(argv, img); generateResultBuddyErosion2D(argv, img); generateResultBuddyDilation2D(argv, img); @@ -147,6 +164,7 @@ int main(int argc, char **argv) { generateResultOpenCVOpening2D(); generateResultOpenCVClosing2D(); generateResultOpenCVResize2D(); + generateResultOpenCVRotate2D(); generateResultEigenConvolve2D(); return 0; diff --git a/benchmarks/ImageProcessing/OpenCVRotate2DBenchmark.cpp b/benchmarks/ImageProcessing/OpenCVRotate2DBenchmark.cpp new file mode 100644 index 00000000..ae859c8b --- /dev/null +++ b/benchmarks/ImageProcessing/OpenCVRotate2DBenchmark.cpp @@ -0,0 +1,110 @@ +//===- OpenCVRotate2DBenchmark.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 Rotate2D. +// +//===----------------------------------------------------------------------===// + +#include +#include +#include + +using namespace cv; +using namespace std; + +const float angle = 30.0; + +// Declare input image and output image. +Mat inputImageRotate2D, outputImageRotate2D; + +// Declare output image size +Size outputImageSizeRotate2D; + +Mat CalculateRotationMatrix() { + // Get the size of the image + int inputImageHeight = inputImageRotate2D.rows; + int inputImageWidth = inputImageRotate2D.cols; + + // Calculate the center + Point2f center(inputImageWidth / 2.0, inputImageHeight / 2.0); + + // Get the rotation matrix + Mat rotationMatrix = getRotationMatrix2D(center, angle, 1.0); + + // Get the output image size + double cos = std::abs(rotationMatrix.at(0, 0)); + double sin = std::abs(rotationMatrix.at(0, 1)); + int outputImageWidth = + static_cast((inputImageHeight * sin) + (inputImageWidth * cos)); + int outputImageHeight = + static_cast((inputImageHeight * cos) + (inputImageWidth * sin)); + + outputImageSizeRotate2D = Size(outputImageWidth, outputImageHeight); + + // Adjust the rotation matrix + rotationMatrix.at(0, 2) += (outputImageWidth / 2.0) - center.x; + rotationMatrix.at(1, 2) += (outputImageHeight / 2.0) - center.y; + + return rotationMatrix; +} + +void initializeOpenCVRotate2D(char **argv) { + inputImageRotate2D = imread(argv[1], IMREAD_GRAYSCALE); +} + +// Benchmarking functions. +static void OpenCV_Rotate2D(benchmark::State &state) { + + for (auto _ : state) { + for (int i = 0; i < state.range(0); ++i) { + Mat rotationMatrix = CalculateRotationMatrix(); + warpAffine(inputImageRotate2D, outputImageRotate2D, rotationMatrix, + outputImageSizeRotate2D); + } + } +} + +// Register benchmarking function. +void registerBenchmarkOpenCVRotate2D() { + BENCHMARK(OpenCV_Rotate2D)->Arg(1)->Unit(benchmark::kMillisecond); +} + +// Generate result image. +void generateResultOpenCVRotate2D() { + + Mat rotationMatrix = CalculateRotationMatrix(); + + // Choose a PNG compression level + vector compressionParams; + compressionParams.push_back(IMWRITE_PNG_COMPRESSION); + compressionParams.push_back(9); + + // Write output to PNG. + bool result = false; + try { + warpAffine(inputImageRotate2D, outputImageRotate2D, rotationMatrix, + outputImageSizeRotate2D); + result = imwrite("ResultOpenCVRotate2D.png", outputImageRotate2D, + 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; +} \ No newline at end of file