MATLAB pcolor/surf bilinear interpolation (shading interp)
Asked Answered
H

1

8

Consider the following MATLAB code:

C = [ 0 0 0 0 0
      0 1 2 1 0
      0 2 4 2 0
      0 1 2 1 0
      0 0 0 0 0 ];
pcolor( C );
shading interp;
axis square

Note that C is invariant under 90 degree rotations. Also note this sentence from the help for pcolor:

With shading interp, each cell is colored by bilinear interpolation of the colors at its four vertices, using all elements of C.

However, the plotted image is as follows:

CodeOutput

Note that the image is not invariant under 90 degree rotations (consider e.g. the four corners). Now, unless I horribly misunderstand bilinear interpolation, this must be wrong. MATLAB seems to be interpolating on triangles, which is not the same as bilinear interpolation.

Is there any way of working round this MATLAB bug, and getting correct bilinear interpolation? (Other than manually interpolating additional points myself, which still would not cure the issue if one zoomed in far enough.)

Hyams answered 18/11, 2017 at 15:32 Comment(4)
Interesting to note that this gives the exact same coloring as surf(C); shading('interp'); view(2);Meredith
Yes. It's clearly forming a grid of triangles. Some MATLAB programmer didn't understand what bilinear interpolation is.Hyams
Do I understand correctly: you don't want to use the resulting figure just for illustration purposes (so you could just interpolate yourself and use a 300dpi png of reasonable size), but rather do some further analysis on it? If so, I'd say you should give latex/tikz a try. Have you considered it?Jamilla
I am after a publication quality image. So I would rather save in a vector format and be sure that it's going to scale arbitrarily well. This is not actually targeting LaTeX, though MATLAB's EPS/PDF output is actually more of a pain than its EMF/SVG output. In any case, however the figure is exported (even if e.g. matlab2tikz is used), it will preserve the incorrect interpolation.Hyams
B
1

I remember having read a few threads concerning this weird behavior in the official Matlab forums, in the past. Unfortunately, I found none right now with a quick search. Anyway... you aren't the first used pointing out that shading interp, used in combination with with pcolor, behaves in a weird manner, creating shapes that don't reflect the underlying data.

The main problem is that shading interp interpolates between data points without caring about how sensible your grid is to smoothing. If you want a result that doesn't look jagged, you have to provide data sampled at a higher resolution:

C = [
    0 0 0 0 0
    0 1 2 1 0
    0 2 4 2 0
    0 1 2 1 0
    0 0 0 0 0
];
C = interp2(C,5,'cubic');

pcolor(C);
shading interp;
axis square;

This produces an amazing result, and the output doesn't show any artifact or asymmetry:

Output

Bushing answered 18/11, 2017 at 18:5 Comment(3)
OP: "Other than manually interpolating additional points myself, which still would not cure the issue if one zoomed in far enough."Meredith
This is the solution I had resorted to independently. But it's far from ideal. For one thing, saving as SVG/EMF produces very poor results with such fine grids, generating huge files, with many artefacts (e.g. white lines).Hyams
Run the following code and look at the two generated files. For me, the EMF has a vertical white line in the middle (and if you use interp2(C,5) it has many such lines). The SVG shows clear triangles. C = [ 0 0 0 0 0; 0 1 2 1 0; 0 2 4 2 0; 0 1 2 1 0; 0 0 0 0 0 ]; C = interp2(C,3); pcolor(C); shading interp; axis square; colormap( parula( 2 ^ 16 ) ); drawnow; saveas( gcf, 'out.emf' ); saveas( gcf, 'out.svg' );Hyams

© 2022 - 2025 — McMap. All rights reserved.