Main Page | Namespace List | Class List | File List | Namespace Members | Class Members | Related Pages

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 
00162   template <typename T>
00163   void
00164   median_peak_remove(CImg<T> &img, int x0, int win, T value = 0)
00165   {
00166     // Compute the threshold to stop the removing
00167     T threshold = im::median(img, x0 - win, x0 + win);
00168 
00169     // Remove values in the right neighbourhood
00170     for (int i = 0; i < win; i++) {
00171       int x = x0 + i;
00172       if (x >= (int)img.width)
00173         break;
00174       if (img(x) < threshold)
00175         break;
00176       img(x) = value;
00177     }
00178 
00179     // Remove values in the left neighbourhood
00180     for (int i = 1; i < win; i++) {
00181       int x = x0 - i;
00182       if (x < 0)
00183         break;
00184       if (img(x) < threshold)
00185         break;
00186       img(x) = value;
00187     }
00188   }
00189 
00196   template <typename T>
00197   int
00198   find_max1(const CImg<T> &img, int x1 = 0, int x2 = -1)
00199   {
00200     if (x2 < 0)
00201       x2 = img.width - 1;
00202 
00203     int best_x = x1;
00204     T best = img(best_x);
00205 
00206     while (x1 < x2) {
00207       x1++;
00208       if (img(x1) > best) {
00209         best = img(x1);
00210         best_x = x1;
00211       }
00212     }
00213   
00214     return best_x;
00215   }
00216 
00224   template <typename T>
00225   int
00226   find_max_x(const CImg<T> &img, int y, int x1 = 0, int x2 = -1)
00227   {
00228     if (x2 < 0)
00229       x2 = img.width - 1;
00230 
00231     int best_x = x1;
00232     T best = img(best_x, y);
00233 
00234     while (x1 < x2) {
00235       x1++;
00236       if (img(x1, y) > best) {
00237         best = img(x1, y);
00238         best_x = x1;
00239       }
00240     }
00241   
00242     return best_x;
00243   }
00244 
00252   template <typename T>
00253   T&
00254   paste_image(const T &src, T &tgt, int x0, int y0)
00255   {
00256     for (int x = 0; x < (int)src.width; x++) {
00257       for (int y = 0; y < (int)src.height; y++) {
00258         tgt(x0 + x, y0 + y) = src(x, y);
00259       }
00260     }
00261     return tgt;
00262   }
00263 
00268   template<typename T>
00269   CImg<T> sum_y(const CImg<T> &img)
00270   {
00271     CImg<T> result(img.width, 1);
00272     for (int x = 0; x < (int)img.width; x++) {
00273       T sum = 0;
00274       for (int y = 0; y < (int)img.height; y++)
00275         sum += img(x,y);
00276       result(x) = sum;
00277     }
00278     return result;
00279   }
00280 
00292   template <typename T>
00293   CImg<T>&
00294   set_range1(CImg<T> &img, int x1 = 0, int x2 = img.width - 1, T value = 0)
00295   {
00296     if (x1 < 0)
00297       x1 = 0;
00298     if (x2 > (int)img.width - 1)
00299       x2 = img.width - 1;
00300 
00301     for (int x = x1; x <= x2; x++)
00302       img(x) = value;
00303 
00304     return img;
00305   }
00306 
00316   template <typename T>
00317   CImg<T>
00318   max_x(const CImg<T> &img, int x1 = 0, int x2 = img.width - 1)
00319   {
00320     CImg<T> result(img.height);
00321   
00322     for (int y = 0; y < (int)img.height; y++) {
00323       T max = img(x1, y);
00324       for (int x = x1 + 1; x <= x2; x++) {
00325         if (img(x, y) > max)
00326           max = img(x, y);
00327       }
00328       result(y) = max;
00329     }
00330 
00331     return result;
00332   }
00333 
00343   template <typename T>
00344   T
00345   median(CImg<T> &img, int x1, int x2)
00346   {
00347     if (x1 < 0)
00348       x1 = 0;
00349     if (x2 >= (int)img.width)
00350       x2 = img.width - 1;
00351 
00352     std::vector<T> values(x2 - x1 + 1);
00353     for (int x = x1; x <= x2; x++)
00354       values[x - x1] = img(x);
00355     return util::median(values);
00356   }
00357 
00369   template <typename T>
00370   T
00371   line_sum(CImg<T> &img, const geom::Line &line)
00372   {
00373     // Check single point
00374     if ((int)(line.a.x + 0.5) == (int)(line.b.x + 0.5) &&
00375         (int)(line.a.y + 0.5) == (int)(line.b.y + 0.5))
00376       return img((int)(line.a.x + 0.5), (int)(line.b.y + 0.5));
00377 
00378     // Compute line
00379     float dx = line.b.x - line.a.x;
00380     float dy = line.b.y - line.a.y;
00381     float div = cimg::max(cimg::abs(dx), cimg::abs(dy));
00382     dx /= div;
00383     dy /= div;
00384 
00385     // Add value to points along the line
00386     T result = 0;
00387     for (int i = 0; i <= div; i++) {
00388       int x = (int)(line.a.x + i * dx + 0.5);
00389       int y = (int)(line.a.y + i * dy + 0.5);
00390       result += img(x, y);
00391     }
00392 
00393     return result;
00394   }
00395 
00396 };
00397 
00398 #endif /* IM_HH */

Generated on Sat Feb 26 22:54:39 2005 for GoCam by doxygen 1.3.4