forked from frcs/colour-transfer
-
Notifications
You must be signed in to change notification settings - Fork 0
/
pdf_transfer.m
executable file
·102 lines (78 loc) · 2.51 KB
/
pdf_transfer.m
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
%
% simple implementation of N-Dimensional PDF Transfer
%
% [DR] = pdf_transferND(D0, D1, rotations);
%
% D0, D1 = NxM matrix containing N-dimensional features
% rotations = { {R_1}, ... , {R_n} } with R_i PxN
%
% note that we can use more than N projection axes. In this case P > N
% and the inverse transformation is done by least mean square.
% Using more than N axes leads to a more stable (but also slower)
% convergence.
%
% (c) F. Pitie 2007
%
% see reference:
% Automated colour grading using colour distribution transfer. (2007)
% Computer Vision and Image Understanding.
%
function [DR] = pdf_transfer(D0, D1, Rotations, varargin)
nb_iterations = length(Rotations);
numvarargs = length(varargin);
if numvarargs > 1
error('pdf_transfer:TooManyInputs', ...
'requires at most 1 optional input');
end
optargs = {1};
optargs(1:numvarargs) = varargin;
[relaxation] = optargs{:};
prompt = '';
for it=1:nb_iterations
fprintf(repmat('\b',[1, length(prompt)]))
prompt = sprintf('IDT iteration %02d / %02d', it, nb_iterations);
fprintf(prompt);
R = Rotations{it};
nb_projs = size(R,1);
% apply rotation
D0R = R * D0;
D1R = R * D1;
D0R_ = zeros(size(D0));
% get the marginals, match them, and apply transformation
for i=1:nb_projs
% get the data range
datamin = min([D0R(i,:) D1R(i,:)])-eps;
datamax = max([D0R(i,:) D1R(i,:)])+eps;
u = (0:(300-1))/(300-1)*(datamax - datamin) + datamin;
% get the projections
p0R = hist(D0R(i,:), u);
p1R = hist(D1R(i,:), u);
% get the transport map
f = pdf_transfer1D(p0R, p1R);
% apply the mapping
D0R_(i,:) = (interp1(u, f', D0R(i,:))-1)/(300-1)*(datamax-datamin) + datamin;
end
D0 = relaxation * (R \ (D0R_ - D0R)) + D0;
end
fprintf(repmat('\b',[1, length(prompt)]))
DR = D0;
end
%
% 1D - PDF Transfer
%
function f = pdf_transfer1D(pX,pY)
nbins = max(size(pX));
eps = 1e-6; % small damping term that faciliates the inversion
PX = cumsum(pX + eps);
PX = PX/PX(end);
PY = cumsum(pY + eps);
PY = PY/PY(end);
% inversion
f = interp1(PY, 0:nbins-1, PX, 'linear');
f(PX<=PY(1)) = 0;
f(PX>=PY(end)) = nbins-1;
if sum(isnan(f))>0
error('colour_transfer:pdf_transfer:NaN', ...
'pdf_transfer has generated NaN values');
end
end