diff --git a/benchmarks/ImageProcessing/BuddyRotate2DBenchmark.cpp b/benchmarks/ImageProcessing/BuddyRotate2DBenchmark.cpp new file mode 100644 index 00000000..2b828866 --- /dev/null +++ b/benchmarks/ImageProcessing/BuddyRotate2DBenchmark.cpp @@ -0,0 +1,133 @@ +//===- 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. +// +//===- BuddyRotate2DBenchmark.cpp -----------------------------------------===// +//===----------------------------------------------------------------------===// +// +// This file implements the benchmark for Rotate2D operation. +// +//===----------------------------------------------------------------------===// + +#include +#include +#include +#include +#include + +using namespace cv; +using namespace std; + +// Declare input image. +Mat inputImageBuddyRotate2D; + +// Define the angle. +float BuddyRotate2DAngle; + +// Define sizes of input. +intptr_t sizesInputBuddyRotate2D[2]; + +// Define Angle option selected. +dip::ANGLE_TYPE AngleType; + +void initializeBuddyRotate2D(char **argv) { + inputImageBuddyRotate2D = imread(argv[1], IMREAD_GRAYSCALE); + + sizesInputBuddyRotate2D[0] = inputImageBuddyRotate2D.rows; + sizesInputBuddyRotate2D[1] = inputImageBuddyRotate2D.cols; + + if (static_cast(argv[2]) == "DEGREE") { + AngleType = dip::ANGLE_TYPE::DEGREE; + } else { + AngleType = dip::ANGLE_TYPE::RADIAN; + } + + std::string argAngle = argv[3]; + try { + BuddyRotate2DAngle = std::stof(argAngle); + } catch (const std::exception &e) { + cout << "Exception converting rotation angle to float." << endl; + } +} + +static void Buddy_Rotate2D_DEGREE(benchmark::State &state) { + // Define the MemRef descriptor for input. + Img inputBuddyRotate2D(inputImageBuddyRotate2D); + + for (auto _ : state) { + for (int i = 0; i < state.range(0); ++i) { + // Call the MLIR Rotate2D function. + MemRef output = dip::Rotate2D( + &inputBuddyRotate2D, BuddyRotate2DAngle, dip::ANGLE_TYPE::DEGREE); + } + } +} + +static void Buddy_Rotate2D_RADIAN(benchmark::State &state) { + // Define the MemRef descriptor for input. + Img inputBuddyRotate2D(inputImageBuddyRotate2D); + + for (auto _ : state) { + for (int i = 0; i < state.range(0); ++i) { + // Call the MLIR Rotate2D function. + MemRef output = dip::Rotate2D( + &inputBuddyRotate2D, BuddyRotate2DAngle, dip::ANGLE_TYPE::RADIAN); + } + } +} + +// Register benchmarking function. +void registerBenchmarkBuddyRotate2D() { + if (AngleType == dip::ANGLE_TYPE::DEGREE) { + BENCHMARK(Buddy_Rotate2D_DEGREE)->Arg(1)->Unit(benchmark::kMillisecond); + } else { + BENCHMARK(Buddy_Rotate2D_RADIAN)->Arg(1)->Unit(benchmark::kMillisecond); + } +} + +// Generate result image. +void generateResultBuddyRotate2D() { + // Define the MemRef descriptor for input. + Img input(inputImageBuddyRotate2D); + MemRef output(sizesInputBuddyRotate2D); + // Run the rotate 2D operation. + if (AngleType == dip::ANGLE_TYPE::DEGREE) { + // Call the MLIR Rotate2D function. + output = dip::Rotate2D(&input, BuddyRotate2DAngle, dip::ANGLE_TYPE::DEGREE); + } else { + // Call the MLIR Rotate2D function. + output = dip::Rotate2D(&input, BuddyRotate2DAngle, dip::ANGLE_TYPE::RADIAN); + } + + // Define a cv::Mat with the output of the rotate operation. + Mat outputImage(output.getSizes()[0], output.getSizes()[1], CV_32FC1, + output.getData()); + + // Choose a PNG compression level + vector compressionParams; + compressionParams.push_back(IMWRITE_PNG_COMPRESSION); + compressionParams.push_back(9); + + // Write output to PNG. + bool result = true; + try { + result = imwrite("ResultBuddyRotate2D.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 b1113e4a..f5594d6e 100644 --- a/benchmarks/ImageProcessing/CMakeLists.txt +++ b/benchmarks/ImageProcessing/CMakeLists.txt @@ -117,3 +117,30 @@ target_link_libraries(image-processing-benchmark # Link Buddy MLIR DIP Library. BuddyLibDIP ) + +#------------------------------------------------------------------------------- +# Image Processing Rotate Benchmark Target +#------------------------------------------------------------------------------- + +add_executable(image-processing-rotate-benchmark + MainRotate.cpp + BuddyRotate2DBenchmark.cpp + OpenCVRotate2DBenchmark.cpp + ) + +target_include_directories(image-processing-rotate-benchmark + PRIVATE + ${BUDDY_SOURCE_DIR}/benchmarks/ImageProcessing/include/ + ) + +target_link_directories(image-processing-rotate-benchmark + PRIVATE + ${BUDDY_MLIR_LIB_DIR} + ) + +target_link_libraries(image-processing-rotate-benchmark + GoogleBenchmark + ${OpenCV_LIBS} + # Link Buddy MLIR DIP Library. + BuddyLibDIP + ) diff --git a/benchmarks/ImageProcessing/MainRotate.cpp b/benchmarks/ImageProcessing/MainRotate.cpp new file mode 100644 index 00000000..438ee808 --- /dev/null +++ b/benchmarks/ImageProcessing/MainRotate.cpp @@ -0,0 +1,60 @@ +//===- MainRotate.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 is the main file of the image processing rotate benchmark. +// +//===----------------------------------------------------------------------===// + +#include +#include + +void initializeBuddyRotate2D(char **); +void initializeOpenCVRotate2D(char **); + +void generateResultBuddyRotate2D(); +void generateResultOpenCVRotate2D(); + +void registerBenchmarkBuddyRotate2D(); +void registerBenchmarkOpenCVRotate2D(); + +// Run benchmarks. +int main(int argc, char **argv) { + if (argc != 4) { + throw std::invalid_argument( + "Wrong format of command line arguments.\n" + "Correct format is ./image-processing-rotate-benchmark " + " \n where " + "image path provides path of the image to be processed, Rotate option " + "available are DEGREE, RADIAN. " + "RotateAngle accepts a float number for Rotate option." + "OpenCV rotate() only supports 90, 180 and 270 degree.\n"); + } + + initializeBuddyRotate2D(argv); + initializeOpenCVRotate2D(argv); + + registerBenchmarkBuddyRotate2D(); + registerBenchmarkOpenCVRotate2D(); + + ::benchmark::Initialize(&argc, argv); + ::benchmark::RunSpecifiedBenchmarks(); + + // Generate result image. + generateResultBuddyRotate2D(); + generateResultOpenCVRotate2D(); + + return 0; +} diff --git a/benchmarks/ImageProcessing/OpenCVRotate2DBenchmark.cpp b/benchmarks/ImageProcessing/OpenCVRotate2DBenchmark.cpp new file mode 100644 index 00000000..e751887a --- /dev/null +++ b/benchmarks/ImageProcessing/OpenCVRotate2DBenchmark.cpp @@ -0,0 +1,122 @@ +//===- 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's Rotate Operations. +// +//===----------------------------------------------------------------------===// + +#include +#include +#include + +using namespace cv; +using namespace std; + +// Declare input and output image. +Mat inputImageOpenCVRotate2D, outputImageOpenCVRotate2D; + +// Define the angle. +int OpenCVRotate2DAngle; + +// Define sizes of input. +intptr_t sizesInputOpenCVRotate2D[2]; +cv::Size sizesOutputOpenCVRotate2D; + +// Define Angle option selected. +dip::ANGLE_TYPE OpenCVAngleType; + +// Define OpenCV Rotate option. +cv::RotateFlags RotateFlag = cv::ROTATE_90_CLOCKWISE; + +// Define the OpenCV Rotate benchmark option. +bool OpenCVRunRotate = true; + +void initializeOpenCVRotate2D(char **argv) { + inputImageOpenCVRotate2D = imread(argv[1], IMREAD_GRAYSCALE); + + sizesInputOpenCVRotate2D[0] = inputImageOpenCVRotate2D.rows; + sizesInputOpenCVRotate2D[1] = inputImageOpenCVRotate2D.cols; + + if (static_cast(argv[2]) == "DEGREE") { + OpenCVAngleType = dip::ANGLE_TYPE::DEGREE; + } else { + OpenCVAngleType = dip::ANGLE_TYPE::RADIAN; + } + + std::string argAngle = argv[3]; + try { + OpenCVRotate2DAngle = std::stoi(argAngle); + OpenCVRotate2DAngle = OpenCVRotate2DAngle % 360; + } catch (const std::exception &e) { + cout << "OpenCV rotate() support three ways: 90 degrees clockwise, 180 " + "degrees clockwise, 270 degrees clockwise." + << endl; + } + if (OpenCVRotate2DAngle == 90) { + RotateFlag = cv::ROTATE_90_CLOCKWISE; + } else if (OpenCVRotate2DAngle == 180) { + RotateFlag = cv::ROTATE_180; + } else if (OpenCVRotate2DAngle == 270) { + RotateFlag = cv::ROTATE_90_COUNTERCLOCKWISE; + } else { + OpenCVRunRotate = false; + } +} + +// Benchmarking function. +static void OpenCV_Rotate2D_DEGREE(benchmark::State &state) { + for (auto _ : state) { + for (int i = 0; i < state.range(0); ++i) { + cv::rotate(inputImageOpenCVRotate2D, outputImageOpenCVRotate2D, + RotateFlag); + } + } +} + +// Register benchmarking function. +void registerBenchmarkOpenCVRotate2D() { + if (OpenCVAngleType == dip::ANGLE_TYPE::DEGREE && OpenCVRunRotate == true) { + BENCHMARK(OpenCV_Rotate2D_DEGREE)->Arg(1)->Unit(benchmark::kMillisecond); + } +} + +// Generate result image. +void generateResultOpenCVRotate2D() { + // Run the rotate 2D operation. + if (OpenCVAngleType == dip::ANGLE_TYPE::DEGREE && OpenCVRunRotate == true) { + cv::rotate(inputImageOpenCVRotate2D, outputImageOpenCVRotate2D, + OpenCVRotate2DAngle); + + // 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 { + result = imwrite("ResultOpenCVRotate2D.png", outputImageOpenCVRotate2D, + 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; + } +}