Unable to display cropped image in the image axes properly

Hi,
I have a Matlab GUI where I load two sets of images in 2 separate image axes. I use a Slider to browse through the images simultaneously. Images displayed in image axes 1 are the original images. Images displayed in image axes 2 are the segmented images. I use a CROP button which would crop the image in image axes1 and display the resultant image in image axes 2 thus overriding the previously saved segmented image in image axes2. However, when I click the CROP button, the resultant image is displayed in Image axes 1 instead of being shown in image axes2. Please note that the CROP button uses the drawfreehand() function which crops the image displayed in image axes 1 manually. Any suggestions would be appreciated.
function pushbutton3_Callback(hObject, eventdata, handles)
% hObject handle to pushbutton3 (see GCBO)
% eventdata reserved - to be defined in a future version of MATLAB
% handles structure with handles and user data (see GUIDATA)
handles = guidata(hObject);
seg=handles.seg;
value=handles.value;
corr_image = handles.InputImage;
hr=corr_image{value};
MM=drawfreehand(handles.axes1);
M = MM.createMask();
imshow(imcrop(M),'parent',handles.axes2);
handles.seg{value}=seg;
guidata(hObject, handles);
h1 = msgbox('Finished correction images');
uiwait(h1,1)
close (h1)
end

 Accepted Answer

I'm not sure if you realize that you're starting an interactive imcrop() session.
imshow(imcrop(M),'parent',handles.axes2);
When you do this, the current axes is axes1. Running imcrop(M) will start an interactive cropping session in axes1. Once the user completes the selection and commits, the cropped image will be passed to imshow(), which will display it in axes2. If you want to start the interactive selection in axes2, you can do that a number of ways:
imshow(M,'parent',handles.axes2);
imshow(imcrop(handles.axes2),'parent',handles.axes2);
If you intend to automatically crop the image to the extent of the ROI bounding box, that's a different story.
M = MM.createMask();
S = regionprops(M,'boundingbox');
% assuming there's only one object in the mask
M = imcrop(M,S(1).BoundingBox + [-1 -1 1 1]); % use a bit of padding
imshow(M,'parent',handles.axes2);
It's also not really clear why you want to display a cropped copy of the ROI mask instead of the source.

7 Comments

Hi @DGM,
i tried the above process but I get the following error:
Error in
matlab.graphics.internal.figfile.FigFile/read>@(hObject,eventdata)trnew('pushbutton2_Callback',hObject,eventdata,guidata(hObject))
Error while evaluating UIControl Callback.
Unable to resolve the name MM.createMask.
Error in trnew>pushbutton3_Callback (line 248)
M = MM.createMask();
Error in gui_mainfcn (line 95)
feval(varargin{:});
Error in trnew (line 42)
gui_mainfcn(gui_State, varargin{:});
Error in
matlab.graphics.internal.figfile.FigFile/read>@(hObject,eventdata)trnew('pushbutton3_Callback',hObject,eventdata,guidata(hObject))
Error while evaluating UIControl Callback.
The original images are displayed in image axes 1. The images displayed in the image axes 2 are the result of segmentations on image axes1(region growing algorithm). By using the CROP button, I want to manually perform the segmentation(on the images displayed in image axes1) if the results displayed in the image axes 2 initially are not correct.
After you've used drawfreehand to create some arbitrarily-shaped binary image mask M, how exactly do you want to crop it? Interactively, or crop it to the bounding box? And why? Maybe you don't need to crop it, unless you just want to display it larger in an axes so it's easier to see.
"i tried the above process ..."
... Which one, and how exactly? I suggested two different approaches, one to perform interactive cropping in axes2 and display the result in axes2, and the other to perform automatic cropping and display the result in axes2. I have to ask, because neither one changes this line:
M = MM.createMask();
which is part of the original preceding code. I don't know how you're getting an error when both suggested edits only change code that would be executed after the point at which the error is occurring.
I'm assuming you misinterpreted the scope of what I was suggesting to edit, so I'll just be more explicit in both cases. There may yet be other issues, but let's try to make sure we're at least on the same page so to speak:
For interactive cropping and display in axes2:
% ...
MM=drawfreehand(handles.axes1); % existing code
M = MM.createMask(); % existing code
imshow(M,'parent',handles.axes2);
imshow(imcrop(handles.axes2),'parent',handles.axes2);
handles.seg{value}=seg; % existing code
guidata(hObject, handles); % existing code
% ...
For automatic cropping, with display in axes2:
% ...
MM=drawfreehand(handles.axes1); % existing code
M = MM.createMask(); % existing code
S = regionprops(M,'boundingbox');
M = imcrop(M,S(1).BoundingBox + [-1 -1 1 1]);
imshow(M,'parent',handles.axes2);
handles.seg{value}=seg; % existing code
guidata(hObject, handles); % existing code
% ...
I have to point out that I haven't tested these within the larger scope of your GUI code. I don't know if there are other errors in the surrounding code. There are some path assumptions and other issues with trying to get it to run that I tend to shrug off as unrelated to the question at hand. I merely tested this in a simplified setup using two simple axes in a figure. There's plenty of probability that I'm missing other code issues that are related.
For what it's worth, this is what I used for testing:
clc; clf; clear variables
ip = imread('cameraman.tif');
% set up axes and handles vector
subplot(2,1,1); h(1) = gca;
subplot(2,1,2); h(2) = gca;
% put an image in axes1
subplot(2,1,1); imshow(ip);
MM=drawfreehand(h(1));
M = MM.createMask();
% example 1
%imshow(M,'parent',handles.axes2);
%imshow(imcrop(handles.axes2),'parent',handles.axes2);
% example 2
S = regionprops(M,'boundingbox');
M = imcrop(M,S.BoundingBox + [-1 -1 1 1]);
imshow(M,'parent',h(2));
By cropping, I was trying to extract the ROI from the original image and display it in a separate image axes. The new image axes should only contain the extracted ROI. All the other background would be black.
If you want to display a cropped copy of the ROI of the original image, you can do something like this:
clc; clf; clear variables
ip = imread('cameraman.tif');
% set up axes and handles vector
subplot(2,1,1); h(1) = gca;
subplot(2,1,2); h(2) = gca;
% put an image in axes1
subplot(2,1,1); imshow(255-ip);
MM=drawfreehand(h(1));
M = MM.createMask();
S = regionprops(M,'boundingbox');
maskedimage = cast(double(ip).*M,class(ip)); % apply the mask to the image
maskedimage = imcrop(maskedimage,S.BoundingBox + [-1 -1 1 1]); % crop masked image
imshow(maskedimage,'parent',h(2));
This is based on the second (automatic) example in my standalone test code, but can be extended to either.
Hi @DGM,
That worked perfectly. Thank you.

Sign in to comment.

More Answers (0)

Categories

Find more on Interactive Control and Callbacks in Help Center and File Exchange

Products

Release

R2020b

Asked:

on 23 Jul 2021

Commented:

on 24 Jul 2021

Community Treasure Hunt

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

Start Hunting!