模糊检测
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
BlurExtent
blurDetection.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
CPP代码:
#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;
}