problem with Slider and ButtonDownFcn in Matlab
I have a problem with Slider and ButtonDownFcn.
Currently I display to the user an image in the GUI (using GUIDE), then I let them select a license plate by drawing a rectangle around it.
I have added slider to turn the image in degrees.
When I turn the image and then click on it, the image returns to its initial state (angle).
What can do to make sure that the image stays in its location and then draw the rectangle on it?
This is my ButtonDownFcn function:
function axes1_ButtonDownFcn(hObject, eventdata, handles)
global image h
imshow(image, []);
h = imrect;
setColor(h, 'black');
This is my slider function:
function slider2_Callback(hObject, eventdata, handles)
global image hImage
slider_value = get(handles.slider2,'Value');
axes(handles.axes1);
hImage = imshow(imrotate(image,slider_value,'bilinear'), 开发者_运维技巧'Parent', handles.axes1);
set(hImage, 'ButtonDownFcn', @(s,e) axes1_ButtonDownFcn());
EDIT: now it's all working just fine, and more importantly it is clear.
one last thing do you know how I can remove the numbers from X and Y axes.
I tried with axes off
but it didn't help.
thanks a lot.
I believe it's easier to learn by example. So, I will continue the example I started in your previous question.
When the GUI is started, an image is shown, which you can rotate using the slider. When the image is clicked, select a rectangular ROI (you can continue to rotate the image underneath). Once satisfied, double click the rectangle, and the cropped image is shown on the other axes (one cropped from the rotated image, the other from the original image), then the rectangle is removed.
function rotationGUI2()
%# setup GUI
hFig = figure('menu','none', 'Position',[100 100 750 420]);
hAx = axes('Parent',hFig, 'Units','pixels', 'Position',[50 70 350 300]);
hAx1 = axes('Parent',hFig, 'Units','pixels', 'Position',[450 230 250 140]);
hAx2 = axes('Parent',hFig, 'Units','pixels', 'Position',[450 70 250 140]);
uicontrol('Parent',hFig, 'Style','slider', 'Value',0, 'Min',0,...
'Max',360, 'SliderStep',[1 10]./360, ...
'Position',[100 20 300 30], 'Callback',@slider_callback)
hTxt = uicontrol('Style','text', 'String','0', ...
'Units','pixels', 'Position',[240 25 20 15]);
%# read and show image
I = imread('cameraman.tif');
hImg = imshow(I, 'Parent',hAx);
set(hImg, 'ButtonDownFcn',@image_ButtonDownFcn); %# attach event listener
%# Callback functions
function slider_callback(hObj, eventdata)
angle = round( get(hObj,'Value') ); %# rotation angle
I_rot = imrotate(I, angle, 'bilinear', 'crop'); %# rotate image
set(hImg, 'CData',I_rot) %# update image
set(hTxt, 'String',num2str(angle)) %# update text
end
function image_ButtonDownFcn(hObj,eventdata)
hRect = imrect(hAx);
setColor(hRect, 'black');
rectPos = wait(hRect);
delete(hRect)
I1 = imcrop(I, rectPos); %# crop from original image
I2 = imcrop(get(hImg,'CData'), rectPos); %# crop from rotated image
imshow(I1, 'Parent',hAx1)
imshow(I2, 'Parent',hAx2)
end
end
Again, recreating the example using a GUIDE-generated figure should be similar. HTH
EDIT
Below you will find a similar example generated by GUIDE. As before, you will have to create the GUI and add the components by drag-drop. Use the "Property Inspector" to adjust their properties as required. More importantly, give each a unique Tag
. I'm using:
- imgAxis, cropAxis, processAxis
- loadButton, processButton
- angleSlider, angleText
It is good practice not to use global variables, instead store your data in the handles
structure which gets passed around to the callback functions. Just remember to call the guidata
function at the end of any method that changes its data, to commit the changes.
For the part where you manually attach a handler to the image ButtonDownFcn
event, you should also pass the handles
structure to the arguments list.
That said, here the code behind the GUI (relevant parts):
%# --- Executes just before untitled is made visible.
function untitled_OpeningFcn(hObject, eventdata, handles, varargin)
%# store handles to figure, axes, and others
handles.fig = hObject;
handles.hAx = findobj(hObject, 'Tag','imgAxis');
handles.hAxCrop = findobj(hObject, 'Tag','cropAxis');
handles.hAxProcess = findobj(hObject, 'Tag','processAxis');
handles.img = [];
handles.hImg = [];
handles.hImgCrop = [];
%# disable interaction of some components until image is loaded
set(findobj(hObject, 'Tag','angleSlider'), 'Enable','off')
set(findobj(hObject, 'Tag','processButton'), 'Enable','off')
%# Update handles structure
guidata(hObject, handles);
end
%# --- Outputs from this function are returned to the command line.
function varargout = untitled_OutputFcn(hObject, eventdata, handles)
varargout{1} = handles.fig;
end
%# --- Executes on slider movement.
function angleSlider_Callback(hObject, eventdata, handles)
angle = round( get(hObject,'Value') ); %# rotation angle
I_rot = imrotate(handles.img, angle, 'bilinear', 'crop'); %# rotate image
set(handles.hImg, 'CData',I_rot) %# update image
set(findobj(handles.fig,'Tag','angleText'), 'String',num2str(angle))
end
%# --- Executes on button press in processButton.
function processButton_Callback(hObject, eventdata, handles)
%# get cropped image
I = get(handles.hImgCrop, 'CData');
%# do some processing: here i'm simply detecting the edges
if isrgb(I), I = rgb2gray(I); end
%#BW = im2bw(I, graythresh(I));
BW = edge(I, 'canny');
%# show processed image
imshow(BW, 'Parent',handles.hAxProcess)
%# Update handles structure
guidata(hObject, handles);
end
%# --- Executes on button press in loadButton.
function loadButton_Callback(hObject, eventdata, handles)
%# get image file location
[fName, fPath] = uigetfile(...
{'*.psd;*.bmp;*.jpg;*.tif;*.png;*.gif','All Image Files'; ...
'*.*','All Files' }, 'File Selector', ...
fullfile(matlabroot,'toolbox','images','imdemos'));
if fPath==0
msgbox('No file selected', 'File Selector', 'error');
return
end
%# read and show image
handles.img = imread( fullfile(fPath,fName) );
handles.hImg = imshow(handles.img, 'Parent',handles.hAx);
%# attach handler
set(handles.hImg, 'ButtonDownFcn',{@imgAxis_ButtonDownFcn,handles});
%# reenable disabled components
set(findobj(handles.fig, 'Tag','angleSlider'), 'Enable','on')
%# Update handles structure
guidata(hObject, handles);
end
%# --- Executes on mouse press over axes background.
function imgAxis_ButtonDownFcn(hObject, eventdata, handles)
%# check if some image is shown
if isempty(handles.hImg) || ~ishandle(handles.hImg)
return
end
%# select ROI using a rectangle
hRect = imrect(handles.hAx);
setColor(hRect, 'black');
rectPos = wait(hRect);
delete(hRect)
%# crop image from rotated image, and show it
I = imcrop(get(handles.hImg,'CData'), rectPos);
handles.hImgCrop = imshow(I, 'Parent',handles.hAxCrop);
%# reenable disabled components
set(findobj(handles.fig, 'Tag','processButton'), 'Enable','on')
%# Update handles structure
guidata(hObject, handles);
end
I hope this makes it all clear
In your axes1_ButtonDownFcn
, the line imshow(image, []);
is what shows you the non-rotated image when you click on it. I think removing that line should get rid of your problem. You can then use gca
to get your axes handle instead. In short, try this
function axes1_ButtonDownFcn(hObject, eventdata, handles)
global image h
h = imrect(gca);
setColor(h, 'black');
精彩评论