#include "opencv2/core.hpp" #include "opencv2/core/utility.hpp" #include "opencv2/imgproc.hpp" #include "opencv2/imgcodecs.hpp" #include "opencv2/highgui.hpp" #include #include using namespace cv; using namespace std; static void convolveDFT(InputArray A, InputArray B, OutputArray C) { // Calculate the size of the output array int outputRows = A.rows() + B.rows() - 1; int outputCols = A.cols() + B.cols() - 1; // Reallocate the output array if needed C.create(outputRows, outputCols, A.type()); Size dftSize; // Calculate the size of DFT transform dftSize.width = getOptimalDFTSize(A.cols() + B.cols() - 1); dftSize.height = getOptimalDFTSize(A.rows() + B.rows() - 1); // Allocate temporary buffers and initialize them with 0's Mat tempA(dftSize, A.type(), Scalar::all(0)); Mat tempB(dftSize, B.type(), Scalar::all(0)); // Copy A and B to the top-left corners of tempA and tempB, respectively Mat roiA(tempA, Rect(0, 0, A.cols(), A.rows())); A.copyTo(roiA); Mat roiB(tempB, Rect(0, 0, B.cols(), B.rows())); B.copyTo(roiB); // Now transform the padded A & B in-place; // use "nonzeroRows" hint for faster processing dft(tempA, tempA, 0, A.rows()); dft(tempB, tempB, 0, B.rows()); // Multiply the spectrums; // the function handles packed spectrum representations well mulSpectrums(tempA, tempB, tempA, 0); // Transform the product back from the frequency domain. // Even though all the result rows will be non-zero, // you need only the first C.rows of them, and thus you // pass nonzeroRows == C.rows dft(tempA, tempA, DFT_INVERSE + DFT_SCALE, C.rows()); // Now copy the result back to C. tempA(Rect(0, 0, C.cols(), C.rows())).copyTo(C); // All the temporary buffers will be deallocated automatically } static void help(const char ** argv) { printf("\nThis program demonstrates the use of convolution using discrete Fourier transform (DFT)\n" "An image is convolved with kernel filter using DFT.\n" "Usage:\n %s [input -- default lena.jpg]\n", argv[0]); } const char* keys = { "{help h||}{@input|lena.jpg|input image file}" }; int main(int argc, const char** argv) { // Load the image in grayscale help(argv); CommandLineParser parser(argc, argv, keys); if (parser.has("help")) { help(argv); return 0; } string filename = parser.get(0); Mat img = imread(samples::findFile(filename), IMREAD_GRAYSCALE); // Check if the image is loaded successfully if (img.empty()) { std::cerr << "Error: Image not loaded!" << std::endl; return -1; } // Convert the image to CV_32F Mat img_32f; img.convertTo(img_32f, CV_32F); float kernelData[9] = { 1.0f/9, 1.0f/9, 1.0f/9, 1.0f/9, 1.0f/9, 1.0f/9, 1.0f/9, 1.0f/9, 1.0f/9 }; // example of blur filter, can be changed to other filter as well. Mat kernel(3, 3, CV_32F, kernelData); // Perform convolution of the image with the sharpening kernel Mat result; convolveDFT(img_32f, kernel, result); // Normalize the result for better visualization normalize(result, result, 0, 255, NORM_MINMAX); // Convert result back to 8-bit for display Mat result_8u; result.convertTo(result_8u, CV_8U); // Display the images imshow("Original Image", img); imshow("Output Image", result_8u); waitKey(0); // Wait for a key press to close the windows return 0; }