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
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
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
00192 T threshold = im::median(img, x0 - win, x0 + win);
00193
00194
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
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
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
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
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