Switch to unified view

a b/matlab/normalizeStaining.m
1
function [Inorm H E] = normalizeStaining(I, Io, beta, alpha, HERef, maxCRef)
2
% normalizeStaining: Normalize the staining appearance of images
3
% originating from H&E stained sections.
4
%
5
% Example use:
6
% See test.m.
7
%
8
% Input:
9
% I         - RGB input image;
10
% Io        - (optional) transmitted light intensity (default: 240);
11
% beta      - (optional) OD threshold for transparent pixels (default: 0.15);
12
% alpha     - (optional) tolerance for the pseudo-min and pseudo-max (default: 1);
13
% HERef     - (optional) reference H&E OD matrix (default value is defined);
14
% maxCRef   - (optional) reference maximum stain concentrations for H&E (default value is defined);
15
%
16
% Output:
17
% Inorm     - normalized image;
18
% H         - (optional) hematoxylin image;
19
% E         - (optional)eosin image;
20
%
21
% References:
22
% A method for normalizing histology slides for quantitative analysis. M.
23
% Macenko et al., ISBI 2009
24
%
25
% Efficient nucleus detector in histopathology images. J.P. Vink et al., J
26
% Microscopy, 2013
27
%
28
% Copyright (c) 2013, Mitko Veta
29
% Image Sciences Institute
30
% University Medical Center
31
% Utrecht, The Netherlands
32
% 
33
% See the license.txt file for copying permission.
34
%
35
36
% transmitted light intensity
37
if ~exist('Io', 'var') || isempty(Io)
38
    Io = 240;
39
end
40
41
% OD threshold for transparent pixels
42
if ~exist('beta', 'var') || isempty(beta)
43
    beta = 0.15;
44
end
45
46
% tolerance for the pseudo-min and pseudo-max
47
if ~exist('alpha', 'var') || isempty(alpha)
48
    alpha = 1;
49
end
50
51
% reference H&E OD matrix
52
if ~exist('HERef', 'var') || isempty(HERef)
53
    HERef = [
54
        0.5626    0.2159
55
        0.7201    0.8012
56
        0.4062    0.5581
57
        ];
58
end
59
60
% reference maximum stain concentrations for H&E
61
if ~exist('maxCRef)', 'var') || isempty(maxCRef)
62
    maxCRef = [
63
        1.9705
64
        1.0308
65
        ];
66
end
67
68
h = size(I,1);
69
w = size(I,2);
70
71
I = double(I);
72
73
I = reshape(I, [], 3);
74
75
% calculate optical density
76
OD = -log((I+1)/Io);
77
78
% remove transparent pixels
79
ODhat = OD(~any(OD < beta, 2), :);
80
81
% calculate eigenvectors
82
[V, ~] = eig(cov(ODhat));
83
84
% project on the plane spanned by the eigenvectors corresponding to the two
85
% largest eigenvalues
86
That = ODhat*V(:,2:3);
87
88
% find the min and max vectors and project back to OD space
89
phi = atan2(That(:,2), That(:,1));
90
91
minPhi = prctile(phi, alpha);
92
maxPhi = prctile(phi, 100-alpha);
93
94
vMin = V(:,2:3)*[cos(minPhi); sin(minPhi)];
95
vMax = V(:,2:3)*[cos(maxPhi); sin(maxPhi)];
96
97
% a heuristic to make the vector corresponding to hematoxylin first and the
98
% one corresponding to eosin second
99
if vMin(1) > vMax(1)
100
    HE = [vMin vMax];
101
else
102
    HE = [vMax vMin];
103
end
104
105
% rows correspond to channels (RGB), columns to OD values
106
Y = reshape(OD, [], 3)';
107
108
% determine concentrations of the individual stains
109
C = HE \ Y;
110
111
% normalize stain concentrations
112
maxC = prctile(C, 99, 2);
113
114
C = bsxfun(@rdivide, C, maxC);
115
C = bsxfun(@times, C, maxCRef);
116
117
% recreate the image using reference mixing matrix
118
Inorm = Io*exp(-HERef * C);
119
Inorm = reshape(Inorm', h, w, 3);
120
Inorm = uint8(Inorm);
121
122
if nargout > 1
123
    H = Io*exp(-HERef(:,1) * C(1,:));
124
    H = reshape(H', h, w, 3);
125
    H = uint8(H);
126
end
127
128
if nargout > 2
129
    E = Io*exp(-HERef(:,2) * C(2,:));
130
    E = reshape(E', h, w, 3);
131
    E = uint8(E);
132
end
133
134
end