Moving ROIs within images and across images

I have a code where I read in two images and display it side-by-side. I draw a region of interest within the first image, and the region is automatically shown on the second image. When I move the rectangle to another region within the first image, only that rectangle moves (not the second image's rectangle). How can I fix this so that when I move the first rectangle, the second move moves to the same position as well.
What I have now
% Read images
I = imread('cameraman.tif');
I2 = imread('cameraman.tif');
% plot image 1 & draw a rectangular ROI on images
subplot(1,2,1); imshow(I);
roi = drawrectangle('LineWidth',2,'Color','white');
subplot(1,2,2); imshow(I2);
roi2 = drawrectangle(gca,'Position',roi.Position);
% set up listeners for ROI moving events
addlistener(roi,'MovingROI',@allevents);
addlistener(roi,'ROIMoved',@allevents);
% allevents callback function displays the previous position & the current position of the ROI
function allevents(~,evt)
evname = evt.EventName;
switch(evname)
case{'MovingROI'}
disp(['ROI moving previous position: ' mat2str(evt.PreviousPosition)]);
disp(['ROI moving current position: ' mat2str(evt.CurrentPosition)]);
case{'ROIMoved'}
disp(['ROI moved previous position: ' mat2str(evt.PreviousPosition)]);
disp(['ROI moved current position: ' mat2str(evt.CurrentPosition)]);
end
end

 Accepted Answer

Ameer Hamza
Ameer Hamza on 11 Nov 2020
Edited: Ameer Hamza on 11 Nov 2020
Currently, your event lister function is just priting the values. You need to set the position too. Try following code
% Read images
I = imread('cameraman.tif');
I2 = imread('cameraman.tif');
% plot image 1 & draw a rectangular ROI on images
subplot(1,2,1); imshow(I);
roi = drawrectangle('LineWidth',2,'Color','white');
subplot(1,2,2); imshow(I2);
roi2 = drawrectangle(gca,'Position',roi.Position);
% set up listeners for ROI moving events
addlistener(roi,'MovingROI',@(r1,evt) allevents(r1,evt,roi2));
addlistener(roi,'ROIMoved',@(r1,evt) allevents(r1,evt,roi2));
% allevents callback function displays the previous position & the current position of the ROI
function allevents(roi1,evt,roi2)
evname = evt.EventName;
roi2.Position = roi1.Position;
switch(evname)
case{'MovingROI'}
disp(['ROI moving previous position: ' mat2str(evt.PreviousPosition)]);
disp(['ROI moving current position: ' mat2str(evt.CurrentPosition)]);
case{'ROIMoved'}
disp(['ROI moved previous position: ' mat2str(evt.PreviousPosition)]);
disp(['ROI moved current position: ' mat2str(evt.CurrentPosition)]);
end
end
Or a simpler solution using linkprop()
% Read images
I = imread('cameraman.tif');
I2 = imread('cameraman.tif');
% plot image 1 & draw a rectangular ROI on images
subplot(1,2,1); imshow(I);
roi = drawrectangle('LineWidth',2,'Color','white');
subplot(1,2,2); imshow(I2);
roi2 = drawrectangle(gca,'Position',roi.Position);
linkprop([roi, roi2], 'Position')

15 Comments

This is perfect! Thank you! Although both solutions work, I chose the second one because it is simpler!
I am glad to be of help! :)
I guess 2nd solution will also be more efficient.
Another modification: what if I want two window for the two images but still link areas across?
Something like this
% Read images
I = imread('cameraman.tif');
I2 = imread('cameraman.tif');
% plot image 1 & draw a rectangular ROI on images
subplot(1,2,1); imshow(I);
roi11 = drawrectangle('LineWidth',2,'Color','white');
roi12 = drawrectangle('LineWidth',2,'Color','white');
subplot(1,2,2); imshow(I2);
roi21 = drawrectangle(gca,'Position',roi11.Position);
roi22 = drawrectangle(gca,'Position',roi12.Position);
hl1 = linkprop([roi11, roi21], 'Position')
hl2 = linkprop([roi12, roi22], 'Position')
As in separate window figures instead of subplot. I tried using the following code, but once I move the rectangle, it does not move in the other two figures.
% Read images
I = imread('cameraman.tif');
I2 = imread('cameraman.tif');
I3 = imread('cameraman.tif');
% plot image 1 & draw a rectangular ROI on images
% subplot(1,3,1); imshow(I);
figure, imshow(I);
roi = drawrectangle('LineWidth',2,'Color','white');
% subplot(1,3,2); imshow(I2);
figure, imshow(I2);
roi2 = drawrectangle(gca,'Position',roi.Position);
% subplot(1,3,3); imshow(I3);
figure, imshow(I3);
roi3 = drawrectangle(gca,'Position',roi.Position);
linkprop([roi, roi2, roi3], 'Position')
This code works fine in R2020b. All rectanges move simultaneously. There might be some issue related to R2019b.
Thank you so much!!! Since I am using the MATLAB Online, it is probably not showing up correctly. Thank you for answering my questions!
How are you using MATLAB R2019b in MATLAB online? I tried this code in MATLAB online too and it works fine.
I got it to work! Thank you!
Can matlab zoom into my region of interest rather than showing the entire image for all images on one separate window (2 subplots)?
For example, I have this for now. But when I change the position of the rectangle, the subplots do not change.
% read three images
I = imread('cameraman.tif');
I2 = imread('cameraman.tif');
% show first image & draw a rectangular ROI on image
figure, imshow(I);
title('cameraman.tif', 'FontSize', 9);
roi = drawrectangle('LineWidth',2,'Color','white');
% zoom in on those ROIs for each picture
I_roi = I(roi.Position(2):(roi.Position(2)+roi.Position(4)),roi.Position(1):(roi.Position(1)+roi.Position(3)),:); % store roi in matrix
I2_roi = I2(roi.Position(2):(roi.Position(2)+roi.Position(4)),roi.Position(1):(roi.Position(1)+roi.Position(3)),:);
% show the images as a subplot
figure;
subplot(1,2,1); imshow(I_roi);
subplot(1,2,2); imshow(I2_roi);
% link rectangular ROIs across the images
linkprop(roi, 'Position');
You need to use event listeners for this
% read three images
I = imread('cameraman.tif');
I2 = imread('cameraman.tif');
% show first image & draw a rectangular ROI on image
figure, imshow(I);
title('cameraman.tif', 'FontSize', 9);
roi = drawrectangle('LineWidth',2,'Color','white');
% zoom in on those ROIs for each picture
I_roi = imcrop(I, roi.Position); % store roi in matrix
I2_roi = imcrop(I, roi.Position);
% show the images as a subplot
figure;
ax1 = subplot(1,2,1); imshow(I_roi);
ax2 = subplot(1,2,2); imshow(I2_roi);
% set up listeners for ROI moving events
addlistener(roi,'MovingROI',@(r1,evt) allevents(r1,evt,I,ax1,ax2));
addlistener(roi,'ROIMoved',@(r1,evt) allevents(r1,evt,I,ax1,ax2));
% allevents callback function displays the previous position & the current position of the ROI
function allevents(roi,evt,I,ax1,ax2)
rect = roi.Position;
im_ = imcrop(I, rect);
imshow(im_, 'Parent', ax1)
imshow(im_, 'Parent', ax2)
end
I'm really sorry for asking so many questions! I'm still learning MATLAB. I'm trying to use this code to look at specific areas of Whole Slide Images. When I move the ROI rectangle, the first image (zoomed in version) replaces the second subplot and the third subplot. Is there a way to fix this?
For example the three regions are
When I move the region, it becomes this
% select three tif files that corresponds to the same case
[file1,path1] = uigetfile('*.tif');
[file2,path2] = uigetfile('*.tif');
[file3,path3] = uigetfile('*.tif');
if isequal(file1,0) || isequal(file2,0) || isequal(file3,0)
disp('User selected Cancel');
else
% read three images
I = imread(fullfile(path1,file1));
I2 = imread(fullfile(path2,file2));
I3 = imread(fullfile(path3,file3));
% show first image & draw a rectangular ROI on image
figure, imshow(I);
% title('cameraman.tif', 'FontSize', 9);
roi = drawrectangle('LineWidth',2,'Color','white');
% zoom in on those ROIs for each picture
I_roi = imcrop(I, roi.Position); % store roi in matrix
I2_roi = imcrop(I2, roi.Position);
I3_roi = imcrop(I3, roi.Position);
% show the images as a subplot
figure;
ax1 = subplot(1,3,1); imshow(I_roi);
ax2 = subplot(1,3,2); imshow(I2_roi);
ax3 = subplot(1,3,3); imshow(I3_roi);
% set up listeners for ROI moving events
addlistener(roi,'MovingROI',@(r1,evt) allevents(r1,evt,I,ax1,ax2,ax3));
addlistener(roi,'ROIMoved',@(r1,evt) allevents(r1,evt,I,ax1,ax2,ax3));
end
% allevents callback function displays the previous position & the current position of the ROI
function allevents(roi,~,I,ax1,ax2,ax3)
rect = roi.Position;
im_ = imcrop(I, rect);
imshow(im_, 'Parent', ax1)
imshow(im_, 'Parent', ax2)
imshow(im_, 'Parent', ax3)
end
You need to pass all three images to the event function
function allevents(roi,~,I,I2,I3,ax1,ax2,ax3)
rect = roi.Position;
imshow(imcrop(I, rect), 'Parent', ax1)
imshow(imcrop(I2, rect), 'Parent', ax2)
imshow(imcrop(I3, rect), 'Parent', ax3)
end
and change event listener line to
% set up listeners for ROI moving events
addlistener(roi,'MovingROI',@(r1,evt) allevents(r1,evt,I,I2,I3,ax1,ax2,ax3));
addlistener(roi,'ROIMoved',@(r1,evt) allevents(r1,evt,I,I2,I3,ax1,ax2,ax3));
Thank you! That works!
I added titles to each subplot. However, when I move the ROIs to another area, the title disappears.
Is there a way to keep the title on top of the image at all times?
% select three tif files that corresponds to the same case
[file1,path1] = uigetfile('*.tif');
[file2,path2] = uigetfile('*.tif');
[file3,path3] = uigetfile('*.tif');
if isequal(file1,0) || isequal(file2,0) || isequal(file3,0)
disp('User selected Cancel');
else
% read three images
I = imread(fullfile(path1,file1));
I2 = imread(fullfile(path2,file2));
I3 = imread(fullfile(path3,file3));
% show first image & draw a rectangular ROI on image
figure, imshow(I); title(file1,'Interpreter','none');
roi = drawrectangle('LineWidth',1,'Color','white');
% zoom in on those ROIs for each picture
I_roi = imcrop(I, roi.Position); % store roi in matrix
I2_roi = imcrop(I2, roi.Position);
I3_roi = imcrop(I3, roi.Position);
% show the images as a subplot
fig = figure;
pos_fig = [0 0 1920 1080];
set(fig, 'Position', pos_fig)
ax1 = subplot(1,3,1); imshow(I_roi); th1 = title(file1, 'FontSize', 7, 'Interpreter','none');
ax2 = subplot(1,3,2); imshow(I2_roi); th2 = title(file2, 'FontSize', 7, 'Interpreter','none');
ax3 = subplot(1,3,3); imshow(I3_roi); th3 = title(file3, 'FontSize', 7, 'Interpreter','none');
% set up listeners for ROI moving events
addlistener(roi,'MovingROI',@(r1,evt) allevents(r1,evt,I,I2,I3,ax1,ax2,ax3));
addlistener(roi,'ROIMoved',@(r1,evt) allevents(r1,evt,I,I2,I3,ax1,ax2,ax3));
end
% allevents callback function displays the previous position & the current position of the ROI
function allevents(roi,~,I,I2,I3,ax1,ax2,ax3)
rect = roi.Position;
imshow(imcrop(I, rect), 'Parent', ax1)
imshow(imcrop(I2, rect), 'Parent', ax2)
imshow(imcrop(I3, rect), 'Parent', ax3)
end
Try this definition of event callback function
function allevents(roi,~,I,I2,I3,ax1,ax2,ax3)
rect = roi.Position;
ax1.Children.CData = imcrop(I, rect); axis(ax1, 'auto');
ax2.Children.CData = imcrop(I2, rect); axis(ax2, 'auto');
ax3.Children.CData = imcrop(I3, rect); axis(ax3, 'auto');
end
Thank you so much! It works!

Sign in to comment.

More Answers (1)

Thanks everyone that contributed.
please may i know if it is possible to get the pixel values in the defined roi and calculate the mean value.
Thanks in advace

2 Comments

Yes
croppedImage = imcrop(originalImage, roi.Position); % Get values in the rectangle.
meanValue = mean2(croppedImage)
Thanks so much Image Analyst. It works fine.
However, I am not sure why is not working with circular roi "drawcircle"
Many thanks

Sign in to comment.

Products

Release

R2019b

Community Treasure Hunt

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

Start Hunting!