Stacked image plot with custom x-axis help

2 visualizaciones (últimos 30 días)
Duane
Duane el 15 de Feb. de 2024
Editada: Sameer el 26 de Mzo. de 2024
Dear Sirs,
I am working on a utility that will plot a stack of identically-sized RGB images, and allow the user to zoom and pan the set as a group.
Both x and y axes have a relationship to linear distance, and I would like that to be reflected in the numeric tick-marks in the plot, but so far I have not found a satisfactory solution.
I have tried building the stack with image(...) calls, which gives me a stack that zooms/pans properly in pixels, but I don't know how to display distances on the x-axis. If I use imshow(image, 'XData', ...) the plots are compressed in the x-direction (as if it is taking the numerical value, and using that in pixels), but I think it is still zooming/panning OK.
Ideally, I'd like the tool-tip to report the modified X value as well, and draw a vertical line through all plots of the stack. My code is below:
function showImages(sampleImage)
% from phantom data calibrated
scaleFactor = 0.0578; % mm/pixel
% For labelling
fullImageWidth = size(sampleImage, 2);
fullImageWidthPixels = 1:fullImageWidth;
fullImageWidthmm = zeros(1, fullImageWidth);
flippedPixels = fliplr(fullImageWidthPixels);
if rem(fullImageWidth, 2) == 0
% width is even pixels, so dividing by 2 will yield whole
% numbers
fullImageWidthmm(1:fullImageWidth/2) = flippedPixels((fullImageWidth/2)+1:end) * -scaleFactor;
fullImageWidthmm(fullImageWidth/2 + 1: end) = fullImageWidthPixels(1:fullImageWidth/2) * scaleFactor;
else
fullImageWidthmm(1:(fullImageWidth - 1)/2) = flippedPixels((fullImageWidth/2)+1:end) * -scaleFactor;
fullImageWidthmm((fullImageWidth + 1)/2:end) = fullImageWidthPixels(1:fullImageWidth/2) * scaleFactor;
end
% plot stack of images
figure();
t=tiledlayout('vertical','TileSpacing','tight','Padding','tight');
for i=1:5
h(i)=nexttile();
imshow(sampleImage, 'XData', fullImageWidthmm);
%image(sampleImage);
end
axis on;
% make all plots scale together
linkaxes(h);
end
I have attached a sample image.
Thanks!
Duane

Respuesta aceptada

Sameer
Sameer el 26 de Mzo. de 2024
Editada: Sameer el 26 de Mzo. de 2024
Hi Duane,
From my understanding, you are working on a project to create a utility that can display a stack of RGB images of the same size, with functionality for zooming and panning across the entire stack simultaneously. You want the x and y axes to accurately reflect linear distances. You've experimented with using image(...) for building the stack, which works for zooming and panning but doesn't allow for accurate distance representation on the x-axis. Attempting to use imshow(...) resulted in images being compressed in the x-direction.
Your approach to displaying the images with spatial scaling on the x-axis is fundamentally correct, However, there appears to be a slight confusion in the way ‘imshow’ interprets the 'XData' and 'YData' parameters, leading to the compression issue you observed.
When you use ‘imshow(image, 'XData', [xmin xmax], 'YData', [ymin ymax]) ’, MATLAB scales the x-axis and y-axis of the displayed image to cover the range specified by [xmin xmax] and [ymin ymax], respectively. This means if your x-axis values (in your case, ‘fullImageWidthmm’) do not match the pixel width of the image, imshow will stretch or compress the image to fit into the specified x-axis range.
To ensure your images are displayed correctly without compression and with the correct spatial scaling on the x-axis, you should ensure that the range specified by ‘fullImageWidthmm’ exactly matches the physical size of your image. From your description, it seems you would like to convert pixel dimensions to millimeters using the scaleFactor.
Here's a revised approach to ensure the images are displayed correctly with spatial scaling:
  1. Correct Calculation of fullImageWidthmm: You've calculated fullImageWidthmm to represent the physical size of the image in millimeters. Ensure this calculation correctly reflects the physical size of your image from one side to the other.
  2. Use imshow with Correctly Calculated 'XData' and 'YData': When you use imshow, ensure that the range you specify in 'XData' accurately reflects the physical size of the image.
Here's a simplified version of your function with corrections and clarifications:
function showImages(sampleImage)
scaleFactor = 0.0578; % mm/pixel
% Calculate the physical size of the image in millimeters
imageWidthPixels = size(sampleImage, 2);
imageHeightPixels = size(sampleImage, 1);
imageWidthmm = imageWidthPixels * scaleFactor;
imageHeightmm = imageHeightPixels * scaleFactor;
% Define the spatial extent of the image
xData = [0 imageWidthmm]; % Starting from 0 to the width in mm
yData = [0 imageHeightmm]; % Starting from 0 to the height in mm
% Plot stack of images
figure();
t = tiledlayout('vertical', 'TileSpacing', 'tight', 'Padding', 'tight');
for i = 1:5
h(i) = nexttile();
imshow(sampleImage, 'XData', xData, 'YData', yData);
axis on; % Show axis
end
% Make all plots scale together
linkaxes(h, 'xy');
end
This function assumes you start the physical dimensions from 0 to the width/height in millimeters, but you can adjust xData and yData as needed based on your specific requirements.
I hope this helps!
Sameer

Más respuestas (0)

Categorías

Más información sobre Specifying Target for Graphics Output en Help Center y File Exchange.

Productos


Versión

R2023b

Community Treasure Hunt

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

Start Hunting!

Translated by