Skip to content

Commit

Permalink
Initial commit
Browse files Browse the repository at this point in the history
  • Loading branch information
mitkovetta committed Jun 8, 2015
1 parent 664382d commit 158d07a
Show file tree
Hide file tree
Showing 6 changed files with 176 additions and 2 deletions.
10 changes: 8 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,2 +1,8 @@
# staining-normalization
Staining unmixing and normalization for histopathology images
# Staining unmixing and normalization

NOTE: Originally published at the Assessment of Mitosis Detection Algorithms 2013 challenge website (http://http://amida13.isi.uu.nl).

One of the major difficulties in histopathology image analysis is apperance variability. For example, when performing mitosis detection, many false positives can arise when the histopathology slide is overstained. This MATLAB code performs staining unmixing (separation of the hematoxylin and eosing stains) and apperance normalization. It is based on the method described in [1]. Some examples of staining normalization can be seen in the figure below.

[1] A method for normalizing histology slides for quantitative analysis, M Macenko, M Niethammer, JS Marron, D Borland, JT Woosley, G Xiaojun, C Schmitt, NE Thomas, IEEE ISBI, 2009. dx.doi.org/10.1109/ISBI.2009.5193250

Binary file added example1.tif
Binary file not shown.
Binary file added example2.tif
Binary file not shown.
23 changes: 23 additions & 0 deletions licence.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
Copyright (c) 2013, Mitko Veta
Image Sciences Institute
University Medical Center
Utrecht, The Netherlands

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.

134 changes: 134 additions & 0 deletions normalizeStaining.m
Original file line number Diff line number Diff line change
@@ -0,0 +1,134 @@
function [Inorm, H, E] = normalizeStaining(I, Io, beta, alpha, HERef, maxCRef)
% Normalize the staining appearance of images originating from H&E stained
% sections.
%
% Example use:
% See test.m.
%
% Input:
% I - RGB input image;
% Io - (optional) transmitted light intensity (default: 240);
% beta - (optional) OD threshold for transparent pixels (default: 0.15);
% alpha - (optional) tolerance for the pseudo-min and pseudo-max (default: 1);
% HERef - (optional) reference H&E OD matrix (default value is defined);
% maxCRef - (optional) reference maximum stain concentrations for H&E (default value is defined);
%
% Output:
% Inorm - normalized image;
% H - (optional) hematoxylin image;
% E - (optional)eosin image;
%
% References:
% A method for normalizing histology slides for quantitative analysis. M.
% Macenko et al., ISBI 2009
%
% Efficient nucleus detector in histopathology images. J.P. Vink et al., J
% Microscopy, 2013
%
% Copyright (c) 2013, Mitko Veta
% Image Sciences Institute
% University Medical Center
% Utrecht, The Netherlands
%
% See the license.txt file for copying permission.
%

% transmitted light intensity
if ~exist('Io', 'var') || isempty(Io)
Io = 240;
end

% OD threshold for transparent pixels
if ~exist('beta', 'var') || isempty(beta)
beta = 0.15;
end

% tolerance for the pseudo-min and pseudo-max
if ~exist('alpha', 'var') || isempty(alpha)
alpha = 1;
end

% reference H&E OD matrix
if ~exist('HERef', 'var') || isempty(HERef)
HERef = [
0.5626 0.2159
0.7201 0.8012
0.4062 0.5581
];
end

% reference maximum stain concentrations for H&E
if ~exist('maxCRef)', 'var') || isempty(maxCRef)
maxCRef = [
1.9705
1.0308
];
end

h = size(I,1);
w = size(I,2);

I = double(I);

I = reshape(I, [], 3);

% calculate optical density
OD = -log((I+1)/Io);

% remove transparent pixels
ODhat = OD(~any(OD < beta, 2), :);

% calculate eigenvectors
[V, ~] = eig(cov(ODhat));

% project on the plane spanned by the eigenvectors corresponding to the two
% largest eigenvalues
That = ODhat*V(:,2:3);

% find the min and max vectors and project back to OD space
phi = atan2(That(:,2), That(:,1));

minPhi = prctile(phi, alpha);
maxPhi = prctile(phi, 100-alpha);

vMin = V(:,2:3)*[cos(minPhi); sin(minPhi)];
vMax = V(:,2:3)*[cos(maxPhi); sin(maxPhi)];

% a heuristic to make the vector corresponding to hematoxylin first and the
% one corresponding to eosin second
if vMin(1) > vMax(1)
HE = [vMin vMax];
else
HE = [vMax vMin];
end

% rows correspond to channels (RGB), columns to OD values
Y = reshape(OD, [], 3)';

% determine concentrations of the individual stains
C = HE \ Y;

% normalize stain concentrations
maxC = prctile(C, 99, 2);

C = bsxfun(@rdivide, C, maxC);
C = bsxfun(@times, C, maxCRef);

% recreate the image using reference mixing matrix
Inorm = Io*exp(-HERef * C);
Inorm = reshape(Inorm', h, w, 3);
Inorm = uint8(Inorm);

if nargout > 1
H = Io*exp(-HERef(:,1) * C(1,:));
H = reshape(H', h, w, 3);
H = uint8(H);
end

if nargout > 2
E = Io*exp(-HERef(:,2) * C(2,:));
E = reshape(E', h, w, 3);
E = uint8(E);
end

end
11 changes: 11 additions & 0 deletions test.m
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
I1 = imread('example1.tif');
I2 = imread('example2.tif');

[Inorm1 H1 E1] = normalizeStaining(I1);
[Inorm2 H2 E2] = normalizeStaining(I2);

figure('Name', 'Original image 1'), imshow(I1, []);
figure('Name', 'Normalized image 1'), imshow(Inorm1, []);

figure('Name', 'Original image 2'), imshow(I2, []);
figure('Name', 'Normalized image 2'), imshow(Inorm2, []);

0 comments on commit 158d07a

Please sign in to comment.