|
a |
|
b/whole_mount_tiles_stitching.m |
|
|
1 |
function msg = whole_mount_tiles_stitching |
|
|
2 |
%% Whole Mount Tile Stitching |
|
|
3 |
|
|
|
4 |
%% Purpose: |
|
|
5 |
% This function creates a whole-mount image from individual tiles and implements |
|
|
6 |
% black_border_removal to remove border around image in the case of old |
|
|
7 |
% images that were scanned with a border. |
|
|
8 |
|
|
|
9 |
%% ------------------------------------------------------------------------ |
|
|
10 |
|
|
|
11 |
% directory = ''; name the needed directory that contains tiled images to |
|
|
12 |
% be re-stitched together |
|
|
13 |
% subj = XX; % patient number |
|
|
14 |
% slice = "XX"; % slide name |
|
|
15 |
% scanner = "Olympus"; % scanner name indictate tile sizes |
|
|
16 |
% anot_micro = "Nikon"; % scanner used if originally annotated on a |
|
|
17 |
% previous scanner |
|
|
18 |
|
|
|
19 |
for d = 1:numel(directory) |
|
|
20 |
tic; |
|
|
21 |
addpath(directory(d)) |
|
|
22 |
subj_slice = sprintf('%i_%s',subj(d),slice(d)); |
|
|
23 |
fprintf('Processing: %s\n',subj_slice); |
|
|
24 |
|
|
|
25 |
disp('Loading images'); |
|
|
26 |
|
|
|
27 |
files = fullfile(directory(d),'tile*.tiff'); |
|
|
28 |
input_images = dir(files); |
|
|
29 |
input_images = {input_images.name}'; |
|
|
30 |
|
|
|
31 |
if (isempty(input_images)) |
|
|
32 |
files = fullfile(directory(d), 'tile*.jpg'); % adjust extension if needed |
|
|
33 |
input_images = dir(files); |
|
|
34 |
input_images = {input_images.name}'; |
|
|
35 |
end |
|
|
36 |
|
|
|
37 |
name = strsplit(input_images{numel(input_images)},{'_','.'}); |
|
|
38 |
xmax = str2num(name{2}(2:end)); |
|
|
39 |
ymax = str2num(name{3}(2:end)); |
|
|
40 |
|
|
|
41 |
x = [1 xmax]; |
|
|
42 |
y = [1 ymax]; |
|
|
43 |
|
|
|
44 |
xx = 1; |
|
|
45 |
yy = 1; |
|
|
46 |
|
|
|
47 |
|
|
|
48 |
if strcmp(scanner(d),'Huron') |
|
|
49 |
resize_factor = 10; % 8 nikon/olympus 12 huron |
|
|
50 |
else |
|
|
51 |
resize_factor = 8; |
|
|
52 |
end |
|
|
53 |
|
|
|
54 |
im = uint8(imread(input_images{numel(input_images)})); |
|
|
55 |
im_size = size(im); |
|
|
56 |
im = imrotate(imresize(im,1/8),90); |
|
|
57 |
ximage = cell(1,numel(input_images)); |
|
|
58 |
yimage = cell(1,numel(input_images)); |
|
|
59 |
for i = 1:numel(input_images) |
|
|
60 |
ximage{i} = ones(size(im(:,:,1)),'uint8') * xx; |
|
|
61 |
ximage{i} = imresize(ximage{i},[1 size(im,1)],'nearest'); |
|
|
62 |
ximage{i} = imrotate(ximage{i},90); |
|
|
63 |
|
|
|
64 |
xx = xx + 1; |
|
|
65 |
if xx > xmax |
|
|
66 |
xx = 1; |
|
|
67 |
end |
|
|
68 |
|
|
|
69 |
yimage{i} = ones(size(im(:,:,1)),'uint8') * yy; |
|
|
70 |
yimage{i} = imresize(yimage{i},[1 size(im,2)],'nearest'); |
|
|
71 |
yimage{i} = imrotate(yimage{i},90); |
|
|
72 |
|
|
|
73 |
yy = yy + 1; |
|
|
74 |
if yy > ymax |
|
|
75 |
yy = 1; |
|
|
76 |
end |
|
|
77 |
end |
|
|
78 |
|
|
|
79 |
disp('Creating rows'); |
|
|
80 |
% Arrange rows |
|
|
81 |
ind1 = y(1); |
|
|
82 |
ind2 = y(2); |
|
|
83 |
rows = cell(1,xmax); |
|
|
84 |
for i = 1:xmax |
|
|
85 |
im = cell(1,ymax); |
|
|
86 |
ind3 = 1; |
|
|
87 |
for j = ind1:ind2 |
|
|
88 |
im{ind3} = imrotate(imresize(uint8(imread(input_images{j})),1),90); |
|
|
89 |
ind3 = ind3 + 1; |
|
|
90 |
end |
|
|
91 |
|
|
|
92 |
rows{i} = imtile(im,'GridSize',[1 ymax]); clear im; |
|
|
93 |
rows{i} = imrotate(rows{i},180); % flips orientation |
|
|
94 |
|
|
|
95 |
ind1 = ind1 + ymax; |
|
|
96 |
ind2 = ind2 + ymax; |
|
|
97 |
if ind2 > numel(input_images) |
|
|
98 |
break |
|
|
99 |
end |
|
|
100 |
end |
|
|
101 |
|
|
|
102 |
toc |
|
|
103 |
xx = 1; |
|
|
104 |
xrows = cell(1,xmax); |
|
|
105 |
missing_vals = cell(1,xmax); |
|
|
106 |
for i = 1:xmax |
|
|
107 |
xrows{i} = ximage(xx:xmax:size(ximage,2)); % creates image rows |
|
|
108 |
xrows{i} = imtile(xrows{i},'GridSize',[1 size(rows{1},2)]); |
|
|
109 |
missing_vals{i} = uint8((xrows{i} == 0)*i); % xrows is filled with 0s beyond what was created above |
|
|
110 |
xrows{i} = xrows{i} + missing_vals{i}; |
|
|
111 |
|
|
|
112 |
xx = xx + 1; |
|
|
113 |
if xx > xmax |
|
|
114 |
break |
|
|
115 |
end |
|
|
116 |
end |
|
|
117 |
|
|
|
118 |
yy = 1; |
|
|
119 |
ycols = cell(1,ymax); |
|
|
120 |
missing_vals = cell(1,ymax); |
|
|
121 |
for i = 1:ymax |
|
|
122 |
ycols{i} = yimage(yy:ymax:size(yimage,2)); % creates image cols |
|
|
123 |
ycols{i} = imtile(ycols{i},'GridSize',[1 xmax*size(rows{1},1)])'; % inverting creates col from row |
|
|
124 |
missing_vals{i} = uint8((ycols{i} == 0)*i); |
|
|
125 |
ycols{i} = ycols{i} + missing_vals{i}; |
|
|
126 |
|
|
|
127 |
yy = yy + 1; |
|
|
128 |
|
|
|
129 |
if yy > ymax |
|
|
130 |
break |
|
|
131 |
end |
|
|
132 |
end |
|
|
133 |
|
|
|
134 |
toc |
|
|
135 |
|
|
|
136 |
disp('Compiling image'); |
|
|
137 |
|
|
|
138 |
whole_image = imtile(rows,'GridSize',[xmax 1]); |
|
|
139 |
whole_image = imrotate(whole_image,-180); |
|
|
140 |
|
|
|
141 |
whole_ximage = flipud(imtile(xrows,'GridSize',[xmax 1])); % tile numbering starts in LL |
|
|
142 |
whole_ximage = double(whole_ximage); |
|
|
143 |
% figure(); imagesc(whole_ximage); |
|
|
144 |
|
|
|
145 |
whole_yimage = imtile(ycols,'GridSize',[1 ymax]); |
|
|
146 |
whole_yimage = double(whole_yimage); |
|
|
147 |
% figure(); imagesc(whole_yimage); |
|
|
148 |
toc |
|
|
149 |
disp('Saving image'); |
|
|
150 |
% figure(); imshow(whole_image); |
|
|
151 |
% saveas(gcf,sprintf('%s_whole_mount_recon_%i',subj_slice,resize_factor),'tif'); |
|
|
152 |
|
|
|
153 |
toc |
|
|
154 |
msg = 'done'; |
|
|
155 |
disp(msg) |