|
|
|
| |
Terrain Tutorial
Smoothing with a Matrix Filter
In the previous section, when smoothing a point, only one of its neighbours was taken into account. However there is no reason for this restriction. In fact in image processing smoothing usually takes into account a larger set of neighbours. A common way of specifying how each of the neighbours will affect the result is using a matrix. For instance a matrix 3x3 will take into account all the connecting neighbours.
The filter specified in the previous section can be defined using a matrix as follows:
m = [ 0 0 0
(1-k) k 0
0 0 0];
The center of the matrix relates to the point being smoothed, and the other values represent the contribution of the neighbours. In the general form, a 3x3 matrix will look like:
m = [ m11 m12 m13
m21 m22 m23
m31 m32 m33];
The computation of the new height for a grid point (x,z), h[x,z], using the matrix above results in:
h[x,z] = m11 * h[x-1,z-1] + m12 * h[x,z-1] + m13 * h[x+1,z-1] +
m21 * h[x-1,z] + m22 * h[x,z] + m23 * h[x+1,z] +
m31 * h[x-1,z+1] + m32 * h[x,z+1] + m33 * h[x+1,z+1];
The larger the matrix the larger the neighbourhood. For instance a 5x5 matrix can use up to 24 neighbours. Matrices can grow as large as you want, however for a terrain smoothing problem 5x5 seems to be enough. In the general case, if you don't want to change the overall height of the surface the components of the matrix should add up to 1.0
The following images shows the original terrain and the result of applying an average matrix 3x3 (i.e. all components equal and adding up to 1.0).
The matrix used is
m = [ 1/9 1/9 1/9
1/9 1/9 1/9
1/9 1/9 1/9];
The following figure shows the result using a 5x5 average matrix:
As you can see the 5x5 matrix produces a smoother terrain as expected.
There is just one problem to solve: what if using a matrix 3x3, the grid point you're smoothing is a border or corner point? Then the formula above will have missing points. A simple solution to the problem is to apply the matrix to the existing points in the terrain, and afterwards divide the result by the sum of the components used. This approach assumes that the sum of all the matrix components is 1.0. For instance for a corner point we'll have:
h[x,z] = m22 * h[x,z] + m23 * h[x+1,z] +
m32 * h[x,z+1] + m33 * h[x+1,z+1];
h[x,z] = h[x,z] / (m22 + m23 + m32 + m33)
|