gml_Morph.h

Go to the documentation of this file.
00001 /**
00002  * @file gml_Morph.h
00003  *
00004  *  Utilities for scanners which perform morphological operations
00005  *  or convolutions.
00006  *
00007  * Copyright (c) 2004 CLIPS-IMAG
00008  *
00009  * See the file "gml_LicenseTerms.txt" for information on usage and redistribution
00010  * of this file, and for a DISCLAIMER OF ALL WARRANTIES.
00011  *
00012  *  Created on January 14, 2004 (JL).
00013  */
00014 
00015 #ifndef __GML_MORPH__
00016 #define __GML_MORPH__
00017 
00018 #include <assert.h>
00019 
00020 #include "gml/base/gml_Types.h"
00021 #include "gml/math/gml_Math.h"
00022 
00023 ///
00024 /// gml_TNeighborhood --
00025 ///   A structured type for 3x3 pixel neighborhoods.
00026 ///
00027 struct gml_TNeighborhood
00028 {
00029   union { UInt32 un; struct { UInt32 p0 : 8; UInt32 nw : 8; UInt32 n  : 8; UInt32 ne : 8; }; };
00030   union { UInt32 uc; struct { UInt32 p1 : 8; UInt32 w  : 8; UInt32 c  : 8; UInt32 e  : 8; }; };
00031   union { UInt32 us; struct { UInt32 p2 : 8; UInt32 sw : 8; UInt32 s  : 8; UInt32 se : 8; }; };
00032 };
00033 
00034 
00035 ///
00036 /// gml_Shift --
00037 ///   Shift neighborhood <nb> to the west, and push in the <n>, <c> and <s> values
00038 ///   in the newly empty north, center and south slots.
00039 ///
00040 inline static 
00041 void gml_Shift (gml_TNeighborhood &nb, const UInt32 n, const UInt32 c, const UInt32 s)
00042 {
00043   nb.un = ((nb.un & 0x00FFFFFF) << 8) | n;
00044   nb.uc = ((nb.uc & 0x00FFFFFF) << 8) | c;
00045   nb.us = ((nb.us & 0x00FFFFFF) << 8) | s;
00046 }
00047 
00048 
00049 ///
00050 /// gml_Apply --
00051 ///   Multiply the terms of <nb> by those of <kernel>, divide the result by <weight>
00052 ///   and return the result.
00053 ///
00054 inline static 
00055 UInt8 gml_Apply (const gml_TNeighborhood nb, const gml_TNeighborhood kernel, const UInt16 weight)
00056 {
00057   return (
00058       nb.nw * (SInt16) kernel.nw 
00059     + nb.n  * (SInt16) kernel.n
00060     + nb.ne * (SInt16) kernel.ne
00061     + nb.w  * (SInt16) kernel.w
00062     + nb.c  * (SInt16) kernel.c
00063     + nb.e  * (SInt16) kernel.e
00064     + nb.sw * (SInt16) kernel.sw
00065     + nb.s  * (SInt16) kernel.s
00066     + nb.se * (SInt16) kernel.se
00067     ) / weight;
00068 } 
00069 
00070 
00071 ///
00072 /// gml_Zero --
00073 ///   Zeroes the given neighborhood.
00074 ///
00075 inline static
00076 void gml_Zero (gml_TNeighborhood &nb)
00077 {
00078   nb.un = 0;
00079   nb.uc = 0;
00080   nb.us = 0;
00081 }
00082 
00083 ///
00084 /// gml_Morph_GaussianBlur --
00085 ///   Apply the 3x3 gaussian blur kernel to <nb>
00086 ///
00087 inline static 
00088 UInt8 gml_Morph_GaussianBlur (const gml_TNeighborhood nb)
00089 {
00090   return (
00091     (nb.nw + nb.ne + nb.sw + nb.se) + 
00092     ((nb.n + nb.e + nb.w + nb.s) << 1) + 
00093     (nb.c << 2)
00094     ) >> 4;
00095 }
00096 
00097 
00098 ///
00099 /// gml_Morph_Dilate_Gray --
00100 ///   Apply the 3x3 dilation operator to <nb>
00101 ///
00102 inline static 
00103 UInt8 gml_Morph_Dilate_Gray (const gml_TNeighborhood nb)
00104 {
00105   return Max (
00106     Max (nb.nw, nb.n, nb.ne),
00107     Max (nb.w,  nb.c, nb.e ),
00108     Max (nb.sw, nb.s, nb.se)
00109     );
00110 } 
00111 
00112 
00113 ///
00114 /// gml_Morph_Erode_Gray --
00115 ///   Apply the 3x3 erosion operator to <nb>
00116 ///
00117 inline static 
00118 UInt8 gml_Morph_Erode_Gray (const gml_TNeighborhood nb)
00119 {
00120   return Min (
00121     Min (nb.nw, nb.n, nb.ne),
00122     Min (nb.w,  nb.c, nb.e ),
00123     Min (nb.sw, nb.s, nb.se)
00124     );
00125 } 
00126 
00127 
00128 ///
00129 /// gml_Morph_Dilate_Binary --
00130 ///   Apply the 3x3 dilation operator to <nb>
00131 ///
00132 inline static 
00133 UInt8 gml_Morph_Dilate_Binary (const gml_TNeighborhood nb)
00134 {
00135   return nb.nw | nb.n | nb.ne | nb.w | nb.c | nb.e | nb.sw | nb.s | nb.se ;
00136 } 
00137 
00138 
00139 ///
00140 /// gml_Morph_Erode_Binary --
00141 ///   Apply the 3x3 erosion operator to <nb>
00142 ///
00143 inline static 
00144 UInt8 gml_Morph_Erode_Binary (const gml_TNeighborhood nb)
00145 {
00146   return nb.nw & nb.n & nb.ne & nb.w & nb.c & nb.e & nb.sw & nb.s & nb.se ;
00147 } 
00148 
00149 
00150 
00151 ///
00152 /// gml_Morph_SobelX --
00153 ///   Apply the 3x3 horizontal sobel operator to <nb>
00154 ///
00155 inline static 
00156 UInt8 gml_Morph_SobelX (const gml_TNeighborhood nb)
00157 {
00158   return ((
00159     -1 * nb.nw + 0 * nb.n + 1 * nb.ne +
00160     -2 * nb.w  + 0 * nb.c + 2 * nb.e  +
00161     -1 * nb.sw + 0 * nb.s + 1 * nb.se
00162   ) >> 3)
00163   + 127;
00164 } 
00165 
00166 
00167 ///
00168 /// gml_Morph_SobelY --
00169 ///   Apply the 3x3 horizontal sobel operator to <nb>
00170 ///
00171 inline static 
00172 UInt8 gml_Morph_SobelY (const gml_TNeighborhood nb)
00173 {
00174   return ((
00175     -1 * nb.nw + -2 * nb.n + -1 * nb.ne +
00176      0 * nb.w  +  0 * nb.c +  0 * nb.e  +
00177      1 * nb.sw +  2 * nb.s +  1 * nb.se
00178   ) >> 3)
00179   + 127;
00180 } 
00181 
00182 
00183 ///
00184 /// gml_Morph_EdgeX --
00185 ///   Apply the 3x3 horizontal sobel operator to <nb>
00186 ///
00187 inline static 
00188 UInt8 gml_Morph_EdgeX (const gml_TNeighborhood nb)
00189 {
00190   return ((
00191     -2 * nb.nw + 2 * nb.n + 0 * nb.ne +
00192     -2 * nb.w  + 2 * nb.c + 0 * nb.e  +
00193      0 * nb.sw + 0 * nb.s + 0 * nb.se
00194   ) >> 3)
00195   + 127;
00196 } 
00197 
00198 
00199 ///
00200 /// gml_Morph_EdgeY --
00201 ///   Apply the 3x3 horizontal sobel operator to <nb>
00202 ///
00203 inline static 
00204 UInt8 gml_Morph_EdgeY (const gml_TNeighborhood nb)
00205 {
00206   return ((
00207     -2 * nb.nw + -2 * nb.n + 0 * nb.ne +
00208      2 * nb.w  +  2 * nb.c + 0 * nb.e  +
00209      0 * nb.sw +  0 * nb.s + 0 * nb.se
00210   ) >> 3)
00211   + 127;
00212 }
00213 
00214 ///
00215 /// gml_Morph_AbsSobelX --
00216 ///   Apply the 3x3 horizontal absolute sobel operator to <nb>
00217 ///
00218 inline static 
00219 UInt8 gml_Morph_AbsSobelX (const gml_TNeighborhood nb)
00220 {
00221   return labs (
00222     (nb.ne - nb.nw) +
00223     2 * (nb.e - nb.w) +
00224     (nb.se - nb.sw)
00225   ) >> 2;
00226 } 
00227 
00228 
00229 ///
00230 /// gml_Morph_AbsSobelY --
00231 ///   Apply the 3x3 horizontal absolute sobel operator to <nb>
00232 ///
00233 inline static 
00234 UInt8 gml_Morph_AbsSobelY (const gml_TNeighborhood nb)
00235 {
00236   return labs ( 
00237     (nb.sw - nb.nw) +
00238     2 * (nb.s - nb.n) +
00239     (nb.se - nb.ne)
00240   ) >> 2;
00241 } 
00242 
00243 
00244 ///
00245 /// gml_Morph_ConservativeSmooth --
00246 ///   Return the value of <nb>'s center coefficient clamped between the minimum
00247 ///   and maximum values of its neighbors
00248 ///
00249 inline static 
00250 UInt8 gml_Morph_ConservativeSmooth (const gml_TNeighborhood nb)
00251 {
00252   UInt8 min = 
00253     Min (
00254       Min (Min (nb.nw, nb.n), Min (nb.ne, nb.e)),
00255       Min (Min (nb.se, nb.s), Min (nb.sw, nb.w))
00256     );
00257   UInt8 max = 
00258     Max (
00259       Max (Max (nb.nw, nb.n), Max (nb.ne, nb.e)),
00260       Max (Max (nb.se, nb.s), Max (nb.sw, nb.w))
00261     );
00262   return Clamp (nb.c, (UInt32) min, (UInt32) max);
00263 } 
00264 
00265 inline static
00266 void gml_SortTwoBytes (UInt8 &b0, UInt8 &b1)
00267 {
00268   UInt8 r0 = Min (b0, b1);
00269   UInt8 r1 = Max (b0, b1);
00270   b0 = r0;
00271   b1 = r1;
00272 }
00273 
00274 ///
00275 /// gml_Morph_Median_bin --
00276 ///   Return the neighborhood median value.
00277 ///   Uses no branching (simple bubble sort).
00278 ///
00279 inline static 
00280 UInt8 gml_Morph_Median_bin (const gml_TNeighborhood nb)
00281 {
00282   UInt8 cond = 
00283     ((nb.nw + 1) >> 8) +
00284     ((nb.n  + 1) >> 8) +
00285     ((nb.ne + 1) >> 8) +
00286     ((nb.w  + 1) >> 8) +
00287     ((nb.e  + 1) >> 8) +
00288     ((nb.sw + 1) >> 8) +
00289     ((nb.s  + 1) >> 8) +
00290     ((nb.se + 1) >> 8);
00291   return (cond > 3) ? 0xFF : 0x00;
00292 }
00293 
00294 ///
00295 /// gml_Morph_Median --
00296 ///   Return the neighborhood median value.
00297 ///   Uses no branching (simple bubble sort).
00298 ///
00299 inline static 
00300 UInt8 gml_Morph_Median (const gml_TNeighborhood nb)
00301 {
00302   UInt8 a0 = nb.nw;
00303   UInt8 a1 = nb.n;
00304   UInt8 a2 = nb.ne;
00305   UInt8 a3 = nb.w;
00306   UInt8 a4 = nb.c;
00307   UInt8 a5 = nb.e;
00308   UInt8 a6 = nb.sw;
00309   UInt8 a7 = nb.s;
00310   UInt8 a8 = nb.se;
00311   
00312   gml_SortTwoBytes (a0, a1);
00313   gml_SortTwoBytes (a2, a3);
00314   gml_SortTwoBytes (a4, a5);
00315   gml_SortTwoBytes (a6, a7);
00316   gml_SortTwoBytes (a1, a2);
00317   gml_SortTwoBytes (a3, a4);
00318   gml_SortTwoBytes (a5, a6);
00319   gml_SortTwoBytes (a7, a8);
00320 
00321   gml_SortTwoBytes (a0, a1);
00322   gml_SortTwoBytes (a2, a3);
00323   gml_SortTwoBytes (a4, a5);
00324   gml_SortTwoBytes (a6, a7);
00325   gml_SortTwoBytes (a1, a2);
00326   gml_SortTwoBytes (a3, a4);
00327   gml_SortTwoBytes (a5, a6);
00328   gml_SortTwoBytes (a7, a8);
00329 
00330   gml_SortTwoBytes (a0, a1);
00331   gml_SortTwoBytes (a2, a3);
00332   gml_SortTwoBytes (a4, a5);
00333   gml_SortTwoBytes (a6, a7);
00334   gml_SortTwoBytes (a1, a2);
00335   gml_SortTwoBytes (a3, a4);
00336   gml_SortTwoBytes (a5, a6);
00337   gml_SortTwoBytes (a7, a8);
00338 
00339   gml_SortTwoBytes (a0, a1);
00340   gml_SortTwoBytes (a2, a3);
00341   gml_SortTwoBytes (a4, a5);
00342   gml_SortTwoBytes (a6, a7);
00343   gml_SortTwoBytes (a1, a2);
00344   gml_SortTwoBytes (a3, a4);
00345   gml_SortTwoBytes (a5, a6);
00346   gml_SortTwoBytes (a7, a8);
00347 
00348   return a4;
00349 }
00350 #endif /* __GML_MORPH__ */
00351 
Generated on Tue Jun 12 14:03:27 2007 for gml by Doxygen 1.5.2.