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
00039 #ifndef IMAGE_TRANSFORMS_C_DEFINED
00040 #define IMAGE_TRANSFORMS_C_DEFINED
00041
00042 #include "Image/Transforms.H"
00043
00044 #include "Image/CutPaste.H"
00045 #include "Image/Image.H"
00046 #include "Image/MathOps.H"
00047 #include "Image/Pixels.H"
00048 #include "Image/Rectangle.H"
00049 #include "Util/Assert.H"
00050 #include "Util/log.H"
00051
00052 #include <algorithm>
00053 #include <cmath>
00054 #include <vector>
00055 #include <cstdio>
00056
00057 #define SEGOBJ_START 0.9
00058 #define SEGOBJ_STEP 0.05
00059 #define SEGOBJ_MINA 0.005
00060 #define SEGOBJ_EXPL 1.05
00061
00062
00063 template <class T>
00064 Image<byte> segmentObject(const Image<T>& src,
00065 const Point2D<int>& seed)
00066 {
00067 ASSERT(src.initialized());
00068 Image<T> tmp;
00069 bool explode = false; int prev = 0; double thresh = 1.0;
00070 double step = double(src.getVal(seed.i, seed.j)) * SEGOBJ_STEP;
00071 int minadiff = int(float(src.getSize()) * SEGOBJ_MINA);
00072 double efac = SEGOBJ_EXPL;
00073 int iter;
00074
00075 while(explode == false && minadiff > 0 && efac > 1)
00076 {
00077 thresh = double(src.getVal(seed.i, seed.j)) * SEGOBJ_START;
00078 iter = 0;
00079 while(explode == false && thresh > 0)
00080 {
00081 int area = flood(src, tmp, seed, (T)thresh, (T)255.0);
00082 LDEBUG("prev=%d area=%d minadiff=%d thresh=%f efac=%f\n",
00083 prev, area, minadiff, thresh, efac);
00084 if (iter > 2 && area > prev + minadiff &&
00085 area > int(double(prev)*efac))
00086 explode = true;
00087 else
00088 { prev = area; thresh -= step; }
00089 iter ++;
00090 }
00091 minadiff -= minadiff / 4; efac *= 0.95;
00092 }
00093
00094 thresh += step;
00095 flood(src, tmp, seed, (T)thresh, (T)255.0);
00096 return Image<byte>(tmp);
00097 }
00098
00099
00100 template <class T>
00101 int segmentLandmark(const Image<T>& src,
00102 const Point2D<int>& seed, Image<byte>& target,
00103 double& activity, double& standout,
00104 float& area_percentage)
00105 {
00106 ASSERT(src.initialized());
00107 Image<T> tmp;
00108
00109 bool explode = false; int prev = 0;
00110 double thresh = 1.0;
00111 double step = double(src.getVal(seed.i, seed.j)) * SEGOBJ_STEP;
00112 int minadiff = int(float(src.getSize()) * SEGOBJ_MINA);
00113 double efac = SEGOBJ_EXPL;
00114 double valdiff = 0.0, maxvaldiff = 0.0, sumvaldiff = 0.0,
00115 prev_thresh = 0.0, maxthresh = 0.0;
00116 int iter = 0; int flood_count = 0;
00117 bool gradual_descent = false;
00118
00119 thresh = double(src.getVal(seed.i, seed.j)) * SEGOBJ_START;
00120 prev_thresh = thresh; activity = 0.0;
00121 while(minadiff > 0 && thresh > 0)
00122 {
00123 explode = false;
00124 while(explode == false && thresh > 0)
00125 {
00126 int area = flood(src, tmp, seed, (T)thresh, (T)255.0);
00127
00128
00129
00130 if ((area > prev + minadiff &&
00131 area > int(double(prev)*efac))
00132 || area > 2 * prev)
00133 {
00134 explode = true;
00135 gradual_descent = false;
00136 flood_count++;
00137 valdiff = prev_thresh - thresh;
00138 sumvaldiff += valdiff;
00139
00140 if(maxvaldiff < valdiff)
00141 {
00142 maxthresh = thresh + step;
00143 maxvaldiff = valdiff;
00144 }
00145 prev_thresh = thresh;
00146 }
00147 else if(area > prev + minadiff/4) gradual_descent = true;
00148 prev = area; thresh -= step;
00149 iter ++;
00150 }
00151 }
00152
00153 if(maxvaldiff == 0.0)
00154 {
00155
00156
00157
00158 if(gradual_descent == true)
00159 standout = 0.0;
00160
00161 else standout = double(src.getVal(seed.i, seed.j)) * SEGOBJ_START;
00162 maxthresh = step;
00163 }
00164 else standout = maxvaldiff;
00165
00166 if(maxthresh <= 0) return -1;
00167
00168
00169 if(flood_count != 0)
00170 if(maxvaldiff <= sumvaldiff/(double)flood_count)
00171 thresh = step;
00172 else thresh = maxthresh;
00173
00174 else thresh = step;
00175
00176 int area = flood(src, tmp, seed, (T)thresh, (T)255.0);
00177 if (area == -1) return -1;
00178 target = (Image<byte>)tmp;
00179
00180
00181 double threshold = thresh; double sum = 0.0;
00182 thresh = double(src.getVal(seed.i, seed.j)) * SEGOBJ_START;
00183 prev = 0; int sum_area = 0;
00184 activity = thresh;
00185
00186 while(thresh >= threshold)
00187 {
00188 area = flood(src, tmp, seed, (T)thresh, (T)255.0);
00189 if(area > prev)
00190 activity = thresh;
00191
00192 sum += activity * (area - prev);
00193 sum_area += area - prev;
00194 thresh -= step; prev = area;
00195 }
00196
00197 if( sum_area != 0)activity = sum/(double)sum_area;
00198 else activity = threshold;
00199
00200 if(standout > activity)
00201 standout = activity;
00202
00203 area_percentage = (area * 100.0f)/ (float)src.getSize();
00204
00205 return area;
00206 }
00207
00208
00209 template <class T>
00210 Image<byte> contour2D(const Image<T>& src, const byte onval, const byte offval)
00211 {
00212 ASSERT(src.initialized());
00213
00214 Image<byte> result(src.getDims(), NO_INIT);
00215 typename Image<T>::const_iterator sptr = src.begin();
00216 Image<byte>::iterator dptr = result.beginw();
00217 T z = T(); const int h = src.getHeight(), w = src.getWidth();
00218
00219
00220
00221
00222
00223
00224 for (int i = 0; i < w; ++i) if (*sptr++) *dptr++ = onval; else *dptr++ = offval;
00225
00226
00227 if (h == 1) return result;
00228
00229
00230 for (int j = 1; j < h-1; ++j)
00231 {
00232
00233 if (*sptr++) *dptr++ = onval; else *dptr++ = offval;
00234
00235
00236 if (w == 1) continue;
00237
00238
00239 for (int i = 1; i < w-1; ++i) {
00240 if (*sptr && (sptr[-1] == z || sptr[1] == z || sptr[-w] == z || sptr[w] == z))
00241 *dptr++ = onval; else *dptr++ = offval;
00242 ++sptr;
00243 }
00244
00245
00246 if (*sptr++) *dptr++ = onval; else *dptr++ = offval;
00247 }
00248
00249
00250 for (int i = 0; i < w; ++i) if (*sptr++) *dptr++ = onval; else *dptr++ = offval;
00251
00252 return result;
00253 }
00254
00255
00256 template <class T>
00257 Image<T> chamfer34(const Image<T>& src, const T dmax)
00258 {
00259
00260 ASSERT(src.initialized());
00261 ASSERT(src.getWidth() >= 3 && src.getHeight() >= 3);
00262
00263 Image<T> result = src;
00264
00265 const Dims dims = src.getDims();
00266 const int size = src.getSize();
00267 const int w = dims.w();
00268 const T zero = T();
00269
00270 typename Image<T>::const_iterator sptr = src.begin();
00271 typename Image<T>::iterator dptr = result.beginw();
00272
00273
00274 for (int i = 0; i < size; i ++)
00275 if (*sptr++) *dptr++ = zero; else *dptr++ = dmax;
00276 dptr = result.beginw();
00277
00278 const float tmaxf = float(dmax);
00279
00280
00281 float d1, d2, d3, d4;
00282
00283
00284 ++ dptr;
00285
00286
00287 for (int i = 1; i < w; ++i)
00288 {
00289 d1 = std::min(dptr[-1] + 3.0F, dptr[-1 + w] + 4.0F);
00290 d2 = std::min(float(*dptr), d1);
00291 *dptr++ = clamped_convert<T>(std::min(d2, tmaxf));
00292 }
00293
00294
00295 for (int j = 1; j < dims.h() - 1; ++j)
00296 {
00297
00298 d1 = std::min(dptr[-w] + 3.0F, float(*dptr));
00299 *dptr++ = clamped_convert<T>(std::min(d1, tmaxf));
00300
00301
00302 for (int k = 1; k < w; k++)
00303 {
00304 d1 = std::min(dptr[-w - 1] + 4.0F, dptr[-w] + 3.0F);
00305 d2 = std::min(dptr[-1] + 3.0F, float(*dptr));
00306 d3 = std::min(dptr[-1 + w] + 4.0F, d1);
00307 d4 = std::min(d2, d3);
00308 *dptr++ = clamped_convert<T>(std::min(d4, tmaxf));
00309 }
00310 }
00311
00312
00313
00314 d1 = std::min(dptr[-w] + 3.0F, float(*dptr));
00315 *dptr++ = clamped_convert<T>(std::min(d1, tmaxf));
00316
00317
00318 for (int j = 1; j < w; ++j)
00319 {
00320 d1 = std::min(dptr[-w - 1] + 4.0F, dptr[-w] + 3.0F);
00321 d2 = std::min(dptr[-1] + 3.0F, float(*dptr));
00322 d3 = std::min(d1, d2);
00323 *dptr++ = clamped_convert<T>(std::min(d3, tmaxf));
00324 }
00325 --dptr;
00326
00327
00328
00329 --dptr;
00330
00331
00332 for (int j = w-2; j >= 0; --j)
00333 {
00334 d1 = std::min(dptr[1] + 3.0F, dptr[-w + 1] + 4.0F);
00335 d2 = std::min(float(*dptr), d1);
00336 *dptr-- = clamped_convert<T>(std::min(d2, tmaxf));
00337 }
00338
00339
00340 for (int j = dims.h() - 2; j >= 1; --j)
00341 {
00342
00343 d1 = std::min(dptr[w] + 3.0F, float(*dptr));
00344 *dptr-- = clamped_convert<T>(std::min(d1, tmaxf));
00345
00346
00347 for (int k = w - 2; k >= 0; k--)
00348 {
00349 d1 = std::min(float(*dptr), dptr[-w + 1] + 4.0F);
00350 d2 = std::min(dptr[1] + 3.0F, dptr[w] + 3.0F);
00351 d3 = std::min(dptr[w + 1] + 4.0F, d1);
00352 d4 = std::min(d2, d3);
00353 *dptr-- = clamped_convert<T>(std::min(d4, tmaxf));
00354 }
00355 }
00356
00357
00358
00359 d1 = std::min(dptr[w] + 3.0F, float(*dptr));
00360 *dptr-- = clamped_convert<T>(std::min(d1, tmaxf));
00361
00362
00363 for (int j = w-2; j >= 0; --j)
00364 {
00365 d1 = std::min(dptr[1] + 3.0F, float(*dptr));
00366 d2 = std::min(dptr[w] + 3.0F, dptr[w + 1] + 4.0F);
00367 d3 = std::min(d1, d2);
00368 *dptr-- = clamped_convert<T>(std::min(d3, tmaxf));
00369 }
00370
00371 return result;
00372 }
00373
00374
00375 template <class T>
00376 Image<T> saliencyChamfer34(const Image<T>& src, const T dmax)
00377 {
00378
00379 ASSERT(src.initialized());
00380 ASSERT(src.getWidth() >= 3 && src.getHeight() >= 3);
00381
00382 Image<T> result = src;
00383
00384 const Dims dims = src.getDims();
00385 const int size = src.getSize();
00386 const int w = dims.w();
00387 const int h = dims.h();
00388 const T zero = T();
00389
00390 Image<T> magImg = src;
00391
00392 #define ALGORITHM CHAMFER34
00393 #if ALGORITHM == CHAMFER34
00394 int MASK_SIZE = 5;
00395 const int x_offset[] = { -1, 0, 1, -1, 0 };
00396 const int y_offset[] = { -1, -1, -1, 0, 0 };
00397 const int i_offset[] = { 4, 3, 4, 3, 0 };
00398 #elif ALGORITHM == CHAMFER5711
00399 int MASK_SIZE = 9;
00400 int x_offset[] = { -1, 1, -2, -1, 0, 1, 2, -1, 0 };
00401 int y_offset[] = { -2, -2, -1, -1, -1, -1, -1, 0, 0 };
00402 int i_offset[] = { 11, 11, 11, 7, 5, 7, 11, 5, 0 };
00403 #endif
00404
00405 typename Image<T>::iterator sptr = magImg.beginw();
00406 typename Image<T>::iterator dptr = result.beginw();
00407
00408 float K = 1.0F;
00409
00410
00411 for (int i = 0; i < size; i ++)
00412 if (*sptr++ > 0) *dptr++ = zero; else *dptr++ = dmax;
00413
00414 double prev_measure = 0, min_measure = 0, measure = 0;
00415 double min_dist,min_mag;
00416 int d[MASK_SIZE],m[MASK_SIZE];
00417
00418 int max_iter = 10;
00419
00420
00421 sptr = magImg.beginw();
00422 dptr = result.beginw();
00423
00424
00425 int j = 0;
00426 bool change = false;
00427 do {
00428 j++;
00429 change = false;
00430
00431
00432 for (int y = 1; y < h-1; y++) {
00433 for (int x = 1; x < w-1; x++) {
00434
00435 prev_measure = (double) (dptr[x + w*y]+K) /
00436 (double) ((unsigned int)sptr[x + w*y]+K);
00437 for (int i = 0; i < MASK_SIZE; i++) {
00438 int xn = x + x_offset[i]; int yn = y + y_offset[i];
00439 d[i] = (int)(dptr[xn + w*yn] + i_offset[i]);
00440 m[i] = (unsigned int)sptr[xn + yn*w];
00441 }
00442
00443 min_dist = d[0];
00444 min_mag = m[0];
00445 min_measure = (double) (d[0]+K) / (double) (m[0]+K);
00446 for (int i = 1; i < MASK_SIZE; i++) {
00447 measure = (double) (d[i]+K) / (double) (m[i]+K);
00448 if (measure < min_measure) {
00449 min_measure = measure;
00450 min_dist = d[i];
00451 min_mag = m[i];
00452 }
00453 }
00454 dptr[x + y*w] = (T)min_dist;
00455 sptr[x + y*w] = (T)min_mag;
00456
00457 if (prev_measure != min_measure)
00458 change = true;
00459 }
00460 }
00461
00462
00463 for (int y = h-2; y >= 1; y--) {
00464 for (int x = w-2; x >= 1; x--) {
00465 prev_measure = (double) (dptr[x + y*w]+K) /
00466 (double) ((unsigned int)sptr[x + y*w]+K);
00467 for (int i = 0; i < MASK_SIZE; i++) {
00468 int xn = x - x_offset[i]; int yn = y - y_offset[i];
00469 d[i] = (int)( dptr[xn + yn*w] + i_offset[i]);
00470 m[i] = (unsigned int)sptr[xn + yn*w];
00471 }
00472
00473 min_dist = d[0];
00474 min_mag = m[0];
00475 min_measure = (double) (d[0]+K) / (double) (m[0]+K);
00476 for (int i = 1; i < MASK_SIZE; i++) {
00477 measure = (double) (d[i]+K) / (double) (m[i]+K);
00478 if (measure < min_measure) {
00479 min_measure = measure;
00480 min_dist = d[i];
00481 min_mag = m[i];
00482 }
00483 }
00484 dptr[x + y*w] = (T)min_dist;
00485 sptr[x + y*w] = (T)min_mag;
00486
00487 if (prev_measure != min_measure)
00488 change = true;
00489 }
00490 }
00491 } while (change && j < max_iter);
00492
00493
00494 for (int y = 1; y < h-1; y++) {
00495 for (int x = 1; x < w-1; x++) {
00496 dptr[x + y*w] = (T) ((double) (dptr[x +y*w]+K) /
00497 (double) ((unsigned int)sptr[x + y*w]+K));
00498 }
00499 }
00500
00501
00502 T max_val = dptr[0];
00503 for (int y = 1; y < h-1; y++)
00504 for (int x = 1; x < w-1; x++)
00505 if (dptr[x + y*w] > max_val)
00506 max_val = dptr[x + y*w];
00507
00508 for (int y = 1; y < h-1; y++)
00509 for (int x = 1; x < w-1; x++)
00510 dptr[x + y*w] = (unsigned char)(dptr[x + y*w] * 255 / max_val);
00511
00512
00513
00514
00515
00516
00517
00518
00519 return result;
00520 }
00521
00522
00523 template <class T>
00524 Image<typename promote_trait<T, float>::TP>
00525 dct(const Image<T>& src, const int offx, const int offy, const int size)
00526 {
00527 ASSERT(src.initialized());
00528 ASSERT(offx + size <= src.getWidth() && offy + size <= src.getHeight());
00529
00530 int m = (int)(log((double)size) / log(2.0) + 0.001);
00531 ASSERT((1 << m) == size);
00532 int N = 1 << m;
00533
00534 float x[512][512], ct[512], s[512][512];
00535 for (int ii = 0; ii < N; ii ++)
00536 for (int jj = 0; jj < N; jj ++)
00537 x[ii][jj] = (float)src.getVal(ii+offx, jj+offy);
00538
00539
00540
00541
00542
00543
00544
00545
00546
00547
00548
00549
00550
00551
00552
00553
00554
00555
00556
00557
00558
00559
00560
00561
00562
00563
00564
00565
00566
00567
00568
00569
00570
00571
00572
00573
00574
00575
00576 {
00577 int is,id,i0,i1,i2,i3;
00578
00579
00580 {
00581 int n2,n4;
00582 double e;
00583 float *p;
00584
00585 n2 = N << 1; p = ct;
00586
00587 for (int k = 1; k < m; k++) {
00588 e = M_PI / n2;
00589 n2 = n2 >> 1;
00590 n4 = n2 >> 2;
00591
00592 for (int j = 0; j < n4; j++) {
00593 *p++ = cos(((j<<2)+1)*e);
00594 *p++ = sin(((j<<2)+1)*e);
00595 *p++ = cos((((j<<2)+1)<<1)*e);
00596
00597 }
00598 }
00599 *p = cos(M_PI/4.0);
00600 }
00601
00602
00603 {
00604 int n1,n2,n;
00605
00606 for(n1=0; n1 <= N; n1++)
00607 for (n2=0; n2<N; n2++ )
00608 s[n1][n2] = x[n1][n2];
00609
00610 for (int cols=0; cols<N; cols++) {
00611 for(n=0; n < N/2; n++) {
00612 x[cols][n] = s[cols][2*n];
00613 x[cols][N-n-1] = s[cols][2*n+1];
00614 }
00615 }
00616 }
00617
00618 for (int rows=0; rows<N; rows++) {
00619 int p=0;
00620 int n2 = N << 1;
00621 for (int k = 1; k < m; k++) {
00622 n2 = n2 >> 1;
00623 const int n4 = n2 >> 2;
00624
00625 for (int j = 0; j < n4; j++) {
00626 is = j;
00627 id = n2 << 1;
00628
00629 again1:
00630 for (i0 = is; i0 < N; i0 +=id) {
00631 i1 = i0 + n4;
00632 i2 = i1 + n4;
00633 i3 = i2 + n4;
00634
00635 float t1 = 2 * (x[rows][i0] - x[rows][i2]) *ct[p] ;
00636 float t2 = (-2) * (x[rows][i1] - x[rows][i3]) * ct[p+1];
00637
00638 x[rows][i0] = x[rows][i0] + x[rows][i2];
00639 x[rows][i1] = x[rows][i1] + x[rows][i3];
00640 x[rows][i2] = t1 + t2;
00641 x[rows][i3] = 2 * (t1 - t2) * ct[p+2];
00642
00643
00644 if (k==m-1) {
00645 x[rows][i2] = x[rows][i2]/2;
00646 x[rows][i3] = x[rows][i3]/2;
00647 }
00648 }
00649 is = (id << 1) - n2 + j;
00650 id = id << 2;
00651 if ( is < N ) goto again1;
00652 p+=3;
00653 }
00654 }
00655
00656 is = 0;
00657 id = 4;
00658 l_again1:
00659 for( i0 = is; i0 < N; i0 += id) {
00660 i1 = i0 + 1;
00661 float t1 = x[rows][i0];
00662 x[rows][i0] = t1 + x[rows][i1];
00663
00664 if (i0 != 0) x[rows][i0] = x[rows][i0]/2;
00665 x[rows][i1] = (t1 - x[rows][i1]) * ct[p];
00666 }
00667 is = (id << 1) - 2;
00668 id = id << 2;
00669 if( is < N ) goto l_again1;
00670 }
00671
00672
00673 {
00674 int v1, v2, v3,i,k;
00675 float xt;
00676
00677
00678 for (int cols =0; cols<N; cols ++) {
00679 v1 = (m+1)/2;
00680 v2 = 1 << v1;
00681 v3 = N-1-v2;
00682 int j=0;
00683 for(i=1; i<=v3; i++){
00684 k= N>>1;
00685 while(k<=j){
00686 j=j-k;
00687 k=k>>1;
00688 }
00689 j +=k;
00690 if(i<j){
00691 xt=x[cols][j];
00692 x[cols][j]=x[cols][i];
00693 x[cols][i]=xt;
00694 }
00695 }
00696 }
00697 }
00698
00699 {
00700 int step,loops,ep,i,l;
00701
00702 for (int rows=0; rows<N; rows++) {
00703 step =N;
00704 loops = 1;
00705 for (int k=1; k<m; k++) {
00706 step = step>>1;
00707 ep = step>>1;
00708 loops = loops <<1;
00709 for (int j=0; j<(step>>1); j++) {
00710 l=ep;
00711 for (i=1; i<loops;i++) {
00712 x[rows][l+step] = x[rows][l+step]-x[rows][l];
00713 l =l+step;
00714 }
00715 ep +=1;
00716 }
00717 }
00718 }
00719 }
00720
00721 {
00722 int n1,n2,n;
00723
00724 for(n1=0; n1 <= N; n1++)
00725 for (n2=0; n2<N; n2++ )
00726 s[n1][n2] = x[n1][n2];
00727
00728 for (int rows=0; rows<N; rows++) {
00729 for(n=0; n < N/2; n++) {
00730 x[n][rows] = s[2*n][rows];
00731 x[N-n-1][rows] = s[2*n+1][rows];
00732 }
00733 }
00734 }
00735
00736 for (int cols=0; cols<N; cols++) {
00737 int p=0;
00738
00739 int n2 = N << 1;
00740 for (int k = 1; k < m; k++) {
00741 n2 = n2 >> 1;
00742 const int n4 = n2 >> 2;
00743
00744 for (int j = 0; j < n4; j++) {
00745 is = j;
00746 id = n2 << 1;
00747 again2:
00748 for (i0 = is; i0 < N; i0 +=id) {
00749 i1 = i0 + n4;
00750 i2 = i1 + n4;
00751 i3 = i2 + n4;
00752
00753 float t1 = 2 * (x[i0][cols] - x[i2][cols]) *ct[p] ;
00754 float t2 = (-2) * (x[i1][cols]-x[i3][cols])* ct[p+1];
00755
00756 x[i0][cols] = x[i0][cols] + x[i2][cols];
00757 x[i1][cols] = x[i1][cols] + x[i3][cols];
00758 x[i2][cols] = t1 + t2;
00759 x[i3][cols] = 2 * (t1 - t2) * ct[p+2];
00760
00761
00762 if (k==m-1) {
00763 x[i2][cols] = x[i2][cols]/2;
00764 x[i3][cols] = x[i3][cols]/2;
00765 }
00766 }
00767
00768 is = (id << 1) - n2 + j;
00769 id = id << 2;
00770 if ( is < N ) goto again2;
00771 p+=3;
00772 }
00773 }
00774
00775
00776 is = 0;
00777 id = 4;
00778 l_again2:
00779 for( i0 = is; i0 < N; i0 += id) {
00780 i1 = i0 + 1;
00781
00782 float t1 = x[i0][cols];
00783 x[i0][cols] = t1 + x[i1][cols];
00784
00785 if (i0 != 0) x[i0][cols] = x[i0][cols]/2;
00786 x[i1][cols] = (t1 - x[i1][cols]) * ct[p];
00787 }
00788
00789 is = (id << 1) - 2;
00790 id = id << 2;
00791 if( is < N ) goto l_again2;
00792
00793 }
00794
00795
00796 {
00797 int v1, v2, v3,i,k;
00798 float xt;
00799
00800 for (int rows =0; rows<N; rows ++) {
00801 v1 = (m+1)/2;
00802 v2 = 1 << v1;
00803 v3 = N-1-v2;
00804 int j=0;
00805 for(i=1; i<=v3; i++){
00806 k= N>>1;
00807 while(k<=j){
00808 j=j-k;
00809 k=k>>1;
00810 }
00811 j +=k;
00812 if(i<j){
00813 xt=x[j][rows];
00814 x[j][rows]=x[i][rows];
00815 x[i][rows]=xt;
00816 }
00817 }
00818 }
00819 }
00820
00821
00822 {
00823 int step,loops,ep,i,l;
00824
00825 for (int cols=0; cols<N; cols++) {
00826 step =N;
00827 loops = 1;
00828 for (int k=1; k<m; k++) {
00829 step = step>>1;
00830 ep = step>>1;
00831 loops = loops <<1;
00832 for (int j=0; j<(step>>1); j++) {
00833 l=ep;
00834 for (i=1; i<loops; i++) {
00835 x[l+step][cols] = x[l+step][cols] - x[l][cols];
00836 l =l+step;
00837 }
00838 ep +=1;
00839 }
00840 }
00841 }
00842 }
00843
00844 }
00845 typedef typename promote_trait<T, float>::TP TF;
00846 Image<TF> result(N, N, NO_INIT);
00847 for (int ii = 0; ii < N; ii ++)
00848 for (int jj = 0; jj < N; jj ++)
00849 result.setVal(ii, jj, x[ii][jj] * 4.0F);
00850
00851 return result;
00852 }
00853
00854
00855 template <class T>
00856 float infoFFT(const Image<T>& src, const float eps, const Rectangle& rect)
00857 {
00858 Image<float> tmp = crop(src, rect);
00859 Image<float> tmp2 = infoFFT(tmp, eps);
00860 float mini, maxi;
00861 getMinMax(tmp2, mini, maxi);
00862 return maxi;
00863 }
00864
00865
00866 template <class T>
00867 Image<float> infoFFT(const Image<T>& src, const float eps)
00868 {
00869 Image<float> result(src.getWidth() / 4, src.getHeight() / 4, NO_INIT);
00870
00871
00872 const Dims dims = src.getDims();
00873
00874 for (int cx = 0; cx < dims.w(); cx += 4)
00875 for (int cy = 0; cy < dims.h(); cy += 4)
00876 {
00877 int offx = cx - 8, offy = cy - 8;
00878 if (dims.w() > 32 && dims.h() > 32)
00879 {
00880
00881 if (offx == dims.w() - 16) offx = dims.w();
00882
00883
00884 if (offy == dims.h() - 16) offy = dims.h();
00885 }
00886
00887 if (offx >= 0 &&
00888 offy >= 0 &&
00889 offx+16 <= dims.w() &&
00890 offy+16 <= dims.h())
00891 {
00892
00893
00894 float data[16][33];
00895 for (int row = 0; row < 16; row ++)
00896 for (int col = 0; col < 16; col ++)
00897 {
00898 data[row][col*2+2] = 0.0;
00899 data[row][col*2+1] = (float) src.getVal(offx+col, offy+row);
00900 }
00901
00902 for (int row = 0; row < 16; row ++)
00903 {
00904
00905
00906 int j = 1;
00907 for (int i = 1; i < 32; i += 2)
00908 {
00909 if (j > i)
00910 { float tmp = data[row][i]; data[row][i] = data[row][j];
00911 data[row][j] = tmp; tmp = data[row][i+1];
00912 data[row][i+1] = data[row][j+1]; data[row][j+1] = tmp; }
00913 int m = 16; while (m >= 2 && j > m) { j -= m; m >>= 1; }
00914 j += m;
00915 }
00916 int mmax = 2;
00917 while (32 > mmax)
00918 {
00919 int istep = mmax << 1; float theta = -2*M_PI/(float)mmax;
00920 float wtemp = sin(0.5*theta); float wpr = -2.0*wtemp*wtemp;
00921 float wpi = sin(theta); float wr = 1.0; float wi = 0.0;
00922 for (int m = 1; m < mmax; m += 2)
00923 {
00924 for (int i = m; i <= 32; i += istep)
00925 {
00926 j = i + mmax;
00927 float tempr=wr*data[row][j]-wi*data[row][j+1];
00928 float tempi = wr*data[row][j+1]+wi*data[row][j];
00929 data[row][j] = data[row][i]-tempr;
00930 data[row][j+1] = data[row][i+1]-tempi;
00931 data[row][i]+=tempr;
00932 data[row][i+1]+=tempi;
00933 }
00934 wr=(wtemp=wr)*wpr-wi*wpi+wr; wi=wi*wpr+wtemp*wpi+wi;
00935 }
00936 mmax = istep;
00937 }
00938 }
00939
00940
00941 for (int row = 0; row < 16; row ++)
00942 for (int col = 0; col < row; col ++)
00943 {
00944
00945 float tt = data[row][col*2+1];
00946 data[row][col*2+1] = data[col][row*2+1];
00947 data[col][row*2+1] = tt;
00948 tt = data[row][col*2+2];
00949 data[row][col*2+2] = data[col][row*2+2];
00950 data[col][row*2+2] = tt;
00951 }
00952
00953
00954 for (int row = 0; row < 16; row ++)
00955 {
00956
00957
00958 int j = 1;
00959 for (int i = 1; i < 32; i += 2)
00960 {
00961 if (j > i)
00962 { float tmp = data[row][i]; data[row][i] = data[row][j];
00963 data[row][j] = tmp; tmp = data[row][i+1];
00964 data[row][i+1] = data[row][j+1]; data[row][j+1] = tmp; }
00965 int m = 16; while (m >= 2 && j > m) { j -= m; m >>= 1; }
00966 j += m;
00967 }
00968 int mmax = 2;
00969 while (32 > mmax)
00970 {
00971 int istep = mmax << 1; float theta = -2*M_PI/(float)mmax;
00972 float wtemp = sin(0.5*theta); float wpr = -2.0*wtemp*wtemp;
00973 float wpi = sin(theta); float wr = 1.0; float wi = 0.0;
00974 for (int m = 1; m < mmax; m += 2)
00975 {
00976 for (int i = m; i <= 32; i += istep)
00977 {
00978 j = i + mmax;
00979 float tempr=wr*data[row][j]-wi*data[row][j+1];
00980 float tempi = wr*data[row][j+1]+wi*data[row][j];
00981 data[row][j] = data[row][i]-tempr;
00982 data[row][j+1] = data[row][i+1]-tempi;
00983 data[row][i]+=tempr;
00984 data[row][i+1]+=tempi;
00985 }
00986 wr=(wtemp=wr)*wpr-wi*wpi+wr; wi=wi*wpr+wtemp*wpi+wi;
00987 }
00988 mmax = istep;
00989 }
00990 }
00991
00992
00993
00994
00995 float nbsup = 0.0;
00996 float epsn = (eps * 256.0 * 127.5)*(eps * 256.0 * 127.5);
00997
00998 for (int row = 0; row < 16; row ++)
00999 for (int col = 1; col <= 32; col += 2)
01000 {
01001 float val = data[row][col]*data[row][col] +
01002 data[row][col+1]*data[row][col+1];
01003 if (val > epsn) nbsup += 1.0;
01004 }
01005 result.setVal(cx/4, cy/4, nbsup / 256.0);
01006 }
01007 else
01008 result.setVal(cx/4, cy/4, 0.0);
01009 }
01010
01011 return result;
01012 }
01013
01014
01015 double learningCoeff(const Image<float>& featureMap,
01016 const Image<byte>& targetDMap,
01017 const bool softmask,
01018 const int in_thresh, const int out_thresh)
01019 {
01020 ASSERT(featureMap.initialized()); ASSERT(targetDMap.initialized());
01021 ASSERT(featureMap.isSameSize(targetDMap));
01022
01023 const bool havein = (in_thresh >= 0 && in_thresh <= 255);
01024 const bool haveou = (out_thresh >= 0 && out_thresh <= 255);
01025
01026 if (softmask)
01027 {
01028
01029
01030
01031
01032 float av = mean(featureMap) / float(featureMap.getSize());
01033 float oav = sum(featureMap * targetDMap) / (255.0f * sum(targetDMap));
01034 Image<float> mask = binaryReverse(targetDMap, byte(255));
01035 float iav = sum(featureMap * mask) / (255.0f * sum(mask));
01036
01037 if (!havein && !haveou)
01038 { LFATAL("At least one threshold must be valid"); return 0.0;}
01039 else if (!havein && haveou)
01040 return double((av - oav) / av);
01041 else if (havein && !haveou)
01042 return double((iav - av) / av);
01043 else
01044 return double((iav - oav) / av);
01045 }
01046 else
01047 {
01048
01049
01050
01051
01052
01053
01054
01055
01056 Image<byte>::const_iterator dmapptr = targetDMap.begin();
01057 Image<float>::const_iterator sptr = featureMap.begin(),
01058 stop = featureMap.end();
01059
01060 float glob_min = *sptr; float glob_max = *sptr;
01061 float in_max = 0.0f; float out_max = 0.0f;
01062
01063 while (sptr != stop)
01064 {
01065 const int mapval = *dmapptr++;
01066 const float val = *sptr++;
01067 if (mapval <= in_thresh && val > in_max) in_max = val;
01068 if (mapval >= out_thresh && val > out_max) out_max = val;
01069 if (val < glob_min) glob_min = val;
01070 if (val > glob_max) glob_max = val;
01071 }
01072
01073 if (!havein && !haveou)
01074 { LFATAL("At least one threshold must be valid"); return 0.0;}
01075 else if (!havein && haveou)
01076 return -double(in_max) / (double(glob_max) - double(glob_min));
01077 else if (havein && !haveou)
01078 return double(in_max) / (double(glob_max) - double(glob_min));
01079 else
01080 return (double(in_max) - double(out_max)) /
01081 (double(glob_max) - double(glob_min));
01082 }
01083 }
01084
01085
01086 template <class T>
01087 Image<T> scaleBlock(const Image<T>& src, const Dims newDims)
01088 {
01089 int new_w = newDims.w(), new_h = newDims.h();
01090 std::vector<int> col_idx(new_w), row_idx(new_h);
01091 int w = src.getWidth(), h = src.getHeight();
01092
01093 for (int x = 0; x < new_w; x++)
01094 col_idx[x] = (int)((float)x / (float)new_w * (float)w);
01095 for (int y = 0; y < new_h; y++)
01096 row_idx[y] = (int)((float)y / (float)new_h * (float)h);
01097
01098 Image<T> result(new_w, new_h, NO_INIT);
01099 typename Image<T>::iterator rptr = result.beginw();
01100 for (int y = 0; y < new_h; y++)
01101 for (int x = 0; x < new_w; x++)
01102 {
01103 *rptr++ = src.getVal(col_idx[x],row_idx[y]);
01104 }
01105 return result;
01106 }
01107
01108
01109 template <class T>
01110 int floodClean(const Image<T>& src, Image<T>& dest, const Point2D<int>& seed,
01111 const T thresh, const T val, int numConn)
01112 {
01113 ASSERT(src.initialized()); ASSERT(src.coordsOk(seed));
01114
01115
01116
01117
01118
01119 if (!dest.initialized()) dest.resize(src.getDims(),true);
01120
01121 if (src.getVal(seed) < thresh) return -1;
01122
01123
01124 std::vector<Point2D<int> > stk;
01125 const int STACKSIZE = 256 * 256 + 20;
01126 stk.reserve(STACKSIZE);
01127 stk.push_back(seed);
01128
01129
01130 std::vector<Point2D<int> > dirs(8);
01131 dirs[0] = Point2D<int>(1,0); dirs[1] = Point2D<int>(0,1);
01132 dirs[2] = Point2D<int>(0,-1); dirs[3] = Point2D<int>(-1,0);
01133 dirs[4] = Point2D<int>(1,1); dirs[5] = Point2D<int>(1,-1);
01134 dirs[6] = Point2D<int>(-1,-1); dirs[7] = Point2D<int>(-1,1);
01135
01136
01137 Image<byte> visited(src.getDims(), ZEROS);
01138 int nbpix = 0;
01139
01140 while (! stk.empty())
01141 {
01142 Point2D<int> index = stk.back(); stk.pop_back();
01143 if (!visited.getVal(index))
01144 {
01145
01146 dest.setVal(index, val);
01147 visited.setVal(index,1);
01148 ++nbpix;
01149
01150 for (int i = 0; i < numConn; i++)
01151 {
01152 Point2D<int> idx2 = index + dirs[i];
01153 if ((src.coordsOk(idx2)) &&
01154 (!visited.getVal(idx2)) &&
01155 (src.getVal(idx2) >= thresh)
01156 )
01157 stk.push_back(idx2);
01158 }
01159 }
01160 }
01161 return nbpix;
01162 }
01163
01164
01165 template <class T>
01166 int floodCleanBB(const Image<T>& src, Image<T>& dest, const Point2D<int>& seed,
01167 const T thresh, const T val, Rectangle& bbox)
01168 {
01169 ASSERT(src.initialized()); ASSERT(src.coordsOk(seed));
01170
01171 int ll = src.getWidth(), rr = -1, tt = src.getHeight(), bb = -1;
01172
01173
01174
01175
01176
01177 if (!dest.initialized()) dest.resize(src.getDims(),true);
01178
01179 if (src.getVal(seed) < thresh) return -1;
01180
01181
01182 std::vector<Point2D<int> > stk;
01183 const int STACKSIZE = 256 * 256 + 20;
01184 stk.reserve(STACKSIZE);
01185 stk.push_back(seed);
01186
01187
01188 std::vector<Point2D<int> > dirs(8);
01189 dirs[0] = Point2D<int>(1,0); dirs[1] = Point2D<int>(0,1);
01190 dirs[2] = Point2D<int>(1,1); dirs[3] = Point2D<int>(1,-1);
01191 dirs[4] = Point2D<int>(0,-1); dirs[5] = Point2D<int>(-1,0);
01192 dirs[6] = Point2D<int>(-1,-1); dirs[7] = Point2D<int>(-1,1);
01193
01194
01195 Image<byte> visited(src.getDims(), ZEROS);
01196 int nbpix = 0;
01197
01198 while (! stk.empty())
01199 {
01200 Point2D<int> index = stk.back(); stk.pop_back();
01201 if (visited.getVal(index) == 0)
01202 {
01203
01204 dest.setVal(index, val);
01205 visited.setVal(index,1);
01206 ++nbpix;
01207
01208
01209 if (index.i < ll) ll = index.i;
01210 if (index.i > rr) rr = index.i;
01211 if (index.j < tt) tt = index.j;
01212 if (index.j > bb) bb = index.j;
01213
01214 for (int i = 0; i < 8; i++)
01215 {
01216 Point2D<int> idx2 = index + dirs[i];
01217 if ((src.coordsOk(idx2)) &&
01218 (src.getVal(idx2) >= thresh) &&
01219 (visited.getVal(idx2) == 0))
01220 stk.push_back(idx2);
01221 }
01222 }
01223 }
01224 if (nbpix > 0) bbox = Rectangle::tlbrI(tt,ll,bb,rr);
01225 return nbpix;
01226 }
01227
01228
01229 template <class T>
01230 Image<float> distDegrade(const Image<T>& src, const Point2D<int>& foa, const float area)
01231 {
01232 float s2 = area / 100.0;
01233 float dist2,dx,dy;
01234 const T zero = T();
01235 Image<float> result(src.getDims(),ZEROS);
01236 typename Image<float>::iterator rptr = result.beginw();
01237 typename Image<T>::const_iterator sptr = src.begin();
01238
01239 for (int y = 0; y < src.getHeight(); y++)
01240 for (int x = 0; x < src.getWidth(); x++)
01241 {
01242 if (*sptr > zero)
01243 {
01244 dx = x - foa.i;
01245 dy = y - foa.j;
01246 dist2 = dx * dx + dy * dy;
01247 if (dist2 == 0.0)
01248 *rptr = 1.0;
01249 else
01250 *rptr = 1.0 - exp( - s2 / dist2);
01251 }
01252 sptr++; rptr++;
01253 }
01254 return result;
01255 }
01256
01257
01258 template <class T>
01259 Image<byte> segmentObjectClean(const Image<T>& src,
01260 const Point2D<int>& seed, int numConn)
01261 {
01262 float start = 0.5, pstep = 0.05, mina = 0.05, expl = 1.05;
01263 float stop = 0.1;
01264 ASSERT(src.initialized());
01265 Image<T> tmp;
01266 bool explode = false; int prev = 0; double thresh = 1.0, minThresh = 0.0;
01267 double step = double(src.getVal(seed.i, seed.j)) * pstep;
01268 int minadiff = int(float(src.getSize()) * mina);
01269 double efac = expl;
01270 int iter = 0;
01271
01272
01273 while(!explode && minadiff > 0 && efac > 1.0)
01274 {
01275
01276 thresh = double(src.getVal(seed.i, seed.j)) * start;
01277 minThresh = double(src.getVal(seed.i, seed.j)) * stop;
01278 iter = 0;
01279
01280
01281 while(!explode && thresh > minThresh)
01282 {
01283 tmp.freeMem();
01284 int area = floodClean(src, tmp, seed, (T)thresh, (T)255.0, numConn);
01285 LDEBUG("%d->%d[%d] t=%.3f efac=%.3f",
01286 prev, area, minadiff, thresh, efac);
01287
01288
01289
01290
01291 if (iter > 1 && area > prev + minadiff &&
01292 area > int(double(prev)*efac))
01293 explode = true;
01294 else
01295 { prev = area; thresh -= step; }
01296 iter ++;
01297 }
01298
01299 minadiff -= minadiff / 4; efac *= 0.95;
01300 }
01301
01302
01303 thresh += step;
01304 tmp.freeMem();
01305 floodClean(src, tmp, seed, (T)thresh, (T)255.0, numConn);
01306
01307 return Image<byte>(tmp);
01308 }
01309
01310
01311 template <class T>
01312 Image<T> highThresh(const Image<T>& src, const T thresh, const T val)
01313 {
01314 ASSERT(src.initialized());
01315 Image<T> res(src);
01316 typename Image<T>::iterator aptr = res.beginw(), stop = res.endw();
01317
01318 while (aptr != stop)
01319 {
01320 if (*aptr >= thresh) *aptr = val;
01321 ++aptr;
01322 }
01323 return res;
01324 }
01325
01326
01327 template <class T_or_RGB>
01328 Image<T_or_RGB> replaceVals(const Image<T_or_RGB>& src,
01329 const T_or_RGB from,
01330 const T_or_RGB to,
01331 const T_or_RGB other)
01332 {
01333 Image<T_or_RGB> result(src.getDims(), NO_INIT);
01334 typename Image<T_or_RGB>::const_iterator sptr = src.begin();
01335 typename Image<T_or_RGB>::iterator rptr = result.beginw();
01336 while (rptr != result.endw())
01337 *rptr++ = (*sptr++ == from) ? to : other;
01338 return result;
01339 }
01340
01341
01342 template <class T_or_RGB>
01343 Image<T_or_RGB> replaceVals(const Image<T_or_RGB>& src,
01344 const T_or_RGB from,
01345 const T_or_RGB to)
01346 {
01347 if (from == to) return src;
01348 Image<T_or_RGB> result(src.getDims(), NO_INIT);
01349 typename Image<T_or_RGB>::const_iterator sptr = src.begin();
01350 typename Image<T_or_RGB>::iterator rptr;
01351 for (rptr = result.beginw(); rptr != result.endw(); ++rptr, ++sptr)
01352 *rptr = (*sptr == from) ? to : *sptr;
01353 return result;
01354 }
01355
01356
01357 template <class T_or_RGB>
01358 Image<T_or_RGB> composite(const Image<T_or_RGB>& fg,
01359 const Image<T_or_RGB>& bg,
01360 const T_or_RGB transparent)
01361 {
01362 ASSERT(fg.isSameSize(bg));
01363
01364 Image<T_or_RGB> result(fg.getDims(), NO_INIT);
01365 typename Image<T_or_RGB>::const_iterator
01366 fgptr = fg.begin(), bgptr = bg.begin(), stop = fg.end();
01367 typename Image<T_or_RGB>::iterator rptr = result.beginw();
01368
01369 while(fgptr != stop)
01370 {
01371 if (*fgptr == transparent) *rptr++ = *bgptr;
01372 else *rptr++ = *fgptr;
01373
01374 ++fgptr; ++bgptr;
01375 }
01376
01377 return result;
01378 }
01379
01380
01381 template <class T_or_RGB>
01382 Image<T_or_RGB> createMask(const Image<T_or_RGB>& fg,
01383 const Image<bool> mask,
01384 const T_or_RGB transparent = T_or_RGB())
01385 {
01386 ASSERT(fg.isSameSize(mask));
01387 Image<T_or_RGB> result(fg.getDims(), NO_INIT);
01388 typename Image<T_or_RGB>::const_iterator
01389 fgptr = fg.begin(), stop = fg.end();
01390 typename Image<bool>::const_iterator
01391 maskptr = mask.begin();
01392 typename Image<T_or_RGB>::iterator rptr = result.beginw();
01393
01394 while(fgptr != stop)
01395 {
01396 if (*maskptr) *rptr++ = *fgptr;
01397 else *rptr++ = transparent;
01398
01399 ++fgptr; ++maskptr;
01400 }
01401
01402 return result;
01403
01404 }
01405
01406
01407 template <class T_or_RGB>
01408 Image<T_or_RGB> mosaic(const Image<T_or_RGB>& fg,
01409 const Image<T_or_RGB>* bg,
01410 const T_or_RGB* transvalues,
01411 const uint Nimages)
01412 {
01413 uint i;
01414 for(i = 0; i < Nimages; i++)
01415 ASSERT(fg.isSameSize(bg[i]));
01416
01417 Image<T_or_RGB> result(fg.getDims(), NO_INIT);
01418 typename Image<T_or_RGB>::const_iterator
01419 fgptr = fg.begin(), stop = fg.end();
01420
01421 typename Image<T_or_RGB>::const_iterator bgptr[Nimages];
01422 for(i = 0; i < Nimages; i++)
01423 bgptr[i] = bg[i].begin();
01424
01425 typename Image<T_or_RGB>::iterator rptr = result.beginw();
01426
01427 while(fgptr != stop)
01428 {
01429 i = 0;
01430 while(*fgptr != transvalues[i] && i < Nimages) i++;
01431 if (i < Nimages)
01432 *rptr++ = *bgptr[i];
01433 else
01434 *rptr++ = *fgptr;
01435
01436 ++fgptr;
01437 for(i = 0; i < Nimages; i++)
01438 bgptr[i]++;
01439 }
01440
01441 return result;
01442 }
01443
01444
01445 template <class T_or_RGB>
01446 Image<T_or_RGB> alphaBlend(const Image<T_or_RGB>& fg,
01447 const Image<T_or_RGB>& bg,
01448 const double alpha,
01449 const T_or_RGB transparent)
01450 {
01451 ASSERT(fg.isSameSize(bg));
01452 ASSERT(alpha>=0 && alpha<=1);
01453
01454 Image<T_or_RGB> result(fg.getDims(), NO_INIT);
01455 typename Image<T_or_RGB>::const_iterator
01456 fgptr = fg.begin(), bgptr = bg.begin(), stop = fg.end();
01457 typename Image<T_or_RGB>::iterator rptr = result.beginw();
01458
01459 while(fgptr != stop)
01460 {
01461 if (*fgptr == transparent) *rptr++ = *bgptr;
01462 else *rptr++ = T_or_RGB((*fgptr) * (1-alpha) + T_or_RGB(*bgptr) * alpha);
01463
01464 ++fgptr; ++bgptr;
01465 }
01466
01467 return result;
01468 }
01469
01470
01471 template <class T>
01472 Image<byte> makeBinary(const Image<T>& src, const T& threshold,
01473 const byte lowVal, const byte highVal)
01474 {
01475 Image<byte> result(src.getDims(), NO_INIT);
01476 typename Image<T>::const_iterator sptr = src.begin();
01477 Image<byte>::iterator rptr = result.beginw(), stop = result.endw();
01478 while (rptr != stop)
01479 *rptr++ = (*sptr++ <= threshold) ? lowVal : highVal;
01480 return result;
01481 }
01482
01483
01484 template <class T>
01485 Image<byte> makeBinary2(const Image<T>& src,
01486 const T& lowThresh, const T& highThresh,
01487 const byte lowVal, const byte highVal)
01488 {
01489 Image<byte> result(src.getDims(), NO_INIT);
01490 typename Image<T>::const_iterator sptr = src.begin();
01491 Image<byte>::iterator rptr = result.beginw(), stop = result.endw();
01492 while (rptr != stop)
01493 {
01494 *rptr++ = (*sptr >= lowThresh && *sptr <= highThresh) ? highVal : lowVal;
01495 sptr++;
01496 }
01497 return result;
01498 }
01499
01500
01501 template <class T_or_RGB>
01502 void pasteImage(Image<T_or_RGB>& background,
01503 const Image<T_or_RGB>& foreground,
01504 const T_or_RGB& transparent,
01505 const Point2D<int> location,
01506 float opacity)
01507 {
01508 float op2 = 1.0F - opacity;
01509 int bw = background.getWidth();
01510 int bh = background.getHeight();
01511 int fw = foreground.getWidth();
01512 int fh = foreground.getHeight();
01513
01514 Point2D<int> bStart = location;
01515 Point2D<int> fStart(0,0);
01516 Point2D<int> bEnd(location.i + fw, location.j + fh);
01517 Point2D<int> fEnd(fw,fh);
01518
01519 if (bStart.i < 0) { fStart.i -= bStart.i; bStart.i = 0; }
01520 if (bStart.j < 0) { fStart.j -= bStart.j; bStart.j = 0; }
01521 if (bEnd.i > bw) { fEnd.i -= (bEnd.i - bw); bEnd.i = bw; }
01522 if (bEnd.j > bh) { fEnd.j -= (bEnd.j - bh); bEnd.j = bh; }
01523
01524
01525 typename Image<T_or_RGB>::iterator bPtr1, bPtr2;
01526 typename Image<T_or_RGB>::const_iterator fPtr1, fPtr2;
01527 bPtr1 = background.beginw() + bStart.j * bw + bStart.i;
01528 fPtr1 = foreground.begin() + fStart.j * fw + fStart.i;
01529
01530
01531 for (int y = bStart.j; y < bEnd.j; ++y)
01532 {
01533 bPtr2 = bPtr1; fPtr2 = fPtr1;
01534 for (int x = bStart.i; x < bEnd.i; ++x)
01535 {
01536 if (*fPtr2 != transparent)
01537 *bPtr2 = T_or_RGB(*bPtr2 * op2 + *fPtr2 * opacity);
01538 ++bPtr2; ++fPtr2;
01539 }
01540 bPtr1 += bw; fPtr1 += fw;
01541 }
01542 }
01543
01544
01545 template <class T>
01546 void inplacePasteGabor(Image<T>& dst,
01547 const Image<T>& gabor,
01548 const Point2D<int>& pos, const T background)
01549 {
01550 int w = dst.getWidth(), h = dst.getHeight();
01551 int iw = gabor.getWidth(), ih = gabor.getHeight();
01552 ASSERT(pos.i + iw <= w && pos.j + ih <= h);
01553 T dist, idist;
01554
01555 typename Image<T>::const_iterator sptr = gabor.begin();
01556 typename Image<T>::iterator dptr = dst.beginw() + pos.i + pos.j * w;
01557 for (int j = 0; j < ih; j ++)
01558 {
01559 for (int i = 0; i < iw; i ++)
01560 {
01561 dist = T(*dptr - background);
01562 if (dist < 0.0F) dist = T(dist * -1);
01563 if (*sptr < 0.0F) idist = T(*sptr * -1);
01564 else idist = *sptr;
01565
01566 if (dist < idist)
01567 {
01568 *dptr = T(*sptr+background);
01569 }
01570 dptr++;
01571 sptr++;
01572 }
01573 dptr += w - iw;
01574 }
01575 }
01576
01577
01578 template <class T>
01579 int flood(const Image<T>& src,
01580 Image<T>& dest, const Point2D<int>& seed,
01581 const T thresh, const T val)
01582 {
01583 ASSERT(src.initialized());
01584 ASSERT(src.coordsOk(seed));
01585
01586
01587 if (!dest.initialized()) dest.resize(src.getDims(), true);
01588
01589 if (src.getVal(seed) < thresh) return -1;
01590
01591 const T zero = T();
01592
01593 const int size = src.getSize();
01594 const int w = src.getWidth();
01595
01596
01597 std::vector<int> stk;
01598
01599 const int STACKSIZE = 256 * 256 + 20;
01600 stk.reserve(STACKSIZE);
01601
01602 stk.push_back(seed.i + w * seed.j);
01603
01604 Image<T> input = src;
01605 typename Image<T>::iterator const inptr = input.beginw();
01606
01607 int nbpix = 0;
01608
01609 while (! stk.empty())
01610 {
01611 int index = stk.back(); stk.pop_back();
01612 if (inptr[index] != zero)
01613 {
01614
01615 dest.setVal(index, val);
01616 inptr[index] = zero;
01617 ++nbpix;
01618
01619
01620 if ((index+1 < size) && (inptr[index+1] >= thresh))
01621 stk.push_back( index+1 );
01622
01623 if ((index+w < size) && (inptr[index+w] >= thresh))
01624 stk.push_back( index+w );
01625
01626 if ((index+w+1 < size) && (inptr[index+w+1] >= thresh))
01627 stk.push_back( index+w+1 );
01628
01629 if ((index+w-1 < size) && (inptr[index+w-1] >= thresh))
01630 stk.push_back( index+w-1 );
01631
01632 if ((index-1 >= 0) && (inptr[index-1] >= thresh))
01633 stk.push_back( index-1 );
01634
01635 if ((index-w >= 0) && (inptr[index-w] >= thresh))
01636 stk.push_back( index-w );
01637
01638 if ((index-w-1 >= 0) && (inptr[index-w-1] >= thresh))
01639 stk.push_back( index-w-1 );
01640
01641 if ((index-w+1 >= 0) && (inptr[index-w+1] >= thresh))
01642 stk.push_back( index-w+1 );
01643 }
01644 }
01645 return nbpix;
01646 }
01647
01648
01649 template <class T>
01650 int countParticles(const Image<T>& src, const T thresh)
01651 {
01652 Point2D<int> p;
01653 int nbpart = 0;
01654 Image<T> tmp = src;
01655 T fill = thresh;
01656 const T zero = T();
01657 if (fill >= zero + (T)1.0) fill -= (T)1.0;
01658 else LFATAL("Cannot count particles with such low threshold");
01659
01660 for (p.i = 0; p.i < src.getWidth(); ++p.i)
01661 for (p.j = 0; p.j < src.getHeight(); ++p.j)
01662 if (tmp.getVal(p) >= thresh)
01663 {
01664 ++nbpart;
01665 Image<T> tmp2 = tmp;
01666 flood(tmp2, tmp, p, thresh, fill);
01667 }
01668 return nbpart;
01669 }
01670
01671
01672 template <class T>
01673 void inplaceAddBGnoise(Image<T>& src, const float range)
01674 {
01675
01676 #define BGNOISELEVEL 0.00001
01677
01678 inplaceAddBGnoise2(src, range * BGNOISELEVEL);
01679 }
01680
01681
01682 template <class T>
01683 void inplaceAddBGnoise2(Image<T>& src, const float range)
01684 {
01685 ASSERT(src.initialized());
01686 const int w = src.getWidth(), h = src.getHeight();
01687
01688
01689 int siz = std::min(w, h) / 10;
01690
01691 typename Image<T>::iterator sptr = src.beginw() + siz + siz * w;
01692
01693 for (int j = siz; j < h - siz; ++j)
01694 {
01695 for (int i = siz; i < w - siz; ++i)
01696 *sptr++ += clamped_convert<T>(range * randomDouble());
01697 sptr += siz + siz;
01698 }
01699 }
01700
01701
01702 #include "inst/Image/Transforms.I"
01703
01704
01705
01706
01707
01708
01709
01710 #endif // !IMAGE_TRANSFORMS_C_DEFINED