├── BlurDetectionFFT.cbp ├── Lena.jpg ├── Lena_1.jpg ├── Lena_10.jpg ├── Lena_1_5.jpg ├── Lena_2.jpg ├── Lena_3.jpg ├── Lena_5.jpg ├── README.md └── main.cpp /BlurDetectionFFT.cbp: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 48 | 49 | -------------------------------------------------------------------------------- /Lena.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Qengineering/Blur-detection-with-FFT-in-C/9c182424afbf44f3bce04a8ed1bca9afc7d656da/Lena.jpg -------------------------------------------------------------------------------- /Lena_1.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Qengineering/Blur-detection-with-FFT-in-C/9c182424afbf44f3bce04a8ed1bca9afc7d656da/Lena_1.jpg -------------------------------------------------------------------------------- /Lena_10.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Qengineering/Blur-detection-with-FFT-in-C/9c182424afbf44f3bce04a8ed1bca9afc7d656da/Lena_10.jpg -------------------------------------------------------------------------------- /Lena_1_5.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Qengineering/Blur-detection-with-FFT-in-C/9c182424afbf44f3bce04a8ed1bca9afc7d656da/Lena_1_5.jpg -------------------------------------------------------------------------------- /Lena_2.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Qengineering/Blur-detection-with-FFT-in-C/9c182424afbf44f3bce04a8ed1bca9afc7d656da/Lena_2.jpg -------------------------------------------------------------------------------- /Lena_3.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Qengineering/Blur-detection-with-FFT-in-C/9c182424afbf44f3bce04a8ed1bca9afc7d656da/Lena_3.jpg -------------------------------------------------------------------------------- /Lena_5.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Qengineering/Blur-detection-with-FFT-in-C/9c182424afbf44f3bce04a8ed1bca9afc7d656da/Lena_5.jpg -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Blur-detection-with-FFT-in-C 2 | ![output image]( https://qengineering.eu/images/LenaBlur.png )

3 | This is a C++ implementation of the blur detection written in Python.
4 | https://github.com/whdcumt/BlurDetection.

5 | Paper: http://www.cse.cuhk.edu.hk/leojia/all_final_papers/blur_detect_cvpr08.pdf

6 | As known, blur is the lack of detailed features in an image. Detailed features have the most energy in the high-frequency Fourier spectrum. As to blurry regions (clouds, for instance), which have energy levels in low frequencies. This fact lets the blur detecting work. After removing the low frequencies, the energy of the remaining high part is measured. The higher output, the sharper the image must be. Please note, you should have OpenCV installed. 7 | 8 | ------------ 9 | 10 | [![paypal](https://qengineering.eu/images/TipJarSmall4.png)](https://www.paypal.com/cgi-bin/webscr?cmd=_s-xclick&hosted_button_id=CPZTM5BB3FCYL) 11 | -------------------------------------------------------------------------------- /main.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | using namespace cv; 5 | using namespace std; 6 | 7 | #define BLOCK 60 8 | 9 | int main(int argc, char **argv) { 10 | if (argc <= 1) { 11 | fprintf(stderr, "Error: missing image file\n"); 12 | return 1; 13 | } 14 | string image_file = argv[1]; 15 | 16 | cout << "Processing " << image_file << std::endl; 17 | Mat frame = imread(image_file, IMREAD_GRAYSCALE); 18 | 19 | int cx = frame.cols/2; 20 | int cy = frame.rows/2; 21 | 22 | // Go float 23 | Mat fImage; 24 | frame.convertTo(fImage, CV_32F); 25 | 26 | // FFT 27 | cout << "Direct transform...\n"; 28 | Mat fourierTransform; 29 | dft(fImage, fourierTransform, DFT_SCALE|DFT_COMPLEX_OUTPUT); 30 | 31 | //center low frequencies in the middle 32 | //by shuffling the quadrants. 33 | Mat q0(fourierTransform, Rect(0, 0, cx, cy)); // Top-Left - Create a ROI per quadrant 34 | Mat q1(fourierTransform, Rect(cx, 0, cx, cy)); // Top-Right 35 | Mat q2(fourierTransform, Rect(0, cy, cx, cy)); // Bottom-Left 36 | Mat q3(fourierTransform, Rect(cx, cy, cx, cy)); // Bottom-Right 37 | 38 | Mat tmp; // swap quadrants (Top-Left with Bottom-Right) 39 | q0.copyTo(tmp); 40 | q3.copyTo(q0); 41 | tmp.copyTo(q3); 42 | 43 | q1.copyTo(tmp); // swap quadrant (Top-Right with Bottom-Left) 44 | q2.copyTo(q1); 45 | tmp.copyTo(q2); 46 | 47 | // Block the low frequencies 48 | // #define BLOCK could also be a argument on the command line of course 49 | fourierTransform(Rect(cx-BLOCK,cy-BLOCK,2*BLOCK,2*BLOCK)).setTo(0); 50 | 51 | //shuffle the quadrants to their original position 52 | Mat orgFFT; 53 | fourierTransform.copyTo(orgFFT); 54 | Mat p0(orgFFT, Rect(0, 0, cx, cy)); // Top-Left - Create a ROI per quadrant 55 | Mat p1(orgFFT, Rect(cx, 0, cx, cy)); // Top-Right 56 | Mat p2(orgFFT, Rect(0, cy, cx, cy)); // Bottom-Left 57 | Mat p3(orgFFT, Rect(cx, cy, cx, cy)); // Bottom-Right 58 | 59 | p0.copyTo(tmp); 60 | p3.copyTo(p0); 61 | tmp.copyTo(p3); 62 | 63 | p1.copyTo(tmp); // swap quadrant (Top-Right with Bottom-Left) 64 | p2.copyTo(p1); 65 | tmp.copyTo(p2); 66 | 67 | // IFFT 68 | cout << "Inverse transform...\n"; 69 | Mat invFFT; 70 | Mat logFFT; 71 | double minVal,maxVal; 72 | 73 | dft(orgFFT, invFFT, DFT_INVERSE|DFT_REAL_OUTPUT); 74 | 75 | //img_fft = 20*numpy.log(numpy.abs(img_fft)) 76 | invFFT = cv::abs(invFFT); 77 | cv::minMaxLoc(invFFT,&minVal,&maxVal,NULL,NULL); 78 | 79 | //check for impossible values 80 | if(maxVal<=0.0){ 81 | cerr << "No information, complete black image!\n"; 82 | return 1; 83 | } 84 | 85 | cv::log(invFFT,logFFT); 86 | logFFT *= 20; 87 | 88 | //result = numpy.mean(img_fft) 89 | cv::Scalar result= cv::mean(logFFT); 90 | cout << "Result : "<< result.val[0] << endl; 91 | 92 | // show if you like 93 | Mat finalImage; 94 | logFFT.convertTo(finalImage, CV_8U); // Back to 8-bits 95 | imshow("Input", frame); 96 | imshow("Result", finalImage); 97 | cv::waitKey(); 98 | // end show if you like 99 | 100 | return 0; 101 | } 102 | --------------------------------------------------------------------------------