Event listener for multiple draggable rectangles using imrect in matlab

function computeButton_Callback(hObject, eventdata, handles)
% hObject handle to computeButton (see GCBO)
% eventdata reserved - to be defined in a future version of MATLAB
% handles structure with handles and user data (see GUIDATA)
PImage=handles.ProcessedImage;
Image=handles.Image;
imshow(Image);
hold on;
bw=bwconncomp(PImage,4);
regions=regionprops(bw,'BoundingBox','PixelIdxList');
for i=1:length(regions)
box=regions(i).BoundingBox;
h=imrect(gca,box);
%rectangle('Position',box,'EdgeColor','black','LineWidth',2);
end
%I want to make an event listener that would record the
%properties(height,width) of all the rectangles and even
%the changes on each of the draggable rectangles on the Image.

 채택된 답변

Do you really want to listen to all the changes in position of the rectangles? There will be a lot of event recorded when the user drag a handle. If you only need to know what the current position of the rectangles is at some point in the code, you can just query it. For that, you obviously need to save the rectangle handles somewhere:
%...
hrectangles = gobjects(numel(regions), 1); %allocate storage for rectangle handles
for i = 1:numel(regions)
box = regions(i).BoundingBox;
hrectangles(i) = imrect(gca, box); %store rectangle handles
end
%...
%code where you need to know what the coordinates of the rectangles are:
rectpos = cell2mat(arrayfun(@getPosition, hrectangles, 'UniformOutput', false));
If you really want to listen to all the changes, you can add a new position callback to each rectangle and do whatever you need to do in that callback:
for i = 1:numel(regions)
box = regions(i).BoundingBox;
h = imrect(gca, box);
h.addNewPositionCallback(@(newpos) RectPositionChangedCallback(h, newpos)
end
with
function RectPositionChangedCallback(recthandle, newposition)
%do something with new position
end

댓글 수: 6

I am interested in all the the rectangles and after a user have adjusted the size of the rectangle(s) using a mouse then finally I would save all the rectangles parameters in the file.How would I do that?
I would add a button to the GUI for the user to tell you when they're done adjusting all the rectangles. In the button callback, you then query each rectangle location and save that to file.
So, in your computeButton callback, you simply store all the rectangle handles, as per my first example:
%...
handles.hrectangles = gobjects(numel(regions), 1); %allocate storage for rectangle handles
for i = 1:numel(regions)
box = regions(i).BoundingBox;
handles.hrectangles(i) = imrect(gca, box); %store rectangle handles
end
guidata(hObject, handles); %save handles structure
In you new button callback:
function SaveRectButton_Callback(hObject, eventdata, handles)
rectpos = cell2mat(arrayfun(@getPosition, handles.hrectangles, 'UniformOutput', false));
dlmwrite('somefile.txt', rectpos); %or however you want to save the rectangles
end
I am getting following error.
While converting from 'imrect':
The conversion returned a value of class 'matlab.mixin.Heterogeneous', which cannot be inserted into an array of class
'matlab.graphics.GraphicsPlaceholder'.
Error in draggable>computeButton_Callback (line 107)
handles.hrectangles(i) = imrect(gca, box); %store rectangle handles
Error in gui_mainfcn (line 95)
feval(varargin{:});
Error in draggable (line 42)
gui_mainfcn(gui_State, varargin{:});
Error in @(hObject,eventdata)draggable('computeButton_Callback',hObject,eventdata,guidata(hObject))
Error while evaluating UIControl Callback
For some reason, I thought the rectangles created by imrect were graphics objects (which can be stored in a gobject array), but no, they're their own class.
I don't think you can preinitialise an array of rectangle objects, so the workaround is to either grow the array or use a cell array:
handles.hrectangles = cell(numel(regions), 1); %allocate cell array for storing for rectangle handles
for i = 1:numel(regions)
box = regions(i).BoundingBox;
handles.hrectangles{i} = imrect(gca, box); %store rectangle handles in cell array
end
guidata(hObject, handles); %save handles structure
In the event handler, just replace arrayfun by cellfun:
function SaveRectButton_Callback(hObject, eventdata, handles)
rectpos = cell2mat(cellfun(@getPosition, handles.hrectangles, 'UniformOutput', false));
dlmwrite('somefile.txt', rectpos); %or however you want to save the rectangles
end
This is working well Now but only with one issue now.if I delete or add a rectangle(s) then it shows following error.
Invalid or deleted object.
Error in imrect/getPosition (line 110)
pos = obj.api.getPosition();
Error in draggable>saveButton_Callback (line 144)
rectpos = cell2mat(cellfun(@getPosition, handles.hrectangles, 'UniformOutput', false));
Error in gui_mainfcn (line 95)
feval(varargin{:});
Error in draggable (line 42)
gui_mainfcn(gui_State, varargin{:});
Error in @(hObject,eventdata)draggable('saveButton_Callback',hObject,eventdata,guidata(hObject))
Indeed, if a rectangle is deleted, then its handle is no longer valid, and getPosition is not going to be happy. The simplest thing is to remove these deleted handles from the cell array:
hvalidrects = handles.hrectangles(cellfun(@isvalid, handles.hrectangles)); %remove deleted handles
rectpos = cell2mat(cellfun(@getPosition, hvalidrects, 'UniformOutput', false)); %get position of valid rectangles
If a rectangle is added, you need to add it to cell array in whichever function is creating this new rectangle.

댓글을 달려면 로그인하십시오.

추가 답변 (1개)

Rajeev Yadav
Rajeev Yadav 2022년 7월 14일
편집: Rajeev Yadav 2022년 7월 14일
Can we add ARROW KEYS (UP ARROW, RIGHT ARROW, LEFT ARROW,DOWN ARROW) with fixed step size control to move the rectangle?

카테고리

도움말 센터File Exchange에서 App Building에 대해 자세히 알아보기

태그

질문:

2016년 9월 8일

편집:

2022년 7월 14일

Community Treasure Hunt

Find the treasures in MATLAB Central and discover how the community can help you!

Start Hunting!

Translated by