im.hh

00001 #ifndef IM_HH
00002 #define IM_HH
00003 
00004 #include <assert.h>
00005 #include "CImg.h"
00006 #include "util.hh"
00007 
00008 using namespace cimg_library;
00009 
00011 namespace im {
00012 
00014   template <typename T>
00015   struct PixelSum {
00016 
00018     PixelSum(const CImg<T> &img) : img(img), sum(0), count(0) { }
00019 
00021     void operator()(int x, int y)
00022     {
00023       sum += img(x, y);
00024       count++;
00025     }
00026 
00027     const CImg<T> &img; 
00028     T sum; 
00029     int count; 
00030   };
00031 
00032 
00043   template <typename T>
00044   CImg<T>
00045   peak_filter(int width, int sign = 1)
00046   {
00047     assert(width % 2 == 1);
00048     CImg<T> filter(width, width);
00049     filter.fill(-sign);
00050     filter(filter.width / 2, filter.height / 2) -= filter.sum();
00051 
00052     return filter;
00053   }
00054 
00058   template <typename T>
00059   void
00060   zero_negatives(CImg<T> &img)
00061   {
00062     for (int i = 0; i < (int)img.size(); i++)
00063       if (img[i] < 0)
00064         img[i] = 0;
00065   }
00066 
00074   template <typename T>
00075   void
00076   weight_gaussian(CImg<T> &img, float xc, float yc, 
00077                   float x_sigma2, float y_sigma2)
00078   {
00079     cimg_mapXY(img, x, y) {
00080       float exponent = 0;
00081       if (x_sigma2 > 0)
00082         exponent += -0.5 * (xc - x) * (xc - x) / x_sigma2;
00083       if (y_sigma2 > 0)
00084         exponent += -0.5 * (yc - y) * (yc - y) / y_sigma2;
00085       img(x,y) *= exp(exponent);
00086     }
00087   }
00088 
00108   template<typename T>
00109   CImg<T> hough(const CImg<T> &src, float theta1, float theta2, 
00110                 int num_thetas, int max_rho)
00111   {
00112     int num_rhos = max_rho * 2 + 1;
00113     int rho_center = num_rhos / 2;
00114   
00115     CImg<T> result = CImg<T>(num_thetas, num_rhos);
00116     result.fill(0);
00117 
00118     cimg_mapXY(src, x, y) {
00119 
00120       // Skip non-positive pixels
00121       if (src(x,y) <= 0)
00122         continue;
00123 
00124       float rho_x = (float)x - src.width/2;
00125       float rho_y = (float)y - src.height/2;
00126       float rho0 = std::sqrt(rho_x * rho_x + rho_y * rho_y);
00127       float theta0 = std::atan2(rho_y, rho_x) / M_PI * 180;
00128 
00129       if (theta0 < 0) {
00130         theta0 += 180;
00131         rho0 = - rho0;
00132       }
00133 
00134       // Iterate all thetas and compute corresponding rho
00135       float theta_delta = (theta2 - theta1) / (num_thetas - 1);
00136       for (int t = 0; t < num_thetas; t++) {
00137         float theta = theta1 + t * theta_delta;
00138         float r = rho0 * std::cos((theta0 - theta) / 180 * M_PI) + rho_center;
00139         if (r < 0 || r >= result.dimy())
00140           continue;
00141 
00142         int ir = (int)floor(r);
00143         float w = r - ir;
00144 
00145         result(t, ir) += src(x, y) * (1 - w);
00146         if (ir + 1 < (int)result.height)
00147           result(t, ir+1) += src(x, y) * w;
00148       }
00149     }
00150 
00151     return result;
00152   }
00153 
00154 
00164   template <typename T>
00165   T
00166   median(CImg<T> &img, int x1, int x2)
00167   {
00168     if (x1 < 0)
00169       x1 = 0;
00170     if (x2 >= (int)img.width)
00171       x2 = img.width - 1;
00172 
00173     std::vector<T> values(x2 - x1 + 1);
00174     for (int x = x1; x <= x2; x++)
00175       values[x - x1] = img(x);
00176     return util::median(values);
00177   }
00178 
00179 
00187   template <typename T>
00188   void
00189   median_peak_remove(CImg<T> &img, int x0, int win, T value = 0)
00190   {
00191     // Compute the threshold to stop the removing
00192     T threshold = im::median(img, x0 - win, x0 + win);
00193 
00194     // Remove values in the right neighbourhood
00195     for (int i = 0; i < win; i++) {
00196       int x = x0 + i;
00197       if (x >= (int)img.width)
00198         break;
00199       if (img(x) < threshold)
00200         break;
00201       img(x) = value;
00202     }
00203 
00204     // Remove values in the left neighbourhood
00205     for (int i = 1; i < win; i++) {
00206       int x = x0 - i;
00207       if (x < 0)
00208         break;
00209       if (img(x) < threshold)
00210         break;
00211       img(x) = value;
00212     }
00213   }
00214 
00221   template <typename T>
00222   int
00223   find_max1(const CImg<T> &img, int x1 = 0, int x2 = -1)
00224   {
00225     if (x2 < 0)
00226       x2 = img.width - 1;
00227 
00228     int best_x = x1;
00229     T best = img(best_x);
00230 
00231     while (x1 < x2) {
00232       x1++;
00233       if (img(x1) > best) {
00234         best = img(x1);
00235         best_x = x1;
00236       }
00237     }
00238   
00239     return best_x;
00240   }
00241 
00249   template <typename T>
00250   int
00251   find_max_x(const CImg<T> &img, int y, int x1 = 0, int x2 = -1)
00252   {
00253     if (x2 < 0)
00254       x2 = img.width - 1;
00255 
00256     int best_x = x1;
00257     T best = img(best_x, y);
00258 
00259     while (x1 < x2) {
00260       x1++;
00261       if (img(x1, y) > best) {
00262         best = img(x1, y);
00263         best_x = x1;
00264       }
00265     }
00266   
00267     return best_x;
00268   }
00269 
00277   template <typename T>
00278   T&
00279   paste_image(const T &src, T &tgt, int x0, int y0)
00280   {
00281     for (int x = 0; x < (int)src.width; x++) {
00282       for (int y = 0; y < (int)src.height; y++) {
00283         tgt(x0 + x, y0 + y) = src(x, y);
00284       }
00285     }
00286     return tgt;
00287   }
00288 
00293   template<typename T>
00294   CImg<T> sum_y(const CImg<T> &img)
00295   {
00296     CImg<T> result(img.width, 1);
00297     for (int x = 0; x < (int)img.width; x++) {
00298       T sum = 0;
00299       for (int y = 0; y < (int)img.height; y++)
00300         sum += img(x,y);
00301       result(x) = sum;
00302     }
00303     return result;
00304   }
00305 
00317   template <typename T>
00318   CImg<T>&
00319   set_range1(CImg<T> &img, int x1 = 0, int x2 = INT_MAX, T value = 0)
00320   {
00321     if (x1 < 0)
00322       x1 = 0;
00323     if (x2 > (int)img.width - 1)
00324       x2 = img.width - 1;
00325 
00326     for (int x = x1; x <= x2; x++)
00327       img(x) = value;
00328 
00329     return img;
00330   }
00331 
00341   template <typename T>
00342   CImg<T>
00343   max_x(const CImg<T> &img, int x1 = 0, int x2 = -1)
00344   {
00345     CImg<T> result(img.height);
00346   
00347     if (x2 < 0)
00348       x2 = img.width - 1;
00349 
00350     for (int y = 0; y < (int)img.height; y++) {
00351       T max = img(x1, y);
00352       for (int x = x1 + 1; x <= x2; x++) {
00353         if (img(x, y) > max)
00354           max = img(x, y);
00355       }
00356       result(y) = max;
00357     }
00358 
00359     return result;
00360   }
00361 
00373   template <typename T>
00374   T
00375   line_sum(CImg<T> &img, const geom::Line &line)
00376   {
00377     // Check single point
00378     if ((int)(line.a.x + 0.5) == (int)(line.b.x + 0.5) &&
00379         (int)(line.a.y + 0.5) == (int)(line.b.y + 0.5))
00380       return img((int)(line.a.x + 0.5), (int)(line.b.y + 0.5));
00381 
00382     // Compute line
00383     float dx = line.b.x - line.a.x;
00384     float dy = line.b.y - line.a.y;
00385     float div = cimg::max(cimg::abs(dx), cimg::abs(dy));
00386     dx /= div;
00387     dy /= div;
00388 
00389     // Add value to points along the line
00390     T result = 0;
00391     for (int i = 0; i <= div; i++) {
00392       int x = (int)(line.a.x + i * dx + 0.5);
00393       int y = (int)(line.a.y + i * dy + 0.5);
00394       result += img(x, y);
00395     }
00396 
00397     return result;
00398   }
00399 
00400 };
00401 
00402 #endif /* IM_HH */

Generated on Tue Apr 8 09:58:19 2008 for GoCam by  doxygen 1.4.6