模糊检测
2004 Blur Detection for Digital Images Using Wavelet Transform
算法原理:
(1)haar wavelet transform
(2)规则集合(参考论文^_^)
MATLAB代码:
testDemo.m文件
clear; clc; % img = imread('lena0.png'); % img = imread('lena.png'); % img = imread('chicky_512.png'); % img = imread('baboon.jpg'); % img = imread('HappyFish.jpg'); img = imread('10.jpg'); % img = imread('11.jpg'); % img = imread('12.jpg'); if ndims(img) > 2 img = rgb2gray(img); end % % gaussian blur % sigma = 0.01; % gfilter = fspecial('gaussian', [5 5], sigma); % img = imfilter(img, gfilter, 'replicate'); % imshow(img); [unblured, BlurExtent] = blurDetection(img, 35, 0.05); unblured BlurExtentblurDetection.m文件
function [unblured, BlurExtent] = blurDetection(img, threshold, MinZero) % 2004 Blur Detection for Digital Images Using Wavelet Transform if nargin < 3 MinZero = 0.05; if nargin < 2 threshold = 35; if nargin < 1 img = imread('lena.png'); end end end if ndims(img) > 2 img = rgb2gray(img); end img0 = single(img); [m0, n0] = size(img); m = ceil(single(m0) / 16) * 16; n = ceil(single(n0) / 16) * 16; img = zeros(m, n); img(1:m0, 1:n0) = img0; tic; %% Algorithm 1: HWT for edge detection % Step1 (Harr wavelet transform) % level1 [m, n] = size(img); level1 = getWaveletLevel(img); % level2 m = m / 2; n = n / 2; level2 = getWaveletLevel(level1(1:m, 1:n)); % level3 m = m / 2; n = n / 2; level3 = getWaveletLevel(level2(1:m, 1:n)); % Step2 [m, n] = size(img); Emap1 = sqrt(level1(1:m/2, n/2+1:n).^2 + level1(m/2+1:m, 1:n/2).^2 + level1(m/2+1:m, n/2+1:n).^2); m = m/2; n = n/2; Emap2 = sqrt(level2(1:m/2, n/2+1:n).^2 + level2(m/2+1:m, 1:n/2).^2 + level2(m/2+1:m, n/2+1:n).^2); m = m/2; n = n/2; Emap3 = sqrt(level3(1:m/2, n/2+1:n).^2 + level3(m/2+1:m, 1:n/2).^2 + level3(m/2+1:m, n/2+1:n).^2); % Step3 Emax1 = getEmax(Emap1, 8); Emax2 = getEmax(Emap2, 4); Emax3 = getEmax(Emap3, 2); %% Algorithm2: blur detection scheme % Step1 (Alegorithm 1) % Step2 (Rule1) [m, n] = size(Emax1); Nedge = 0; Eedge = zeros(m, n); for i = 1:m for j = 1:n if Emax1(i, j) > threshold || Emax2(i, j) > threshold || Emax3(i, j) > threshold Nedge = Nedge + 1; Eedge(i, j) = 1; end end end % Step3 (Rule2) Nda = 0; for i = 1:m for j = 1:n if Eedge(i, j) == 1 ... && Emax1(i, j) > Emax2(i, j) && Emax2(i, j) > Emax3(i, j) Nda = Nda + 1; end end end % Step4 (Rule3,4) Nrg = 0; Eedge_Gstep_Roof = zeros(m, n); for i = 1:m for j = 1:n if Eedge(i, j) == 1 ... && (Emax1(i, j) < Emax2(i, j) && Emax2(i, j) < Emax3(i, j) ... || (Emax2(i,j) > Emax1(i,j) && Emax2(i,j) > Emax3(i,j))) Nrg = Nrg + 1; Eedge_Gstep_Roof(i, j) = 1; end end end % Step5 (Rule5) Nbrg = 0; for i = 1:m for j = 1:n if Eedge_Gstep_Roof(i, j) == 1 && Emax1(i, j) < threshold Nbrg = Nbrg + 1; end end end % Step6 Per = double(Nda) / Nedge; unblured = Per > MinZero; % Step7 BlurExtent = double(Nbrg) / Nrg; toc; % function [ level1 ] = getWaveletLevel( img ) [m, n] = size(img); % haar wavelet trainform level1_horizontal = zeros(m, n); for i = 1:n/2 level1_horizontal(:, i) = (img(:, 2*i-1) + img(:, 2*i)) / 2; level1_horizontal(:, i+n/2) = img(:, 2*i-1) - level1_horizontal(:, i); end level1 = zeros(m, n); for i = 1:m/2 level1(i, :) = (level1_horizontal(2*i-1, :) + level1_horizontal(2*i, :)) / 2; level1(i+m/2, :) = level1_horizontal(2*i-1, :) - level1(i, :); end function Emax = getEmax(Emap, scale) [m, n] = size(Emap); Emax = zeros(m/scale, n/scale); for i = 1:m/scale for j = 1:n/scale Emax(i,j) = max(max(Emap(scale*(i-1)+1:scale*i, scale*(j-1)+1:scale*j))); end end
#include <iostream> #include "cv.h" #include "highgui.h" using namespace std; using namespace cv; void getHaarWavelet(const Mat &src, Mat &dst) { int height = src.size().height; int width = src.size().width; dst.create(height, width, CV_32F); Mat horizontal = Mat::zeros(height, width, CV_32F); for(int i = 0; i < height; i++) { for(int j = 0; j < width/2; j++) { float meanPixel = (src.at<float>(i,2*j) + src.at<float>(i,2*j+1)) / 2; horizontal.at<float>(i, j) = meanPixel; horizontal.at<float>(i, j + width/2) = src.at<float>(i, 2*j) - meanPixel; } } for(int i = 0; i < height/2; i++) { for(int j = 0; j < width; j++) { float meanPixel = (horizontal.at<float>(2*i,j) + horizontal.at<float>(2*i+1,j)) / 2; dst.at<float>(i, j) = meanPixel; dst.at<float>(i + height/2, j) = horizontal.at<float>(2*i, j) - meanPixel; } } horizontal.release(); } void getEmax(const Mat &src, Mat &dst, int scale) { int height = src.size().height; int width = src.size().width; int h_scaled = height / scale; int w_scaled = width / scale; dst.create(h_scaled, w_scaled, CV_32F); for(int i = 0; i<h_scaled; i++) { for(int j = 0; j<w_scaled; j++) { double maxValue; minMaxLoc(src(Rect(scale*j, scale*i, scale, scale)), NULL, &maxValue); dst.at<float>(i,j) = float(maxValue); } } } int main(int argc, char * argv[]) { char *path = argv[1]; float threshold = 35; float MinZero = 0.05; if (argc < 2) { path = "lena.png"; //path = "lena0.png"; //path = "chicky_512.png"; //path = "baboon.jpg"; //path = "HappyFish.jpg"; //path = "10.jpg"; //path = "11.jpg"; //path = "12.jpg"; } Mat img0 = imread(path, CV_LOAD_IMAGE_GRAYSCALE); int height0 = img0.size().height; int width0 = img0.size().width; img0.convertTo(img0, CV_32F); int height = ceilf(float(height0) / 16) * 16; int width = ceilf(float(width0) / 16) * 16; Mat img = Mat::zeros(height, width, CV_32F); Mat temp = img(Rect(0, 0, width0, height0)); img0.copyTo(img(Rect(0, 0, width0, height0))); // start time record clock_t start = clock(); // Algorithm 1: HWT for edge detection // Step1 (Harr wavelet transform) Mat level1; getHaarWavelet(img, level1); Mat level2; getHaarWavelet(level1(Rect(0, 0, width/2, height/2)), level2); Mat level3; getHaarWavelet(level2(Rect(0, 0, width/4, height/4)), level3); // Step2 Mat HL1, LH1, HH1, Emap1; pow(level1(Rect(width/2, 0, width/2, height/2)), 2.0, HL1); pow(level1(Rect(0, height/2, width/2, height/2)), 2.0, LH1); pow(level1(Rect(width/2, height/2, width/2, height/2)), 2.0, HH1); sqrt(HL1 + LH1 + HH1, Emap1); Mat HL2, LH2, HH2, Emap2; pow(level2(Rect(width/4, 0, width/4, height/4)), 2.0, HL2); pow(level2(Rect(0, height/4, width/4, height/4)), 2.0, LH2); pow(level2(Rect(width/4, height/4, width/4, height/4)), 2.0, HH2); sqrt(HL2 + LH2 + HH2, Emap2); Mat HL3, LH3, HH3, Emap3; pow(level3(Rect(width/8, 0, width/8, height/8)), 2.0, HL3); pow(level3(Rect(0, height/8, width/8, height/8)), 2.0, LH3); pow(level3(Rect(width/8, height/8, width/8, height/8)), 2.0, HH3); sqrt(HL3 + LH3 + HH3, Emap3); // Step3 Mat Emax1, Emax2, Emax3; getEmax(Emap1, Emax1, 8); getEmax(Emap2, Emax2, 4); getEmax(Emap3, Emax3, 2); // Algorithm2: blur detection scheme // Step1 (Alegorithm 1) // Step2 int m = Emax1.size().height; int n = Emax1.size().width; int Nedge = 0; Mat Eedge = Mat::zeros(m, n, CV_32F); for(int i = 0; i<m; i++) { for(int j = 0; j<n; j++) { if(Emax1.at<float>(i,j)>threshold || Emax2.at<float>(i,j)>threshold || Emax3.at<float>(i,j)>threshold) { ++Nedge; Eedge.at<float>(i,j) = 1.0; } } } // Step3 (Rule2) int Nda = 0; for(int i = 0; i<m; i++) { for(int j = 0; j<n; j++) { float tempEmax2 = Emax2.at<float>(i,j); if(Eedge.at<float>(i,j) > 0.1 && Emax1.at<float>(i,j)>tempEmax2 && tempEmax2 >Emax3.at<float>(i,j)) { ++Nda; } } } // Step4 (Rule3,4) int Nrg = 0; Mat Eedge_Gstep_Roof = Mat::zeros(m, n, CV_32F); for(int i = 0; i<m; i++) { for(int j = 0; j<n; j++) { float tempEmax1 = Emax1.at<float>(i,j); float tempEmax2 = Emax2.at<float>(i,j); float tempEmax3 = Emax3.at<float>(i,j); if(Eedge.at<float>(i,j) > 0.1 && (tempEmax1<tempEmax2 && tempEmax2<tempEmax3 || tempEmax2>tempEmax1 && tempEmax2>tempEmax3)) { ++Nrg; Eedge_Gstep_Roof.at<float>(i,j) = 1.0; } } } // Step5 (Rule5) int Nbrg = 0; for(int i = 0; i<m; i++) { for(int j = 0; j<n; j++) { if(Eedge_Gstep_Roof.at<float>(i,j) > 0.1 && Emax1.at<float>(i,j) < threshold) { ++Nbrg; } } } // Step6 float Per = float(Nda) / Nedge; int unblured = 0; if(Per > MinZero) unblured = 1; // Step7 float BlurExtent = float(Nbrg) / Nrg; // start time record clock_t finish = clock(); float costtime = (float)(finish - start) / CLOCKS_PER_SEC; cout << endl; cout << "image: " << path << endl; cout << "height: " << height0 << endl; cout << "width: " << width0 << endl; if (unblured == 1) cout << "The image is clear" << endl; else cout << "The image is blured" << endl; cout << "Num of edge points: " << Nedge << endl; cout << "Num of Dirac and Astep: " << Nda << endl; cout << "Num of Roof and Gstep: " << Nrg << endl; cout << "Num of Roof and Gstep lost sharp: " << Nbrg << endl; cout << "BlurExtent: " << BlurExtent << endl; cout << "Time cost: " << costtime << " s" << endl; return 0; }