aboutsummaryrefslogtreecommitdiff
path: root/Gem/cMatrix.html
diff options
context:
space:
mode:
authorTravis CI <zmoelnig@travis-ci.umlaeute.mur.at>2015-03-19 23:06:26 +0000
committerTravis CI <zmoelnig@travis-ci.umlaeute.mur.at>2015-03-19 23:06:26 +0000
commitbdae26678d39c83280ed5e353986705da6f423c5 (patch)
treea977d9c7a25b275245787de02830a05e30fa0fb9 /Gem/cMatrix.html
parent095b7e513f736567848173f2572d8b329ad75af9 (diff)
Gem 4990e2aec04f67a68fbd2878f4d99bb8042f68fa osx/x86_64
built 'master:4990e2aec04f67a68fbd2878f4d99bb8042f68fa' for osx/x86_64
Diffstat (limited to 'Gem/cMatrix.html')
-rw-r--r--Gem/cMatrix.html270
1 files changed, 270 insertions, 0 deletions
diff --git a/Gem/cMatrix.html b/Gem/cMatrix.html
new file mode 100644
index 0000000..fe4cd04
--- /dev/null
+++ b/Gem/cMatrix.html
@@ -0,0 +1,270 @@
+<html>
+<head>
+<title>Matrix Operations for Image Processing</title>
+</head>
+<body bgcolor="#ffffff" text="#000000">
+<!--no_print--><br><center><table width=564><tr><td>
+<h2>Matrix Operations for Image Processing</h2>
+<!--no_print--><h3>Paul Haeberli</h3>
+<h3>Nov 1993</h3>
+<img src=../tribar.gif alt="Horiz Bar" width=561 height=3>
+<h3>Introduction</h3>
+<p>
+Four by four matrices are commonly used to transform geometry for 3D
+rendering. These matrices may also be used to transform RGB colors, to scale
+RGB colors, and to control hue, saturation and contrast. The most important
+advantage of using matrices is that any number of color transformations
+can be composed using standard matrix multiplication.
+<p>
+Please note that for these operations to be correct, we really must operate
+on linear brightness values. If the input image is in a non-linear brightness
+space RGB colors must be transformed into a linear space before these
+matrix operations are used.
+
+<h3>Color Transformation</h3>
+RGB colors are transformed by a four by four matrix as shown here:
+
+<pre>
+ xformrgb(mat,r,g,b,tr,tg,tb)
+ float mat[4][4];
+ float r,g,b;
+ float *tr,*tg,*tb;
+ {
+ *tr = r*mat[0][0] + g*mat[1][0] +
+ b*mat[2][0] + mat[3][0];
+ *tg = r*mat[0][1] + g*mat[1][1] +
+ b*mat[2][1] + mat[3][1];
+ *tb = r*mat[0][2] + g*mat[1][2] +
+ b*mat[2][2] + mat[3][2];
+ }
+</pre>
+
+<h3>The Identity</h3>
+This is the identity matrix:
+<pre>
+ float mat[4][4] = {
+ 1.0, 0.0, 0.0, 0.0,
+ 0.0, 1.0, 0.0, 0.0,
+ 0.0, 0.0, 1.0, 0.0,
+ 0.0, 0.0, 0.0, 1.0,
+ };
+</pre>
+Transforming colors by the identity matrix will leave them unchanged.
+
+<h3>Changing Brightness</h3>
+To scale RGB colors a matrix like this is used:
+<pre>
+ float mat[4][4] = {
+ rscale, 0.0, 0.0, 0.0,
+ 0.0, gscale, 0.0, 0.0,
+ 0.0, 0.0, bscale, 0.0,
+ 0.0, 0.0, 0.0, 1.0,
+ };
+</pre>
+Where rscale, gscale, and bscale specify how much to scale the r, g, and b
+components of colors. This can be used to alter the color balance of an image.
+<p>
+In effect, this calculates:
+<pre>
+ tr = r*rscale;
+ tg = g*gscale;
+ tb = b*bscale;
+</pre>
+
+<h3>Modifying Saturation</h3>
+
+
+<h3>Converting to Luminance</h3>
+To convert a color image into a black and white image, this matrix is used:
+<pre>
+ float mat[4][4] = {
+ rwgt, rwgt, rwgt, 0.0,
+ gwgt, gwgt, gwgt, 0.0,
+ bwgt, bwgt, bwgt, 0.0,
+ 0.0, 0.0, 0.0, 1.0,
+ };
+</pre>
+Where rwgt is 0.3086, gwgt is 0.6094, and bwgt is 0.0820. This is the
+luminance vector. Notice here that we do not use the standard NTSC weights
+of 0.299, 0.587, and 0.114. The NTSC weights are only applicable to RGB
+colors in a gamma 2.2 color space. For linear RGB colors the values above
+are better.
+<p>
+In effect, this calculates:
+<pre>
+ tr = r*rwgt + g*gwgt + b*bwgt;
+ tg = r*rwgt + g*gwgt + b*bwgt;
+ tb = r*rwgt + g*gwgt + b*bwgt;
+</pre>
+
+<h3>Modifying Saturation</h3>
+
+To saturate RGB colors, this matrix is used:
+
+<pre>
+ float mat[4][4] = {
+ a, b, c, 0.0,
+ d, e, f, 0.0,
+ g, h, i, 0.0,
+ 0.0, 0.0, 0.0, 1.0,
+ };
+</pre>
+Where the constants are derived from the saturation value s
+as shown below:
+
+<pre>
+ a = (1.0-s)*rwgt + s;
+ b = (1.0-s)*rwgt;
+ c = (1.0-s)*rwgt;
+ d = (1.0-s)*gwgt;
+ e = (1.0-s)*gwgt + s;
+ f = (1.0-s)*gwgt;
+ g = (1.0-s)*bwgt;
+ h = (1.0-s)*bwgt;
+ i = (1.0-s)*bwgt + s;
+</pre>
+One nice property of this saturation matrix is that the luminance
+of input RGB colors is maintained. This matrix can also be used
+to complement the colors in an image by specifying a saturation
+value of -1.0.
+<p>
+Notice that when <code>s</code> is set to 0.0, the matrix is exactly
+the "convert to luminance" matrix described above. When <code>s</code>
+is set to 1.0 the matrix becomes the identity. All saturation matrices
+can be derived by interpolating between or extrapolating beyond these
+two matrices.
+<p>
+This is discussed in more detail in the note on
+<a href="../interp/index.html">Image Processing By Interpolation and Extrapolation</a>.
+<h3>Applying Offsets to Color Components</h3>
+To offset the r, g, and b components of colors in an image this matrix is used:
+<pre>
+ float mat[4][4] = {
+ 1.0, 0.0, 0.0, 0.0,
+ 0.0, 1.0, 0.0, 0.0,
+ 0.0, 0.0, 1.0, 0.0,
+ roffset,goffset,boffset,1.0,
+ };
+</pre>
+This can be used along with color scaling to alter the contrast of RGB
+images.
+
+<h3>Simple Hue Rotation</h3>
+To rotate the hue, we perform a 3D rotation of RGB colors about the diagonal
+vector [1.0 1.0 1.0]. The transformation matrix is derived as shown here:
+<p>
+ If we have functions:<br><br>
+<dl>
+<dt><code>identmat(mat)</code>
+<dd>that creates an identity matrix.
+</dl>
+<dl>
+<dt><code>xrotatemat(mat,rsin,rcos)</code>
+<dd>that multiplies a matrix that rotates about the x (red) axis.
+</dl>
+<dl>
+<dt><code>yrotatemat(mat,rsin,rcos)</code>
+<dd>that multiplies a matrix that rotates about the y (green) axis.
+</dl>
+<dl>
+<dt><code>zrotatemat(mat,rsin,rcos)</code>
+<dd>that multiplies a matrix that rotates about the z (blue) axis.
+</dl>
+Then a matrix that rotates about the 1.0,1.0,1.0 diagonal can be
+constructed like this:
+<br>
+First we make an identity matrix
+<pre>
+ identmat(mat);
+</pre>
+Rotate the grey vector into positive Z
+<pre>
+ mag = sqrt(2.0);
+ xrs = 1.0/mag;
+ xrc = 1.0/mag;
+ xrotatemat(mat,xrs,xrc);
+
+ mag = sqrt(3.0);
+ yrs = -1.0/mag;
+ yrc = sqrt(2.0)/mag;
+ yrotatemat(mat,yrs,yrc);
+</pre>
+Rotate the hue
+<pre>
+ zrs = sin(rot*PI/180.0);
+ zrc = cos(rot*PI/180.0);
+ zrotatemat(mat,zrs,zrc);
+</pre>
+Rotate the grey vector back into place
+<pre>
+ yrotatemat(mat,-yrs,yrc);
+ xrotatemat(mat,-xrs,xrc);
+</pre>
+The resulting matrix will rotate the hue of the input RGB colors. A rotation
+of 120.0 degrees will exactly map Red into Green, Green into Blue and
+Blue into Red. This transformation has one problem, however, the luminance
+of the input colors is not preserved. This can be fixed with the following
+refinement:
+
+<h3>Hue Rotation While Preserving Luminance</h3>
+
+We make an identity matrix
+<pre>
+ identmat(mmat);
+</pre>
+Rotate the grey vector into positive Z
+<pre>
+ mag = sqrt(2.0);
+ xrs = 1.0/mag;
+ xrc = 1.0/mag;
+ xrotatemat(mmat,xrs,xrc);
+ mag = sqrt(3.0);
+ yrs = -1.0/mag;
+ yrc = sqrt(2.0)/mag;
+ yrotatemat(mmat,yrs,yrc);
+ matrixmult(mmat,mat,mat);
+</pre>
+Shear the space to make the luminance plane horizontal
+<pre>
+ xformrgb(mmat,rwgt,gwgt,bwgt,&lx,&ly,&lz);
+ zsx = lx/lz;
+ zsy = ly/lz;
+ zshearmat(mat,zsx,zsy);
+</pre>
+Rotate the hue
+<pre>
+ zrs = sin(rot*PI/180.0);
+ zrc = cos(rot*PI/180.0);
+ zrotatemat(mat,zrs,zrc);
+</pre>
+Unshear the space to put the luminance plane back
+<pre>
+ zshearmat(mat,-zsx,-zsy);
+</pre>
+Rotate the grey vector back into place
+<pre>
+ yrotatemat(mat,-yrs,yrc);
+ xrotatemat(mat,-xrs,xrc);
+</pre>
+<h3>Conclusion</h3>
+I've presented several matrix transformations that may be applied
+to RGB colors. Each color transformation is represented by
+a 4 by 4 matrix, similar to matrices commonly used to transform 3D geometry.
+<p>
+<a href="matrix.c">Example C code</a>
+that demonstrates these concepts is provided for your enjoyment.
+<p>
+These transformations allow us to adjust image contrast, brightness, hue and
+saturation individually. In addition, color matrix transformations concatenate
+in a way similar to geometric transformations. Any sequence of
+operations can be combined into a single matrix using
+matrix multiplication.
+<!--no_print--><p>
+<!--no_print--><center>
+<!--no_print--><a href=../index.html#matrix><img src=../gobot.gif width=564 height=25 border=0></a>
+<!--no_print--><br>
+<!--no_print--></center>
+<!--no_print--></td></tr></table></center>
+</body>
+</html>
+