forked from petersaj/AP_histology
-
Notifications
You must be signed in to change notification settings - Fork 0
/
AP_rotate_histology.m
157 lines (119 loc) · 5.3 KB
/
AP_rotate_histology.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
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
function AP_rotate_histology(im_path)
% AP_rotate_histology(im_path)
%
% Pad, center, and rotate images of histological slices
% Andy Peters ([email protected])
slice_dir = dir([im_path filesep '*.tif']);
slice_fn = natsortfiles(cellfun(@(path,fn) [path filesep fn], ...
{slice_dir.folder},{slice_dir.name},'uni',false));
slice_im = cell(length(slice_fn),1);
for curr_slice = 1:length(slice_fn)
slice_im{curr_slice} = imread(slice_fn{curr_slice});
end
% Pad all slices centrally to the largest slice and make matrix
slice_size_max = max(cell2mat(cellfun(@size,slice_im,'uni',false)),[],1);
slice_im_pad = ...
cell2mat(cellfun(@(x) x(1:slice_size_max(1),1:slice_size_max(2),:), ...
reshape(cellfun(@(im) padarray(im, ...
[ceil((slice_size_max(1) - size(im,1))./2), ...
ceil((slice_size_max(2) - size(im,2))./2)],0,'both'), ...
slice_im,'uni',false),1,1,1,[]),'uni',false));
% Draw line to indicate midline for rotation
rotation_fig = figure;
align_axis = nan(2,2,length(slice_im));
for curr_im = 1:length(slice_im)
imshow(slice_im_pad(:,:,:,curr_im));
title('Click and drag reference line (e.g. midline)')
curr_line = imline;
align_axis(:,:,curr_im) = curr_line.getPosition;
end
close(rotation_fig);
% Get angle for all axes
align_angle = squeeze(atan2d(diff(align_axis(:,1,:),[],1),diff(align_axis(:,2,:),[],1)));
align_center = permute(nanmean(align_axis,1),[2,3,1]);
% Set target angle as the nearest multiple of 90
target_angle = round(nanmean(align_angle)/90)*90;
% Set target position as the average center of the reference lines
target_position = nanmean(align_center,2);
im_aligned = zeros(size(slice_im_pad),class(slice_im_pad));
for curr_im = 1:length(slice_im)
angle_diff = target_angle - align_angle(curr_im);
x_diff = target_position(1) - align_center(1,curr_im);
y_diff = target_position(2) - align_center(2,curr_im);
im_aligned(:,:,:,curr_im) = ...
imrotate(imtranslate(slice_im_pad(:,:,:,curr_im), ...
[x_diff,y_diff]),angle_diff,'bilinear','crop');
end
% Pull up slice viewer to scroll through slices with option to flip
% Create figure, set button functions
gui_fig = figure('KeyPressFcn',@keypress);
gui_data.curr_slice = 1;
gui_data.im_aligned = im_aligned;
gui_data.slice_fn = slice_fn;
% Set up axis for histology image
gui_data.histology_ax = axes('YDir','reverse');
hold on; colormap(gray); axis image off;
gui_data.histology_im_h = image(gui_data.im_aligned(:,:,:,1), ...
'Parent',gui_data.histology_ax);
% Create title to write area in
gui_data.histology_ax_title = title(gui_data.histology_ax, ...
'1/2: change slice, Shift 1/2: re-order slice, Arrows: flip, Esc: save & quit','FontSize',14);
% Upload gui data
guidata(gui_fig,gui_data);
end
function keypress(gui_fig,eventdata)
shift_on = any(strcmp(eventdata.Modifier,'shift'));
% Get guidata
gui_data = guidata(gui_fig);
switch eventdata.Key
% 1/2: switch slice
% Shift + 1/2: move slice in stack
case '1'
if ~shift_on
gui_data.curr_slice = max(gui_data.curr_slice - 1,1);
set(gui_data.histology_im_h,'CData',gui_data.im_aligned(:,:,:,gui_data.curr_slice))
guidata(gui_fig,gui_data);
elseif shift_on && gui_data.curr_slice ~= 1
slice_flip = [gui_data.curr_slice-1,gui_data.curr_slice];
gui_data.im_aligned(:,:,:,slice_flip) = flip(gui_data.im_aligned(:,:,:,slice_flip),4);
gui_data.curr_slice = slice_flip(1);
guidata(gui_fig,gui_data);
end
case '2'
if ~shift_on
gui_data.curr_slice = ...
min(gui_data.curr_slice + 1,size(gui_data.im_aligned,4));
set(gui_data.histology_im_h,'CData',gui_data.im_aligned(:,:,:,gui_data.curr_slice))
guidata(gui_fig,gui_data);
elseif shift_on && gui_data.curr_slice ~= size(gui_data.im_aligned,4)
slice_flip = [gui_data.curr_slice,gui_data.curr_slice+1];
gui_data.im_aligned(:,:,:,slice_flip) = flip(gui_data.im_aligned(:,:,:,slice_flip),4);
gui_data.curr_slice = slice_flip(2);
guidata(gui_fig,gui_data);
end
% Arrow keys: flip slice
case {'leftarrow','rightarrow'}
gui_data.im_aligned(:,:,:,gui_data.curr_slice) = ...
fliplr(gui_data.im_aligned(:,:,:,gui_data.curr_slice));
set(gui_data.histology_im_h,'CData',gui_data.im_aligned(:,:,:,gui_data.curr_slice))
guidata(gui_fig,gui_data);
case {'uparrow','downarrow'}
gui_data.im_aligned(:,:,:,gui_data.curr_slice) = ...
flipud(gui_data.im_aligned(:,:,:,gui_data.curr_slice));
set(gui_data.histology_im_h,'CData',gui_data.im_aligned(:,:,:,gui_data.curr_slice))
guidata(gui_fig,gui_data);
% Escape: save and close
case 'escape'
opts.Default = 'Yes';
opts.Interpreter = 'tex';
user_confirm = questdlg('\fontsize{15} Save and quit?','Confirm exit',opts);
if strcmp(user_confirm,'Yes')
% Overwrite old images with new ones
for curr_im = 1:size(gui_data.im_aligned,4)
imwrite(gui_data.im_aligned(:,:,:,curr_im),gui_data.slice_fn{curr_im},'tif');
end
disp(['Saved padded/centered/rotated slices']);
close(gui_fig)
end
end
end