function MW_src = perform_histogram_matching_wavelet(MW_src,MW_tgt, Jmin, options)
% perform_histogram_matching_wavelet - match the histogram of a wavelet transform
%
% Matching of wavelet coefficients only:
% options.dotransform=0
% MW_src = perform_histogram_matching_wavelet(MW_src,MW_tgt,Jmin,options);
% Matching of image + wavelet coefficients:
% options.dotransform=1
% M_src = perform_histogram_matching_wavelet(M_src,M_tgt,Jmin,options);
%
% Match the spacial histogram of the image and the histogram of each
% wavelet sub-band.
%
% Works also for color images.
%
% You can set options.use_histomatching=0 if you want to equalize the
% kurtosis and skewness of subbands and not their histograms
% (works well for natural images).
%
% Copyright (c) 2004 Gabriel Peyr?
if nargin>=4
if ~isstruct(options)
error('options should be a structure.');
end
end
options.null = 0;
dotransform = getoptions(options, 'dotransform', 1);
niter_synthesis = getoptions(options, 'niter_synthesis', 1);
if nargin<3
Jmin = 3;
end
if niter_synthesis>1
options.niter_synthesis = 1;
for i=1:niter_synthesis
MW_src = perform_histogram_matching_wavelet(MW_src,MW_tgt, Jmin, options);
end
return;
end
if size(MW_src,3)==3
options.color_mode = 'pca';
[MW_src,options.ColorP] = change_color_mode(MW_src,+1,options);
[MW_tgt,options.ColorP] = change_color_mode(MW_tgt,+1,options);
for i=1:size(MW_src,3)
MW_src(:,:,i) = perform_histogram_matching_wavelet(MW_src(:,:,i),MW_tgt(:,:,i),Jmin, options);
end
[MW_src,options.ColorP] = change_color_mode(MW_src,-1,options);
return;
end
if size(MW_src,3)>1
for i=1:size(MW_src,3)
MW_src(:,:,i) = perform_histogram_matching_wavelet(MW_src(:,:,i),MW_tgt(:,:,i),Jmin, options);
end
return;
end
% for spacial histogram, do not consider absval
options.absval = 0;
options.rows = 0;
options.cols = 0;
if dotransform == 1
% perform image extension
n1 = size(MW_src,1);
n2 = size(MW_tgt,1);
n = max(n1,n2);
n = 2^( ceil(log2(n)) );
MW_src = perform_image_extension(MW_src,n);
MW_tgt = perform_image_extension(MW_tgt,n);
options.wavelet_type = 'biorthogonal_swapped';
options.wavelet_vm = 4;
% perform spacial matching
MW_src = perform_matching(MW_src, MW_tgt, options);
% compute transform
MW_src = perform_wavelet_transform(MW_src, Jmin, +1, options);
MW_tgt = perform_wavelet_transform(MW_tgt, Jmin, +1, options);
% perform coefficients matching
options.dotransform = 0;
MW_src = perform_histogram_matching_wavelet(MW_src,MW_tgt,Jmin, options);
% undo transforms
MW_src = perform_wavelet_transform(MW_src, Jmin, -1, options);
MW_tgt = perform_wavelet_transform(MW_tgt, Jmin, -1, options);
% perform spacial matching
MW_src = perform_matching(MW_src, MW_tgt, options);
MW_src = MW_src(1:n1,1:n1);
return;
end
if size(MW_src,1)~=size(MW_tgt,1)
error('Wavelets coefficients should be of the same size.');
end
mm = size(MW_src);
Jmax = log2(mm)-1;
for j=Jmax:-1:Jmin
for q=1:3
[selx,sely] = compute_quadrant_selection(j,q);
MW_src(selx,sely) = match_statistics(MW_src(selx,sely), MW_tgt(selx,sely), options);
end
end
% match low scales
selx = 1:2^Jmin; sely = 1:2^Jmin;
MW_src(selx,sely) = perform_matching(MW_src(selx,sely), MW_tgt(selx,sely), options);
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
function x = perform_matching(x,y, options)
% x = perform_histogram_matching(x,y, options);
x = perform_histogram_equalization(x,y, options);
function M = perform_image_extension(M,n)
m = size(M,1);
k = n-m;
while k>size(M,1)
M = perform_image_extension(M,size(M,1)*2);
k = k - size(M,1)/2;
end
M = [M; M(end:-1:end-k+1,:)];
M = [M, M(:,end:-1:end-k+1)];
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
function x = match_statistics(x,y, options)
options.null = 0;
if isfield(options, 'use_histomatching')
use_histomatching = options.use_histomatching;
else
use_histomatching = 1;
end
if isfield(options, 'nb_bins')
nb_bins = options.nb_bins;
else
nb_bins = 100;
end
if use_histomatching
options.absval = 1;
x = perform_matching(x, y, options);
else
x = perform_kurtosis_equalization(x,y);
end