-
Notifications
You must be signed in to change notification settings - Fork 10
/
Copy pathimtool3D.m
3933 lines (3548 loc) · 170 KB
/
imtool3D.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
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
classdef imtool3D < handle
%This is a image slice viewer with built in scroll, contrast, zoom and
%ROI tools.
%
% Use this class to place a self-contained image viewing panel within
% a GUI (or any figure).
%
% Similar to imtool but with slice scrolling, mouse controls, and
% drag&drop image files feature. Always open in grayscale (intensity)
% images by default. Use button below the left scrollbar to turn into RGB
% and control color channels. Use the mouse to control how the image is
% displayed. A left click allows window and leveling, a right click is
% for panning, and a middle click is for zooming. Also the scroll wheel
% can be used to scroll through slices.
% Drag and drop one or multiple images on the viewer to open them.
% Switch between multiple images using the up or down arrows.
% Go across time frame (4th dim) using left/right arrows
% Open 5D images or multiple 4D images.
%
%----------------------------------------------------------------------
%Inputs:
%
% I An m x n x k image array of grayscale values. Default
% is a 100x100x3 random noise image.
% position The position of the panel containing the image and all
% the tools. Format is [xmin ymin width height]. Default
% position is [0 0 1 1] (units = normalized). See the
% setPostion and setUnits methods to change the postion
% or units.
% h Handle of the parent figure. If no handles is provided,
% a new figure will be created.
% range The display range of the image. Format is [min max].
% The range can be adjusted with the contrast tool or
% with the setRange method. Default is [min(I) max(I)].
%----------------------------------------------------------------------
%Output:
%
% tool The imtool3D object. Use this object as input to the
% class methods described below.
%----------------------------------------------------------------------
%Constructor Syntax
%
%tool = imtool3d() creates an imtool3D panel in the current figure with
%a random noise image. Returns the imtool3D object.
%
%tool = imtool3d(I) sets the image of the imtool3D panel.
%
%tool = imtool3D(I,position) sets the position of the imtool3D panel
%within the current figure. The default units are normalized.
%
%tool = imtool3D(I,position,h) puts the imtool3D panel in the figure
%specified by the handle h.
%
%tool = imtool3D(I,position,h,range) sets the display range of the
%image according to range=[min max].
%
%tool = imtool3D(I,position,h,range,tools) lets the scroll wheel
%properly sync if you are displaying multiple imtool3D objects in the
%same figure.
%
%tool = imtool3D(I,position,h,range,tools,mask) allows you to overlay a
%semitransparent binary mask on the image data.
%
%Note that you can pass an empty matrix for any input variable to have
%the constructor use default values. ex. tool=imtool3D([],[],h,[]).
%----------------------------------------------------------------------
%Examples:
%
% ## open a 5D volume
% A = rand(100,100,30,10,3);
% imtool3D(A)
%
%
% ## open an MRI volume
% load mri % example mri image provided by MATLAB
% D = squeeze(D);
% D = permute(D(end:-1:1,:,:),[2 1 3]); % LPI orientation
% tool = imtool3D(D);
% tool.setAspectRatio([1 1 2.5]) % set voxel size to 1mm x 1mm x 2.5mm
%
%
% ## open in RGB mode
% I = imread('board.tif');
% tool = imtool3D(I);
% % use RGB mode
% tool.isRGB = 1;
% tool.RGBdim = 3;
% tool.RGBindex = [1 2 3];
%
% Note: Use the button bellow left slider ('.' or 'R','G','B') to turn between RGB and grayscale and to select active color channel
%
%
% ## include in a GUI
% % Add viewer in a panel in the middle of the GUI
% GUI = figure('Name','GUI with imtool3D embedded');
% annotation(GUI,'textbox',[0 .5 1 .5],'String','Create your own GUI here',...
% 'HorizontalAlignment','center','VerticalAlignment','middle');
% Position = [0 0 1 .5]; % Bottom. normalized units
% tool = imtool3D([],Position,GUI)
% % set image
% load mri
% tool.setImage(squeeze(D))
%
%
% ## play a video
% v = VideoReader('xylophone.mp4');
% tool = imtool3D(v.read([1 Inf]));
% tool.isRGB = 1;
%
% Note: use left/right arrows to move through image frames
% use shift+right for fast forward (10-by-10 frames)
%
% ## Compare two images
% A = imread('cameraman.tif');
% B = imrotate(A,5,'bicubic','crop');
% tool = imtool3D({A,B})
%
% % Option 1: fuse both images in grayscale
% tool.setNvol(2); % show top image (B)
% tool.setOpacity(.5) % set opacity of current image (B)
%
% % Option 2: fuse both images with false colors
% tool.setNvol(1);
% tool.changeColormap('red');
% tool.setNvol(2);
% tool.changeColormap('green')
% tool.setOpacity(.5) % set opacity of current image (B)
%
% % Option 3: distribute images in different RGB channels
% tool.isRGB = 1;
% tool.RGBdim = 5; % different images are stacked in the 5th dimension
% tool.RGBindex = [1 2 2]; % red for the 1st image, blue and green for the 2nd
%
% % Option 4: alternate both images
% tool = imtool3D({A,B})
% tool.grid = 1;
% for loop=1:10
% tool.setNvol(mod(loop,2)+1);
% pause(.5)
% end
%
%
%----------------------------------------------------------------------
%Methods:
%
% tool.setImage(I) displays a new image. I can be a cell of multiple
% images or a N-D matrix
%
% I = tool.getImage() returns the image being shown by the tool
% I = tool.getImage(1) returns all the images loaded in the tool
%
% setMask(tool,mask) replaces the overlay mask with a new one
%
% tool.rescaleFactor = scale; sets the zoom scale of the image (1 is 100%, 2 is 200%)
%
% tool.isRGB = 0/1 turns between RGB and grayscale.
%
% tool.RGBdim = 3/4/5; select matrix dimension along which RGB planes
% are selected
%
% tool.RGBindex = [1x3 Int]; select the planes along RGBdim used for
% RGB planes
%
% tool.setAspectRatio([1x3 double]) sets the pixel size in the 3
% directions
%
% tool.setviewplane(view) sets the view to 'axial', 'coronal' or 'saggital'
%
% tool.label({label}) sets the labels of all images loaded in the
% tool
%
% setAlpha(tool,alpha) sets the transparency of the overlaid mask
%
% alpha = getAlpha(tool) gets the current transparency of the
% overlaid mask
%
% setPosition(tool,position) sets the position of tool.
%
% position = getPosition(tool) returns the position of the tool
% relative to its parent figure.
%
% setUnits(tool,Units) sets the units of the position of tool. See
% uipanel properties for possible unit strings.
%
% units = getUnits(tool) returns the units of used for the position
% of the tool.
%
% handles = getHandles(tool) returns a structured variable, handles,
% which contains all the handles to the various objects used by
% imtool3D.
%
% setDisplayRange(tool,range) sets the display range of the image.
% see the 'Clim' property of an Axes object for details.
%
% range=getDisplayRange(tool) returns the current display range of
% the image.
%
% setWindowLevel(tool,W,L) sets the display range of the image in
% terms of its window (diff(range)) and level (mean(range)).
%
% [W,L] = getWindowLevel(tool) returns the display range of the image
% in terms of its window (W) and level (L)
%
% setCurrentSlice(tool,slice) sets the current displayed slice.
%
% slice = getCurrentSlice(tool) returns the currently displayed
% slice number.
%
%----------------------------------------------------------------------
%Notes:
%
% Author: Justin Solomon, July, 26 2013 (Latest update April, 16,
% 2016)
%
% Contact: [email protected]
%
% Current Version 2.4
% Version Notes:
% 1.1-added method to get information about the
% currently selected ROI.
%
% 2.0- Completely redesigned the tool. Window and
% leveleing, pan, and zoom are now done with the
% mouse as is standard in most medical image viewers.
% Also the overall astestic design of the tool is
% improved with a new black theme. Added ability to
% change the colormap of the image. Also when
% resizing the figure, the tool behaves better and
% maintains maximum viewing area for the image while
% keeping the tool buttons correctly sized.
% IMPORTANT: Any code that worked with the version
% 1.0 may not be compatible with version 2.0.
%
% 2.1- Added crop tool, help button, and button that
% resets the pan and zoom settings to show the entire
% image (useful when you're zoomed in and you just
% want to zoom out quickly. Also made the window and
% level adjustable by draging the lines on the
% histogram
%
% 2.2- Added support for Matlab 2014b. Added ability
% to overlay a semi-transparent binary mask on the
% image data. Useful to visiulize segmented data.
%
% 2.3- Simplified the ROI tools. imtool3D no longer
% relies on MATLAB'S imroi classes, rather I've made
% a set of ROI classes just for imtool3D. This
% greatly simplifies the integration of the ROI
% tools. You can export and delete the ROIs directly
% from their context menus.
%
% 2.3.1- Make sure the figure is centered when
% creating an imtool3D object in a new figure
%
% 2.3.2- Squished a few bugs for older Matlab
% versions. Added method to set and get the
% transparency of the overlaid mask. Refined the
% panning and zooming.
%
% 2.3.3- Fixed a bug with the cropping function
%
% 2.3.4- Added check box to toggle on and off the
% mask overlay. Fixed a bug with the interactive
% window and leveling using the histogram view. Added
% a paint brush to allow user to quickly segment
% something
%
% 2.4- Added methods to get the min, max, and range
% of pixel values. Updated the window and leveling to
% be adaptive to the dynamic range of the image data.
% Should work well if the range is small or large.
%
% 2.4.1- fixed a small bug related to windowing with
% the mouse.
%
% 2.4.2- Added a "smart" paint brush which helps to
% segment borders cleanly.
%
% Created in MATLAB_R2015b
%
% Requires the image processing toolbox
properties (SetAccess = private, GetAccess = private)
I %Image data (MxNxKxTxV) matrix of image data
Nvol % Current volume
Ntime % Current time
range % Range of images
NvolOpts % [Struct] with .Climits (color limits (Clim) for each Nvol to display images in I (cell))
% .Opacity
% .Cmap (color map per Nvol)
mask %Indexed mask that can be overlaid on the image data
maskHistory %History of mask for undo
maskSelected %Index of the selected mask color
maskUpdated=1%Recompute stats in mask?
lockMask %Lock other mask colors
maskColor %Nx3 vector specifying the RGB color of the overlaid mask. Default is red (i.e., [1 0 0]);
handles %Structured variable with all the handles
centers %list of bin centers for histogram
alpha %transparency of the overlaid mask (default is .2)
Orient % [0,-90] vertical or horizontal
aspectRatio = [1 1 1];
viewplane = 3; % Direction of the 3rd dimension
optdlg % option dialog object
end
properties
windowSpeed=2; %Ratio controls how fast the window and level change when you change them with the mouse
upsample = false;
upsampleMethod = 'lanczos3'; %Can be any of {'bilinear','bicubic','box','triangle','cubic','lanczos2','lanczos3'}
Visible = true; %lets the user hide the imtool3D panel
grid = false;
montage = false;
brushsize = 5; % default size of the brush
gamma = 1; % gamma correction
isRGB = false; % colored image?
RGBindex = [1 2 3]; % R, G, and B bands index in case of color image
RGBdim = 3; % [3, 4 or 5] dimension along which RGB planes are extracted
RGBdecorrstretch = false;
RGBalignhisto = false;
registrationMode = false;
label = {''};
end
properties (Dependent = true)
rescaleFactor %This is the screen pixels/image pixels. used to resample image data when being displayed
end
events
newImage
maskChanged
maskUndone
newMousePos
newSlice
end
methods
function tool = imtool3D(varargin) %Constructor
% Parse Inputs
[I, position, h, range, tools, mask, enableHist] = parseinputs(varargin{:});
% display figure
try, Orient = uigetpref('imtool3D','rot90','Set orientation','How to display the first dimension of the matrix?',{'Vertically (Photo)','Horizontally (Medical)'},'CheckboxState',1,'HelpString','Help','HelpFcn','helpdlg({''If this option is wrongly set, image will be rotated by 90 degree.'', ''Horizontal orientation is usually used in Medical (first dimension is Left-Right)'', '''', ''This preference can be reset in the Settings menu (<about> button).'', '''', ''Orientation can also be changed while viewing an image using the command: tool.setOrient(''''vertical'''')''})');
catch
Orient = 'vertical';
end
if ~ispref('imtool3D','ScrollWheelFcn') && strfind(lower(Orient),'vertical')
setpref('imtool3D','ScrollWheelFcn','zoom')
end
if isempty(h)
h=figure;
set(h,'Toolbar','none','Menubar','none','NextPlot','new')
set(h,'Units','Pixels');
pos=get(h,'Position');
Af=pos(3)/pos(4); %input Ratio of the figure
if iscell(I)
S = [size(I{1},1) size(I{1},2) size(I{1},3)];
else
S = [size(I,1) size(I,2) size(I,3)];
end
if strfind(lower(Orient),'vertical')
AI=S(2)/S(1); %input Ratio of the image
else
AI=S(1)/S(2); %input Ratio of the image
end
if Af>AI %Figure is too wide, make it taller to match
pos(4)=pos(3)/AI;
elseif Af<AI %Figure is too long, make it wider to match
pos(3)=AI*pos(4);
end
%set minimal size
try
%https://undocumentedmatlab.com/articles/working-with-non-standard-dpi-displays
ScreenSizeW = java.awt.Toolkit.getDefaultToolkit.getScreenSize.getWidth;
ScreenSizeH = java.awt.Toolkit.getDefaultToolkit.getScreenSize.getHeight;
screensize=[0 0 ScreenSizeW ScreenSizeH];
catch
screensize = get(0,'ScreenSize');
end
pos(3)=min(max(700,pos(3)),screensize(3)*.9);
pos(4)=min(max(500,pos(4)),screensize(4)*.9);
%make sure the figure is centered
pos(1) = ceil((screensize(3)-pos(3))/2);
pos(2) = ceil((screensize(4)-pos(4))/2);
set(h,'Position',pos)
set(h,'Units','normalized');
end
%find the parent figure handle if the given parent is not a
%figure
if ~strcmp(get(h,'type'),'figure')
fig = getParentFigure(h);
else
fig = h;
end
if ~exist('overview_zoom_in.png','file')
repopath = fileparts(mfilename('fullpath'));
addpath(genpath(fullfile(repopath,'src')))
addpath(genpath(fullfile(repopath,'External')));
end
%--------------------------------------------------------------
tool.lockMask = true;
tool.handles.fig=fig;
tool.handles.parent = h;
tool.maskColor = [ 0 0 0;
1 0 0;
1 1 0;
0 1 0;
0 1 1;
0 0 1;
1 0 1];
tool.maskColor = cat(1,tool.maskColor,colorcube(30));
tool.maskColor(end-5:end,:) = [];
tool.maskColor(end+1,:) = [0.8500 0.3250 0.0980];
tool.maskSelected = 1;
tool.maskHistory = cell(1,10);
tool.alpha = .2;
tool.Nvol = 1;
tool.Ntime = 1;
%Create the panels and slider
w=30; %Pixel width of the side panels
h=110; %Pixel height of the histogram panel
wbutt=20; %Pixel size of the buttons
tool.handles.Panels.Large = uipanel(tool.handles.parent,'Units','normalized','Position',position,'Title','','Tag','imtool3D');
pos=getpixelposition(tool.handles.parent); pos(1) = pos(1)+position(1)*pos(3); pos(2) = pos(2)+position(2)*pos(4); pos(3) = pos(3)*position(3); pos(4) = pos(4)*position(4);
tool.handles.Panels.Hist = uipanel(tool.handles.Panels.Large,'Units','Pixels','Position',[w pos(4)-w-h pos(3)-2*w h],'Title','');
tool.handles.Panels.Image = uipanel(tool.handles.Panels.Large,'Units','Pixels','Position',[w w pos(3)-2*w pos(4)-2*w],'Title','');
tool.handles.Panels.Tools = uipanel(tool.handles.Panels.Large,'Units','Pixels','Position',[0 pos(4)-w pos(3) w],'Title','');
tool.handles.Panels.ROItools = uipanel(tool.handles.Panels.Large,'Units','Pixels','Position',[pos(3)-w w w pos(4)-2*w],'Title','');
tool.handles.Panels.Slider = uipanel(tool.handles.Panels.Large,'Units','Pixels','Position',[0 w w pos(4)-2*w],'Title','');
tool.handles.Panels.Info = uipanel(tool.handles.Panels.Large,'Units','Pixels','Position',[0 0 pos(3) w],'Title','');
try
set(cell2mat(struct2cell(tool.handles.Panels)),'BackgroundColor','k','ForegroundColor','w','HighlightColor','k')
catch
objarr=struct2cell(tool.handles.Panels);
objarr=[objarr{:}];
set(objarr,'BackgroundColor','k','ForegroundColor','w','HighlightColor','k');
end
%Create Color Channel Picker below slider for rgb images
butString = {'.','R','G','B'};
tool.handles.SliderColor = uicontrol(tool.handles.Panels.Slider,'Style','pushbutton','String',butString{1},'Position',[max(0,w-wbutt) 0 wbutt wbutt],'TooltipString',sprintf('Color channel used by slider:\n. channels are split\nR slider control red\nG slider control green\nB slider control Blue'));
fun=@(src,evnt)SelectSliderColor(tool);
c = uicontextmenu(tool.handles.fig);
set(tool.handles.SliderColor,'Callback',fun,'UIContextMenu',c)
tool.handles.uimenu.RGB(1) = uimenu('Parent',c,'Label','switch to RGB/Monochrome','Callback',@(src,evnt) assignval(tool,'isRGB',~tool.isRGB));
tool.handles.uimenu.RGB(2) = uimenu('Parent',c,'Label','RGB dimension');
tool.handles.uimenu.RGB(3) = uimenu('Parent',tool.handles.uimenu.RGB(2) ,'Label','slice (3rd)','Callback',@(src,evnt) assignval(tool,'RGBdim',3),'Checked','on');
tool.handles.uimenu.RGB(4) = uimenu('Parent',tool.handles.uimenu.RGB(2),'Label','time (4th)','Callback',@(src,evnt) assignval(tool,'RGBdim',4));
tool.handles.uimenu.RGB(5) = uimenu('Parent',tool.handles.uimenu.RGB(2),'Label','volume (5th)','Callback',@(src,evnt) assignval(tool,'RGBdim',5));
tool.handles.uimenu.RGB(6) = uimenu('Parent',c,'Label','RGB index','Callback',@(src,evnt) dlgsetRGBindex(tool));
tool.handles.uimenu.RGB(7) = uimenu('Parent',c,'Label','align RGB bands','Callback',@(src,evnt) assignval(tool,'RGBalignhisto',~tool.RGBalignhisto));
%Create Slider for scrolling through image stack
tool.handles.Slider = uicontrol(tool.handles.Panels.Slider,'Style','Slider','Position',[0 wbutt w pos(4)-2*w-wbutt],'TooltipString','Change Slice (can use scroll wheel also)');
scrollfun = getpref('imtool3D','ScrollWheelFcn','slice');
tool.setScrollWheelFun(scrollfun,0,tools);
%Create image axis
tool.handles.Axes = axes('Position',[0 0 1 1],'Parent',tool.handles.Panels.Image,'Color','none');
tool.handles.I = imshow(zeros(3,3),[0 1],'Parent',tool.handles.Axes); hold on;
set(tool.handles.I,'Clipping','off')
tool.setOrient(Orient)
set(tool.handles.Axes,'XLimMode','manual','YLimMode','manual','Clipping','off');
%Set up the binary mask viewer
im = ind2rgb(zeros(3,3),tool.maskColor);
tool.handles.mask = imshow(im);
set(tool.handles.Axes,'Position',[0 0 1 1],'Color','none','XColor','r','YColor','r','GridLineStyle','--','LineWidth',1.5,'XTickLabel','','YTickLabel','');
axis off
grid off
axis fill
%Set up image info display
tool.handles.Info=uicontrol(tool.handles.Panels.Info,'Style','text','String','(x,y) val','Units','Normalized','Position',[0 .1 .5 .8],'BackgroundColor','k','ForegroundColor','w','FontSize',12,'HorizontalAlignment','Left');
fun=@(src,evnt)getImageInfo(src,evnt,tool);
set(tool.handles.fig,'WindowButtonMotionFcn',fun);
%tool.handles.LabelText=uicontrol(tool.handles.Panels.Info,'Style','text','Units','Normalized','Position',[.25 .1 .3 .8],'BackgroundColor','k','ForegroundColor','w','FontSize',12,'HorizontalAlignment','Center');
tool.handles.LabelText=annotation(tool.handles.Panels.Image,'textbox','EdgeColor','none','String','','Position',[0 0 1 0.05],'Color',[1 1 1],'Interpreter','none');
c = uicontextmenu(tool.handles.fig);
tool.handles.SliceText=uicontrol(tool.handles.Panels.Info,'Style','text','UIContextMenu',c,'String','','Units','Normalized','Position',[.5 .1 .43 .8],'BackgroundColor','k','ForegroundColor','w','FontSize',12,'HorizontalAlignment','Right', 'TooltipString', 'Use arrows to navigate through time (4th dim) and volumes (5th dim)');
uimenu('Parent',c,'Label','100%','Callback',@(s,h) assignval(tool, 'rescaleFactor',1))
uimenu('Parent',c,'Label','10%','Callback',@(s,h) assignval(tool, 'rescaleFactor',.1))
uimenu('Parent',c,'Label','50%','Callback',@(s,h) assignval(tool, 'rescaleFactor',.5))
uimenu('Parent',c,'Label','200%','Callback',@(s,h) assignval(tool, 'rescaleFactor',2))
uimenu('Parent',c,'Label','400%','Callback',@(s,h) assignval(tool, 'rescaleFactor',4))
% Help Annotation when cursor hover Help Button
tool.handles.HelpAnnotation = [];
%Set up mouse button controls
fun=@(hObject,eventdata) imageButtonDownFunction(hObject,eventdata,tool);
set(tool.handles.mask,'ButtonDownFcn',fun)
set(tool.handles.I,'ButtonDownFcn',fun)
%create the tool buttons
wp=w;
w=wbutt;
buff=(wp-w)/2;
% icon directory
if ~isdeployed
MATLABdir = fullfile(toolboxdir('matlab'), 'icons');
else
if ~ispc
MATLABdir = '/opt/mcr/v95/mcr/toolbox/matlab/icons';
else
% TODO:
MATLABdir = fullfile(toolboxdir('matlab'), 'icons');
end
end
%Create the histogram plot
%set(tool.handles.Panels.Image,'Visible','off')
if enableHist
tool.handles.HistAxes = axes('Position',[.025 .15 .95 .55],'Parent',tool.handles.Panels.Hist);
hold(tool.handles.HistAxes,'on')
tool.handles.HistLine=[plot([0 1],[0 1],'-w','LineWidth',1);...
plot([0 1],[0 1],'-g','LineWidth',1);...
plot([0 1],[0 1],'-b','LineWidth',1)];
hold(tool.handles.HistAxes,'off');
set(tool.handles.HistAxes,'Color','none','XColor','w','YColor','w','FontSize',9,'YTick',[])
axis on
hold on
axis fill
xlim(get(gca,'Xlim'))
tool.handles.Histrange(1)=plot([0 0 0],[0 .5 1],'.-r');
tool.handles.Histrange(2)=plot([1 1 1],[0 .5 1],'.-r');
tool.handles.Histrange(3)=plot([0.5 0.5 0.5],[0 .5 1],'.--r');
tool.handles.HistImageAxes = axes('Position',[.025 .75 .95 .2],'Parent',tool.handles.Panels.Hist);
set(tool.handles.HistImageAxes,'Units','Pixels'); pos=get(tool.handles.HistImageAxes,'Position'); set(tool.handles.HistImageAxes,'Units','Normalized');
tool.handles.HistImage=imshow(repmat(linspace(0,1,256),[round(pos(4)) 1]),[0 1]);
set(tool.handles.HistImageAxes,'XColor','w','YColor','w','XTick',[],'YTick',[])
axis on;
box on;
axis normal
fun = @(hObject,evnt)histogramButtonDownFunction(hObject,evnt,tool,1);
set(tool.handles.Histrange(1),'ButtonDownFcn',fun);
fun = @(hObject,evnt)histogramButtonDownFunction(hObject,evnt,tool,2);
set(tool.handles.Histrange(2),'ButtonDownFcn',fun);
fun = @(hObject,evnt)histogramButtonDownFunction(hObject,evnt,tool,3);
set(tool.handles.Histrange(3),'ButtonDownFcn',fun);
%Create histogram checkbox
tool.handles.Tools.Hist = uicontrol(tool.handles.Panels.Tools,'Style','ToggleButton','String','','Position',[buff buff w w],'TooltipString','Show Colorbar and histogram of current slice');
MATLABicondir = fullfile(toolboxdir('matlab'), 'icons');
icon_colorbar = makeToolbarIconFromPNG(fullfile(MATLABicondir,'tool_colorbar.png'));
set(tool.handles.Tools.Hist,'CData',icon_colorbar)
fun=@(hObject,evnt) ShowHistogram(hObject,evnt,tool,wp,h);
set(tool.handles.Tools.Hist,'Callback',fun)
lp=buff+w;
else
lp=buff;
end
%Set up the resize function
fun=@(x,y) panelResizeFunction(x,y,tool,wp,h,wbutt);
set(tool.handles.Panels.Large,'ResizeFcn',fun)
%% TOOLBAR ON TOP
%Create window and level boxes
tool.handles.Tools.TL = uicontrol(tool.handles.Panels.Tools,'Style','text','String','L','Position',[lp+buff buff w w],'BackgroundColor','k','ForegroundColor','w','TooltipString',sprintf('Intensity Window Lower Bound\nRight Click to set current window to all volumes\n(left click and drag on the image to control window width and level)'));
tool.handles.Tools.L = uicontrol(tool.handles.Panels.Tools,'Style','Edit','String','0','Position',[lp+buff+w buff 2*w w],'TooltipString',sprintf('Intensity Window Lower Bound\nRight Click to set current window to all volumes\n(left click and drag on the image to control window width and level)'),'BackgroundColor',[.2 .2 .2],'ForegroundColor','w');
tool.handles.Tools.TU = uicontrol(tool.handles.Panels.Tools,'Style','text','String','U','Position',[lp+2*buff+3*w buff w w],'BackgroundColor','k','ForegroundColor','w','TooltipString',sprintf('Intensity Window Upper Bound\nRight Click to set current window to all volumes\n(left click and drag on the image to control window width and level)'));
tool.handles.Tools.U = uicontrol(tool.handles.Panels.Tools,'Style','Edit','String','1','Position',[lp+2*buff+4*w buff 2*w w],'TooltipString',sprintf('Intensity Window Upper Bound\nRight Click to set current window to all volumes\n(left click and drag on the image to control window width and level)'),'BackgroundColor',[.2 .2 .2],'ForegroundColor','w');
tool.handles.Tools.TO = uicontrol(tool.handles.Panels.Tools,'Style','text','String','O','Position',[lp+2*buff+6*w buff w w],'BackgroundColor','k','ForegroundColor','w','TooltipString',sprintf('Opacity'));
tool.handles.Tools.O = uicontrol(tool.handles.Panels.Tools,'Style','Edit','String','1','Position',[lp+2*buff+7*w buff w w],'TooltipString',sprintf('Opacity'),'BackgroundColor',[.2 .2 .2],'ForegroundColor','w');
tool.handles.Tools.SO = uicontrol(tool.handles.Panels.Tools,'Style','Slider','Position',[lp+2*buff+8*w buff w/2 w],'TooltipString',sprintf('Opacity'),'Min',0,'Max',1,'Value',1,'SliderStep',[.1 .1]);
lp=lp+3*buff+8.5*w;
%Creat window and level callbacks
fun=@(hobject,evnt) WindowLevel_callback(hobject,evnt,tool);
funSameWL = @(src,evnt) tool.setClimits(repmat({get(tool.handles.Axes(tool.Nvol),'Clim')},[1 length(tool.I)]));
funAutoRange = @(src,evnt) tool.setClimits(double(range_outlier(tool.I{tool.Nvol}(:),5)));
c = uicontextmenu(tool.handles.fig);
set(tool.handles.Tools.L,'Callback',fun,'UIContextMenu',c); % right click set the same range for all volumes
set(tool.handles.Tools.U,'Callback',fun,'UIContextMenu',c);
uimenu('Parent',c,'Label','Auto window level','Callback',funAutoRange)
uimenu('Parent',c,'Label','Same window level for all volumes','Callback',funSameWL)
fun=@(hobject,evnt) setOpacity(tool,[], hobject);
set(tool.handles.Tools.O,'Callback',fun);
set(tool.handles.Tools.SO,'Callback',fun);
%Create view restore button
tool.handles.Tools.ViewRestore = uicontrol(tool.handles.Panels.Tools,'Style','pushbutton','String','','Position',[lp buff w w],'TooltipString',sprintf('Reset Pan and Zoom\n(Right Click (Ctrl+Click) to Pan and Middle (Shift+Click) Click to zoom)'));
icon_save = makeToolbarIconFromPNG('overview_zoom_in.png');
set(tool.handles.Tools.ViewRestore,'CData',icon_save);
fun=@(hobject,evnt) resetViewCallback(hobject,evnt,tool);
set(tool.handles.Tools.ViewRestore,'Callback',fun)
lp=lp+w+2*buff;
%Create grid checkbox
tool.handles.Tools.Grid = uicontrol(tool.handles.Panels.Tools,'Style','checkbox','String','Grid?','Position',[lp buff 2.5*w w],'BackgroundColor','k','ForegroundColor','w');
fun=@(hObject,evnt) toggleGrid(hObject,evnt,tool);
set(tool.handles.Tools.Grid,'Callback',fun)
set(tool.handles.Tools.Grid,'TooltipString','Toggle Gridlines')
lp=lp+2.5*w;
%Create the mask view switch
tool.handles.Tools.Mask = uicontrol(tool.handles.Panels.Tools,'Style','checkbox','String','Mask?','Position',[lp buff 3*w w],'BackgroundColor','k','ForegroundColor','w','TooltipString','Toggle Binary Mask (spacebar)','Value',1);
fun=@(hObject,evnt) toggleMask(hObject,evnt,tool);
set(tool.handles.Tools.Mask,'Callback',fun)
lp=lp+3*w;
%Create colormap pulldown menu
mapNames={'Gray','Parula','Jet','HSV','Hot','Cool','red','green','blue','Spring','Summer','Autumn','Winter','Bone','Copper','Pink','Lines','colorcube','flag','prism','white'};
tool.handles.Tools.Color = uicontrol(tool.handles.Panels.Tools,'Style','popupmenu','String',mapNames,'Position',[lp buff 3.5*w w]);
fun=@(hObject,evnt) changeColormap(tool,[],hObject);
set(tool.handles.Tools.Color,'Callback',fun)
set(tool.handles.Tools.Color,'TooltipString','Select a colormap')
lp=lp+3.5*w+buff;
%Create viewplane button
tool.handles.Tools.ViewPlane = uicontrol(tool.handles.Panels.Tools,'Style','popupmenu','String',{'Axial','Sagittal','Coronal'},'Position',[lp buff 3.5*w w],'Value',4-tool.viewplane,'TooltipString','Select slicing plane orientation (for 3D volume)');
lp=lp+3.5*w+buff;
fun=@(hObject,evnt) setviewplane(tool,hObject);
set(tool.handles.Tools.ViewPlane,'Callback',fun)
%Create montage button
tool.handles.Tools.montage = uicontrol(tool.handles.Panels.Tools,'Style','togglebutton','Position',[lp buff w w],'Value',0,'TooltipString','display multiple slices as montage');
icon_profile = makeToolbarIconFromPNG('icon_montage.png');
set(tool.handles.Tools.montage ,'Cdata',icon_profile)
lp=lp+w+buff;
fun=@(hObject,evnt) toggleMontage(hObject,[],tool); % show 12 slices by default
set(tool.handles.Tools.montage,'Callback',fun)
%Create Help Button
pos = get(tool.handles.Panels.Tools,'Position');
tool.handles.Tools.Help = uicontrol(tool.handles.Panels.Tools,'Style','checkbox','String','Help','Position',[pos(3)-5*w buff 3*w-buff w],'BackgroundColor',[0, 0.65, 1],'ForegroundColor',[1 1 1],'FontWeight','bold');
fun = @(hObject,evnt) showhelpannotation(tool);
if nargin==0, set(tool.handles.Tools.Help,'Value',1), showhelpannotation(tool); end
set(tool.handles.Tools.Help,'Callback',fun)
tool.handles.Tools.About = uicontrol(tool.handles.Panels.Tools,'Style','popupmenu','String',{'about','Settings','Dock figure','Export imtool object'},'Position',[pos(3)-2*w-buff buff 4*w w],'TooltipString','Help with imtool3D');
fun=@(hObject,evnt) displayHelp(hObject,evnt,tool);
set(tool.handles.Tools.About,'Callback',fun)
%% MASK TOOLBAR ON RIGHT
%Create mask2poly button
tool.handles.Tools.mask2poly = uicontrol(tool.handles.Panels.ROItools,'Style','pushbutton','String','','Position',[buff buff w w],'TooltipString','Mask2Poly');
icon_profile = makeToolbarIconFromPNG([MATLABicondir '/linkproduct.png']);
set(tool.handles.Tools.mask2poly ,'Cdata',icon_profile)
fun=@(hObject,evnt) mask2polyImageCallback(hObject,evnt,tool);
set(tool.handles.Tools.mask2poly ,'Callback',fun)
addlistener(tool,'newSlice',@tool.SliceEvents);
%Create Circle ROI button
tool.handles.Tools.CircleROI = uicontrol(tool.handles.Panels.ROItools,'Style','pushbutton','String','','Position',[buff buff+w w w],'TooltipString','Create Elliptical ROI');
icon_ellipse = makeToolbarIconFromPNG([MATLABicondir '/tool_shape_ellipse.png']);
set(tool.handles.Tools.CircleROI,'Cdata',icon_ellipse)
fun=@(hObject,evnt) measureImageCallback(hObject,evnt,tool,'ellipse');
set(tool.handles.Tools.CircleROI,'Callback',fun)
%Create Square ROI button
tool.handles.Tools.SquareROI = uicontrol(tool.handles.Panels.ROItools,'Style','pushbutton','String','','Position',[buff buff+2*w w w],'TooltipString','Create Rectangular ROI');
icon_rect = makeToolbarIconFromPNG([MATLABicondir '/tool_shape_rectangle.png']);
set(tool.handles.Tools.SquareROI,'Cdata',icon_rect)
fun=@(hObject,evnt) measureImageCallback(hObject,evnt,tool,'rectangle');
set(tool.handles.Tools.SquareROI,'Callback',fun)
%Create Polygon ROI button
tool.handles.Tools.PolyROI = uicontrol(tool.handles.Panels.ROItools,'Style','pushbutton','String','\_/','Position',[buff buff+3*w w w],'TooltipString','Create Polygon ROI');
fun=@(hObject,evnt) measureImageCallback(hObject,evnt,tool,'polygon');
set(tool.handles.Tools.PolyROI,'Callback',fun)
%Create line profile button
tool.handles.Tools.Ruler = uicontrol(tool.handles.Panels.ROItools,'Style','pushbutton','String','','Position',[buff buff+4*w w w],'TooltipString','Measure Distance');
icon_distance = makeToolbarIconFromPNG([MATLABicondir '/tool_line.png']);
set(tool.handles.Tools.Ruler,'CData',icon_distance);
fun=@(hObject,evnt) measureImageCallback(hObject,evnt,tool,'profile');
set(tool.handles.Tools.Ruler,'Callback',fun)
%Create smooth3 button
tool.handles.Tools.smooth3 = uicontrol(tool.handles.Panels.ROItools,'Style','pushbutton','String','','Position',[buff buff+5*w w w],'TooltipString','Smooth Mask in 3D');
icon_profile = makeToolbarIconFromPNG('icon_smooth3.png');
set(tool.handles.Tools.smooth3 ,'Cdata',icon_profile)
fun=@(hObject,evnt) smooth3Callback(hObject,evnt,tool);
set(tool.handles.Tools.smooth3 ,'Callback',fun)
%Create maskinterp button
tool.handles.Tools.maskinterp = uicontrol(tool.handles.Panels.ROItools,'Style','pushbutton','String','','Position',[buff buff+6*w w w],'TooltipString','Interp Mask');
icon_profile = makeToolbarIconFromPNG('icon_interpmask.png');
set(tool.handles.Tools.maskinterp ,'Cdata',icon_profile)
fun=@(hObject,evnt) maskinterpImageCallback(hObject,evnt,tool);
set(tool.handles.Tools.maskinterp ,'Callback',fun)
%Create active countour button
tool.handles.Tools.maskactivecontour = uicontrol(tool.handles.Panels.ROItools,'Style','pushbutton','String','','Position',[buff buff+7*w w w],'TooltipString','Active Contour 3D');
icon_profile = makeToolbarIconFromPNG('icon_activecontour.png');
set(tool.handles.Tools.maskactivecontour ,'Cdata',icon_profile)
fun=@(hObject,evnt) ActiveCountourCallback(hObject,evnt,tool);
set(tool.handles.Tools.maskactivecontour ,'Callback',fun)
addlistener(tool,'maskChanged',@tool.maskEvents);
addlistener(tool,'maskUndone',@tool.maskEvents);
%Paint brush tool button
tool.handles.Tools.PaintBrush = uicontrol(tool.handles.Panels.ROItools,'Style','togglebutton','String','','Position',[buff buff+8*w w w],'TooltipString','Paint Brush Tool (B)');
icon_profile = makeToolbarIconFromPNG([MATLABicondir '/tool_data_brush.png']);
set(tool.handles.Tools.PaintBrush ,'Cdata',icon_profile)
fun=@(hObject,evnt) PaintBrushCallback(hObject,evnt,tool,'Normal');
set(tool.handles.Tools.PaintBrush ,'Callback',fun)
tool.handles.PaintBrushObject=[];
%Smart Paint brush tool button
tool.handles.Tools.SmartBrush = uicontrol(tool.handles.Panels.ROItools,'Style','togglebutton','String','','Position',[buff buff+9*w w w],'TooltipString','Smart Brush Tool (S)');
icon_profile = makeToolbarIconFromPNG('tool_data_brush_smart.png');
set(tool.handles.Tools.SmartBrush ,'Cdata',icon_profile)
fun=@(hObject,evnt) PaintBrushCallback(hObject,evnt,tool,'Smart');
set(tool.handles.Tools.SmartBrush ,'Callback',fun)
%undo mask button
tool.handles.Tools.undoMask = uicontrol(tool.handles.Panels.ROItools,'Style','pushbutton','String','','Position',[buff buff+10*w w w],'TooltipString','Undo (Z)');
icon_profile = load([MATLABicondir filesep 'undo.mat']);
set(tool.handles.Tools.undoMask ,'Cdata',icon_profile.undoCData)
fun=@(hObject,evnt) maskUndo(tool);
set(tool.handles.Tools.undoMask ,'Callback',fun)
% %Create poly tool button
% tool.handles.Tools.mask2poly = uicontrol(tool.handles.Panels.ROItools,'Style','pushbutton','String','','Position',[buff buff+8*w w w],'TooltipString','mask2poly');
% icon_profile = makeToolbarIconFromPNG([MATLABdir '/linkproduct.png']);
% set(tool.handles.Tools.mask2poly ,'Cdata',icon_profile)
% fun=@(hObject,evnt) CropImageCallback(hObject,evnt,tool);
% set(tool.handles.Tools.mask2poly ,'Callback',fun)
pos=get(tool.handles.Panels.ROItools,'Position');
% mask selection
for islct=1:5
tool.handles.Tools.maskSelected(islct) = uicontrol(tool.handles.Panels.ROItools,'Style','togglebutton','String',num2str(islct),'Position',[buff pos(4)-islct*w w w],'Tag','MaskSelected');
set(tool.handles.Tools.maskSelected(islct) ,'Cdata',repmat(permute(tool.maskColor(islct+1,:)*tool.alpha+(1-tool.alpha)*[.4 .4 .4],[3 1 2]),w,w))
set(tool.handles.Tools.maskSelected(islct) ,'Callback',@(hObject,evnt) setmaskSelected(tool,islct))
c = uicontextmenu(tool.handles.fig);
set(tool.handles.Tools.maskSelected(islct),'UIContextMenu',c)
uimenu('Parent',c,'Label','delete','Callback',@(hObject,evnt) maskClean(tool,islct))
if islct == 5
uimenu('Parent',c,'Label','Set value','Callback',@(hObject,evnt) maskCustomValue(tool))
end
end
% lock mask
tool.handles.Tools.maskLock = uicontrol(tool.handles.Panels.ROItools,'Style','togglebutton','Position',[buff pos(4)-(islct+1)*w w w], 'Value', 1, 'TooltipString', 'Protect other labels (except selected one)');
icon_profile = makeToolbarIconFromPNG('icon_lock.png');
set(tool.handles.Tools.maskLock ,'Cdata',icon_profile)
set(tool.handles.Tools.maskLock ,'Callback',@(hObject,evnt) setlockMask(tool))
% mask statistics
tool.handles.Tools.maskStats = uicontrol(tool.handles.Panels.ROItools,'Style','togglebutton','Position',[buff pos(4)-(islct+2)*w w w], 'Value', 1, 'TooltipString', sprintf('Statistics in the different ROI\n(or in the whole volume if mask empty)'));
icon_hist = makeToolbarIconFromPNG('plottype-histogram.png');
icon_hist = min(1,max(0,imresize_noIPT(icon_hist,[16 16])));
set(tool.handles.Tools.maskStats ,'Cdata',icon_hist)
set(tool.handles.Tools.maskStats ,'Callback',@(hObject,evnt) StatsCallback(hObject,evnt,tool))
% mask save
tool.handles.Tools.maskSave = uicontrol(tool.handles.Panels.ROItools,'Style','togglebutton','Position',[buff pos(4)-(islct+3)*w w w], 'Value', 1, 'TooltipString', 'Save mask');
icon_save = makeToolbarIconFromPNG([MATLABicondir '/file_save.png']);
icon_save = min(1,max(0,imresize_noIPT(icon_save,[16 16])));
set(tool.handles.Tools.maskSave ,'Cdata',icon_save)
fun=@(hObject,evnt) saveMask(tool,hObject);
set(tool.handles.Tools.maskSave ,'Callback',fun)
% mask load
tool.handles.Tools.maskLoad = uicontrol(tool.handles.Panels.ROItools,'Style','togglebutton','Position',[buff pos(4)-(islct+4)*w w w], 'Value', 1, 'TooltipString', 'Load mask');
icon_load = makeToolbarIconFromPNG([MATLABicondir '/file_open.png']);
set(tool.handles.Tools.maskLoad ,'Cdata',icon_load)
fun=@(hObject,evnt) loadMask(tool,hObject);
set(tool.handles.Tools.maskLoad ,'Callback',fun)
%Set font size of all the tool objects
try
set(cell2mat(struct2cell(tool.handles.Tools)),'FontSize',9,'Units','Pixels')
catch
objarr=struct2cell(tool.handles.Tools);
objarr=[objarr{:}];
set(objarr,'FontSize',9,'Units','Pixels')
end
set(tool.handles.fig,'NextPlot','new')
% delete if main is deleted
figfun = get(tool.handles.fig,'CloseRequestFcn');
if ischar(figfun)
set(tool.handles.fig,'CloseRequestFcn',@(src,evt) cellfun(@(x) feval(x), {figfun,@() delete(tool)}));
else
set(tool.handles.fig,'CloseRequestFcn',@(src,evt) cellfun(@(x) feval(x,src,evt), {figfun,@(h,e) delete(tool)}));
end
%%
% add shortcuts
set(gcf,'Windowkeypressfcn', @(hobject, event) tool.shortcutCallback(event))
%run the reset view callback
resetViewCallback([],[],tool)
% Enable/Disable buttons based on mask
tool.maskEvents;
% set Image
setImage(tool, varargin{:})
% disable ROI tools if no image processing toolbox
result = license('test','image_toolbox') && ~isempty(which('poly2mask.m'));
if result==0
warning('Image processing toolbox is missing... ROI tools will not work')
set(findobj(tool.handles.Panels.ROItools,'type','uicontrol'),'visible','off');
set(tool.handles.Tools.maskLoad,'visible','on');
set(tool.handles.Tools.maskStats,'visible','on');
set(tool.handles.Tools.maskSelected,'visible','on');
set(tool.handles.Tools.montage,'visible','on');
end
try
% Add Drag and Drop feature
% txt_drop = annotation(tool.handles.Panels.Image,'textbox','Visible','off','EdgeColor','none','FontSize',25,'String','DROP!','Position',[0.5 0.5 0.6 0.1],'FitBoxToText','on','Color',[1 0 0]);
wrn = warning('off','MATLAB:ui:javaframe:PropertyToBeRemoved');
jFrame = get(tool.handles.fig, 'JavaFrame');
jAxis = jFrame.getAxisComponent();
java_dnd(jAxis, @(s, e)onDrop(tool, s, e))
warning(wrn);
catch err
warning(err.message)
end
end
function setPosition(tool,position)
% tool.setPosition(position)
% ex: tool.setPosition([0 0 1 .5])
set(tool.handles.Panels.Large,'Position',position)
end
function position = getPosition(tool)
% position = tool.getPosition()
position = get(tool.handles.Panels.Large,'Position');
end
function setUnits(tool,units)
% tool.setUnits(units)
% ex: tool.setUnits('pixels')
set(tool.handles.Panels.Large,'Units',units)
end
function units = getUnits(tool)
% tool.getUnits()
units = get(tool.handles.Panels.Large,'Units');
end
function setMask(tool,mask)
% tool.setMask(mask)
% ex: S = tool.getImageSize();
% mask = ones(S(1:3),'uint8');
% tool.setMask(mask)
% 4D mask --> indice along 4th dim
if ndims(mask)>3, [~,masktmp] = max(uint8(mask(:,:,:,:)),[],4); mask = uint8(masktmp).*uint8(any(mask(:,:,:,:),4)); end
if ~isempty(mask) && (size(mask,1)~=size(tool.I{1},1) || size(mask,2)~=size(tool.I{1},2) || size(mask,3)~=size(tool.I{1},3))
warning(sprintf('Mask (%dx%dx%d) is inconsistent with Image (%dx%dx%d)',size(mask,1),size(mask,2),size(mask,3),size(tool.I{1},1),size(tool.I{1},2),size(tool.I{1},3)))
mask = [];
end
if isempty(mask) && (isempty(tool.mask) || size(tool.mask,1)~=size(tool.I{1},1) || size(tool.mask,2)~=size(tool.I{1},2) || size(tool.mask,3)~=size(tool.I{1},3))
tool.mask=zeros([size(tool.I{1},1) size(tool.I{1},2) size(tool.I{1},3)],'uint8');
elseif ~isempty(mask)
if islogical(mask)
maskOld = tool.mask;
if isempty(maskOld), maskOld = mask; end
maskOld(maskOld==tool.maskSelected)=0;
if tool.lockMask
maskOld(mask & maskOld==0) = tool.maskSelected;
else
maskOld(mask) = tool.maskSelected;
end
tool.mask=uint8(maskOld);
else
if max(mask(:))>255
tool.mask=uint16(mask);
else
tool.mask=uint8(mask);
end
end
end
showSlice(tool)
notify(tool,'maskChanged')
end
function Num = getmaskSelected(tool)
% Ind = tool.getmaskSelected()
% Get the mask index currently selected
% (Mask is multi-label uint8 indexed image)
Num = tool.maskSelected;
end
function mask = getMask(tool,all)
% mask = tool.getMask(all);
% ex: mask = tool.getMask(); get currently selected
% index of the 3D mask
% mask = tool.getMask(1); get the entire multi-label mask
if nargin<2, all=false; end
if all
mask = tool.mask;
else
mask = tool.mask==tool.maskSelected;
end
end
function maskUndo(tool)
% tool.maskUndo() undo last operation done on the mask
if ~isempty(tool.maskHistory{end-1})
tool.mask=tool.maskHistory{end-1};
showSlice(tool)
tool.maskHistory = circshift(tool.maskHistory,1,2);
tool.maskHistory{1}=[];
end
if isempty(tool.maskHistory{end-1})
set(tool.handles.Tools.undoMask, 'Enable', 'off')
end
notify(tool,'maskUndone')
end
function maskClean(tool,islct)
% tool.maskClean(islct)
% ex: tool.maskClean(1) set mask to 0 for index '1'
if islct == 5
islct = str2num(get(tool.handles.Tools.maskSelected(5),'String'));
end
tool.mask(tool.mask==islct)=0;
showSlice(tool)
notify(tool,'maskChanged')
end
function maskCustomValue(tool,islct)
% tool.maskCustomValue(islct) sets a new label islct
% ex: tool.maskCustomValue(3)
if nargin<2
islct = inputdlg('Mask Value');
if isempty(islct) || isempty(str2num(islct{1}))
return;
else
islct = str2num(islct{1});
islct = floor(islct(1));
end
end
togglebutton(tool.handles.Tools.maskSelected(5))
Cdata = get(tool.handles.Tools.maskSelected(5),'Cdata');
Color = tool.maskColor(mod(islct+1,end),:)*tool.alpha+(1-tool.alpha)*[.4 .4 .4];
Cdata(:,:,1) = Color(1);
Cdata(:,:,2) = Color(2);
Cdata(:,:,3) = Color(3);
set(tool.handles.Tools.maskSelected(5),'Cdata',Cdata,'String',num2str(islct));
tool.maskSelected = islct;
end
function setmaskSelected(tool,islct)
if islct == 5
tool.maskSelected = str2num(get(tool.handles.Tools.maskSelected(5),'String'));
else
tool.maskSelected = islct;
end
set(tool.handles.Tools.maskSelected(min(5,islct)),'FontWeight','bold','FontSize',12,'ForegroundColor',[1 1 1]);
set(tool.handles.Tools.maskSelected(setdiff(1:5,islct)),'FontWeight','normal','FontSize',9,'ForegroundColor',[0 0 0]);
end
function setlockMask(tool)
% tool.setlockMask() toggle lock on (preventing overwritting of other labels) or off
tool.lockMask = ~tool.lockMask;
CData = get(tool.handles.Tools.maskLock,'CData');
S = size(CData);
CData = CData.*repmat(permute(([0.4 0.4 0.4]*(~tool.lockMask) + 1./[0.4 0.4 0.4]*tool.lockMask),[3 1 2]),S(1), S(2));
set(tool.handles.Tools.maskLock,'CData',CData)
end
function setMaskColor(tool,maskColor)
% tool.setMaskColor(maskColor)
% tool.setMaskColor('y') for yellow mask for all labels
% tool.setMaskColor(hsv(30))
if ischar(maskColor)
switch maskColor
case 'y'
maskColor = [1 1 0];
case 'm'
maskColor = [1 0 1];
case 'c'
maskColor = [0 1 1];
case 'r'
maskColor = [1 0 0];
case 'g'
maskColor = [0 1 0];
case 'b'
maskColor = [0 0 1];
case 'w'
maskColor = [1 1 1];
case 'k'