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 #include "SpaceVariant/SpaceVariantTransforms.H"
00037 #include "Image/MatrixOps.H"
00038 #include "Image/CutPaste.H"
00039 #include "Image/LowPass.H"
00040 #include "Image/ImageSet.H"
00041 #include "Image/Pixels.H"
00042 #include "Util/Assert.H"
00043
00044 #include <cmath>
00045 #include <deque>
00046
00047 #define PI 3.14159265F
00048 #define PI2 PI/2.0F
00049 #define EPS 0.001F
00050
00051
00052
00053
00054 SpaceVariantTransform::SpaceVariantTransform() :
00055 itsLookup(), itsRevLookup(), itsStd(), itsMaxStd(0.0), isInitialized(false)
00056 {
00057 }
00058
00059
00060 SpaceVariantTransform::~SpaceVariantTransform()
00061 {
00062 }
00063
00064
00065 bool SpaceVariantTransform::initialized() const
00066 {
00067 return isInitialized;
00068 }
00069
00070
00071 void SpaceVariantTransform::to(const int x, const int y,
00072 int& rings, int& wedges) const
00073 {
00074 std::pair<float, float> p = itsRevLookup.getVal(x, y);
00075 rings = (int)round(p.first); wedges = (int)round(p.second);
00076 }
00077
00078
00079 void SpaceVariantTransform::to(const int x, const int y,
00080 float& rings, float& wedges) const
00081 {
00082 std::pair<float, float> p = itsRevLookup.getVal(x, y);
00083 rings = p.first; wedges = p.second;
00084 }
00085
00086
00087 void SpaceVariantTransform::from(const int rings, const int wedges,
00088 int& x, int& y) const
00089 {
00090 std::pair<float, float> p = itsLookup.getVal(rings, wedges);
00091 x = (int)round(p.first); y = (int)round(p.second);
00092 }
00093
00094
00095 void SpaceVariantTransform::from(const int rings, const int wedges,
00096 float& x, float& y) const
00097 {
00098 std::pair<float,float> p = itsLookup.getVal(rings, wedges);
00099 x = p.first; y = p.second;
00100 }
00101
00102
00103 const Dims& SpaceVariantTransform::getCTDims() const
00104 {
00105 return itsRevLookup.getDims();
00106 }
00107
00108
00109 const Dims& SpaceVariantTransform::getSVDims() const
00110 {
00111 return itsLookup.getDims();
00112 }
00113
00114
00115 const float& SpaceVariantTransform::getRFSize(const uint u, const uint v) const
00116 {
00117 return itsStd.getVal(u,v);
00118 }
00119
00120
00121 float SpaceVariantTransform::getRFSize(const float& u, const float& v) const
00122 {
00123 return itsStd.getValInterp(u,v);
00124 }
00125
00126
00127 const float& SpaceVariantTransform::getRFSize(const uint pos) const
00128 {
00129 return itsStd.getVal(pos);
00130 }
00131
00132
00133 float SpaceVariantTransform::getMaxRFSize() const
00134 {
00135 return itsMaxStd;
00136 }
00137
00138
00139 SpaceVariantTransform::const_iterator SpaceVariantTransform::begin() const
00140 {
00141 return itsLookup.begin();
00142 }
00143
00144
00145 SpaceVariantTransform::const_iterator SpaceVariantTransform::end() const
00146 {
00147 return itsLookup.end();
00148 }
00149
00150
00151 SpaceVariantTransform::const_iterator SpaceVariantTransform::rbegin() const
00152 {
00153 return itsRevLookup.begin();
00154 }
00155
00156
00157 SpaceVariantTransform::const_iterator SpaceVariantTransform::rend() const
00158 {
00159 return itsRevLookup.end();
00160 }
00161
00162
00163 Image<float>::const_iterator SpaceVariantTransform::rfbegin() const
00164 {
00165 return itsStd.begin();
00166 }
00167
00168
00169 Image<float>::const_iterator SpaceVariantTransform::rfend() const
00170 {
00171 return itsStd.end();
00172 }
00173
00174
00175 float SpaceVariantTransform::computeDistance(const float& theta,
00176 const uint cx, const uint cy,
00177 const uint imgw, const uint imgh)
00178 {
00179
00180 float d = 0.0F;
00181
00182
00183
00184 const float angle_ru = -1.0F * atan2(cy, imgw-cx);
00185 const float angle_rl = atan2(imgh-cy, imgw-cx);
00186 const float angle_lu = 3.0F*PI2 - atan2(cx, cy);
00187 const float angle_ll = PI2 + atan2(cx, imgh-cy);
00188
00189
00190
00191 if ((theta > angle_lu) && (theta <= 3.0F*PI2))
00192 d = cy/cos(3.0F*PI2 - theta);
00193 else if ((theta >= -PI2) && (theta <= angle_ru))
00194 d = cy/cos(theta + PI2);
00195 else if ((theta > angle_ru) && (theta <= angle_rl))
00196 d = (imgw-cx)/cos(std::abs(theta));
00197 else if ((theta > angle_rl) && (theta <= angle_ll))
00198 d = (imgh-cy)/cos(std::abs(theta - PI2));
00199 else if ((theta > angle_ll) && (theta <= angle_lu))
00200 d = cx/cos(std::abs(PI - theta));
00201
00202 ASSERT(d>0.0F);
00203 return d;
00204 }
00205
00206
00207
00208
00209 FovealTransform::FovealTransform() : u_FoveaSize(0)
00210 { }
00211
00212
00213 FovealTransform::SCALE_TYPE
00214 FovealTransform::toScaleType(const std::string& scale_type_string)
00215 {
00216 if (scale_type_string.compare("FULL") == 0)
00217 return FULL;
00218 else if (scale_type_string.compare("CROP") == 0)
00219 return CROP;
00220 else
00221 return NONE;
00222 }
00223
00224
00225 void FovealTransform::setup(const uint imgw, const uint imgh,
00226 const uint rings, const uint wedges,
00227 const float& alpha, const float& beta,
00228 const float& gain, const float& exponent, const float& offset,
00229 const float& ppdx, const float& ppdy,
00230 const SCALE_TYPE& scale_type, const float& s,
00231 const float& fovea_cuttoff)
00232 {
00233
00234
00235
00236 itsLookup = Image<std::pair<float,float> >(rings*2, wedges/2, NO_INIT);
00237 itsRevLookup = Image<std::pair<float,float> >(imgw, imgh, NO_INIT);
00238 itsStd = Image<float>(rings*2, wedges/2, NO_INIT);
00239
00240 iterator iterf(itsLookup.beginw());
00241 while (iterf != itsLookup.endw())
00242 *iterf++ = std::pair<float,float>(-1.0F, -1.0F);
00243
00244 iterf = itsRevLookup.beginw();
00245 while (iterf != itsRevLookup.endw())
00246 *iterf++ = std::pair<float,float>(-1.0F, -1.0F);
00247
00248 Image<float>::iterator iterv(itsStd.beginw());
00249 while (iterv != itsStd.endw())
00250 *iterv++ = -1.0F;
00251
00252
00253 const uint w2 = wedges / 2;
00254 const uint w22 = w2/2;
00255 const float wstep = PI2 / (w22);
00256 const float wstep2 = wstep/2;
00257
00258 const int sx = imgw - 1;
00259 const int sy = imgh - 1;
00260 const float cx = (float)sx/2.0F;
00261 const float cy = (float)sy/2.0F;
00262
00263
00264
00265
00266
00267
00268
00269
00270
00271
00272
00273 float scale = 0.0F;
00274 if (scale_type == NONE)
00275 scale = s;
00276 else if (scale_type == CROP)
00277 scale = (rings-1-EPS)/log( ((sx>sy) ? cy : cx) * alpha + beta);
00278 else if (scale_type == FULL)
00279 scale = (rings-1-EPS)/log( sqrt(cx*cx + cy*cy) * alpha + beta);
00280
00281
00282
00283
00284
00285
00286
00287
00288
00289 if (fovea_cuttoff > 0.0)
00290 {
00291 u_FoveaSize = uint(2.0F * scale * log(fovea_cuttoff * alpha * scale));
00292 if (u_FoveaSize < 0)
00293 LFATAL("for the desired transform parameters and foveal cuttoff, there are no pixels "
00294 "in the fovea! Try increasing the fovea size (--retinasv-fovea-size) or "
00295 "increasing the cutoff to be considered the fovea (--retinasv-fovea-cutoff)");
00296 }
00297
00298
00299 for (uint u = 0; u < rings; ++u)
00300 {
00301
00302 float r = (exp(u / scale) - beta)/alpha;
00303
00304
00305
00306
00307
00308 float theta = -PI2 + wstep2;
00309 for (uint v = 0; v < w2; ++v)
00310 {
00311 float xpos = r * cos(theta);
00312 float ypos = r * sin(theta);
00313
00314
00315 const float deg = sqrt((xpos / ppdx)*(xpos / ppdx) + (ypos / ppdy)*(ypos / ppdy));
00316 const float std = (gain*pow(deg,exponent)+offset)*(ppdx+ppdy)/2;
00317
00318 if (std > itsMaxStd)
00319 itsMaxStd = std;
00320
00321 xpos += cx;
00322 ypos += cy;
00323
00324 if (itsRevLookup.coordsOk(xpos, ypos))
00325 {
00326 itsLookup.setVal(rings - 1 + u, v, std::pair<float, float>(xpos, ypos));
00327 itsStd.setVal(rings - 1 + u, v, std);
00328 }
00329 theta += wstep;
00330 }
00331
00332 for (int v = w2 - 1; v >= 0; --v)
00333 {
00334 float xpos = r * cos(theta);
00335 float ypos = r * sin(theta);
00336
00337
00338 const float deg = sqrt((xpos / ppdx)*(xpos / ppdx) + (ypos / ppdy)*(ypos / ppdy));
00339 const float std = (gain*pow(deg,exponent)+offset)*(ppdx+ppdy)/2;
00340
00341 if (std > itsMaxStd)
00342 itsMaxStd = std;
00343
00344 xpos += cx;
00345 ypos += cy;
00346
00347 if (itsRevLookup.coordsOk(xpos, ypos))
00348 {
00349 itsLookup.setVal(rings - u, v, std::pair<float, float>(xpos, ypos));
00350 itsStd.setVal(rings - u, v, std);
00351 }
00352 theta += wstep;
00353 }
00354 }
00355
00356
00357 const float wscale = (w2 - 1 - EPS) / (PI - EPS);
00358 const float r2 = (rings*2-1)/2;
00359 for (uint x = 0; x < imgw; ++x)
00360 for (uint y = 0; y < imgh; ++y)
00361 {
00362 const float xx = x - cx;
00363 const float yy = y - cy;
00364 const float r = sqrt(xx*xx + yy*yy);
00365
00366 float theta = atan2(yy,xx);
00367 if (theta < -PI2)
00368 theta += 2.0F*PI;
00369 theta += PI2 + EPS;
00370
00371
00372 float u = scale * log(r * alpha + beta) - 0.5;
00373
00374
00375 float v;
00376 if (theta > PI)
00377 {
00378 v = (theta - PI) * wscale + EPS;
00379 v = w2 - 1 - v;
00380 u = r2 + 1 - u;
00381 }
00382 else
00383 {
00384 v = theta * wscale;
00385 u = r2 + u;
00386 }
00387
00388
00389 if (u > (rings*2-1))
00390 u = rings*2-1-EPS;
00391
00392 if (u < 0)
00393 u = 0;
00394
00395 if (v > (w2-1))
00396 v= w2-1 - EPS;
00397
00398 if (v < 0)
00399 v = 0;
00400
00401
00402 itsRevLookup.setVal(x, y, std::pair<float,float>(u,v));
00403 }
00404
00405 isInitialized = true;
00406 }
00407
00408
00409 const uint FovealTransform::getFoveaSize() const
00410 {
00411 return u_FoveaSize;
00412 }
00413
00414
00415
00416
00417 template <class T_or_RGB>
00418 Image<T_or_RGB> transformTo(const SpaceVariantTransform& sv, const Image<T_or_RGB>& input,
00419 const ImageSet<typename promote_trait<T_or_RGB, float>::TP>* const cache, const float& offset)
00420 {
00421 typedef typename promote_trait<T_or_RGB, float>::TP TP;
00422
00423
00424 ImageSet<TP> pyr = (cache) ? *cache : getScaleSpace(input, sv.getMaxRFSize());
00425
00426
00427
00428 Image<T_or_RGB> out(sv.getSVDims(), ZEROS);
00429 typename Image<T_or_RGB>::iterator iter(out.beginw());
00430 SpaceVariantTransform::const_iterator sviter(sv.begin());
00431
00432 uint pos = 0;
00433 while (iter != out.endw())
00434 {
00435 const float var = sv.getRFSize(pos) + offset;
00436 if (sviter->first >= 0.0F)
00437 *iter = clamped_convert<T_or_RGB>(getScaleSpacePixel(pyr, sviter->first, sviter->second, var));
00438 ++iter; ++sviter; ++pos;
00439 }
00440 return out;
00441 }
00442
00443
00444 template <class T_or_RGB>
00445 Image<T_or_RGB> transformFrom(const SpaceVariantTransform& sv, const Image<T_or_RGB>& input)
00446 {
00447
00448
00449 Image<T_or_RGB> out(sv.getCTDims(), ZEROS);
00450 typename Image<T_or_RGB>::iterator oiter = out.beginw();
00451 SpaceVariantTransform::const_iterator sviter(sv.rbegin());
00452 while (oiter != out.endw())
00453 {
00454 float u = sviter->first, v = sviter->second;
00455 if (u >= 0.0F)
00456 *oiter = clamped_convert<T_or_RGB>(input.getValInterp(u, v));
00457 ++oiter;++sviter;
00458 }
00459 return out;
00460 }
00461
00462
00463 template <class T_or_RGB>
00464 Image<typename promote_trait<T_or_RGB, float>::TP>
00465 transformToDoG(const SpaceVariantTransform& sv, const Image<T_or_RGB>& input, const float& smult,
00466 const bool centeron, const ImageSet<typename promote_trait<T_or_RGB, float>::TP>* const cache, const float& offset)
00467 {
00468 ASSERT(smult > 1.0F);
00469
00470 typedef typename promote_trait<T_or_RGB, float>::TP TP;
00471
00472
00473 ImageSet<TP> pyr = (cache) ? *cache : getScaleSpace(input, sv.getMaxRFSize() * smult);
00474
00475
00476
00477 Image<TP> out(sv.getSVDims(), ZEROS);
00478 typename Image<TP>::iterator iter(out.beginw());
00479 SpaceVariantTransform::const_iterator sviter(sv.begin());
00480
00481 uint pos = 0;
00482 while (iter != out.endw())
00483 {
00484 const float stdc = sv.getRFSize(pos) + offset;
00485 const float stds = stdc * smult;
00486
00487 if (sviter->first >= 0.0F)
00488 *iter = getDiffScaleSpacePixel(pyr, sviter->first, sviter->second, stdc, stds, centeron);
00489
00490 ++iter; ++sviter; ++pos;
00491 }
00492 return out;
00493 }
00494
00495
00496 template <class T_or_RGB>
00497 Image<typename promote_trait<T_or_RGB, float>::TP>
00498 transformToEdge(const SpaceVariantTransform& sv, const Image<T_or_RGB>& input, const Image<LocalEdge>& edgemap,
00499 const ImageSet<typename promote_trait<T_or_RGB, float>::TP>* const cache, const float& offset)
00500 {
00501
00502 typedef typename promote_trait<T_or_RGB, float>::TP TP;
00503
00504
00505 ImageSet<TP> pyr = (cache) ? *cache : getScaleSpace(input, sv.getMaxRFSize());
00506
00507
00508
00509 Image<TP> out(sv.getSVDims(), ZEROS);
00510 typename Image<TP>::iterator iter(out.beginw());
00511 SpaceVariantTransform::const_iterator sviter(sv.begin());
00512 Image<LocalEdge>::const_iterator edgeiter(edgemap.begin());
00513
00514 uint pos = 0;
00515 while (iter != out.endw())
00516 {
00517 const float std = sv.getRFSize(pos) + offset;
00518 if (sviter->first >= 0.0F)
00519 *iter = getEdgeScaleSpacePixel(pyr, sviter->first, sviter->second, std, *edgeiter);
00520
00521 ++iter; ++sviter; ++pos;++edgeiter;
00522 }
00523 return out;
00524 }
00525
00526
00527 template <class T_or_RGB>
00528 Image<typename promote_trait<T_or_RGB, float>::TP>
00529 transformToEdge(const SpaceVariantTransform& sv, const Image<T_or_RGB>& input, const float& smult, const Image<LocalEdge>& edgemap, const ImageSet<typename promote_trait<T_or_RGB, float>::TP>* const cache, const float& offset)
00530 {
00531 ASSERT((smult >= 1.0F) && (smult <=6.0F));
00532
00533
00534 typedef typename promote_trait<T_or_RGB, float>::TP TP;
00535
00536
00537 ImageSet<TP> pyr = (cache) ? *cache : getScaleSpace(input, sv.getMaxRFSize() * smult);
00538
00539
00540
00541 Image<TP> out(sv.getSVDims(), ZEROS);
00542 typename Image<TP>::iterator iter(out.beginw());
00543 SpaceVariantTransform::const_iterator sviter(sv.begin());
00544 Image<LocalEdge>::const_iterator edgeiter(edgemap.begin());
00545
00546 uint pos = 0;
00547 while (iter != out.endw())
00548 {
00549 const float stdc = sv.getRFSize(pos) + offset;
00550 const float stds = stdc*smult;
00551 if (sviter->first >= 0.0F)
00552 *iter = getEdgeScaleSpacePixel(pyr, sviter->first, sviter->second, stdc, stds, *edgeiter);
00553
00554 ++iter; ++sviter; ++pos;++edgeiter;
00555 }
00556 return out;
00557 }
00558
00559
00560 template <class T_or_RGB>
00561 ImageSet<typename promote_trait<T_or_RGB, float>::TP>
00562 transformToDoGPyramid(const SpaceVariantTransform& sv, const Image<T_or_RGB>& input, const float& smult, const bool centeron, const std::vector<float>& scales, const ImageSet<typename promote_trait<T_or_RGB, float>::TP>* const cache)
00563 {
00564
00565 typedef typename promote_trait<T_or_RGB, float>::TP TP;
00566
00567 ImageSet<TP> retpyr(scales.size(), sv.getSVDims(), NO_INIT);
00568 for (uint ii = 0; ii < scales.size(); ++ii)
00569 retpyr.push_back(transformToDoG(sv, input, smult, centeron, cache, scales[ii]));
00570
00571 return retpyr;
00572 }
00573
00574
00575 template <class T_or_RGB>
00576 ImageSet<typename promote_trait<T_or_RGB, float>::TP>
00577 transformToEdgePyramid(const SpaceVariantTransform& sv, const Image<T_or_RGB>& input, const Image<LocalEdge>& edgemap, const float& orientation, const uint& length, const float& density, const std::vector<float>& scales, const ImageSet<typename promote_trait<T_or_RGB, float>::TP>* const cache)
00578 {
00579
00580 typedef typename promote_trait<T_or_RGB, float>::TP TP;
00581
00582 ImageSet<TP> retpyr(scales.size(), sv.getSVDims(), NO_INIT);
00583 for (uint ii = 0; ii < scales.size(); ++ii)
00584 retpyr.push_back(transformToEdge(sv, input, edgemap, cache, scales[ii]));
00585 return retpyr;
00586 }
00587
00588
00589 template <class T_or_RGB>
00590 ImageSet<typename promote_trait<T_or_RGB, float>::TP>
00591 transformToEdgePyramid(const SpaceVariantTransform& sv, const Image<T_or_RGB>& input, const float& smult, const Image<LocalEdge>& edgemap, const float& orientation, const uint& length, const float& density, const std::vector<float>& scales, const ImageSet<typename promote_trait<T_or_RGB, float>::TP>* const cache)
00592 {
00593
00594 typedef typename promote_trait<T_or_RGB, float>::TP TP;
00595
00596 ImageSet<TP> retpyr(scales.size(), sv.getSVDims(), NO_INIT);
00597 for (uint ii = 0; ii < scales.size(); ++ii)
00598 retpyr.push_back(transformToEdge(sv, input, smult, edgemap, cache, scales[ii]));
00599 return retpyr;
00600 }
00601
00602
00603
00604
00605
00606
00607
00608
00609 template <class T_or_RGB>
00610 Image<T_or_RGB> transformToFoveal(const FovealTransform& sv, const Image<T_or_RGB>& input, const bool interp)
00611 {
00612
00613 Image<typename promote_trait<T_or_RGB, float>::TP> inp = input;
00614
00615
00616
00617 Image<T_or_RGB> out(sv.getSVDims(), ZEROS);
00618
00619 float var = 0;
00620 const uint w2 = sv.getSVDims().w()/2;
00621 const uint h = sv.getSVDims().h();
00622
00623
00624 for (uint r = 0; r < w2; ++r)
00625 {
00626
00627
00628 const float rf = sv.getRFSize(w2 + r,0);
00629 while ((rf - var) > 0.25F)
00630 {
00631 inp = lowPass3(inp);
00632 var += 0.5F;
00633 }
00634
00635
00636 for (uint w = 0; w < h; ++w)
00637 {
00638 const uint u = w2 + r;
00639 if (interp == true){
00640 float x, y;
00641 sv.from(u, w, x, y);
00642 if (x >= 0.0F)
00643 out.setVal(u, w, clamped_convert<T_or_RGB>(inp.getValInterp(x,y)));
00644 }
00645 else{
00646 int x, y;
00647 sv.from(u, w, x, y);
00648 if (x > -1)
00649 out.setVal(u, w, clamped_convert<T_or_RGB>(inp.getVal(x, y)));
00650 }
00651 }
00652
00653
00654 for (uint w = 0; w < h; ++w)
00655 {
00656 const uint u = w2 - r - 1;
00657 if (interp == true){
00658 float x, y;
00659 sv.from(u, w, x, y);
00660 if (x >= 0.0F)
00661 out.setVal(u,w,clamped_convert<T_or_RGB>(inp.getValInterp(x,y)));
00662 }
00663 else{
00664 int x, y;
00665 sv.from(u, w, x, y);
00666 if (x > -1)
00667 out.setVal(u, w, clamped_convert<T_or_RGB>(inp.getVal(x, y)));
00668 }
00669 }
00670 }
00671 return out;
00672 }
00673
00674
00675 template <class T_or_RGB>
00676 Image<typename promote_trait<T_or_RGB, float>::TP>
00677 transformToDoGFoveal(const FovealTransform& sv,const Image<T_or_RGB>& input,
00678 const float& smult, const bool centeron, const bool interp)
00679 {
00680 ASSERT(smult > 1.0F);
00681
00682
00683 Image<typename promote_trait<T_or_RGB, float>::TP> inp = input;
00684
00685
00686
00687 Image<T_or_RGB> out(sv.getSVDims(), ZEROS);
00688
00689
00690 std::deque<Image<typename promote_trait<T_or_RGB, float>::TP> > pyr;
00691
00692 float var = 0;
00693 const uint rings = sv.getSVDims().w();
00694 const uint w2 = rings/2;
00695 const uint h = sv.getSVDims().h();
00696 uint rc = 0;
00697 float rfc = sv.getRFSize(rc,0);
00698
00699
00700 for (uint r = 0; r < w2; ++r)
00701 {
00702
00703
00704 float rf = sv.getRFSize(r,0);
00705 if (rf*(smult - 1) >= 0.5F) rf *= smult; else rf += 0.5F;
00706
00707
00708
00709 while (( rf - var) > 0.25F)
00710 {
00711
00712 while (((rfc - var) <= 0.25F) && (rc < rings))
00713 {
00714 pyr.push_back(inp);
00715 rfc = sv.getRFSize(++rc, 0);
00716 }
00717 inp = lowPass3(inp);
00718 var += 0.5F;
00719 }
00720
00721 Image<typename promote_trait<T_or_RGB, float>::TP> diff;
00722
00723
00724 if (pyr.size() > 0) {
00725 if (centeron)
00726 {
00727 diff = pyr.front();
00728 pyr.pop_front();
00729 diff -= inp;
00730 }
00731 else
00732 {
00733 diff = inp;
00734 diff -= pyr.front();
00735 pyr.pop_front();
00736 }
00737 }
00738
00739
00740 for (uint w = 0; w < h; ++w)
00741 {
00742 const uint u = w2 + r;
00743 if (interp == true){
00744 float x, y;
00745 sv.from(u, w, x, y);
00746 if (x >= 0.0F)
00747 out.setVal(u, w, diff.getValInterp(x, y));
00748 }
00749 else{
00750 int x, y;
00751 sv.from(u, w, x, y);
00752 if (x != -1)
00753 out.setVal(u, w, diff.getVal(x, y));
00754 }
00755 }
00756
00757
00758 for (uint w = 0; w < h; ++w)
00759 {
00760 const uint u = w2 - r - 1;
00761 if (interp == true){
00762 float x, y;
00763 sv.from(u, w, x, y);
00764 if (x >= 0.0F)
00765 out.setVal(u, w, diff.getValInterp(x, y));
00766 }
00767 else {
00768 int x, y;
00769 sv.from(u, w, x, y);
00770 if (x != -1)
00771 out.setVal(u, w, diff.getVal(x, y));
00772 }
00773 }
00774 }
00775 return out;
00776 }
00777
00778
00779
00780
00781 template <class T_or_RGB>
00782 Image<T_or_RGB> replicateHemifield(const Image<T_or_RGB>& inp, const uint pix)
00783 {
00784
00785
00786 Image<T_or_RGB> t =
00787 concatX( flipHoriz(flipVertic( crop(inp, Point2D<int>(inp.getWidth()/2, 0),
00788 Dims(inp.getWidth()/2, pix)) )),
00789 flipHoriz(flipVertic( crop(inp, Point2D<int>(0, 0),
00790 Dims(inp.getWidth()/2, pix)) )) );
00791
00792 Image<T_or_RGB> b =
00793 concatX( flipHoriz(flipVertic( crop(inp, Point2D<int>(inp.getWidth()/2,
00794 inp.getHeight()-pix),
00795 Dims(inp.getWidth()/2, pix)) )),
00796 flipHoriz(flipVertic( crop(inp,Point2D<int>(0,inp.getHeight()-pix),
00797 Dims(inp.getWidth()/2, pix)) )) );
00798
00799 Image<T_or_RGB> output = concatY( concatY(t,inp), b);
00800 return output;
00801 }
00802
00803
00804 template <class T_or_RGB>
00805 void getFoveaPeriphery(const FovealTransform& sv, const Image<T_or_RGB>& ret,
00806 Image<T_or_RGB>& fovea, Image<T_or_RGB>& periph)
00807 {
00808 ASSERT(sv.getSVDims() == ret.getDims());
00809
00810 const uint fix = sv.getFoveaSize();
00811 const uint fix2 = fix / 2;
00812 const uint w = ret.getWidth();
00813 const uint w2 = w / 2;
00814 const uint h = ret.getHeight();
00815
00816 Point2D<int> a(0,0), b(w2-fix2, 0), c(w2+fix2,0);
00817 Dims ad(b.i, h), bd(fix, h), cd(w - c.i, h);
00818
00819 Image<T_or_RGB> lh = crop(ret, a, ad);
00820 Image<T_or_RGB> rh = crop(ret, c, cd);
00821 fovea = crop(ret, b, bd);
00822 periph = concatX(lh, rh);
00823 }
00824
00825
00826 Image<LocalEdge> LocalEdgeMap(const SpaceVariantTransform& sv, const float& smult,
00827 const float& orientation, const uint& length, const uint density)
00828 {
00829 Image<LocalEdge> out(sv.getSVDims(), NO_INIT);
00830 Image<LocalEdge>::iterator ii(out.beginw());
00831 Image<float>::const_iterator tr(sv.rfbegin());
00832 while (ii != out.end())
00833 {
00834 if (*tr >= 0.0)
00835 *ii = LocalEdge(sv.getCTDims(), *tr, smult, orientation, length, density);
00836 ++ii; ++tr;
00837 }
00838 return out;
00839 }
00840
00841 #include "inst/SpaceVariant/SpaceVariantTransforms.I"
00842
00843
00844
00845
00846
00847