contrib/oul/ouml/image_ops.txx
Go to the documentation of this file.
00001 //-*-c++-*--------------------------------------------------------------
00002 #ifndef ouml_image_ops_txx_
00003 #define ouml_image_ops_txx_
00004 /**
00005  * \file
00006  *
00007  * The whole shebang. Hopefully this will find and track eyes
00008  * predominantly using eyespiders.
00009  * \author Brendan McCane
00010  * Copyright (c) 2000 Brendan McCane
00011  * University of Otago, Dunedin, New Zealand
00012  * Reproduction rights limited as described in the COPYRIGHT file.
00013  */
00014 //----------------------------------------------------------------------
00015 #include "image_ops.h"
00016 #include <vcl_cassert.h>
00017 
00018 //----------------------------------------------------------------------
00019 /** -= operator for images
00020  * 
00021  * An in place -= operator for images. Saves from having to copy any
00022  * data anywhere.
00023  *
00024  * \param im1: vil1_memory_image_of<T> &, the image to be modified
00025  * \param im2: vil1_memory_image_of<T> &, the image to subtract from
00026  * \return vil1_memory_image_of<T> &: a reference to im1
00027  *
00028  * \author Brendan McCane
00029  */
00030 //----------------------------------------------------------------------
00031 
00032 template <class T>
00033 vil1_memory_image_of<T> &operator -=
00034 (
00035   vil1_memory_image_of<T> &im1,
00036   vil1_memory_image_of<T> &im2
00037 )
00038 {
00039   assert(im1.width()==im2.width());
00040   assert(im1.height()==im2.height());
00041 
00042   // for efficiency considerations, instead of doing double
00043   // indirection each time a pixel needs to be accessed, access the
00044   // row of pixels for each y-value and then dereference and
00045   // increment these pointers as needed to access each pixel. I
00046   // realise this isn't exactly the best OO style, but efficiency is
00047   // probably very important here.
00048   T *im1_row, *im2_row; 
00049   int width = im1.width(), height = im1.height();
00050   for (int y=0; y<height; y++)
00051   {
00052     im1_row = im1[y];
00053     im2_row = im2[y];
00054     for (int x=0; x<width; x++)
00055     {
00056       (*im1_row) -= (*im2_row);
00057       im1_row++; im2_row++;
00058     }
00059   }
00060 
00061   return im1;
00062 }
00063 
00064 //----------------------------------------------------------------------
00065 /** += operator for images for adding a constant factor
00066  * 
00067  * An in place += operator for images. Saves from having to copy any
00068  * data anywhere.
00069  *
00070  * \param im1: vil1_memory_image_of<T> &, the image to be modified
00071  * \param constant_add: T, the amount to add to each pixel in the image
00072  * \return vil1_memory_image_of<T> &: a reference to im1
00073  *
00074  * \author Brendan McCane
00075  */
00076 //----------------------------------------------------------------------
00077 template <class T>
00078 vil1_memory_image_of<T> &operator +=
00079 (
00080   vil1_memory_image_of<T> &im1,
00081   T constant_add
00082 )
00083 {
00084   // for efficiency considerations, instead of doing double
00085   // indirection each time a pixel needs to be accessed, access the
00086   // row of pixels for each y-value and then dereference and
00087   // increment these pointers as needed to access each pixel. I
00088   // realise this isn't exactly the best OO style, but efficiency is
00089   // probably very important here.
00090   T *im1_row;
00091   int width = im1.width(), height = im1.height();
00092   for (int y=0; y<height; y++)
00093   {
00094     im1_row = im1[y];
00095     for (int x=0; x<width; x++)
00096     {
00097       (*im1_row) += constant_add;
00098       im1_row++; 
00099     }
00100   }
00101 
00102   return im1;
00103 }
00104 
00105 
00106 //----------------------------------------------------------------------
00107 /** threshold_abs
00108  * 
00109  * Threshold the passed in image but in an abs manner. That is, a
00110  * pixel is set if abs(x-y)>threshold. Pixels which satisfy the
00111  * condition are set to their corresponding counterparts in the
00112  * source_vals image, and pixels which fail the condition are set to
00113  * zero_val.
00114  *
00115  * \param image: vil1_memory_image_of<T> &, the image to be modified
00116  * \param source_vals: vil1_memory_image_of<T> &, the image to be modified
00117  * \param threshold: T, the threshold to apply
00118  * \param zero_val: T, the value to set the thresholded pixels to
00119  *
00120  * \author Brendan McCane */
00121 //----------------------------------------------------------------------
00122 
00123 template <class T> void threshold_abs
00124 (
00125   vil1_memory_image_of<T> &image, 
00126   vil1_memory_image_of<T> &source_vals,
00127   T threshold, T zero_val
00128 )
00129 {
00130   assert(image.width()==source_vals.width());
00131   assert(image.height()==source_vals.height());
00132   T *image_row, *src_row;
00133   int width = image.width(), height = image.height();
00134   for (int y=0; y<height; y++)
00135   {
00136     image_row = image[y];
00137     src_row = source_vals[y];
00138     for (int x=0; x<width; x++)
00139     {
00140       if (((*image_row)<threshold)&&((*image_row)>-threshold)) 
00141         *image_row = zero_val;
00142       else *image_row = *src_row;
00143       image_row++; src_row++;
00144     }
00145   }
00146 }
00147 
00148 /** max_val
00149  *
00150  * Return the maximum value for an image. Assumes that a < operator is
00151  * defined on the template parameter.
00152  *
00153  * \param vil1_memory_image_of<T> &image: the source image.
00154  *
00155  * \param T min: the minimum value to use to initialise the search. 
00156  * For unsigned chars this will probably be 0, but for signed ints it
00157  * might be -MAXINT, and for RGB could be rgb<0,0,0> etc.
00158  *
00159  * \return T: the maximum value found.
00160  */
00161 template <class T>
00162 T max_val(const vil1_memory_image_of<T> &image, T min)
00163 {
00164   T max = min;
00165   for (int x=0; x<image.width(); x++)
00166     for (int y=0; y<image.height(); y++)
00167       if (image(x,y)>max)
00168         max = image(x,y);
00169   return max;
00170 }
00171 
00172 /** min_val
00173  *
00174  * Return the minimum value for an image. Assumes that a < operator is
00175  * defined on the template parameter.
00176  *
00177  * \param vil1_memory_image_of<T> &image: the source image.
00178  *
00179  * \param T max: the maximum value to use to initialise the search. 
00180  * For unsigned chars this will probably be 255, but for signed ints it
00181  * might be MAXINT, and for RGB could be rgb<255,255,255> etc.
00182  *
00183  * \return T: the minimum value found.
00184  */
00185 template <class T>
00186 T min_val(const vil1_memory_image_of<T> &image, T max)
00187 {
00188   T min = max;
00189   for (int x=0; x<image.width(); x++)
00190     for (int y=0; y<image.height(); y++)
00191       if (image(x,y)<min)
00192         min = image(x,y);
00193   return min;
00194 }
00195 
00196 /** normalise_image
00197  *
00198  * Normalise an image so that the pixel values fit within the range
00199  * specified. This is useful for normalising prior to saving
00200  * int/double images. Can normalise to 0 to 255 and then save as a pgm
00201  * etc.
00202  *
00203  * \param vil1_memory_image_of<T> &src: the source image
00204  * \param T low: the minimum value to normalise to
00205  * \param T high: the maximum value to normalise to
00206  * \param T min: the smallest possible value of a T
00207  * \param T max: the largest possible value of a T
00208  * \param T epsilon: a small T. Needed for normalising floats etc as
00209  * numerical inaccuracy can cause the result to be slightly greater
00210  * than high.
00211  * \return vil1_memory_image_of<T> *: a new normalised image
00212  */
00213 
00214 template <class T> vil1_memory_image_of<T> *normalise_image
00215 (
00216   const vil1_memory_image_of<T> &src, 
00217   T low, T high,
00218   T min, T max,
00219   T epsilon
00220 )
00221 {
00222   assert(high>low);
00223   assert(max>min);
00224   vil1_memory_image_of<T> *ret = 
00225     new vil1_memory_image_of<T>(src.width(), src.height());
00226   T small = min_val(src, max);
00227   T large = max_val(src, min);
00228   double d1 = (double)(high-low);
00229   assert(d1>0);
00230   double d2 = (double)(large-small);
00231   assert(d2>=0);
00232   if (d2>0)
00233   {
00234     for (int x=0; x<src.width(); x++)
00235       for (int y=0; y<src.height(); y++)
00236       {
00237         (*ret)(x,y) = (T)((src(x,y)-small)*d1/d2+low);
00238         assert(((*ret)(x,y)>=low-epsilon)&&((*ret)(x,y)<=high+epsilon));
00239       }
00240   }
00241   else 
00242   {
00243     for (int x=0; x<src.width(); x++)
00244       for (int y=0; y<src.height(); y++)
00245         (*ret)(x,y) = (T)src(x,y);
00246   }
00247   return ret;
00248 }
00249 
00250 #endif // ouml_image_ops_txx_