diff --git a/benchmarks/ImageProcessing/BuddyResize2DBenchmark.cpp b/benchmarks/ImageProcessing/BuddyResize2DBenchmark.cpp new file mode 100644 index 00000000..528f57a1 --- /dev/null +++ b/benchmarks/ImageProcessing/BuddyResize2DBenchmark.cpp @@ -0,0 +1,219 @@ +//===- BuddyResize2DBenchmark.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 Resize2D operation. +// +//===----------------------------------------------------------------------===// + +#include +#include +#include +#include +#include + +using namespace cv; +using namespace std; + +// Declare input image. +Mat inputImageBuddyResize2D; + +// Define the output size or factor. +int outputRowsBuddyResize2DLength, outputColsBuddyResize2DLength; +float outputRowsBuddyResize2DFactor, outputColsBuddyResize2DFactor; + +// Define sizes of input and output. +intptr_t sizesInputBuddyResize2D[2]; +intptr_t sizesOutputBuddyResize2D[2]; +std::vector factorsOutputBuddyResize2D = {1.0, 1.0}; + +// Declare Interpolation option supported. +enum InterpolationOption { bilinear_interpolation, nearest_neighbour_interpolation }; + +// Declare Scale option supported. +enum ScaleOption { scale_factor, scale_length }; + +// Define Interpolation option selected. +InterpolationOption InterpolationType; + +// Define Scale option selected. +ScaleOption ScaleType; + +void initializeBuddyResize2D(char **argv) { + inputImageBuddyResize2D = imread(argv[1], IMREAD_GRAYSCALE); + + sizesInputBuddyResize2D[0] = inputImageBuddyResize2D.rows; + sizesInputBuddyResize2D[1] = inputImageBuddyResize2D.cols; + + if (static_cast(argv[2]) == "SCALE_FACTOR") { + ScaleType = scale_factor; + } else { + ScaleType = scale_length; + } + + std::string argRow = argv[3]; + std::string argCol = argv[4]; + try { + if (ScaleType == scale_factor) { + float outputRowsBuddyResize2DFactor = std::stof(argRow); + float outputColsBuddyResize2DFactor = std::stof(argCol); + factorsOutputBuddyResize2D[0] = outputRowsBuddyResize2DFactor; + factorsOutputBuddyResize2D[1] = outputColsBuddyResize2DFactor; + sizesOutputBuddyResize2D[0] = sizesInputBuddyResize2D[0] * outputRowsBuddyResize2DFactor; + sizesOutputBuddyResize2D[1] = sizesInputBuddyResize2D[1] * outputColsBuddyResize2DFactor; + } else { + intptr_t outputRowsBuddyResize2DLength = std::stoi(argRow); + intptr_t outputColsBuddyResize2DLength = std::stoi(argCol); + sizesOutputBuddyResize2D[0] = outputRowsBuddyResize2DLength; + sizesOutputBuddyResize2D[1] = outputColsBuddyResize2DLength; + } + } catch (const std::exception& e) { + cout << "Exception converting row and col scale_factor/scale_length to number." << endl; + } + + if (static_cast(argv[5]) == "NEAREST_NEIGHBOUR_INTERPOLATION") { + InterpolationType = nearest_neighbour_interpolation; + } else { + InterpolationType = bilinear_interpolation; + } +} + +static void Buddy_Resize2D_Bilinear_Interpolation_Length(benchmark::State &state) { + // Define the MemRef descriptor for input. + Img inputBuddyResize2D(inputImageBuddyResize2D); + + for (auto _ : state) { + for (int i = 0; i < state.range(0); ++i) { + // Call the MLIR Resize2D function. + MemRef output = dip::Resize2D(&inputBuddyResize2D, + dip::INTERPOLATION_TYPE::BILINEAR_INTERPOLATION, + sizesOutputBuddyResize2D); + } + } +} + +static void Buddy_Resize2D_Nearest_Neighbour_Interpolation_Length(benchmark::State &state) { + // Define the MemRef descriptor for input. + Img inputBuddyResize2D(inputImageBuddyResize2D); + + for (auto _ : state) { + for (int i = 0; i < state.range(0); ++i) { + // Call the MLIR Resize2D function. + MemRef output = dip::Resize2D(&inputBuddyResize2D, + dip::INTERPOLATION_TYPE::NEAREST_NEIGHBOUR_INTERPOLATION, + sizesOutputBuddyResize2D); + } + } +} + +static void Buddy_Resize2D_Bilinear_Interpolation_Factor(benchmark::State &state) { + // Define the MemRef descriptor for input. + Img inputBuddyResize2D(inputImageBuddyResize2D); + + for (auto _ : state) { + for (int i = 0; i < state.range(0); ++i) { + // Call the MLIR Resize2D function. + MemRef output = dip::Resize2D(&inputBuddyResize2D, + dip::INTERPOLATION_TYPE::BILINEAR_INTERPOLATION, + factorsOutputBuddyResize2D); + } + } +} + +static void Buddy_Resize2D_Nearest_Neighbour_Interpolation_Factor(benchmark::State &state) { + // Define the MemRef descriptor for input. + Img inputBuddyResize2D(inputImageBuddyResize2D); + + for (auto _ : state) { + for (int i = 0; i < state.range(0); ++i) { + // Call the MLIR Resize2D function. + MemRef output = dip::Resize2D(&inputBuddyResize2D, + dip::INTERPOLATION_TYPE::NEAREST_NEIGHBOUR_INTERPOLATION, + factorsOutputBuddyResize2D); + } + } +} + +// Register benchmarking function. +void registerBenchmarkBuddyResize2D() { + if (InterpolationType == nearest_neighbour_interpolation && ScaleType == scale_factor) { + BENCHMARK(Buddy_Resize2D_Nearest_Neighbour_Interpolation_Factor) + ->Arg(1) + ->Unit(benchmark::kMillisecond); + } else if (InterpolationType == bilinear_interpolation && ScaleType == scale_factor) { + BENCHMARK(Buddy_Resize2D_Bilinear_Interpolation_Factor) + ->Arg(1) + ->Unit(benchmark::kMillisecond); + } else if (InterpolationType == nearest_neighbour_interpolation && ScaleType == scale_length) { + BENCHMARK(Buddy_Resize2D_Nearest_Neighbour_Interpolation_Length) + ->Arg(1) + ->Unit(benchmark::kMillisecond); + } else if (InterpolationType == bilinear_interpolation && ScaleType == scale_length) { + BENCHMARK(Buddy_Resize2D_Bilinear_Interpolation_Length) + ->Arg(1) + ->Unit(benchmark::kMillisecond); + } +} + +// Generate result image. +void generateResultBuddyResize2D() { + // Define the MemRef descriptor for input. + Img input(inputImageBuddyResize2D); + MemRef output(sizesOutputBuddyResize2D); + // Run the resize 2D operation. + if (InterpolationType == nearest_neighbour_interpolation && ScaleType == scale_factor) { + // Call the MLIR Resize2D function. + output = dip::Resize2D(&input, + dip::INTERPOLATION_TYPE::NEAREST_NEIGHBOUR_INTERPOLATION, + factorsOutputBuddyResize2D); + } else if (InterpolationType == bilinear_interpolation && ScaleType == scale_factor) { + // Call the MLIR Resize2D function. + output = dip::Resize2D(&input, + dip::INTERPOLATION_TYPE::BILINEAR_INTERPOLATION, + factorsOutputBuddyResize2D); + } else if (InterpolationType == nearest_neighbour_interpolation && ScaleType == scale_length) { + // Call the MLIR Resize2D function. + output = dip::Resize2D(&input, + dip::INTERPOLATION_TYPE::NEAREST_NEIGHBOUR_INTERPOLATION, + sizesOutputBuddyResize2D); + } else if (InterpolationType == bilinear_interpolation && ScaleType == scale_length) { + // Call the MLIR Resize2D function. + output = dip::Resize2D(&input, + dip::INTERPOLATION_TYPE::BILINEAR_INTERPOLATION, + sizesOutputBuddyResize2D); + } + + // Define a cv::Mat with the output of the resize 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("ResultBuddyResize2D.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..029beb4a 100644 --- a/benchmarks/ImageProcessing/CMakeLists.txt +++ b/benchmarks/ImageProcessing/CMakeLists.txt @@ -117,3 +117,31 @@ target_link_libraries(image-processing-benchmark # Link Buddy MLIR DIP Library. BuddyLibDIP ) + +#------------------------------------------------------------------------------- +# Image Processing Resize Benchmark Target +#------------------------------------------------------------------------------- + +add_executable(image-processing-resize-benchmark + MainResize.cpp + BuddyResize2DBenchmark.cpp + OpenCVResize2DBenchmark.cpp + ) + +target_include_directories(image-processing-resize-benchmark + PRIVATE + ${BUDDY_SOURCE_DIR}/benchmarks/ImageProcessing/include/ + ) + +target_link_directories(image-processing-resize-benchmark + PRIVATE + ${BUDDY_MLIR_LIB_DIR} + ) + +target_link_libraries(image-processing-resize-benchmark + GoogleBenchmark + ${OpenCV_LIBS} + # Link Buddy MLIR DIP Library. + BuddyLibDIP + ) + \ No newline at end of file diff --git a/benchmarks/ImageProcessing/MainResize.cpp b/benchmarks/ImageProcessing/MainResize.cpp new file mode 100644 index 00000000..8ce9b59a --- /dev/null +++ b/benchmarks/ImageProcessing/MainResize.cpp @@ -0,0 +1,62 @@ +//===- MainResize.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 resize benchmark. +// +//===----------------------------------------------------------------------===// + +#include +#include + +void initializeBuddyResize2D(char **); +void initializeOpenCVResize2D(char **); + +void generateResultBuddyResize2D(); +void generateResultOpenCVResize2D(); + +void registerBenchmarkBuddyResize2D(); +void registerBenchmarkOpenCVResize2D(); + +// Run benchmarks. +int main(int argc, char **argv) { + if (argc != 6) { + throw std::invalid_argument( + "Wrong format of command line arguments.\n" + "Correct format is ./image-processing-resize-benchmark \n where " + "image path provides path of the image to be processed, Scale option " + "available are SCALE_FACTOR, SCALE_LENGTH. " + "RowNum and ColNum are the " + "scale_factors/scale_length for row and col, " + "Interpolation option available " + "are NEAREST_NEIGHBOUR_INTERPOLATION, BILINEAR_INTERPOLATION.\n"); + } + + initializeBuddyResize2D(argv); + initializeOpenCVResize2D(argv); + + registerBenchmarkBuddyResize2D(); + registerBenchmarkOpenCVResize2D(); + + ::benchmark::Initialize(&argc, argv); + ::benchmark::RunSpecifiedBenchmarks(); + + // Generate result image. + generateResultBuddyResize2D(); + generateResultOpenCVResize2D(); + + return 0; +} diff --git a/benchmarks/ImageProcessing/OpenCVResize2DBenchmark.cpp b/benchmarks/ImageProcessing/OpenCVResize2DBenchmark.cpp new file mode 100644 index 00000000..4092fb24 --- /dev/null +++ b/benchmarks/ImageProcessing/OpenCVResize2DBenchmark.cpp @@ -0,0 +1,180 @@ +//===- OpenCVResize2DBenchmark.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 Resize Operations. +// +//===----------------------------------------------------------------------===// + +#include +#include + +using namespace cv; +using namespace std; + +// Declare input image and output image. +Mat inputImageOpenCVResize2D, outputImageOpenCVResize2D; + +// Define the output size or factor. +int outputRowsOpenCVResize2DLength, outputColsOpenCVResize2DLength; +float outputRowsOpenCVResize2DFactor, outputColsOpenCVResize2DFactor; + +// Define sizes of input and output. +intptr_t sizesInputOpenCVResize2D[2]; +cv::Size sizesOutputOpenCVResize2D; +std::vector factorsOutputOpenCVResize2D = {1.0, 1.0}; + +// Declare Interpolation option supported. +enum InterpolationOption { bilinear_interpolation, nearest_neighbour_interpolation }; + +// Declare Scale option supported. +enum ScaleOption { scale_factor, scale_length }; + +// Define Interpolation option selected. +InterpolationOption OpenCVInterpolationType; + +// Define Scale option selected. +ScaleOption OpenCVScaleType; + +void initializeOpenCVResize2D(char **argv) { + inputImageOpenCVResize2D = imread(argv[1], IMREAD_GRAYSCALE); + + sizesInputOpenCVResize2D[0] = inputImageOpenCVResize2D.rows; + sizesInputOpenCVResize2D[1] = inputImageOpenCVResize2D.cols; + + if (static_cast(argv[2]) == "SCALE_FACTOR") { + OpenCVScaleType = scale_factor; + } else { + OpenCVScaleType = scale_length; + } + + std::string argRow = argv[3]; + std::string argCol = argv[4]; + try { + if (OpenCVScaleType == scale_factor) { + float outputRowsOpenCVResize2DFactor = std::stof(argRow); + float outputColsOpenCVResize2DFactor = std::stof(argCol); + factorsOutputOpenCVResize2D[0] = outputRowsOpenCVResize2DFactor; + factorsOutputOpenCVResize2D[1] = outputColsOpenCVResize2DFactor; + } else { + outputRowsOpenCVResize2DLength = std::stoi(argRow); + outputColsOpenCVResize2DLength = std::stoi(argCol); + sizesOutputOpenCVResize2D= cv::Size(outputRowsOpenCVResize2DLength, outputColsOpenCVResize2DLength); + } + } catch (const std::exception& e) { + cout << "Exception converting row and col scale_factor/scale_length to number." << endl; + } + + if (static_cast(argv[5]) == "NEAREST_NEIGHBOUR_INTERPOLATION") { + OpenCVInterpolationType = nearest_neighbour_interpolation; + } else { + OpenCVInterpolationType = bilinear_interpolation; + } +} + +// Benchmarking function. +static void OpenCV_Resize2D_Bilinear_Interpolation_Length(benchmark::State &state) { + for (auto _ : state) { + for (int i = 0; i < state.range(0); ++i) { + cv::resize(inputImageOpenCVResize2D, outputImageOpenCVResize2D, sizesOutputOpenCVResize2D, + 0, 0, cv::INTER_LINEAR); + } + } +} + +static void OpenCV_Resize2D_Nearest_Neighbour_Interpolation_Length(benchmark::State &state) { + for (auto _ : state) { + for (int i = 0; i < state.range(0); ++i) { + cv::resize(inputImageOpenCVResize2D, outputImageOpenCVResize2D, sizesOutputOpenCVResize2D, + 0, 0, cv::INTER_NEAREST); + } + } +} + +static void OpenCV_Resize2D_Bilinear_Interpolation_Factor(benchmark::State &state) { + for (auto _ : state) { + for (int i = 0; i < state.range(0); ++i) { + cv::resize(inputImageOpenCVResize2D, outputImageOpenCVResize2D, cv::Size(0, 0), + factorsOutputOpenCVResize2D[0], factorsOutputOpenCVResize2D[1], cv::INTER_LINEAR); + } + } +} + +static void OpenCV_Resize2D_Nearest_Neighbour_Interpolation_Factor(benchmark::State &state) { + for (auto _ : state) { + for (int i = 0; i < state.range(0); ++i) { + cv::resize(inputImageOpenCVResize2D, outputImageOpenCVResize2D, cv::Size(0, 0), + factorsOutputOpenCVResize2D[0], factorsOutputOpenCVResize2D[1], cv::INTER_NEAREST); + } + } +} + +// Register benchmarking function. +void registerBenchmarkOpenCVResize2D() { + if (OpenCVInterpolationType == nearest_neighbour_interpolation && OpenCVScaleType == scale_factor) { + BENCHMARK(OpenCV_Resize2D_Nearest_Neighbour_Interpolation_Factor) + ->Arg(1) + ->Unit(benchmark::kMillisecond); + } else if (OpenCVInterpolationType == bilinear_interpolation && OpenCVScaleType == scale_factor) { + BENCHMARK(OpenCV_Resize2D_Bilinear_Interpolation_Factor) + ->Arg(1) + ->Unit(benchmark::kMillisecond); + } else if (OpenCVInterpolationType == nearest_neighbour_interpolation && OpenCVScaleType == scale_length) { + BENCHMARK(OpenCV_Resize2D_Nearest_Neighbour_Interpolation_Length) + ->Arg(1) + ->Unit(benchmark::kMillisecond); + } else if (OpenCVInterpolationType == bilinear_interpolation && OpenCVScaleType == scale_length) { + BENCHMARK(OpenCV_Resize2D_Bilinear_Interpolation_Length) + ->Arg(1) + ->Unit(benchmark::kMillisecond); + } +} + +// Generate result image. +void generateResultOpenCVResize2D() { + // Run the resize 2D operation. + if (OpenCVInterpolationType == nearest_neighbour_interpolation && OpenCVScaleType == scale_factor) { + cv::resize(inputImageOpenCVResize2D, outputImageOpenCVResize2D, cv::Size(0, 0), + factorsOutputOpenCVResize2D[0], factorsOutputOpenCVResize2D[1], cv::INTER_NEAREST); + } else if (OpenCVInterpolationType == bilinear_interpolation && OpenCVScaleType == scale_factor) { + cv::resize(inputImageOpenCVResize2D, outputImageOpenCVResize2D, cv::Size(0, 0), + factorsOutputOpenCVResize2D[0], factorsOutputOpenCVResize2D[1], cv::INTER_LINEAR); + } else if (OpenCVInterpolationType == nearest_neighbour_interpolation && OpenCVScaleType == scale_length) { + cv::resize(inputImageOpenCVResize2D, outputImageOpenCVResize2D, sizesOutputOpenCVResize2D, + 0, 0, cv::INTER_NEAREST); + } else if (OpenCVInterpolationType == bilinear_interpolation && OpenCVScaleType == scale_length) { + cv::resize(inputImageOpenCVResize2D, outputImageOpenCVResize2D, sizesOutputOpenCVResize2D, + 0, 0, cv::INTER_LINEAR); + } + + // 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("ResultOpenCVResize2D.png", outputImageOpenCVResize2D, 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; +}