Re-run section of code when rectangle selection is resized

4 次查看(过去 30 天)
I have thermal camera footage that consists of a few hundred frames saved as individual .mat files that contain temperature arrays. I want to run the code below. First, I visualize a particular frame using imagesc. I use drawrectangle to crop the image to a designated ROI of temperatures, then use that position to crop the rest of my frames. I do some math to the "cropped" array values, then display one of the altered frames as another color-scaled image. At this point, I want to be able to click back to my first figure window, make small adjustments to the size of the original ROI, and have the script run through again with the new region to produce an updated final image. I have to be able to see this final, representative image in order to know how much to adjust the ROI. Right now, I'm just running the script over and over again until I'm happy with the crop region. Any ideas?
N = %total number of frames
h = load(['frame100.mat']);
figure
imagesc(h.Frame) % "Frame" is 480x640 double array within the struct "h"
colormap jet
hold on
roi = drawrectangle('Color','w');
z = [1 N-1];
crop = [roi.Position(1) roi.Position(2) z(1) roi.Position(3) roi.Position(4) z(2)];
for i = 0:N
load(['frame' num2str(i) '.mat']);
frames(:,:,i+1) = Frame;
end
croppedFrames = imcrop3(frames,crop);
%
% Do some math to the array values
%
% Display representative altered region of same original frame
representativeFrame = alteredFrames(:,:,100);
figure
imagesc(representativeFrame)
colormap jet
%
% Here is the point at which I want to resize the ROI and have everything up to this point update based on the new array values.
%
%
% More script I want to run after ROI is finalized

采纳的回答

Yash
Yash 2023-9-5
Thankyou for providing me with the necessary scipts and mat files. I reviewed your code and mat files and I'm able to get the desired result that you expected to obtain.
They are a certain changes I've made to your code and I'll be walking you through these changes.
  • Followed a Object Oriented Approach rather than a Procedural Approach since many data has to be communicated between various functions.
  • The class ImageProcessor has certain properties: M, N, z, roi, frames etc..
  • The ImageProcessor class extends the handle class to achive pass-by-reference instead of pass-by-value
  • The constructor of this class initalizes these variables and loads the necessary mat files into frames. It also plots the initial figure.
  • Two uibutton have been implemented to support the necessary features.
  • Each button has been associated with a callback to update the ROI of the image and to process data.
  • The Process data button performs the final calculation.
  • Necessary comments have been added to the script to help you with understanding of the code.
You can run the script with the help of the command below:
obj = ImageProcessor(5);
I have attached the script with this answer and also the necessary resources can be found below:
I hope this helps.
  1 个评论
Maddie Kern
Maddie Kern 2023-9-5
This works brilliantly! I've not used most of these functions in MATLAB, so this is very informative. Thank you so much for all your time and help.

请先登录,再进行评论。

更多回答(1 个)

Yash
Yash 2023-9-1
To achieve the functionality you described, where you can interactively adjust the ROI and have the script update accordingly, you can use a combination of waitfor and callbacks in MATLAB. Here's how you can modify your code to implement this behavior:
N = %total number of frames
h = load(['frame100.mat']);
figure
imagesc(h.Frame) % "Frame" is 480x640 double array within the struct "h"
colormap jet
hold on
roi = drawrectangle('Color','w');
z = [1 N-1];
crop = [roi.Position(1) roi.Position(2) z(1) roi.Position(3) roi.Position(4) z(2)];
% Initialize variable to keep track of ROI change
roiChanged = false;
% Set up a button callback function
function updateROIButtonCallback(~, ~)
% Update the crop parameters based on the new ROI position
crop = [roi.Position(1) roi.Position(2) z(1) roi.Position(3) roi.Position(4) z(2)];
% Signal that ROI has changed
roiChanged = true;
% Close the figure
close(gcf);
end
% Add a button to update ROI with the callback to updateROIButtonCallback
updateButton = uicontrol('Style', 'pushbutton', 'String', 'Update ROI', ...
'Position', [10 10 100 30], 'Callback', @updateROIButtonCallback);
% Wait for the user to interact with the ROI and click the update button
waitfor(updateButton, 'UserData');
if roiChanged
% Loop over frames and perform necessary operations
frames = zeros([size(h.Frame), N]);
for i = 0:N
load(['frame' num2str(i) '.mat']);
frames(:,:,i+1) = Frame;
end
croppedFrames = imcrop3(frames,crop);
% Perform the rest of your calculations
% Display the altered frame
representativeFrame = alteredFrames(:,:,100);
figure
imagesc(representativeFrame)
colormap jet
end
% More script you want to run after ROI is finalized
In this code, a button named "Update ROI" is added to the figure window that allows you to manually trigger the update of the ROI and subsequent processing. The waitfor function waits for a UI event, in this case, clicking the button, before continuing with the script. The UserData property is set to signal that the button has been clicked. This way, you can adjust the ROI in the first figure window, click the "Update ROI" button, and then the script will proceed with the updated ROI and display the final result.
I hope this helps.
  3 个评论
Yash
Yash 2023-9-2
编辑:Yash 2023-9-2
It seems like there might be an issue with the scope of the roi variable within the callback function. To resolve this issue, you can use the gcf (get current figure) and findobj functions to access the ROI within the callback function. Here's how you can modify the updateROIButtonCallback
function updateROIButtonCallback(~, ~)
% Get the current figure
fig = gcf;
% Find the ROI within the current figure
roi = findobj(fig, 'Type', 'images.roi.rectangle');
% Check if ROI exists
if ~isempty(roi)
% Update the crop parameters based on the new ROI position
crop = [roi.Position(1) roi.Position(2) z(1) roi.Position(3) roi.Position(4) z(2)];
% Signal that ROI has changed
roiChanged = true;
% Close the figure
close(fig);
else
% Handle the case when ROI is not found
disp('ROI not found');
end
end
Well, this is one fo the many ways to handle the scope of the roi variable. You can also try other approaches such as
  1. using global keyword to make the roi variable globally available.
  2. by passing the roi as an arguement to the updateROIButtonCallback.
It would also be helpful if you could share your data files, that would help me in delivering better code quality.
I hope this helps.
Maddie Kern
Maddie Kern 2023-9-4
Hi Yash, you've been very helpful so far. I still can't get the code to work. I'll attach my files. script1.m is my original code that does exactly what I need it to, but requires me to constantly re-run the whole thing to adjust the original ROI. It is after line 53 in this script that I would like to then go back and adjust the ROI on Figure 1 and have it update Figures 2 & 3 accordingly. script2.m is a copy with the changes you've suggested so far. A sample of the .mat files used in the scripts are in the zipped folder so you can run the code.

请先登录,再进行评论。

产品


版本

R2023a

Community Treasure Hunt

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

Start Hunting!

Translated by