drawrectangle draws rectangle even though the mouse is clicked outside the parent UIAxes

I have a small app designed using the App Designer. Matlab 2021b
The UI is constructed of Figure->UIAxes only and the UIAxes is much smaller from the Figure.
This is the code of thestartup function.
startupFcn(app)
imshow('peppers.png', 'Parent', app.UIAxes);
h = drawrectangle(app.UIAxes)
end
There are two issues:
  1. While clicking the mouse outside the UIAxes and dragging , the app draws a line (i.e. rectangle with no width) on the UIAxes but outside the image. See attached.
  2. The rectangle can be drawn in the UIAxes but outside the image.See attached.
While using imrect(app.UIAxes) instead, the rectangle can be drawn on the image only. Mouse events outside the image are ignored.
How can I make the drawrectangle work as the imrect? (creating rectangle by clicking on the image only)

 Accepted Answer

Edit: This answer from MATLAB support is pasted from one of the comments below. I'm editing my initial answer to include it so that others can find it more easily:
This is the answer of MATLAB support team and it works fine.
using images.roi.Rectangle instead of drawrectangle.
function startupFcn(app)
app.UIAxes.Visible = 'on';
im = imshow('peppers.png', 'Parent', app.UIAxes);
axis(app.UIAxes, 'tight');
% Assign the ROI creating function as the callback for any button press on image object
im.ButtonDownFcn = @createROI;
function createROI(~,~)
% Create ROI object
roi = images.roi.Rectangle(app.UIAxes);
% Define an ROI start point within the image
beginDrawingFromPoint(roi,[0,0])
end
end
---- Original answer follows ----
You can pass in a DrawingArea to drawrectangle which will constrain the rectangle to the image. That keeps the drawn rectangles inside the image boundaries, although the crosshair will apear when the mouse hovers outside of the image...clicking there will initiate a rectangle inside the image:
im = imread('peppers.png')
imshow(im, 'Parent', app.UIAxes);
h = drawrectangle(app.UIAxes, 'DrawingArea', [0,0,width(im),height(im)])
Alternatively, you could use axis tight to make the axis (including the invisible part) correspond directly to the boundaries of the image.
imshow('peppers.png', 'Parent', app.UIAxes);
axis(app.UIAxes,'tight')
h = drawrectangle(app.UIAxes)

10 Comments

Thanks Dave.
By using the axis(app.UIAxes,'tight') the rectangle area is now limited to the image area.
But still, when clicking far from the UIAxes (see attached), the rectangle starts to be drawn on the image area but as a line.
It looks like the mouse events are catched outside the image/UIAxes and causing the drawrectangle function to start drawing.
@gil - did you try the second method I listed? It was specifically to address this issue.
The mouse events are caught because imshow is not using tight limits on the axes when the axes is a uiaxes. So the mouse events are being caught by the axes, and the are in the axes, but the location of the axes is a little weird. If you set app.UIAxes.Visible = 'on' you can see this. Applying axis tight fixes this.
@Dave B - this is the code:
function startupFcn(app)
app.UIAxes.Visible = 'on';
imshow('peppers.png', 'Parent', app.UIAxes);
axis(app.UIAxes,'tight');
h = drawrectangle(app.UIAxes, 'DrawingArea', [0,0,200,200])
end
See attached App designer - designer.jpg
In red is the Figure. Green is the visibile area of the UIAxes. The blue rectangle is the UIAxes while selecting the UIAxes in the App Designer.
When running the app and clicking outside the blue rectangle (even close to the Figure edge, the rectangle is being drawn. See attached rect.jpg.
I also printed the location of the mouse in relation to the axes position and the mouse dragging is out of the axes area.
The [0,0,200,200]) is just for the test, since I do not have the im. BTW, how do I get 'im' from your example?
I tried axis(app.UIAxes,'tight') by itself and also DrawingArea by itself and also both at the same time. Still, I can initiate the rectangle drawing outside the axes.
You're absolutely correct. I saw that the crosshair showed up in the appropriate drawable area but unfortunately clicks are captured by the roi object anywhere in the window.
I think that as long as you're using drawrectangle, it will capture clicks anywhere in the window - you can constrain the rectangle to the boundaries of the axes (or really, what you probably want, the boundaries of the image) but clicks will continue to initiate a rectangle even when they occur outside of the axes.
Is this a bug or a feature?
In the MATLAB docs it specify that imrect is not recommened and suggests drawrectangle as alternative.
I am using drawrectangle since I can add a label to the rectangle. imrect does not have such feature.
BTW, in the MATLAB imageLabeler app it looks like that the drawrectangle is used and you can initiate rectangle drawing only on the image area.
That's a good question, I'm not sure...I think you're experiencing it as a bug which means it's worth reporting to tech support as they can pass it on to the Image Processing Toolbox developers (who also may have better thoughts on a workaround).
I think the strategy in the imageLabeler app is to use custom mouse button down functions to create and adjust the rois, which creates the same rois as drawrectangle but without the drawrectangle interface.
How to report this issue to the tech support team as a bug?
This is the answer of MATLAB support team and it works fine.
using images.roi.Rectangle instead of drawrectangle.
function startupFcn(app)
app.UIAxes.Visible = 'on';
im = imshow('peppers.png', 'Parent', app.UIAxes);
axis(app.UIAxes, 'tight');
% Assign the ROI creating function as the callback for any button press on image object
im.ButtonDownFcn = @createROI;
function createROI(~,~)
% Create ROI object
roi = images.roi.Rectangle(app.UIAxes);
% Define an ROI start point within the image
beginDrawingFromPoint(roi,[0,0])
end
end
This is the answer of MATLAB support team and it works fine.
If so, you should Accept-click the answer.

Sign in to comment.

More Answers (1)

You can fall back to imrect, if necessary
fcn = makeConstrainToRectFcn('imrect',get(gca,'XLim'),get(gca,'YLim'));
h=imrect('PositionConstraintFcn',fcn)

Products

Release

R2021b

Asked:

gil
on 18 Oct 2021

Edited:

on 3 Nov 2021

Community Treasure Hunt

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

Start Hunting!