Interpolate matrix to same size matrix

Hello, I have a matrix of mostly zeros
X =
0 0 0 0 0 0 0 0 0 0
0 10 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 7 0 0
0 0 0 0 0 0 0 0 10 0
0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0
0 0 0 0 9 8 0 0 0 0
I'd like to keep the non-zero values, but have them spread out to its neighbors in a gradual fashion. The method I use does not really matter, just as long as it creates a gradual peak in a surf plot. Ideally, I would like to be able to change how gradually it spreads (the sigma in a gaussian filter for example). When I used gaussian filters, the value of the original value changes.
Y =
0.1134 0.8382 0.1134 0 0 0 0 0 0 0
0.8382 6.1935 0.8382 0 0 0 0.0794 0.5867 0.0794 0
0.1134 0.8382 0.1134 0 0 0 0.5867 4.4489 1.4249 0.1134
0 0 0 0 0 0 0.0794 1.4249 6.2729 0.8382
0 0 0 0 0 0 0 0.1134 0.8382 0.1134
0 0 0 0.1021 0.8451 0.7726 0.0907 0 0 0
0 0 0 0.8565 7.0898 6.4818 0.7613 0 0 0
This is essentially what I want, but with the original value remaining the same. I tried also interp2 which works well also but the matrix dimensions change. Please let me know if you have a solution. Thanks a lot!

Answers (3)

Jan
Jan on 27 Oct 2016
Edited: Jan on 27 Oct 2016
You can simply overwrite the non-zero values afterwards:
Y(X ~= 0) = X(X ~= 0);
You could simply replace the lower values with the original ones?
A = ... % original matrix with zeros
B = ... smoothed version of A
tf = A~=0 ;
B(tf) = A(tf)

1 Comment

I tried this, but if I overwrite, then the surrounding values are already too small. So in a surf plot, it will look like a very pointy peak and then a gradual decline. I'd like the gradual decline to start from the top.

Sign in to comment.

You can use imresize() or conv2() depending on exactly what you want to do.

3 Comments

But the non-zero values spread out from each other and the matrix enlarges that way. imgaussfilt works very well in my case except that it decreases my original value. Is there any 2D filter that retains the original value and averages values starting from the original values' surroundings? I don't know if that makes sense.
No. You can blur the points with conv2, but this will reduce the center point. If you just replace the center point afterwards, you'll have a big spike on a low blurry hump, like you said. The only way is to blur each region independently and then normalize it. You can find each independent region with bwlabel. So then you'd loop over each region, blurring and normalizing and adding to an accumulation image. Like
[labeledRegions, numRegions] = bwlabel(yourMatrix, 4);
for r = 1 : numRegions
binaryImage = ismember(yourMatrix, r);
thisRegion = binaryImage .* yourMatrix;
% Now blur this region with imgausfilt()
blurredMatrix = imgaussfilt(....You do this...........
% Get the max original value
maxOriginalValue = max(yourMatrix(binaryImage));
% Get the blurred max
maxBlurred = max(blurredMatrix(:));
% Scale it
blurredMatrix = blurredMatrix * maxOriginalValue / maxBlurred;
% Assign it to our final image.
finalImage(binaryImage) = blurredMatrix(binaryImage);
end
This is untested, just off the top of my head so you may need to do debugging.
Thanks a lot for your help. So I played around with it and I've gotten it to work just fine. Values that are next to each other are not scaled correctly, because they are recognized as one region collectively with bwlabel. If you have a solution for this please do let me know!
% %yourMatrix = X (my matrix of values)
finalImage=zeros(7,10);%dimensions of whatever matrix I'm using
[labeledRegions, numRegions] = bwlabel(yourMatrix, 4);
for r = 1 : numRegions
binaryImage = ismember(labeledRegions, r);
thisRegion = binaryImage.*yourMatrix;
% Now blur this region with imgausfilt()
blurredMatrix = imgaussfilt(thisRegion, 7);
% Get the max original value
maxOriginalValue = max(yourMatrix(binaryImage));
% Get the blurred max
maxBlurred = max(blurredMatrix(binaryImage));
% Scale it
blurredMatrix = blurredMatrix * maxOriginalValue / maxBlurred;
% Assign it to our final image. take the average of the values within
% the submatrix and the finalImage
[labeledRegions2, numRegions2] = bwlabel(blurredMatrix, 4);
binaryImage2 = ismember(labeledRegions2, 1);
A = (finalImage(binaryImage2) + blurredMatrix(binaryImage2))/2;
submatrix = reshape(A, max(sum(binaryImage2)), max(sum(binaryImage2')));
finalImage(binaryImage2) = submatrix;
end
before averaging
after averaging
It's not perfect, but It's kind of what I'm going for and my real data will not have so many values on top of each other in any case.
thanks!

Sign in to comment.

Asked:

on 27 Oct 2016

Edited:

on 31 Oct 2016

Community Treasure Hunt

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

Start Hunting!