Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Texture mapping in MATLAB

I have points in 3D space and their corresponding 2D image points. How can I make a mesh out of the 3D points, then texture the triangle faces formed by the mesh?

like image 855
Venus Avatar asked Mar 21 '10 18:03

Venus


People also ask

What do you understand by the term texture mapping?

Texture mapping is a graphic design process in which a two-dimensional (2-D) surface, called a texture map, is "wrapped around" a three-dimensional (3-D)object. Thus, the 3-D object acquires a surface texture similar to that of the 2-D surface.

How do I use Imread in Matlab?

A = imread( filename ) reads the image from the file specified by filename , inferring the format of the file from its contents. If filename is a multi-image file, then imread reads the first image in the file.

How do you warp an image in Matlab?

B = warp( w , A ) performs the geometrical transformation defined in w on input image A and returns the warped image in B .


1 Answers

Note that the function trisurf that you were originally trying to use returns a handle to a patch object. If you look at the 'FaceColor' property for patch objects, you can see that there is no 'texturemap' option. That option is only valid for the 'FaceColor' property of surface objects. You will therefore have to find a way to plot your triangular surface as a surface object instead of a patch object. Here are two ways to approach this:

If your data is in a uniform grid...

If the coordinates of your surface data represent a uniform grid such that z is a rectangular set of points that span from xmin to xmax in the x-axis and ymin to ymax in the y-axis, you can plot it using surf instead of trisurf:

Z = ...  % N-by-M matrix of data
x = linspace(xmin, xmax, size(Z, 2));  % x-coordinates for columns of Z
y = linspace(ymin, ymax, size(Z, 1));  % y-coordinates for rows of Z
[X, Y] = meshgrid(x, y);               % Create meshes for x and y
C = imread('image1.jpg');              % Load RGB image
h = surf(X, Y, Z, flipdim(C, 1), ...   % Plot surface (flips rows of C, if needed)
         'FaceColor', 'texturemap', ...
         'EdgeColor', 'none');
axis equal

In order to illustrate the results of the above code, I initialized the data as Z = peaks;, used the built-in sample image 'peppers.png', and set the x and y values to span from 1 to 16. This resulted in the following texture-mapped surface:

enter image description here

If your data is non-uniformly spaced...

If your data are not regularly spaced, you can create a set of regularly-spaced X and Y coordinates (as I did above using meshgrid) and then use one of the functions griddata or TriScatteredInterp to interpolate a regular grid of Z values from your irregular set of z values. I discuss how to use these two functions in my answer to another SO question. Here's a refined version of the code you posted using TriScatteredInterp (Note: as of R2013a scatteredInterpolant is the recommended alternative):

x = ...  % Scattered x data
y = ...  % Scattered y data
z = ...  % Scattered z data
xmin = min(x);
xmax = max(x);
ymin = min(y);
ymax = max(y);
F = TriScatteredInterp(x(:), y(:), z(:));  % Create interpolant
N = 50;  % Number of y values in uniform grid
M = 50;  % Number of x values in uniform grid
xu = linspace(xmin, xmax, M);         % Uniform x-coordinates
yu = linspace(ymin, ymax, N);         % Uniform y-coordinates
[X, Y] = meshgrid(xu, yu);            % Create meshes for xu and yu
Z = F(X, Y);                          % Evaluate interpolant (N-by-M matrix)
C = imread('image1.jpg');             % Load RGB image
h = surf(X, Y, Z, flipdim(C, 1), ...  % Plot surface
         'FaceColor', 'texturemap', ...
         'EdgeColor', 'none');
axis equal

In this case, you have to first choose the values of N and M for the size of your matrix Z. In order to illustrate the results of the above code, I initialized the data for x, y, and z as follows and used the built-in sample image 'peppers.png':

x = rand(1, 100)-0.5;  % 100 random values in the range -0.5 to 0.5
y = rand(1, 100)-0.5;  % 100 random values in the range -0.5 to 0.5
z = exp(-(x.^2+y.^2)./0.125);  % Values from a 2-D Gaussian distribution

This resulted in the following texture-mapped surface:

enter image description here

Notice that there are jagged edges near the corners of the surface. These are places where there were too few points for TriScatteredInterp to adequately fit an interpolated surface. The Z values at these points are therefore nan, resulting in the surface point not being plotted.

like image 84
gnovice Avatar answered Nov 15 '22 21:11

gnovice