00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037
00038 #include "Image/ImageSetOps.H"
00039
00040 #include "Image/DrawOps.H"
00041 #include "Image/FilterOps.H"
00042 #include "Image/Image.H"
00043 #include "Image/ImageSet.H"
00044 #include "Image/MathOps.H"
00045 #include "Image/Range.H"
00046 #include "Image/ShapeOps.H"
00047 #include "Util/Assert.H"
00048 #include "rutz/compat_cmath.h"
00049
00050
00051
00052
00053
00054
00055
00056
00057 template <class T>
00058 bool isHomogeneous(const ImageSet<T>& x)
00059 {
00060 if (x.size() == 0) return true;
00061
00062 const Dims d = x[0].getDims();
00063
00064 for (uint i = 1; i < x.size(); ++i)
00065 if (d != x[i].getDims())
00066 return false;
00067
00068 return true;
00069 }
00070
00071
00072 template <class T>
00073 bool isDyadic(const ImageSet<T>& pyr)
00074 {
00075 if (pyr.size() == 0) return false;
00076
00077 for (uint i = 1; i < pyr.size(); ++i)
00078 {
00079 const Dims prevdims = pyr[i-1].getDims();
00080 const Dims curdims = pyr[i].getDims();
00081
00082
00083 const int pw2 = std::max(prevdims.w()/2,1);
00084 const int ph2 = std::max(prevdims.h()/2,1);
00085
00086 if (curdims.w() != pw2) return false;
00087 if (curdims.h() != ph2) return false;
00088 }
00089
00090 return true;
00091 }
00092
00093
00094 template <class T>
00095 Image<T> sum(const ImageSet<T>& x)
00096 {
00097 ASSERT(isHomogeneous(x));
00098
00099 Image<T> result(x[0].getDims(), ZEROS);
00100
00101 for (uint a = 0; a < x.size(); ++a)
00102 {
00103 result += x[a];
00104 }
00105
00106 return result;
00107 }
00108
00109
00110 template <class T>
00111 Image<T> mean(const ImageSet<T>& x)
00112 {
00113 Image<T> result = sum(x);
00114 result /= x.size();
00115 return result;
00116 }
00117
00118
00119 template <class T>
00120 Range<T> rangeOf(const ImageSet<T>& x)
00121 {
00122 Range<T> result;
00123
00124 for (uint i = 0; i < x.size(); ++i)
00125 {
00126 result.merge(rangeOf(x[i]));
00127 }
00128
00129 return result;
00130 }
00131
00132
00133 template <class T>
00134 ImageSet<T> takeSlice(const ImageSet<T>* sets, uint nsets, uint level)
00135 {
00136 ImageSet<T> result(nsets);
00137
00138 for (uint i = 0; i < nsets; ++i)
00139 {
00140 result[i] = sets[i][level];
00141 }
00142
00143 return result;
00144 }
00145
00146
00147 template <class T>
00148 Image<T> makeImageArray(const ImageSet<T>& x,
00149 int Nx, int grid_width, T grid_color,
00150 int destX, int destY)
00151 {
00152 if (Nx < 0)
00153 {
00154 Nx = int(ceil(sqrt(x.size())));
00155 }
00156
00157 Image<T> result;
00158
00159
00160
00161
00162
00163 if (destX <= 0 || destY <= 0)
00164 {
00165 destX = x[0].getWidth();
00166 destY = x[0].getHeight();
00167 }
00168
00169 if (isDyadic(x) && destX == x[0].getWidth() && destY == x[0].getHeight())
00170 {
00171
00172
00173 ImageSet<T> y = x;
00174 for (unsigned int i = 1; i < y.size(); ++i)
00175 y[i] = zoomXY(y[i], 1<<i, 1<<i);
00176
00177 result = concatArray(&y[0], y.size(), Nx);
00178 }
00179 else
00180 {
00181 result = concatArray(&x[0], x.size(), Nx, destX, destY);
00182 }
00183
00184 if (grid_width > 0)
00185 drawGrid(result, destX, destY, grid_width, grid_width, grid_color);
00186
00187 return result;
00188 }
00189
00190
00191 template <class T>
00192 ImageSet<T> reduce(const ImageSet<T>& x, int octaves)
00193 {
00194 ImageSet<T> result(x);
00195
00196 for (int n = 0; n < octaves; ++n)
00197 {
00198 for (uint i = 0; i < x.size(); ++i)
00199 {
00200 result[i] = lowPass3(result[i]);
00201 result[i] = decXY(result[i]);
00202 }
00203 }
00204
00205 return result;
00206 }
00207
00208
00209 template <class T>
00210 ImageSet<T> rescale(const ImageSet<T>& x, const Dims& dims)
00211 {
00212 ImageSet<T> result(x.size());
00213
00214 for (uint i = 0; i < x.size(); ++i)
00215 {
00216 result[i] = rescale(x[i], dims);
00217 }
00218
00219 return result;
00220 }
00221
00222
00223 ImageSet<float> orientedFilterSet(const Image<float>& lowPassedInput,
00224 float period,
00225 const float* angles, const uint numAngles)
00226 {
00227 ImageSet<float> result(numAngles);
00228
00229 LINFO("oriented laplacian period is %f", period);
00230
00231 const float k = (2.0f * M_PI) / period;
00232
00233 for (uint i = 0; i < numAngles; ++i)
00234 result[i] = orientedFilter(lowPassedInput, k, angles[i]);
00235
00236 return result;
00237 }
00238
00239
00240 void splitPosNeg(const ImageSet<float>& x, ImageSet<float>& pos, ImageSet<float>& neg)
00241 {
00242 pos = ImageSet<float>(x.size());
00243 neg = ImageSet<float>(x.size());
00244 for (uint i = 0; i < x.size(); ++i)
00245 splitPosNeg(x[i], pos[i], neg[i]);
00246 }
00247
00248
00249
00250
00251
00252
00253
00254
00255 template <class T>
00256 ImageSet<T>& operator-=(ImageSet<T>& x, const Image<T>& y)
00257 {
00258 ASSERT(isHomogeneous(x));
00259
00260 for (uint i = 0; i < x.size(); ++i)
00261 x[i] -= y;
00262
00263 return x;
00264 }
00265
00266
00267 template <class T>
00268 ImageSet<T>& operator+=(ImageSet<T>& x, const Image<T>& y)
00269 {
00270 ASSERT(isHomogeneous(x));
00271
00272 for (uint i = 0; i < x.size(); ++i)
00273 x[i] += y;
00274
00275 return x;
00276 }
00277
00278
00279 template <class T>
00280 ImageSet<T>& operator*=(ImageSet<T>& x, const Image<T>& y)
00281 {
00282 ASSERT(isHomogeneous(x));
00283
00284 for (uint i = 0; i < x.size(); ++i)
00285 x[i] *= y;
00286
00287 return x;
00288 }
00289
00290
00291 template <class T>
00292 ImageSet<T>& operator/=(ImageSet<T>& x, const Image<T>& y)
00293 {
00294 ASSERT(isHomogeneous(x));
00295
00296 for (uint i = 0; i < x.size(); ++i)
00297 x[i] /= y;
00298
00299 return x;
00300 }
00301
00302
00303 template <class T>
00304 ImageSet<T>& operator-=(ImageSet<T>& x, const T& v)
00305 {
00306 for (uint i = 0; i < x.size(); ++i)
00307 x[i] -= v;
00308
00309 return x;
00310 }
00311
00312
00313 template <class T>
00314 ImageSet<T>& operator+=(ImageSet<T>& x, const T& v)
00315 {
00316 for (uint i = 0; i < x.size(); ++i)
00317 x[i] += v;
00318
00319 return x;
00320 }
00321
00322
00323 template <class T>
00324 ImageSet<T>& operator*=(ImageSet<T>& x, const T& v)
00325 {
00326 for (uint i = 0; i < x.size(); ++i)
00327 x[i] *= v;
00328
00329 return x;
00330 }
00331
00332
00333 template <class T>
00334 ImageSet<T>& operator/=(ImageSet<T>& x, const T& v)
00335 {
00336 for (uint i = 0; i < x.size(); ++i)
00337 x[i] /= v;
00338
00339 return x;
00340 }
00341
00342
00343 template <class T>
00344 ImageSet<T> operator-(ImageSet<T>& x, const T& v)
00345 {
00346 ImageSet<T> res = x;
00347 return (res -= v);
00348 }
00349
00350
00351 template <class T>
00352 ImageSet<T> operator+(ImageSet<T>& x, const T& v)
00353 {
00354 ImageSet<T> res = x;
00355 return (res += v);
00356 }
00357
00358
00359 template <class T>
00360 ImageSet<T> operator*(ImageSet<T>& x, const T& v)
00361 {
00362 ImageSet<T> res = x;
00363 return (res *= v);
00364 }
00365
00366
00367 template <class T>
00368 ImageSet<T> operator/(ImageSet<T>& x, const T& v)
00369 {
00370 ImageSet<T> res = x;
00371 return (res /= v);
00372 }
00373
00374
00375 template <class T>
00376 ImageSet<T>& operator-=(ImageSet<T>& x, const ImageSet<T>& y)
00377 {
00378 ASSERT(x.size() == y.size());
00379
00380 for (uint i = 0; i < x.size(); ++i)
00381 x[i] -= y[i];
00382
00383 return x;
00384 }
00385
00386
00387 template <class T>
00388 ImageSet<T>& operator+=(ImageSet<T>& x, const ImageSet<T>& y)
00389 {
00390 ASSERT(x.size() == y.size());
00391
00392 for (uint i = 0; i < x.size(); ++i)
00393 x[i] += y[i];
00394
00395 return x;
00396 }
00397
00398
00399 template <class T>
00400 ImageSet<T>& operator*=(ImageSet<T>& x, const ImageSet<T>& y)
00401 {
00402 ASSERT(x.size() == y.size());
00403
00404 for (uint i = 0; i < x.size(); ++i)
00405 x[i] *= y[i];
00406
00407 return x;
00408 }
00409
00410
00411 template <class T>
00412 ImageSet<T>& operator/=(ImageSet<T>& x, const ImageSet<T>& y)
00413 {
00414 ASSERT(x.size() == y.size());
00415
00416 for (uint i = 0; i < x.size(); ++i)
00417 x[i] /= y[i];
00418
00419 return x;
00420 }
00421
00422
00423 template <class T>
00424 ImageSet<T> clampedDiff(const ImageSet<T>& b, const ImageSet<T>& c)
00425 {
00426 ASSERT(b.size() == c.size());
00427
00428 ImageSet<T> res(b.size());
00429 for (uint i = 0; i < b.size(); ++i)
00430 res[i] = clampedDiff(b[i],c[i]);
00431
00432 return res;
00433 }
00434
00435
00436
00437
00438
00439
00440
00441
00442 template <class T> inline
00443 void doRectify(ImageSet<T>& x)
00444 {
00445 for (uint i = 0; i < x.size(); ++i)
00446 inplaceRectify(x[i]);
00447 }
00448
00449
00450 template <class T> inline
00451 void doLowThresh(ImageSet<T>& x, const T threshold, const T newval)
00452 {
00453 for (uint i = 0; i < x.size(); ++i)
00454 inplaceLowThresh(x[i], threshold, newval);
00455 }
00456
00457
00458 template <class T> inline
00459 void doLowThreshAbs(ImageSet<T>& x, const T threshold, const T newval)
00460 {
00461 for (uint i = 0; i < x.size(); ++i)
00462 inplaceLowThreshAbs(x[i], threshold, newval);
00463 }
00464
00465
00466 template <class T> inline
00467 void doSqrt(ImageSet<T>& x)
00468 {
00469 for (uint i = 0; i < x.size(); ++i)
00470 x[i] = sqrt(x[i]);
00471 }
00472
00473
00474 template <class T> inline
00475 void doSquared(ImageSet<T>& x)
00476 {
00477 for (uint i = 0; i < x.size(); ++i)
00478 x[i] = squared(x[i]);
00479 }
00480
00481
00482 void doMeanNormalize(ImageSet<float>& x)
00483 {
00484 x -= mean(x);
00485 }
00486
00487
00488 void doOneNormalize(ImageSet<float>& x)
00489 {
00490 const Range<float> r = rangeOf(x);
00491
00492 for (uint i = 0; i < x.size(); ++i)
00493 {
00494 x[i] /= r.max();
00495 }
00496 }
00497
00498
00499 void doEnergyNorm(ImageSet<float>& x)
00500 {
00501 for (uint i = 0; i < x.size(); ++i)
00502 {
00503 x[i] = energyNorm(x[i]);
00504 }
00505 }
00506
00507
00508 void doApplyBiases(ImageSet<float>& x, const float* biases)
00509 {
00510 for (uint i = 0; i < x.size(); ++i)
00511 {
00512 x[i] *= biases[i];
00513 }
00514 }
00515
00516
00517 void doAddWeighted(ImageSet<float>& x, const ImageSet<float>& y, float multiple)
00518 {
00519 ASSERT(x.size() == y.size());
00520 for (uint a = 0; a < x.size(); ++a)
00521 x[a] += y[a] * multiple;
00522 }
00523
00524
00525 void doClear(ImageSet<float>& x, float v)
00526 {
00527 for (uint a = 0; a < x.size(); ++a)
00528 {
00529 x[a].clear(v);
00530 }
00531 }
00532
00533
00534
00535 #include "inst/Image/ImageSetOps.I"
00536
00537 template bool isDyadic(const ImageSet<int>& pyr);
00538 template ImageSet<double>& operator/=(ImageSet<double>& x, const double& v);
00539
00540
00541
00542
00543
00544