MATLAB Answers

Leonard
0

Can't get Slider Step in GUI to move in step sizes that I want

Asked by Leonard
on 15 Nov 2014
Latest activity Commented on by Geoff Hayes
on 15 Nov 2014
Here's my complete code for a gui where I want to adjust the threshhold of an image with a slider in the figure. I have everything working except for the slider step size. When I keep the line in that specifies what step size the slider should take, the slider doesn't work at all. When I leave that line out, things work exactly as I want (except for the step size of course).
Any help or input would be greatly appreciated!
function final_image_threshhold = GetImageThreshhold(image,flag)
if (strcmp(flag,'None') == 1)
function_marker = 1;
elseif (strcmp(flag,'AOMDEL') == 1)
function_marker = 2;
else
error('Unknown flag in GetImageThreshhold');
end
max_threshhold = max(image(:));
se = strel('disk',10,4);
if (function_marker == 1)
new_image = 255*(double(image > round(max_threshhold/2)));
default_colormap = 1;
elseif (function_marker == 2)
new_image = image > round(max_threshhold/2);
new_image = bwareaopen(new_image,13);
new_image = bwmorph(new_image,'spur');
new_image = imdilate(imerode(imdilate(new_image,se),se),se);
new_image = bwlabel(new_image);
default_colormap = 1;
else
end
current_figure = imshow(imadjust(uint8(new_image)));
colormap_menu = uicontrol('Style','popupmenu',...
'Value',default_colormap,...
'String',{'ColorMap','winter','lines','jet','hsv','hot','cool','gray'},...
'Position',[20 -10 80 50],...
'Callback', @SetColorMap); %#ok<NASGU>
threshhold_slider = uicontrol('Style','slider',...
'Min',0,'Max',ceil(max_threshhold),'Value',round(max_threshhold/2),...
'SliderStep',[100*round(1/(max_threshhold + 1)),250*round(1/(max_threshhold + 1))],... %%%_______Line in Question_______%%%
'Position',[110 15 410 25],...
'Callback', {@SetThreshholdLevel,image,current_figure,function_marker});
threshhold_button = uicontrol('Style', 'pushbutton',...
'String', 'Continue',...
'Position', [530 14 70 28],...
'Callback', @ThreshButtonDone); %#ok<NASGU>
figure(999); set(999,'Visible','off');
waitfor(999);
final_image_threshhold = get(threshhold_slider,'Value');
close all;
end
function SetColorMap(source,~)
val = get(source,'Value');
maps = get(source,'String');
newmap = maps{val};
colormap(newmap);
end
function SetThreshholdLevel(slider_uic,~,image,current_figure,function_marker)
new_threshhold = round(get(slider_uic,'Value'))
se = strel('disk',10,4);
if (function_marker == 1)
new_image = uint8(image > new_threshhold)*255;
elseif (function_marker == 2)
new_image = uint8(image > round(new_threshhold));
new_image = bwareaopen(new_image,13);
new_image = bwmorph(new_image,'spur');
new_image = imdilate(imerode(imdilate(new_image,se),se),se);
new_image = bwlabel(new_image);
else
end
set(current_figure,'cData',new_image);
end
function ThreshButtonDone(~,~)
close(999);
end

  1 Comment

Leonard - a couple of asides: in several places you have defined a parameter and/or local variable named image. This conflicts with a MATLAB built-in function of the same name, so I recommend that you rename your parameter to something else (just to avoid future bugs in the code if you ever try to call the function image).
As well, it is interesting what you are doing with the other figure 999 to force the program to wait for 999 seconds before closing. I realize why you are doing this (to return the last threshold value) but there is an alternative which is a little tidier. Remove the code
figure(999); set(999,'Visible','off');
waitfor(999);
final_image_threshhold = get(threshhold_slider,'Value');
close all;
and replace with simply
waitfor(current_figure);
which will just wait until the current_figure (it is really the handle to the image, so this should be renamed) is deleted (the image graphics object). Of course, we don't get the final_image_threshhold set, but we can do this by nesting the SetThresholdLevel function within the GetImageThreshhold so that it has access to final_image_threshhold. Remove your SetThresholdLevel and paste the following within the main function
function final_image_threshhold = GetImageThreshhold(image,flag)
. . .
% initialize final_image_threshhold
final_image_threshhold = get(threshhold_slider,'Value');
% slider control callback
function SetThreshholdLevel(slider_uic,~,origImage, ...
current_figure,function_marker)
final_image_threshhold = round(get(slider_uic,'Value'));
se = strel('disk',10,4);
if (function_marker == 1)
newImage = uint8(origImage > final_image_threshhold)*255;
elseif (function_marker == 2)
newImage = uint8(origImage > round(final_image_threshhold));
newImage = bwareaopen(newImage,13);
newImage = bwmorph(newImage,'spur');
newImage = imdilate(imerode(imdilate(newImage,se),se),se);
newImage = bwlabel(newImage);
else
end
set(current_figure,'cData',newImage);
end
% wait for the image graphics object to be deleted
waitfor(current_figure);
Note that I have changed the input parameter from image to origImage, and have renamed the new_image to newImage (not really necessary). More importantly, see how we make use of the final_image_threshhold return value. Try this out if you wish and note that you will have to change the ThreshButtonDown code to
function ThreshButtonDone(~,~)
close(gcf);
end
where gcf gets the current figure handle that we wish to close.

Sign in to comment.

1 Answer

Answer by Geoff Hayes
on 15 Nov 2014
Edited by Geoff Hayes
on 15 Nov 2014
 Accepted Answer

Leonard - consider your line of code to set the step size
'SliderStep',[100*round(1/(max_threshhold + 1)),250*round(1/(max_threshhold + 1))],
where
max_threshhold = max(image(:));
So depending upon the data type of your image, then the max_threshold could be 1 (for single or double input image), 255 (for 8-bit unsigned integer input), etc. Regardless, the code
round(1/(max_threshhold + 1)
will always be zero, so your step sizes will be zero too. I think what you want to do is remove the round altogether since the slider steps are percent changes in the position of the slider (the first being the minor step when the user presses the left or right arrow, and the second being the major step which corresponds to pressing in the trough). Try the following instead
'SliderStep',[100/(double(max_threshhold) + 1),250/(double(max_threshhold) + 1)],
Note the casting of the max_threshold to the double data type. If our input image is an unsigned (or signed) integer, then 100 (or 250) divided by this integer will be an integer...and so will be zero (assuming max_threshold is greater than 100 and 250). By casting to a double, we allow the result to be a rational number.
With the above change and a max_threshold of 255, the minor step will be 0.3906 and the major step will be 0.976. You may want to change the minor step to 0.03906 so that you allow for more than 3-4 steps in your slider.

  2 Comments

Thank you very much for the response, Geoff. I completely overlooked the round step in the line mentioned. Thanks as well for the explanation with the double(max_threshhold) as some of the images which I called this function with were doubles while others were not!
Thanks again!

Sign in to comment.