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_