2D matrix resize or interpolation
Afficher commentaires plus anciens
Hello,
I'm new to matlab and I'm not sure what would be the best way to do the following.
I have an image/data matrix, I, of size (rows,cols) = (y,x) = [384,512].
The spatial resolution in the x direction is 0.078021 cm (total span is ~40cm)
The spatial resolution in the y direction is 0.078021 (total span is ~30cm)
Q1.
If I would like to have a finer sampling of the data by doubling the samples (eg Inew = [768, 1024], which function would you suggest?
Q2.
If I had another separate image but with offset x,y values, how would I interpolate this data onto the same grid as the other matrix?
Thank you for your help,
RR
ps. I found some info on the interp2 function? not sure if this is the best function to use?
ps. I have attached a zip file with
- dicom image (of a radiotherapy dose on a single plane - my image)
- excel workbook with the data extracted
- an m script with what I tried to do but I got an error
Error using griddedInterpolant
The grid must be created from grid vectors which are strictly monotonically increasing.
Error in interp2>makegriddedinterp (line 228)
F = griddedInterpolant(varargin{:});
Error in interp2 (line 136)
F = makegriddedinterp(X, Y, V, method,extrap);
Error in LoadDosePlaneBailey2D (line 70)
Id_cgy_q = interp2(X,Y,Id_cgy,Xq,Yq);
Réponses (3)
Cris LaPierre
le 10 Jan 2025
Modifié(e) : Cris LaPierre
le 10 Jan 2025
0 votes
Q2: What type of images are you working with? Please share an example. You can attach images to your post using the paperclip icon.
16 commentaires
Russell
le 10 Jan 2025
It looks like the pixel info and spreadsheet data are the same.
unzip('SampleFiles.zip')
% Use medical imaging toolbox
MI = medicalImage('ExampleDicomFileDosePlane.dcm')
img = extractFrame(MI,1);
imshow(img,[])
% Resize
B1 = imresize(img,[798,1024]);
figure
imshow(B1,[])
Neither of these approaches take into consideration the actual pixel spacing. Instead, row/col index number is used. To display an image where the X and Y spacing is different, use the XData and YData inputs to imshow.
figure
ext = (size(img)-1).*MI.PixelSpacing
imshow(B1,[],"XData",[0 ext(2)],"YData",[0 ext(1)])
It's subtle, but you can compare the difference using imshowpair
RA = imref2d(size(img));
RB = imref2d(size(img),MI.PixelSpacing(2),MI.PixelSpacing(1));
imshowpair(img,RA,img,RB,'montage')
You could just as easily use the spreadsheet values. However, you lose the metadata information, which captures the pixel spacing.
dose = readmatrix('ExampleTxtDataOfDosePlane.xlsx');
imshow(dose,[])
B2 = imresize(dose,[768, 1024]);
figure
imshow(B2,[],"XData",[0 ext(2)],"YData",[0 ext(1)])
Russell
le 10 Jan 2025
Russell
le 10 Jan 2025
Cris LaPierre
le 10 Jan 2025
medicalImage is part of the Medical Imaging Toolbox. It sounds like you haven't installed it. If it is included on your license, you can install it using the Add-Ons Explorer.
Russell
le 15 Jan 2025
Cris LaPierre
le 15 Jan 2025
Try zipping your second image and attaching it.
Russell
le 22 Jan 2025
Cris LaPierre
le 22 Jan 2025
You talk about images, but are sharing text files. Do you have actual images?
Russell
le 23 Jan 2025
Cris LaPierre
le 23 Jan 2025
If your images are dicoms, there is metadata that might make this process easier.
Russell
le 23 Jan 2025
Modifié(e) : Walter Roberson
le 23 Jan 2025
Cris LaPierre
le 24 Jan 2025
Just confirming that you are working with dxf files, not dicoms, correct?
I'm confused because the most common dxf file is an AutoCAD drawing file.
Russell
le 24 Jan 2025
Cris LaPierre
le 26 Jan 2025
Modifié(e) : Cris LaPierre
le 27 Jan 2025
I'm defnitely not an expert in this space, so I'm still confused. Based on the metadata in the dsf files
- Image_measured_30x40.dxf is actually 21.5x28.7
- Image_prediction1_43x43.dxf is actually 31.1x31.1
- Image_prediction2_30x40.dxf is actually 21.4x28.5
It looks like you have a 2-step process - first to extract the desired region using indexing, then resizing. Given that, I think the best approachis to use imresize on the extracted iage. Pick the approprite method for your task.
Heres a function that will read in your dxf files. Not necessarily the best code, but does the job.
unzip Image_prediction1_43x43.zip
params = readDXF('Image_prediction1_43x43.dxf');
figure
imagesc(params.Pixels)
Xsz = params.Size1*params.Res1
Ysz = params.Size2*params.Res2
function data = readDXF(fname)
data = struct;
fid = fopen(fname);
while ~feof(fid)
ln = fgetl(fid);
[param,val] = strtok(ln,"=");
switch param
case {'[General]','[Geometry]','[Interpretation]','[Patient]','[Field]','[PortalDose]'}
continue
case '[Data]'
fseek(fid,0,'eof');
fgetl(fid);
otherwise
val = strtok(val,'=');
pat = asManyOfPattern(characterListPattern("0123456789-+."));
nums = extract(val,pat);
if length(val)==length(nums{1})
data.(param) = str2double(val);
else
data.(param) = val;
end
end
end
fclose(fid);
val = readmatrix(fname,'FileType','text','NumHeaderLines',48);
data.Pixels = val;
end
Walter Roberson
le 10 Jan 2025
0 votes
If I would like to have a finer sampling of the data by doubling the samples (eg Inew = [768, 1024], which function would you suggest?
If you were willing to have Inew = [767, 1023] instead of [768, 1024] then you can average adjacent rows and adjacent columns and manually insert the averaged values into the proper place. To be honest, though, calling interp2() is a heck of a lot easier.
The reason the output would be Inew = [767, 1023] instead of [768, 1024] is that you would be calculating new points between each existing point. If you had 3 points across then you have 2 intermediate points, for a total of 5. Calculating intermediate points gets you output of size 2*N-1 not output of size 2*N
Getting output exactly twice the original size requires interpolation at "just less than half" apart, like positions 1, 1.49, 1.98, 2.47,...
9 commentaires
Russell
le 10 Jan 2025
Russell
le 10 Jan 2025
If you want the same pixel values in the two pixels, then use the 'nearest' option of imresize. If you don't specify then I believe it uses bicubic interpolation.
img = [1,2,3,4;5,6,7,8]
img2 = imresize(img, 2, 'nearest')
img3 = imresize(img, 2)
Note how it's handling the edge effects -- essentially the pixel value in your top row (1 in my example) is considered in the middle of the upsampled version (your row 2) so that's why in the bicubic version the leftmost is not exactly 1.
Russell
le 10 Jan 2025
img = uint8([1,2,3,4;5,6,7,8])
img3 = imresize(img, 2)
img4 = cast(imresize(double(img),2),'uint8')
Russell
le 14 Jan 2025
Modifié(e) : Walter Roberson
le 14 Jan 2025
Walter Roberson
le 14 Jan 2025
Yes. However, to double the resolution, xq would need to be
linspace(x(1), x(end), 2*(x(end)-x(1)+1))
which would be
linspace(1, 768, 2*768)
This will not be [1, 1.5, 2, 2.5, 3, 3.5, ...] -- instead it will be [[1, 2302/1535, 3069/1535, 3836/1535, 4603/1535 ...] or roughly [1, 1.49967426710098, 1.99934853420195, 2.49902280130293, 2.99869706840391, ...]
Russell
le 14 Jan 2025
Russell
le 15 Jan 2025
Catégories
En savoir plus sur Matrix Indexing dans Centre d'aide et File Exchange
Community Treasure Hunt
Find the treasures in MATLAB Central and discover how the community can help you!
Start Hunting!








