How do I find local threshold for coefficients in image compression using DWT in MATLAB - matlab

I'm trying to write an image compression script in MATLAB using multilayer 3D DWT(color image). along the way, I want to apply thresholding on coefficient matrices, both global and local thresholds.
I like to use the formula below to calculate my local threshold:
where sigma is variance and N is the number of elements.
Global thresholding works fine; but my problem is that the calculated local threshold is (most often!) greater than the maximum band coefficient, therefore no thresholding is applied.
Everything else works fine and I get a result too, but I suspect the local threshold is miscalculated. Also, the resulting image is larger than the original!
I'd appreciate any help on the correct way to calculate the local threshold, or if there's a pre-set MATLAB function.
here's an example output:
here's my code:
clear;
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%%%%% COMPRESSION %%%%%
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% read base image
% dwt 3/5-L on base images
% quantize coeffs (local/global)
% count zero value-ed coeffs
% calculate mse/psnr
% save and show result
% read images
base = imread('circ.jpg');
fam = 'haar'; % wavelet family
lvl = 3; % wavelet depth
% set to 1 to apply global thr
thr_type = 0;
% global threshold value
gthr = 180;
% convert base to grayscale
%base = rgb2gray(base);
% apply dwt on base image
dc = wavedec3(base, lvl, fam);
% extract coeffs
ll_base = dc.dec{1};
lh_base = dc.dec{2};
hl_base = dc.dec{3};
hh_base = dc.dec{4};
ll_var = var(ll_base, 0);
lh_var = var(lh_base, 0);
hl_var = var(hl_base, 0);
hh_var = var(hh_base, 0);
% count number of elements
ll_n = numel(ll_base);
lh_n = numel(lh_base);
hl_n = numel(hl_base);
hh_n = numel(hh_base);
% find local threshold
ll_t = ll_var * (sqrt(2 * log2(ll_n)));
lh_t = lh_var * (sqrt(2 * log2(lh_n)));
hl_t = hl_var * (sqrt(2 * log2(hl_n)));
hh_t = hh_var * (sqrt(2 * log2(hh_n)));
% global
if thr_type == 1
ll_t = gthr; lh_t = gthr; hl_t = gthr; hh_t = gthr;
end
% count zero values in bands
ll_size = size(ll_base);
lh_size = size(lh_base);
hl_size = size(hl_base);
hh_size = size(hh_base);
% count zero values in new band matrices
ll_zeros = sum(ll_base==0,'all');
lh_zeros = sum(lh_base==0,'all');
hl_zeros = sum(hl_base==0,'all');
hh_zeros = sum(hh_base==0,'all');
% initiate new matrices
ll_new = zeros(ll_size);
lh_new = zeros(lh_size);
hl_new = zeros(lh_size);
hh_new = zeros(lh_size);
% apply thresholding on bands
% if new value < thr => 0
% otherwise, keep the previous value
for id=1:ll_size(1)
for idx=1:ll_size(2)
if ll_base(id,idx) < ll_t
ll_new(id,idx) = 0;
else
ll_new(id,idx) = ll_base(id,idx);
end
end
end
for id=1:lh_size(1)
for idx=1:lh_size(2)
if lh_base(id,idx) < lh_t
lh_new(id,idx) = 0;
else
lh_new(id,idx) = lh_base(id,idx);
end
end
end
for id=1:hl_size(1)
for idx=1:hl_size(2)
if hl_base(id,idx) < hl_t
hl_new(id,idx) = 0;
else
hl_new(id,idx) = hl_base(id,idx);
end
end
end
for id=1:hh_size(1)
for idx=1:hh_size(2)
if hh_base(id,idx) < hh_t
hh_new(id,idx) = 0;
else
hh_new(id,idx) = hh_base(id,idx);
end
end
end
% count zeros of the new matrices
ll_new_size = size(ll_new);
lh_new_size = size(lh_new);
hl_new_size = size(hl_new);
hh_new_size = size(hh_new);
% count number of zeros among new values
ll_new_zeros = sum(ll_new==0,'all');
lh_new_zeros = sum(lh_new==0,'all');
hl_new_zeros = sum(hl_new==0,'all');
hh_new_zeros = sum(hh_new==0,'all');
% set new band matrices
dc.dec{1} = ll_new;
dc.dec{2} = lh_new;
dc.dec{3} = hl_new;
dc.dec{4} = hh_new;
% count how many coeff. were thresholded
ll_zeros_diff = ll_new_zeros - ll_zeros;
lh_zeros_diff = lh_zeros - lh_new_zeros;
hl_zeros_diff = hl_zeros - hl_new_zeros;
hh_zeros_diff = hh_zeros - hh_new_zeros;
% show coeff. matrices vs. thresholded version
figure
colormap(gray);
subplot(2,4,1); imagesc(ll_base); title('LL');
subplot(2,4,2); imagesc(lh_base); title('LH');
subplot(2,4,3); imagesc(hl_base); title('HL');
subplot(2,4,4); imagesc(hh_base); title('HH');
subplot(2,4,5); imagesc(ll_new); title({'LL thr';ll_zeros_diff});
subplot(2,4,6); imagesc(lh_new); title({'LH thr';lh_zeros_diff});
subplot(2,4,7); imagesc(hl_new); title({'HL thr';hl_zeros_diff});
subplot(2,4,8); imagesc(hh_new); title({'HH thr';hh_zeros_diff});
% idwt to reconstruct compressed image
cmp = waverec3(dc);
cmp = uint8(cmp);
% calculate mse/psnr
D = abs(cmp - base) .^2;
mse = sum(D(:))/numel(base);
psnr = 10*log10(255*255/mse);
% show images and mse/psnr
figure
subplot(1,2,1);
imshow(base); title("Original"); axis square;
subplot(1,2,2);
imshow(cmp); colormap(gray); axis square;
msg = strcat("MSE: ", num2str(mse), " | PSNR: ", num2str(psnr));
title({"Compressed";msg});
% save image locally
imwrite(cmp, 'compressed.png');

I solved the question.
the sigma in the local threshold formula is not variance, it's the standard deviation. I applied these steps:
used stdfilt() std2() to find standard deviation of my coeff. matrices (thanks to #Rotem for pointing this out)
used numel() to count the number of elements in coeff. matrices
this is a summary of the process. it's the same for other bands (LH, HL, HH))
[c, s] = wavedec2(image, wname, level); %apply dwt
ll = appcoeff2(c, s, wname); %find LL
ll_std = std2(ll); %find standard deviation
ll_n = numel(ll); %find number of coeffs in LL
ll_t = ll_std * (sqrt(2 * log2(ll_n))); %local the formula
ll_new = ll .* double(ll > ll_t); %thresholding
replace the LL values in c in a for loop
reconstruct by applying IDWT using waverec2
this is a sample output:

Related

weighted CDF formula always returns 1

I am reading this paper for enhancing image quality.
my problem is that when I am calculating weighted CDF, I always get 1 as output.
here is the sequence of formulas:
which gamma is defined like this:
which Cw is the weighted CDF:
which I think my main problem would be here.
but to be more clear I will add the rest of the formulas too.
corresponding Weighted Histogram Distribution function is:
and Alpha=C(i) which:
which h_c(i) is clipped histogram , and M is the total intensity levels ( which I'm not sure what is the M, I assumed since sum of Pi should be 1 so it must be sum of the hc_i )
and this is how it is clipping the histogram :
and the clipping limit is calculated with this formula:
here is my code:
sample_img = imread('my image path');
sample_img = im2double(sample_img);
L = 256 % The magnitude of each and every color channel is confined within the range [0 , L-1]
redChannel = sample_img(:,:,1);
greenChannel = sample_img(:,:,2);
blueChannel = sample_img(:,:,3);
max_blue = max(max(blueChannel));
max_green = max(max(greenChannel));
max_red = max(max(redChannel));
min_blue = min(min(blueChannel));
min_green = min(min(greenChannel));
min_red = min(min(redChannel));
bn = blueChannel - min_blue;
rn = redChannel - min_red;
gn = greenChannel - min_green;
max_bn = max(max(bn));
max_rn = max(max(rn));
max_gn = max(max(gn));
b_stretched = bn/max_bn;
r_stretched = rn/max_rn;
g_stretched = gn/max_gn;
% Recombine separate color channels into an RGB image.
rgb_stretched_Image = cat(3, r_stretched, g_stretched, b_stretched);
% Convert RGB to HSI
hsi_image = rgb2hsi(rgb_stretched_Image);
intensity = hsi_image(:, :, 3);
figure()
[counts , binLocations] = imhist(intensity);
imhist(intensity);
hist = counts;
% the clipping limit is computed based on the mean value of the
Tc = mean(hist);
% histogram clipping
length_hist = length(hist);
clipped_hist = zeros(1,length_hist);
for hist_id = 1:length_hist
if hist(hist_id)<Tc
disp('<Tc')
disp(hist(hist_id));
clipped_hist(hist_id) = hist(hist_id);
continue
end
disp('>Tc')
clipped_hist(hist_id) = Tc;
end
% the corresponding PDF (p(i))
% this is where I just used sum(clipped_hist) instead of M
Pi = clipped_hist / sum(clipped_hist);
%CDF
Ci = sum(Pi(1:L));
Alpha = Ci;
%Weighted Histogram Distribution function
Pmin = min(Pi);
Pmax = max(Pi);
Pwi = Pmax * power((Pi-Pmin)/(Pmax-Pmin),Alpha);
%weighted PDF sum
intensity_max = max(max(intensity*L));
Sum_Pwi = sum(Pwi(1:intensity_max));
% weighted CDF
Cwi = sum(Pwi(1:intensity_max)/Sum_Pwi);
%gamma
gamma = 1 - Cwi;
%Transformed pixel intensity
tpi = round(power(intensity/intensity_max,gamma));
since as I said the CDF output is always 1 , the enhanced image is always a white image. and as I see this formula, it must always have 1 as it's output. Am I missing something here ?
and am I right with the M value ?

gradient of a volume in 3 dimensions using Gaussian derivative in matlab

I want to compute gradient of a volume in MATLAB using Gaussian derivative. but I could not. can any one help me please? I do this in a 2D image using this code:
k = gaussiankernel(sigma1,1); % first order derivative of a gaussian with std
sigma1
gx = imfilter(I,k','replicate','conv');
gy = imfilter(I,k,'replicate','conv');
please help me. How can I compute gz using kernel k? or How can I extend this code to 3D?
Thank you in advance.
This is the code to generate adaptive ellipsoid using structuretensor3d:
function SE = AESE3(I,M,l1,l2,l3,phi3,theta3)
%I = input('Enter the input 3d volume: ');
%M = input('Enter the maximum allowed semi-major axes length: ');
% determining ellipsoid parameteres from eigen value decomposition of 3d
% structure tensor
row = size(I,1);
col = size(I,2);
hei = size(I,3);
SE = cell(row,col,hei);
padI = padarray(I,[M M M],'replicate','both');
padrow = size(padI,1);
padcol = size(padI,2);
padhei = size(padI,3);
[se_x,se_y,se_z] = meshgrid(-M:M,-M:M,-M:M);
for m = M+1:padrow-M
for n = M+1:padcol-M
for p = M+1:padhei-M
i = m-M;
j = n-M;
k = p-M;
a = (l1(i,j,k)+eps)/(l1(i,j,k)+l2(i,j,k)+l3(i,j,k)+3*eps)*M;
b = (l2(i,j,k)+eps)/(l1(i,j,k)+l2(i,j,k)+l3(i,j,k)+3*eps)*M;
c = (l3(i,j,k)+eps)/(l1(i,j,k)+l2(i,j,k)+l3(i,j,k)+3*eps)*M;
cos(phi3(i,j,k)) = cos_phi3;
sin(phi3(i,j,k)) = sin_phi3;
cos(theta3(i,j,k)) = cos_theta3;
sin(theta3(i,j,k)) = sin_theta3;
% defining structuring element for each pixel of image
se = ((se_x.*cos_theta3 - se_y.*sin_theta3.*cos_phi3 +
se_z.*sin_theta3.*sin_phi3).^2)./a.^2+((se_x.*sin_theta3 +
se_y.*cos_theta3.*cos_phi3 - se_z.*cos_theta3.*sin_phi3).^2)./b.^2+
((se_y.*sin_phi3 + se_z.*cos_phi3).^2)./c.^2 <= 1;
SE{i,j,k} = se;
end
end
end
end
Can I do this without zero padding?

Matlab argument passing to draw ROC curve

I want to draw a ROC curve using Matlab. Suppose my true positive rate is 3 and false positive rate is 5. Here the code I have to draw ROC curve.
function [Tps, Fps] = ROC(scores, labels)
%% Sort Labels and Scores by Scores
sl = [scores; labels];
[d1 d2] = sort(sl(1,:));
sorted_sl = sl(:,d2);
s_scores = sorted_sl(1,:);
s_labels = round(sorted_sl(2,:));
%% Constants
counts = histc(s_labels, unique(s_labels));
Tps = zeros(1, size(s_labels,2) + 1);
Fps = zeros(1, size(s_labels,2) + 1);
negCount = counts(1);
posCount = counts(2);
%% Shift threshold to find the ROC
for thresIdx = 1:(size(s_scores,2)+1)
% for each Threshold Index
tpCount = 0;
fpCount = 0;
for i = [1:size(s_scores,2)]
if (i >= thresIdx) % We think it is positive
if (s_labels(i) == 1) % Right!
tpCount = tpCount + 1;
else % Wrong!
fpCount = fpCount + 1;
end
end
end
Tps(thresIdx) = tpCount/posCount;
Fps(thresIdx) = fpCount/negCount;
end
%% Draw the Curve
% Sort [Tps;Fps]
x = Tps;
y = Fps;
% Interplotion to draw spline line
count = 100;
dist = (x(1) - x(size(x,2)))/100;
xx = [x(1):-dist:x(size(x,2))];
% In order to get the interpolations, we remove all the unique numbers
[d1 d2] = unique(x);
uni_x = x(1,d2);
uni_y = y(1,d2);
yy = spline(uni_x,uni_y,xx);
% No value should exceed 1
yy = min(yy, 1);
plot(x,y,'x',xx,yy);
How can I pass arguments for this code? How can I pass my true positive and false positive values? Please help, i am new to Matlab.

How does the choice of the wavelet function impact the speed of cwt()?

In cwt() I can specify which wavelet function to use. How does that impact the speed of cwt()?
Here is a benchmark, which I run with the -singleCompThread option when starting MATLAB to force it to use a single computational thread. cwt() was passed a 1,000,000-sample signal and asked to compute scales 1 to 10. My CPU is an i7-3610QM.
Code used:
clear all
%% Benchmark parameters
results_file_name = 'results_scale1-10.csv';
number_of_random_runs = 10;
scales = 1:10;
number_of_random_samples = 1000000;
%% Construct a cell array containing all the wavelet names
wavelet_haar_names = {'haar'};
wavelet_db_names = {'db1'; 'db2'; 'db3'; 'db4'; 'db5'; 'db6'; 'db7'; 'db8'; 'db9'; 'db10'};
wavelet_sym_names = {'sym2'; 'sym3'; 'sym4'; 'sym5'; 'sym6'; 'sym7'; 'sym8'};
wavelet_coif_names = {'coif1'; 'coif2'; 'coif3'; 'coif4'; 'coif5'};
wavelet_bior_names = {'bior1.1'; 'bior1.3'; 'bior1.5'; 'bior2.2'; 'bior2.4'; 'bior2.6'; 'bior2.8'; 'bior3.1'; 'bior3.3'; 'bior3.5'; 'bior3.7'; 'bior3.9'; 'bior4.4'; 'bior5.5'; 'bior6.8'};
wavelet_rbior_names = {'rbio1.1'; 'rbio1.3'; 'rbio1.5'; 'rbio2.2'; 'rbio2.4'; 'rbio2.6'; 'rbio2.8'; 'rbio3.1'; 'rbio3.3'; 'rbio3.5'; 'rbio3.7'; 'rbio3.9'; 'rbio4.4'; 'rbio5.5'; 'rbio6.8'};
wavelet_meyer_names = {'meyr'};
wavelet_dmeyer_names = {'dmey'};
wavelet_gaus_names = {'gaus1'; 'gaus2'; 'gaus3'; 'gaus4'; 'gaus5'; 'gaus6'; 'gaus7'; 'gaus8'};
wavelet_mexh_names = {'mexh'};
wavelet_morl_names = {'morl'};
wavelet_cgau_names = {'cgau1'; 'cgau2'; 'cgau3'; 'cgau4'; 'cgau5'};
wavelet_shan_names = {'shan1-1.5'; 'shan1-1'; 'shan1-0.5'; 'shan1-0.1'; 'shan2-3'};
wavelet_fbsp_names = {'fbsp1-1-1.5'; 'fbsp1-1-1'; 'fbsp1-1-0.5'; 'fbsp2-1-1'; 'fbsp2-1-0.5'; 'fbsp2-1-0.1'};
wavelet_cmor_names = {'cmor1-1.5'; 'cmor1-1'; 'cmor1-0.5'; 'cmor1-1'; 'cmor1-0.5'; 'cmor1-0.1'};
% Concatenate all wavelet names into a single cell array
wavelet_categories_names = who('wavelet*names');
wavelet_names = {};
for wavelet_categories_number=1:size(wavelet_categories_names,1)
temp = wavelet_categories_names(wavelet_categories_number);
temp = eval(temp{1});
wavelet_names = vertcat(wavelet_names, temp);
end
%% Prepare data
random_signal = rand(number_of_random_runs,number_of_random_samples);
%% Run benchmarks
result_file_ID = fopen(results_file_name, 'w');
for wavelet_number = 1:size(wavelet_names,1)
wavelet_name = wavelet_names(wavelet_number,:)
% Compute wavelet on a random signal
tic
for run = 1:number_of_random_runs
cwt(random_signal(run, :),scales,wavelet_name{1});
end
run_time_random_test = toc
fprintf(result_file_ID, '%s,', wavelet_name{1})
fprintf(result_file_ID, '%d\n', run_time_random_test)
end
size(wavelet_names,1)
fclose(result_file_ID);
If you want to see the impact of the choice of the scale:
Code used:
clear all
%% Benchmark parameters
results_file_name = 'results_sym2_change_scale.csv';
number_of_random_runs = 10;
scales = 1:10;
number_of_random_samples = 10000000;
% wavelet_names = {'sym2', 'sym3'}%, 'sym4'};
output_directory = 'output';
wavelet_names = get_all_wavelet_names();
%% Prepare data
random_signal = rand(number_of_random_runs,number_of_random_samples);
%% Prepare result folder
if ~exist(output_directory, 'dir')
mkdir(output_directory);
end
%% Run benchmarks
result_file_ID = fopen(results_file_name, 'w');
for wavelet_number = 1:size(wavelet_names,1)
wavelet_name = wavelet_names{wavelet_number}
if wavelet_number > 1
fprintf(result_file_ID, '%s\n', '');
end
fprintf(result_file_ID, '%s', wavelet_name)
run_time_random_test_scales = zeros(size(scales,2),1);
for scale_number = 1:size(scales,2)
scale = scales(scale_number);
% Compute wavelet on a random signal
tic
for run = 1:number_of_random_runs
cwt(random_signal(run, :),scale,wavelet_name);
end
run_time_random_test = toc
fprintf(result_file_ID, ',%d', run_time_random_test)
run_time_random_test_scales(scale_number) = run_time_random_test;
end
figure
bar(run_time_random_test_scales)
title(['Run time on random signal for ' wavelet_name])
xlabel('Scale')
ylabel('Run time (seconds)')
save_figure( fullfile(output_directory, ['run_time_random_test_' wavelet_name]) )
close all
end
size(wavelet_names,1)
fclose(result_file_ID);
With 3 functions:
get_all_wavelet_names.m:
function [ wavelet_names ] = get_all_wavelet_names( )
%GET_ALL_WAVELET_NAMES Get a list of available wavelet functions
%% Construct a cell array containing all the wavelet names
wavelet_haar_names = {'haar'};
wavelet_db_names = {'db1'; 'db2'; 'db3'; 'db4'; 'db5'; 'db6'; 'db7'; 'db8'; 'db9'; 'db10'};
wavelet_sym_names = {'sym2'; 'sym3'; 'sym4'; 'sym5'; 'sym6'; 'sym7'; 'sym8'};
wavelet_coif_names = {'coif1'; 'coif2'; 'coif3'; 'coif4'; 'coif5'};
wavelet_bior_names = {'bior1.1'; 'bior1.3'; 'bior1.5'; 'bior2.2'; 'bior2.4'; 'bior2.6'; 'bior2.8'; 'bior3.1'; 'bior3.3'; 'bior3.5'; 'bior3.7'; 'bior3.9'; 'bior4.4'; 'bior5.5'; 'bior6.8'};
wavelet_rbior_names = {'rbio1.1'; 'rbio1.3'; 'rbio1.5'; 'rbio2.2'; 'rbio2.4'; 'rbio2.6'; 'rbio2.8'; 'rbio3.1'; 'rbio3.3'; 'rbio3.5'; 'rbio3.7'; 'rbio3.9'; 'rbio4.4'; 'rbio5.5'; 'rbio6.8'};
wavelet_meyer_names = {'meyr'};
wavelet_dmeyer_names = {'dmey'};
wavelet_gaus_names = {'gaus1'; 'gaus2'; 'gaus3'; 'gaus4'; 'gaus5'; 'gaus6'; 'gaus7'; 'gaus8'};
wavelet_mexh_names = {'mexh'};
wavelet_morl_names = {'morl'};
wavelet_cgau_names = {'cgau1'; 'cgau2'; 'cgau3'; 'cgau4'; 'cgau5'};
wavelet_shan_names = {'shan1-1.5'; 'shan1-1'; 'shan1-0.5'; 'shan1-0.1'; 'shan2-3'};
wavelet_fbsp_names = {'fbsp1-1-1.5'; 'fbsp1-1-1'; 'fbsp1-1-0.5'; 'fbsp2-1-1'; 'fbsp2-1-0.5'; 'fbsp2-1-0.1'};
wavelet_cmor_names = {'cmor1-1.5'; 'cmor1-1'; 'cmor1-0.5'; 'cmor1-1'; 'cmor1-0.5'; 'cmor1-0.1'};
% Concatenate all wavelet names into a single cell array
wavelet_categories_names = who('wavelet*names');
wavelet_names = {};
for wavelet_categories_number=1:size(wavelet_categories_names,1)
temp = wavelet_categories_names(wavelet_categories_number);
temp = eval(temp{1});
wavelet_names = vertcat(wavelet_names, temp);
end
end
save_figure.m:
function [ ] = save_figure( output_graph_filename )
% Record aa figure as PNG and fig files
% Create the folder if it doesn't exist already.
[pathstr, name, ext] = fileparts(output_graph_filename);
if ~exist(pathstr, 'dir')
mkdir(pathstr);
end
h = gcf;
set(0,'defaultAxesFontSize',18) % http://www.mathworks.com/support/solutions/en/data/1-8XOW94/index.html?solution=1-8XOW94
boldify(h);
print('-dpng','-r600', [output_graph_filename '.png']);
print(h,[output_graph_filename '.pdf'],'-dpdf','-r600')
saveas(gcf,[output_graph_filename '.fig'], 'fig')
end
and boldify.m:
function boldify(h,g)
%BOLDIFY Make lines and text bold for standard viewgraph style.
% BOLDIFY boldifies the lines and text of the current figure.
% BOLDIFY(H) applies to the graphics handle H.
%
% BOLDIFY(X,Y) specifies an X by Y inch graph of the current
% figure. If text labels have their 'UserData' data property
% set to 'slope = ...', then the 'Rotation' property is set to
% account for changes in the graph's aspect ratio. The
% default is MATLAB's default.
% S. T. Smith
% The name of this function does not represent an endorsement by the author
% of the egregious grammatical trend of verbing nouns.
if nargin < 1, h = gcf;, end
% Set (and get) the default MATLAB paper size and position
set(gcf,'PaperPosition','default');
units = get(gcf,'PaperUnits');
set(gcf,'PaperUnits','inches');
fsize = get(gcf,'PaperPosition');
fsize = fsize(3:4); % Figure size (X" x Y") on paper.
psize = get(gcf,'PaperSize');
if nargin == 2 % User specified graph size
fsize = [h,g];
h = gcf;
end
% Set the paper position of the current figure
set(gcf,'PaperPosition', ...
[(psize(1)-fsize(1))/2 (psize(2)-fsize(2))/2 fsize(1) fsize(2)]);
fsize = get(gcf,'PaperPosition');
fsize = fsize(3:4); % Graph size (X" x Y") on paper.
set(gcf,'PaperUnits',units); % Back to original
% Get the normalized axis position of the current axes
units = get(gca,'Units');
set(gca,'Units','normalized');
asize = get(gca,'Position');
asize = asize(3:4);
set(gca,'Units',units);
ha = get(h,'Children');
for i=1:length(ha)
% if get(ha(i),'Type') == 'axes'
% changed by B. A. Miller
if strcmp(get(ha(i), 'Type'), 'axes') == 1
units = get(ha(i),'Units');
set(ha(i),'Units','normalized');
asize = get(ha(i),'Position'); % Axes Position (normalized)
asize = asize(3:4);
set(ha(i),'Units',units);
[m,j] = max(asize); j = j(1);
scale = 1/(asize(j)*fsize(j)); % scale*inches -normalized units
set(ha(i),'FontWeight','Bold');
set(ha(i),'LineWidth',2);
[m,k] = min(asize); k = k(1);
if asize(k)*fsize(k) > 1/2
set(ha(i),'TickLength',[1/8 1.5*1/8]*scale); % Gives 1/8" ticks
else
set(ha(i),'TickLength',[3/32 1.5*3/32]*scale); % Gives 3/32" ticks
end
set(get(ha(i),'XLabel'),'FontSize',18); % 14-pt labels
set(get(ha(i),'XLabel'),'FontWeight','Bold');
set(get(ha(i),'XLabel'),'VerticalAlignment','top');
set(get(ha(i),'YLabel'),'FontSize',18); % 14-pt labels
set(get(ha(i),'YLabel'),'FontWeight','Bold');
%set(get(ha(i),'YLabel'),'VerticalAlignment','baseline');
set(get(ha(i),'Title'),'FontSize',18); % 16-pt titles
set(get(ha(i),'Title'),'FontWeight','Bold');
% set(get(ha(i), 'FontSize',20, 'XTick',[]));
end
hc = get(ha(i),'Children');
for j=1:length(hc)
chtype = get(hc(j),'Type');
if chtype(1:4) == 'text'
set(hc(j),'FontSize',17); % 12 pt descriptive labels
set(hc(j),'FontWeight','Bold');
ud = get(hc(j),'UserData'); % User data
if length(ud) 8
if ud(1:8) == 'slope = ' % Account for change in actual slope
slope = sscanf(ud,'slope = %g');
slope = slope*(fsize(2)/fsize(1))/(asize(2)/asize(1));
set(hc(j),'Rotation',atan(slope)/pi*180);
end
end
elseif chtype(1:4) == 'line'
set(hc(j),'LineWidth',2);
end
end
end
Bonus: correlation between all wavelets on a random signal with 1000000 samples with the first 10 scales:
Code used:
%% PRE-REQUISITE: You need to download http://www.mathworks.com/matlabcentral/fileexchange/24253-customizable-heat-maps , which gives the function heatmap()
%% Benchmark parameters
scales = 1:10;
number_of_random_samples = 1000000;
% wavelet_names = {'sym2'; 'sym3'; 'sym4'; 'sym5'; 'sym6'; 'sym7'; 'sym8'};
% wavelet_names = {'cgau1'; 'cgau2'; 'cgau3'; 'cgau4'; 'cgau5'};
wavelet_names = {'db2'; 'sym2'};
OUTPUT_FOLDER = 'output_corr';
% wavelet_names = get_all_wavelet_names(); % WARNING: you need to remove all complex wavelets, viz. cgau1, shan, fbsp and cmor, and the heatmap will be pissed to see complex values coming to her.
%% Prepare data
random_signal = rand(1,number_of_random_samples);
results = zeros(size(wavelet_names,1), number_of_random_samples);
%% Prepare result folder
if ~exist(OUTPUT_FOLDER, 'dir')
mkdir(OUTPUT_FOLDER);
end
%% Run benchmarks
for scale_number = 1:size(scales,2)
scale = scales(scale_number);
for wavelet_number = 1:size(wavelet_names,1)
wavelet_name = wavelet_names{wavelet_number}
% Compute wavelet on a random signal
run = 1;
results(wavelet_number, :) = cwt(random_signal(run, :),scale,wavelet_name);
if wavelet_number == 999
break
end
end
correlation_results = corrcoef(results')
heatmap(correlation_results, [], [], '%0.2f', 'MinColorValue', -1.0, 'MaxColorValue', 1.0, 'Colormap', 'jet',...
'Colorbar', true, 'ColorLevels', 64, 'UseFigureColormap', false);
title(['Correlation matrix for scale ' num2str(scale)]);
xlabel(['Wavelet 1 to ' num2str(size(wavelet_names,1)) ' for scale ' num2str(scale)]);
ylabel(['Wavelet 1 to ' num2str(size(wavelet_names,1)) ' for scale ' num2str(scale)]);
snapnow
print('-dpng','-r600',fullfile(OUTPUT_FOLDER, ['scalecorr' num2str(scale) '.png']))
end
Correlation for each wavelet between different scales (1 to 100):
Code used:
%% PRE-REQUISITE: You need to download http://www.mathworks.com/matlabcentral/fileexchange/24253-customizable-heat-maps , which gives the function heatmap()
%% Benchmark parameters
scales = 1:100;
number_of_random_samples = 1000000;
% wavelet_name = 'gaus2';
% wavelet_names = {'sym2', 'sym3'}%, 'sym4'};
OUTPUT_FOLDER = 'output_corr';
wavelet_names = get_all_wavelet_names(); % WARNING: you need to remove all complex wavelets, viz. cgau1, shan, fbsp and cmor, and the heatmap will be pissed to see complex values coming to her.
%% Prepare data
random_signal = rand(1,number_of_random_samples);
results = zeros(size(scales,2), number_of_random_samples);
%% Prepare result folder
if ~exist(OUTPUT_FOLDER, 'dir')
mkdir(OUTPUT_FOLDER);
end
%% Run benchmarks
for wavelet_number = 1:size(wavelet_names,1)
wavelet_name = wavelet_names{wavelet_number}
run_time_random_test_scales = zeros(size(scales,2),1);
for scale_number = 1:size(scales,2)
scale = scales(scale_number);
run = 1;
% Compute wavelet on a random signal
results(scale_number, :) = cwt(random_signal(run, :),scale,wavelet_name);
end
correlation_results = corrcoef(results')
heatmap(correlation_results, [], [], '%0.2f', 'MinColorValue', -1.0, 'MaxColorValue', 1.0, 'Colormap', 'jet',...
'Colorbar', true, 'ColorLevels', 64, 'UseFigureColormap', false);
title(['Correlation matrix for wavelet ' wavelet_name]);
xlabel(['Scales 1 to ' num2str(max(scales)) ' for wavelet ' wavelet_name]);
ylabel(['Scales 1 to ' num2str(max(scales)) ' for wavelet ' wavelet_name]);
snapnow
print('-dpng','-r600',fullfile(OUTPUT_FOLDER, [wavelet_name '_scalecorr_scale1to' num2str(max(scales)) '.png']))
end

How to create 64 Gabor features at each scale and orientation in the spatial and frequency domain

Normally, a Gabor filter, as its name suggests, is used to filter an image and extract everything that it is oriented in the same direction of the filtering.
In this question, you can see more efficient code than written in this Link
Assume 16 scales of Filters at 4 orientations, so we get 64 gabor filters.
scales=[7:2:37], 7x7 to 37x37 in steps of two pixels, so we have 7x7, 9x9, 11x11, 13x13, 15x15, 17x17, 19x19, 21x21, 23x23, 25x25, 27x27, 29x29, 31x31, 33x33, 35x35 and 37x37.
directions=[0, pi/4, pi/2, 3pi/4].
The equation of Gabor filter in the spatial domain is:
The equation of Gabor filter in the frequency domain is:
In the spatial domain:
function [fSiz,filters,c1OL,numSimpleFilters] = init_gabor(rot, RF_siz)
image=imread('xxx.jpg');
image_gray=rgb2gray(image);
image_gray=imresize(image_gray, [100 100]);
image_double=double(image_gray);
rot = [0 45 90 135]; % we have four orientations
RF_siz = [7:2:37]; %we get 16 scales (7x7 to 37x37 in steps of two pixels)
minFS = 7; % the minimum receptive field
maxFS = 37; % the maximum receptive field
sigma = 0.0036*RF_siz.^2 + 0.35*RF_siz + 0.18; %define the equation of effective width
lambda = sigma/0.8; % it the equation of wavelength (lambda)
G = 0.3; % spatial aspect ratio: 0.23 < gamma < 0.92
numFilterSizes = length(RF_siz); % we get 16
numSimpleFilters = length(rot); % we get 4
numFilters = numFilterSizes*numSimpleFilters; % we get 16x4 = 64 filters
fSiz = zeros(numFilters,1); % It is a vector of size numFilters where each cell contains the size of the filter (7,7,7,7,9,9,9,9,11,11,11,11,......,37,37,37,37)
filters = zeros(max(RF_siz)^2,numFilters); % Matrix of Gabor filters of size %max_fSiz x num_filters, where max_fSiz is the length of the largest filter and num_filters the total number of filters. Column j of filters matrix contains a n_jxn_j filter (reshaped as a column vector and padded with zeros).
for k = 1:numFilterSizes
for r = 1:numSimpleFilters
theta = rot(r)*pi/180; % so we get 0, pi/4, pi/2, 3pi/4
filtSize = RF_siz(k);
center = ceil(filtSize/2);
filtSizeL = center-1;
filtSizeR = filtSize-filtSizeL-1;
sigmaq = sigma(k)^2;
for i = -filtSizeL:filtSizeR
for j = -filtSizeL:filtSizeR
if ( sqrt(i^2+j^2)>filtSize/2 )
E = 0;
else
x = i*cos(theta) - j*sin(theta);
y = i*sin(theta) + j*cos(theta);
E = exp(-(x^2+G^2*y^2)/(2*sigmaq))*cos(2*pi*x/lambda(k));
end
f(j+center,i+center) = E;
end
end
f = f - mean(mean(f));
f = f ./ sqrt(sum(sum(f.^2)));
p = numSimpleFilters*(k-1) + r;
filters(1:filtSize^2,p)=reshape(f,filtSize^2,1);
fSiz(p)=filtSize;
end
end
% Rebuild all filters (of all sizes)
nFilts = length(fSiz);
for i = 1:nFilts
sqfilter{i} = reshape(filters(1:(fSiz(i)^2),i),fSiz(i),fSiz(i));
%if you will use conv2 to convolve an image with this gabor, so you should also add the equation below. But if you will use imfilter instead of conv2, so do not add the equation below.
sqfilter{i} = sqfilter{i}(end:-1:1,end:-1:1); %flip in order to use conv2 instead of imfilter (%bug_fix 6/28/2007);
convv=imfilter(image_double, sqfilter{i}, 'same', 'conv');
figure;
imagesc(convv);
colormap(gray);
end
phi = ij*pi/4; % ij = 0, 1, 2, 3
theta = 3;
sigma = 0.65*theta;
filterSize = 7; % 7:2:37
G = zeros(filterSize);
for i=(0:filterSize-1)/filterSize
for j=(0:filterSize-1)/filterSize
xprime= j*cos(phi);
yprime= i*sin(phi);
K = exp(2*pi*theta*sqrt(-1)*(xprime+ yprime));
G(round((i+1)*filterSize),round((j+1)*filterSize)) =...
exp(-(i^2+j^2)/(sigma^2))*K;
end
end
As of R2015b release of the Image Processing Toolbox, you can create a Gabor filter bank using the gabor function in the image processing toolbox, and you can apply it to an image using imgaborfilt.
In the frequency domain:
sigma_u=1/2*pi*sigmaq;
sigma_v=1/2*pi*sigmaq;
u0=2*pi*cos(theta)*lambda(k);
v0=2*pi*sin(theta)*lambda(k);
for u = -filtSizeL:filtSizeR
for v = -filtSizeL:filtSizeR
if ( sqrt(u^2+v^2)>filtSize/2 )
E = 0;
else
v_theta = u*cos(theta) - v*sin(theta);
u_theta = u*sin(theta) + v*cos(theta);
E=(1/2*pi*sigma_u*sigma_v)*((exp((-1/2)*(((u_theta-u0)^2/sigma_u^2))+((v_theta-v0)^2/sigma_v^2))) + (exp((-1/2)*(((u_theta+u0)^2/sigma_u^2))+((v_theta+v0)^2/sigma_v^2))));
end
f(v+center,u+center) = E;
end
end