模糊檢測BlurDetection using wavelet transform

模糊檢測

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;
}


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章