In my last post I described how to create a powerful, nondirectional shading for a geophysical surface using the slope of the data to assign the shading intensity (i.e. areas of greater slope are assigned darker shading). Today I will show hot to create a similar effect in Matlab.
Since the data set I use is from my unpublished thesis in Geology, I am not able to share it, and you will have to use your own data, but the Matlab code is simply adapted. The code snippets below assume you have a geophysical surface already imported in the workspace and stored in a variable called “data”, as well as the derivative in a variable called “data_slope”.
Method 1 – with a slope mask and transparency
Some time ago I read this interesting Image Processing blog post by Steve Eddins at Mathworks on overlaying images using transparency. I encourage readers to take a look at this and other posts by Steve, he’s great! That particular blog post gave me the idea to use transparency and the slope to create my favorite shading in Matlab.
%% alpha transparency code snippet black = cat(3, zeros(size(data)), zeros(size(data)), ... zeros(size(data))); % make a truecolor all-black image gray=black+0.2; % make a truecolor all-gray image alphaI=normalise(data_slope); % create transparency weight matrix % using data_slope imagesc(data);colormap(cube1); % display data hold on h = imagesc(gray); % overlay gray image on data hold off set(h, 'AlphaData', alphaI); % set transparency of gray layer using axis equal; % weight matrix axis tight; axis off;
And here is the result in Figure 1 below – not bad!
Figure 1. Shaded using transparency
Method 2 – using Shaded Pseudo Color
%% shadedpcolor code snippet figure; shadedpcolor(xe,ye,data,(1-normalise(data_slope)),[-5.9834 2.9969], ... [0 1],0.55,cube1,0); axis equal; axis off; axis tight shadedcolorbar([-5.9834 2.9969],0.55,cube1);
The result is in Figure 2. This really looks good. I favor this over the code above it now all the time because it allows greater flexibility (for example shading brightness adjustment), and because it creates a shaded colorbar for you.
Figure 2. Shaded using shadedpcolor
Method 3: 3D
I am trying to write some code to use transparency to apply he shading with the surf command. Another option to generate a real 3D effect much like the one shown in the last post in Surfer I use imageshiny.m, a function by Gordon Cooper available on the Matlab File Exchange. This function will create both a 2D map like the ones above and a 3D map. The 3D map for the gravity data is shown below in Figure 3.
Notice that for imageshiny to work properly you will have to replace all instances of imshow with imagesc in the code if you do not have the Image Processing Toolbox.
Figure 3. Plotted and shaded using imageshiny
It is actually very interesting to look at the ingenious solution the author of imageshiny came up with to assign the shading. When you run imageshiny, each pixel in the surface is assigned simultaneously color and shading. This is done by generating a new matrix of HSV triplets (refer to wikipedia for a review of HSV and HSL) using the data directly: the hue H is assigned with the data (normalized to the interval 0.5 to 1 so as to translate in the color range green to red); saturation S and value V are both assigned using the slope (imageshiny calculates it for you on the fly). The new matrix HSV is then converted to a matrix of RGB triplets, and the latter is used to color the surface when using the surf command. Here below is the relevant code, modified to facilitate reading (data* is the normalized data, slope* is the calculated slope, to distinguish from the variables in my code snippets above):
HSV(:,:,1)=1-data*; HSV(:,:,2)=1-slope*; HSV(:,:,3)=slope*; RGB=hsv2rgb(HSV); figure; clf; surf(data,RGB);axis off; axis tight; shading flat; view(5,85);
I am currently experimenting to see if I can make this function work with different hue combinations.
I am still working at figuring out the right approach and write my own code to drape contours over the surface in 3D. This is actually possible using the Matlab function contour3m, but you need the Mapping Toolbox.