diff --git a/README.md b/README.md index 8de2b5f3..15383591 100644 --- a/README.md +++ b/README.md @@ -126,6 +126,13 @@ $ cmake -G Ninja .. \ -DBUDDY_OPT_STRIP_MINING= \ -DBUDDY_OPT_ATTR= $ cmake --build . -- -$ ninja test +$ ninja test && ninja image-processing-integration-tests ``` +For executing Image Processing integration tests : +``` +cd bin +./image-processing-integration-tests +``` + +where `` is an optional parameter used for pointing to the image which is to be used while executing tests. diff --git a/include/ImageProcessing/Kernels.h b/include/ImageProcessing/Kernels.h index ac159f34..47d745a1 100644 --- a/include/ImageProcessing/Kernels.h +++ b/include/ImageProcessing/Kernels.h @@ -22,6 +22,7 @@ #define IMAGE_PROCESSING_KERNELS // clang-format off +#include #include #include diff --git a/tests/UnitTests/Test.h b/include/Utils/Test.h similarity index 100% rename from tests/UnitTests/Test.h rename to include/Utils/Test.h diff --git a/tests/CMakeLists.txt b/tests/CMakeLists.txt index e1af6d31..9a97fea5 100644 --- a/tests/CMakeLists.txt +++ b/tests/CMakeLists.txt @@ -1 +1,2 @@ add_subdirectory(UnitTests) +add_subdirectory(IntegrationTests) diff --git a/tests/IntegrationTests/CMakeLists.txt b/tests/IntegrationTests/CMakeLists.txt new file mode 100644 index 00000000..6071631f --- /dev/null +++ b/tests/IntegrationTests/CMakeLists.txt @@ -0,0 +1 @@ +add_subdirectory(ImageProcessing) diff --git a/tests/IntegrationTests/ImageProcessing/CMakeLists.txt b/tests/IntegrationTests/ImageProcessing/CMakeLists.txt new file mode 100644 index 00000000..fa6c9ab7 --- /dev/null +++ b/tests/IntegrationTests/ImageProcessing/CMakeLists.txt @@ -0,0 +1,19 @@ +find_package(OpenCV REQUIRED CONFIG) +include_directories(${OpenCV_INCLUDE_DIRS}) + +add_executable( + image-processing-integration-tests + DIPCorr2DTest.cpp +) + +include(GoogleTest) +gtest_discover_tests(image-processing-integration-tests) + +target_link_libraries( + image-processing-integration-tests + ${OpenCV_LIBS} + BuddyCorr2D + Container + + gtest_main +) diff --git a/tests/IntegrationTests/ImageProcessing/DIPCorr2DTest.cpp b/tests/IntegrationTests/ImageProcessing/DIPCorr2DTest.cpp new file mode 100644 index 00000000..1df7d209 --- /dev/null +++ b/tests/IntegrationTests/ImageProcessing/DIPCorr2DTest.cpp @@ -0,0 +1,114 @@ +#include "ImageProcessing/Kernels.h" +#include "Utils/Container.h" + +#include +#include + +#include +#include +#include + +using namespace cv; +using namespace std; + +// Declare the Corr2D C interface. +extern "C" { +void _mlir_ciface_corr_2d_constant_padding( + MemRef *input, MemRef *kernel, MemRef *output, + unsigned int centerX, unsigned int centerY, float constantValue); +} + +// Fixture for testing the dip.corr_2d operation. +class FilterTest : public ::testing::Test { +public: + static void setImageNames(int argc, char **argv) { + if (argc > 1) + testImageName = argv[1]; + else + testImageName = "../../benchmarks/ImageProcessing/Images/YuTu.png"; + } + + const std::string getTestImageName() { return testImageName; } + +private: + static std::string testImageName; +}; + +std::string FilterTest::testImageName; + +bool equalImages(const Mat &img1, const Mat &img2) { + if (img1.rows != img2.rows || img1.cols != img2.cols) { + std::cout << "Produced outputs by DIP and OpenCV differ. Image dimensions " + "are not equal\n"; + return 0; + } + + for (unsigned int y = 0; y < img1.rows; ++y) { + for (unsigned int x = 0; x < img1.cols; ++x) { + if (abs(img1.at(x, y) - img2.at(x, y)) > 10e-2) { + std::cout << "Produced outputs by DIP and OpenCV differ.\n"; + return 0; + } + } + } + return 1; +} + +void testKernelImpl(const Mat &inputImage, unsigned int kernelRows, + unsigned int kernelCols, float *kernelArray, unsigned int x, + unsigned int y) { + // Define container sizes. + intptr_t sizesImage[2] = {inputImage.rows, inputImage.cols}; + intptr_t sizesKernel[2] = {kernelRows, kernelCols}; + + // Define input, kernel, and output. + MemRef input(inputImage, sizesImage); + MemRef kernel(kernelArray, sizesKernel); + MemRef output(sizesImage); + + for (int i = 0; i < inputImage.rows; i++) + for (int j = 0; j < inputImage.cols; j++) + output[i * inputImage.rows + j] = 0; + + Mat kernel1 = Mat(kernelRows, kernelCols, CV_32FC1, kernelArray); + Mat opencvOutput; + + _mlir_ciface_corr_2d_constant_padding(&input, &kernel, &output, x, y, 0); + + filter2D(inputImage, opencvOutput, CV_32FC1, kernel1, cv::Point(x, y), 0.0, + cv::BORDER_CONSTANT); + + // Define a cv::Mat with the output of corr_2d. + Mat dipOutput(inputImage.rows, inputImage.cols, CV_32FC1, output.getData()); + + if (!equalImages(dipOutput, opencvOutput)) { + std::cout << "Different images produced by OpenCV and DIP for kernel :\n" + << kernel1 + << "\n" + "when anchor point was : (" + << x << ", " << y << ").\n"; + return; + } +} + +void testKernel(const Mat &inputImage, unsigned int kernelRows, + unsigned int kernelCols, float *kernelArray) { + for (unsigned int y = 0; y < kernelRows; ++y) + for (unsigned int x = 0; x < kernelCols; ++x) + testKernelImpl(inputImage, kernelRows, kernelCols, kernelArray, x, y); +} + +TEST_F(FilterTest, OpenCVComparison) { + for (auto kernel : kernelMap) { + cv::Mat testImage = cv::imread(getTestImageName(), cv::IMREAD_GRAYSCALE); + testKernel(testImage, get<1>(kernel.second), get<2>(kernel.second), + get<0>(kernel.second)); + } +} + +int main(int argc, char **argv) { + FilterTest::setImageNames(argc, argv); + + ::testing::InitGoogleTest(&argc, argv); + return RUN_ALL_TESTS(); +} diff --git a/tests/UnitTests/TestContainer.cpp b/tests/UnitTests/TestContainer.cpp index 7f2d5a81..bedd046d 100644 --- a/tests/UnitTests/TestContainer.cpp +++ b/tests/UnitTests/TestContainer.cpp @@ -18,8 +18,8 @@ // //===----------------------------------------------------------------------===// -#include "Test.h" #include "Utils/Container.h" +#include "Utils/Test.h" #include // Fixture for testing the MemRef class.