%CLIPGUI GUI to do clipping in grey-values % OUT = CLIPGUI(IN) presents a GUI with a view of IN and % its histogram, and allows the user to select two thresholds % for clipping. OUT will contain the clipped image when the % user is finished. % % The threshold values can be changed by clicking on the % histogram (left mouse button changes the lower value, % right mouse button the upper one). This will update the % display. The image on the left shows the grey-value image, % the one on the right the clipped one. % % In case of a 3D image, it is possible to change the view % by selecting one of the radiobuttons near the top. Also, % you can change the slice by clicking with the left and % right mouse buttons on one of the images. %(c) by Cris Luengo, August 2001 % If you don't want either or to do what they do % now, comment out the section in the function 'KeyPress' that % handles these keys. This section is commented. function out = clipgui(in) % Handle Callback functions & menuing if ischar(in) switch(in) case 'DIP_GetParamList' out = struct('menu','Point',... 'display','Clip GUI',... 'inparams',struct('name', {'in'},... 'description',{'Input image'},... 'type', {'image'},... 'dim_check', {0},... 'range_check',{[]},... 'required', {1},... 'default', {'a'}... ),... 'outparams',struct('name', {'out'},... 'description',{'Output image'},... 'type', {'image'}... )... ); case 'imageclick' ImageClick; case 'histclick' HistogramClick; case 'chngorient' ChangeOrientation; case 'sliceselect' SliceSelect; case 'keypress' KeyPress; otherwise error('Input must be an image!') end return end % Parse input image if ~isa(in,'dip_image') in = dip_image(in); end in = squeeze(in); if ndims(in)<2 | ndims(in)>3 error('Only 2D and 3D images supported.') end if isa(dip_array(in),'double') in = dip_image(in,'sfloat'); end % Create figure window figh = figure; dtu = get(0,'units'); set(0,'units','pixels'); dts = get(0,'ScreenSize'); dts = dts(3:4); set(0,'units',dtu); sz = [880,400]; set(figh,'units','pixels','position',[dts-sz-[10,100],sz],... 'colormap',gray(256),... 'color',get(0,'defaultuicontrolbackground'),... 'KeyPressFcn','clipgui(''keypress'')'); % Create image display axhb = axes('parent',figh,'units','pixels',... 'position',[sz(1)-256-20,60,256,256],... 'visible','off','ydir','reverse','DataAspectRatio',[1,1,1]); axhg = axes('parent',figh,'units','pixels',... 'position',[sz(1)-512-40,60,256,256],... 'visible','off','ydir','reverse','DataAspectRatio',[1,1,1]); udata.img = in; imsz = size(in); if ndims(in)==3 udata.orientation = 3; % axis along which we look: 3 = x-y slices. % 1 = y-z slices. udata.slice = 0; imsz(udata.orientation) = []; else udata.orientation = 0; % meaning 2D. end udata.imghb = image('parent',axhb); udata.imghg = image('parent',axhg); set(axhb,'xlim',[0,imsz(1)]+0.5,'ylim',[0,imsz(2)]+0.5); set(axhg,'xlim',[0,imsz(1)]+0.5,'ylim',[0,imsz(2)]+0.5); if ndims(in)==3 set(udata.imghb,'ButtonDownFcn','clipgui(''imageclick'')'); set(udata.imghg,'ButtonDownFcn','clipgui(''imageclick'')'); % For 3D display: create buttons uicontrol('parent',figh,'style','text',... 'position',[sz(1)-256-60-100,60+256+5,100,20],... 'horizontalalignment','right',... 'string','slice number: '); udata.slicetxt = uicontrol('parent',figh,'style','edit',... 'position',[sz(1)-256-60,60+256+5,60,20],... 'string',num2str(udata.slice),... 'horizontalalignment','left',... 'callback','clipgui(''sliceselect'')'); udata.mxslc = uicontrol('parent',figh,'style','text',... 'position',[sz(1)-256,60+256+5,100,20],... 'string',[' (out of ',num2str(size(udata.img,udata.orientation)),')']); uicontrol('parent',figh,'style','radiobutton','string','X-Y',... 'position',[sz(1)-512+130,60+256+30,50,20],'tag','3',... 'callback','clipgui(''chngorient'')','value',1); uicontrol('parent',figh,'style','radiobutton','string','X-Z',... 'position',[sz(1)-512+130+70,60+256+30,50,20],'tag','2',... 'callback','clipgui(''chngorient'')','value',0); uicontrol('parent',figh,'style','radiobutton','string','Y-Z',... 'position',[sz(1)-512+130+140,60+256+30,50,20],'tag','1',... 'callback','clipgui(''chngorient'')','value',0); end % Create histogram display udata.histh = axes('parent',figh,'units','pixels',... 'position',[600-512-40,60,256,256],... 'box','on'); [hist,bins] = diphist(in,[]); line('parent',udata.histh,'xdata',bins,'ydata',hist,... 'ButtonDownFcn','clipgui(''histclick'')'); yrange = [0,max(hist(2:end-1))]; set(udata.histh,'xlim',bins([1,end]),'ylim',yrange,'ytick',yrange); % I do this because max and min values are too frequent. udata.threshlow = bins(1); udata.threshhigh = bins(end); udata.threshlow_h = line('parent',udata.histh,... 'xdata',[udata.threshlow,udata.threshlow],... 'ydata',yrange,'color',[1,0,0],'EraseMode','xor',... 'ButtonDownFcn','clipgui(''histclick'')'); udata.threshhigh_h = line('parent',udata.histh,... 'xdata',[udata.threshhigh,udata.threshhigh],... 'ydata',yrange,'color',[0,1,0],'EraseMode','xor',... 'ButtonDownFcn','clipgui(''histclick'')'); set(figh,'ButtonDownFcn','clipgui(''histclick'')'); set(udata.histh,'ButtonDownFcn','clipgui(''histclick'')'); % Display image DisplayImage(udata); % Create control buttons uicontrol('parent',figh,'String','Ok',... 'position',[sz(1)-100,20,80,30],... 'Callback','set(gcbf,''tag'',''OK'')'); uicontrol('parent',figh,'String','Cancel',... 'position',[sz(1)-200,20,80,30],... 'Callback','set(gcbf,''tag'',''CANCEL'')'); % Save data into figure window set(figh,'userdata',[]); set(figh,'userdata',udata); % This avoids a very slow update MATLAB sometimes does. % Wait for user to finish waitfor(figh,'tag'); ok = 0; if ishandle(figh) if strcmp(get(figh,'tag'),'OK') ok = 1; udata = get(figh,'userdata'); end delete(figh); end % Perform segmentation if ok out = clip(in,udata.threshhigh,udata.threshlow); else error('Operation cancelled'); end % Done! % Send a new image to the image display (update both) function DisplayImage(udata) switch udata.orientation case 0 data = udata.img; case 1 data = squeeze(udata.img(udata.slice,:,:)); case 2 data = squeeze(udata.img(:,udata.slice,:)); case 3 data = squeeze(udata.img(:,:,udata.slice)); end g = uint8(stretch(data)); b = uint8((clip(data,udata.threshhigh,udata.threshlow)-udata.threshlow)*... (255/(udata.threshhigh-udata.threshlow))); set(udata.imghg,'cdata',g); set(udata.imghb,'cdata',b); % Send a new image to the clipped image display function DisplayBinaryImage(udata) switch udata.orientation case 0 data = udata.img; case 1 data = squeeze(udata.img(udata.slice,:,:)); case 2 data = squeeze(udata.img(:,udata.slice,:)); case 3 data = squeeze(udata.img(:,:,udata.slice)); end b = uint8((clip(data,udata.threshhigh,udata.threshlow)-udata.threshlow)*... (255/(udata.threshhigh-udata.threshlow))); set(udata.imghb,'cdata',b); % Callback for clicking on the image function ImageClick figh = gcbf; if ~isempty(figh) udata = get(figh,'userdata'); imsz = size(udata.img); switch get(figh,'selectiontype') case 'normal' % left mouse click if udata.slice>=imsz(udata.orientation)-1 return end udata.slice = udata.slice+1; case 'alt' % right mouse click if udata.slice<=0 return end udata.slice = udata.slice-1; end DisplayImage(udata); set(udata.slicetxt,'string',num2str(udata.slice)); set(figh,'userdata',[]); set(figh,'userdata',udata); % This avoids a very slow update MATLAB sometimes does. end % Callback for pressing a key function KeyPress figh = gcbf; if ~isempty(figh) udata = get(figh,'userdata'); imsz = size(udata.img); switch get(figh,'currentcharacter') case {'n','N'} % next if udata.slice>=imsz(udata.orientation)-1 return end udata.slice = udata.slice+1; case {'p','P'} % previous if udata.slice<=0 return end udata.slice = udata.slice-1; %--- Handles escape and enter keys that terminate the dialog box. case 27 % set(gcbf,'tag','CANCEL'); return case 13 % set(gcbf,'tag','OK'); return %--- end DisplayImage(udata); set(udata.slicetxt,'string',num2str(udata.slice)); set(figh,'userdata',[]); set(figh,'userdata',udata); % This avoids a very slow update MATLAB sometimes does. end % Callback for the edit box (selecting a slice number) function SliceSelect figh = gcbf; if ~isempty(figh) udata = get(figh,'userdata'); imsz = size(udata.img); udata.slice = str2num(get(udata.slicetxt,'string')); if udata.slice >= imsz(udata.orientation) udata.slice = imsz(udata.orientation)-1; elseif udata.slice <= 0 udata.slice = 0; end DisplayImage(udata); set(udata.slicetxt,'string',num2str(udata.slice)); set(figh,'userdata',[]); set(figh,'userdata',udata); % This avoids a very slow update MATLAB sometimes does. end % Callback for the orientation checkboxes function ChangeOrientation [box,figh] = gcbo; if ~isempty(figh) set(findobj(figh,'type','uicontrol','style','radiobutton'),'value',0); set(box,'value',1); udata = get(figh,'userdata'); udata.orientation = str2num(get(box,'tag')); imsz = size(udata.img); if udata.slice >= imsz(udata.orientation) udata.slice = imsz(udata.orientation)-1; end imsz(udata.orientation) = []; set(get(udata.imghb,'parent'),'xlim',[0,imsz(1)]+0.5,'ylim',[0,imsz(2)]+0.5); set(get(udata.imghg,'parent'),'xlim',[0,imsz(1)]+0.5,'ylim',[0,imsz(2)]+0.5); DisplayImage(udata); set(udata.slicetxt,'string',num2str(udata.slice)); set(udata.mxslc,'string',[' (out of ',num2str(size(udata.img,udata.orientation)),')']); set(figh,'userdata',[]); set(figh,'userdata',udata); % This avoids a very slow update MATLAB sometimes does. end % Callback for clicking on the histogram function HistogramClick figh = gcbf; if ~isempty(figh) udata = get(figh,'userdata'); pt = get(udata.histh,'CurrentPoint'); xlim = get(udata.histh,'xlim'); if pt(1,1)>=xlim(1) & pt(1,1)<=xlim(2) switch get(figh,'selectiontype') case 'normal' % left mouse click if pt(1,1) > udata.threshhigh udata.threshlow = udata.threshhigh; udata.threshhigh = pt(1,1); set(udata.threshhigh_h,'xdata',[udata.threshhigh,udata.threshhigh]); else udata.threshlow = pt(1,1); end set(udata.threshlow_h,'xdata',[udata.threshlow,udata.threshlow]); case 'alt' % right mouse click if pt(1,1) < udata.threshlow udata.threshhigh = udata.threshlow; udata.threshlow = pt(1,1); set(udata.threshlow_h,'xdata',[udata.threshlow,udata.threshlow]); else udata.threshhigh = pt(1,1); end set(udata.threshhigh_h,'xdata',[udata.threshhigh,udata.threshhigh]); end DisplayBinaryImage(udata); set(figh,'userdata',[]); set(figh,'userdata',udata); % This avoids a very slow update MATLAB sometimes does. end end