00001 #include "CUDA/CudaImage.H"
00002 #include "CUDA/CudaImageSet.H"
00003 #include "Util/log.H"
00004 #include "Image/PyramidOps.H"
00005 #include "CudaPyramidOps.H"
00006 #include "CUDA/CudaLowPass.H"
00007 #include "CUDA/CudaKernels.H"
00008 #include "CUDA/CudaMathOps.H"
00009 #include "CUDA/CudaShapeOps.H"
00010 #include "CUDA/CudaFilterOps.H"
00011
00012
00013
00014
00015
00016
00017 CudaImageSet<float> cudaBuildPyrGaussian(const CudaImage<float>& image,
00018 int firstlevel, int depth, int filterSize)
00019 {
00020 ASSERT(image.initialized());
00021
00022 CudaImageSet<float> result(depth);
00023
00024 if (0 >= firstlevel)
00025 result[0] = image;
00026
00027 CudaImage<float> a = CudaImage<float>(image);
00028 for (int lev = 1; lev < depth; ++lev)
00029 {
00030 switch(filterSize)
00031 {
00032 case 5:
00033 a = cudaLowPass5yDec(cudaLowPass5xDec(a));
00034 break;
00035 default:
00036 a = cudaDecX(cudaLowPassX(filterSize, a));
00037 a = cudaDecY(cudaLowPassY(filterSize, a));
00038 break;
00039 }
00040
00041
00042
00043
00044
00045
00046 if (lev >= firstlevel)
00047 result[lev] = a;
00048 }
00049
00050 return result;
00051 }
00052
00053
00054
00055
00056 CudaImageSet<float> cudaBuildPyrLaplacian(const CudaImage<float>& image, int firstlevel, int depth, int filterSize)
00057 {
00058 ASSERT(image.initialized());
00059
00060 CudaImageSet<float> result(depth);
00061
00062 CudaImage<float> lpf = cudaLowPass(filterSize, image);
00063
00064 if (0 >= firstlevel)
00065 result[0] = cudaSubtractImages(image,lpf);
00066 for (int lev = 1; lev < depth; ++lev)
00067 {
00068 const CudaImage<float> dec = cudaDecXY(lpf);
00069 lpf = cudaLowPass(filterSize, dec);
00070
00071 if (lev >= firstlevel)
00072 result[lev] = cudaSubtractImages(dec,lpf);
00073
00074 }
00075
00076 return result;
00077 }
00078
00079
00080
00081 CudaImageSet<float> cudaBuildPyrOrientedFromLaplacian(const CudaImageSet<float>& laplacian,
00082 int filterSize,
00083 float theta, float intens)
00084 {
00085 int attenuation_width = -1;
00086 float spatial_freq = -1.0;
00087
00088 switch (filterSize)
00089 {
00090 case 5: attenuation_width = 3; spatial_freq = M_PI_2; break;
00091 case 9: attenuation_width = 5; spatial_freq = 2.6; break;
00092 default:
00093 LFATAL("Filter size %d is not supported", filterSize);
00094 }
00095
00096
00097 CudaImageSet<float> result(laplacian.size());
00098
00099 for (size_t lev = 0; lev < result.size(); ++lev)
00100 {
00101 if (laplacian[lev].initialized())
00102 {
00103 result[lev] = cudaOrientedFilter(laplacian[lev], spatial_freq,
00104 theta, intens);
00105
00106 cudaInplaceAttenuateBorders(result[lev], attenuation_width);
00107 }
00108 }
00109
00110 return result;
00111 }
00112
00113
00114 CudaImageSet<float> cudaBuildPyrOriented(const CudaImage<float>& image, int firstlevel, int depth, int filterSize,
00115 float theta, float intens)
00116 {
00117 ASSERT(image.initialized());
00118
00119 const CudaImageSet<float> laplacian = cudaBuildPyrLaplacian(image, firstlevel, depth, filterSize);
00120
00121 const CudaImageSet<float> orifilt =
00122 cudaBuildPyrOrientedFromLaplacian(laplacian, filterSize, theta,
00123 intens);
00124
00125 CudaImageSet<float> result(orifilt.size());
00126 for (size_t i = 0; i < result.size(); ++i)
00127 result[i] = orifilt[i];
00128
00129 return result;
00130 }
00131
00132
00133
00134
00135 CudaImageSet<float> cudaBuildPyrLocalAvg(const CudaImage<float>& image, int depth)
00136 {
00137 ASSERT(image.initialized());
00138 ASSERT(depth >= 1);
00139
00140 CudaImageSet<float> result(depth);
00141
00142
00143 const int scale = int(pow(2.0, depth - 1));
00144 result[depth - 1] = cudaQuickLocalAvg(image, scale);
00145
00146 return result;
00147 }
00148
00149
00150 CudaImageSet<float> cudaBuildPyrLocalAvg2x2(const CudaImage<float>& image, int depth)
00151 {
00152 ASSERT(depth >= 0);
00153
00154 if (depth == 0)
00155 return CudaImageSet<float>(0);
00156
00157 CudaImageSet<float> result(depth);
00158 result[0] = image;
00159
00160 for (int i = 1; i < depth; ++i)
00161 result[i] = cudaQuickLocalAvg2x2(result[i-1]);
00162
00163 return result;
00164 }
00165
00166
00167 CudaImageSet<float> cudaBuildPyrLocalMax(const CudaImage<float>& image, int depth)
00168 {
00169 ASSERT(image.initialized());
00170 ASSERT(depth >= 1);
00171
00172 CudaImageSet<float> result(depth);
00173
00174
00175 const int scale = int(pow(2.0, depth - 1));
00176 result[depth - 1] = cudaQuickLocalMax(image, scale);
00177
00178 return result;
00179 }
00180
00181
00182 CudaImageSet<float> cudaBuildPyrGeneric(const CudaImage<float>& image,
00183 int firstlevel, int depth,
00184 const PyramidType typ, const float gabor_theta,
00185 const float intens)
00186 {
00187 switch(typ)
00188 {
00189 case Gaussian3: return cudaBuildPyrGaussian(image, firstlevel, depth, 3);
00190 case Gaussian5: return cudaBuildPyrGaussian(image, firstlevel, depth, 5);
00191 case Gaussian9: return cudaBuildPyrGaussian(image, firstlevel, depth, 9);
00192
00193 case Laplacian5: return cudaBuildPyrLaplacian(image, firstlevel, depth, 5);
00194 case Laplacian9: return cudaBuildPyrLaplacian(image, firstlevel, depth, 9);
00195
00196 case Oriented5: return cudaBuildPyrOriented(image, firstlevel, depth, 5, gabor_theta, intens);
00197 case Oriented9: return cudaBuildPyrOriented(image, firstlevel, depth, 9, gabor_theta, intens);
00198
00199 case QuickLocalAvg: return cudaBuildPyrLocalAvg(image, depth);
00200 case QuickLocalMax: return cudaBuildPyrLocalMax(image, depth);
00201
00202 default:
00203 LFATAL("Attempt to create Pyramid of unknown type %d", typ);
00204 }
00205
00206 ASSERT(false);
00207 return CudaImageSet<float>(0);
00208 }
00209
00210
00211
00212
00213
00214
00215
00216
00217
00218
00219
00220
00221
00222
00223
00224
00225
00226
00227
00228
00229
00230
00231
00232
00233
00234
00235
00236
00237
00238
00239
00240
00241
00242
00243
00244
00245
00246
00247
00248
00249
00250
00251
00252
00253
00254
00255
00256
00257
00258
00259
00260
00261
00262
00263
00264
00265
00266
00267
00268
00269
00270
00271
00272
00273
00274
00275 CudaImage<float> cudaCenterSurround(const CudaImageSet<float>& pyr,
00276 const int lev1, const int lev2,
00277 const bool absol,
00278 const CudaImageSet<float>* clipPyr)
00279 {
00280 ASSERT(lev1 >= 0 && lev2 >= 0);
00281 ASSERT(uint(lev1) < pyr.size() && uint(lev2) < pyr.size());
00282
00283 const int largeLev = std::min(lev1, lev2);
00284 const int smallLev = std::max(lev1, lev2);
00285
00286 if (clipPyr != 0 && clipPyr->isNonEmpty())
00287 {
00288 ASSERT((*clipPyr)[largeLev].getDims() == pyr[largeLev].getDims());
00289 ASSERT((*clipPyr)[smallLev].getDims() == pyr[smallLev].getDims());
00290
00291 return
00292 ::cudaCenterSurround(pyr[largeLev]*(*clipPyr)[largeLev],
00293 pyr[smallLev]*(*clipPyr)[smallLev],
00294 absol);
00295 }
00296 else
00297 return ::cudaCenterSurround(pyr[largeLev], pyr[smallLev], absol);
00298 }
00299
00300 void cudaCenterSurround(const CudaImageSet<float>& pyr,
00301 const int lev1, const int lev2,
00302 CudaImage<float>& pos, CudaImage<float>& neg,
00303 const CudaImageSet<float>* clipPyr)
00304 {
00305 ASSERT(lev1 >= 0 && lev2 >= 0);
00306 ASSERT(uint(lev1) < pyr.size() && uint(lev2) < pyr.size());
00307
00308 const int largeLev = std::min(lev1, lev2);
00309 const int smallLev = std::max(lev1, lev2);
00310
00311 if (clipPyr != 0 && clipPyr->isNonEmpty())
00312 {
00313 ASSERT((*clipPyr)[largeLev].getDims() == pyr[largeLev].getDims());
00314 ASSERT((*clipPyr)[smallLev].getDims() == pyr[smallLev].getDims());
00315
00316 ::cudaCenterSurround(pyr[largeLev]*(*clipPyr)[largeLev],
00317 pyr[smallLev]*(*clipPyr)[smallLev],
00318 pos, neg);
00319 }
00320 else
00321 ::cudaCenterSurround(pyr[largeLev], pyr[smallLev], pos, neg);
00322 }
00323
00324 CudaImage<float> cudaCenterSurroundSingleOpponent(const CudaImageSet<float>& cpyr,
00325 const CudaImageSet<float>& spyr,
00326 const int lev1, const int lev2,
00327 const bool absol,
00328 const CudaImageSet<float>* clipPyr)
00329 {
00330 ASSERT(lev1 >= 0 && lev2 >= 0);
00331 ASSERT(uint(lev1) < cpyr.size() && uint(lev2) < cpyr.size());
00332 ASSERT(uint(lev1) < spyr.size() && uint(lev2) < spyr.size());
00333
00334 const int largeLev = std::min(lev1, lev2);
00335 const int smallLev = std::max(lev1, lev2);
00336
00337 if (clipPyr != 0 && clipPyr->isNonEmpty())
00338 {
00339 ASSERT((*clipPyr)[largeLev].getDims() == cpyr[largeLev].getDims());
00340 ASSERT((*clipPyr)[smallLev].getDims() == cpyr[smallLev].getDims());
00341 ASSERT((*clipPyr)[largeLev].getDims() == spyr[largeLev].getDims());
00342 ASSERT((*clipPyr)[smallLev].getDims() == spyr[smallLev].getDims());
00343
00344 return
00345 ::cudaCenterSurround(cpyr[largeLev]*(*clipPyr)[largeLev],
00346 spyr[smallLev]*(*clipPyr)[smallLev],
00347 absol);
00348 }
00349 else
00350 return ::cudaCenterSurround(cpyr[largeLev], spyr[smallLev], absol);
00351 }
00352
00353 void cudaCenterSurroundSingleOpponent(const CudaImageSet<float>& cpyr,
00354 const CudaImageSet<float>& spyr,
00355 const int lev1, const int lev2,
00356 CudaImage<float>& pos, CudaImage<float>& neg,
00357 const CudaImageSet<float>* clipPyr)
00358 {
00359 ASSERT(lev1 >= 0 && lev2 >= 0);
00360 ASSERT(uint(lev1) < cpyr.size() && uint(lev2) < cpyr.size());
00361 ASSERT(uint(lev1) < spyr.size() && uint(lev2) < spyr.size());
00362
00363 const int largeLev = std::min(lev1, lev2);
00364 const int smallLev = std::max(lev1, lev2);
00365
00366 if (clipPyr != 0 && clipPyr->isNonEmpty())
00367 {
00368 ASSERT((*clipPyr)[largeLev].getDims() == cpyr[largeLev].getDims());
00369 ASSERT((*clipPyr)[smallLev].getDims() == cpyr[smallLev].getDims());
00370 ASSERT((*clipPyr)[largeLev].getDims() == spyr[largeLev].getDims());
00371 ASSERT((*clipPyr)[smallLev].getDims() == spyr[smallLev].getDims());
00372
00373 ::cudaCenterSurround(cpyr[largeLev]*(*clipPyr)[largeLev],
00374 spyr[smallLev]*(*clipPyr)[smallLev],
00375 pos, neg);
00376 }
00377 else
00378 ::cudaCenterSurround(cpyr[largeLev], spyr[smallLev], pos, neg);
00379 }
00380
00381 CudaImage<float> cudaCenterSurroundDiff(const CudaImageSet<float>& pyr1,
00382 const CudaImageSet<float>& pyr2,
00383 const int lev1, const int lev2,
00384 const bool absol,
00385 const CudaImageSet<float>* clipPyr)
00386 {
00387 ASSERT(lev1 >= 0 && lev2 >= 0);
00388 ASSERT(uint(lev1) < pyr1.size() && uint(lev2) < pyr1.size());
00389
00390 const int largeLev = std::min(lev1, lev2);
00391 const int smallLev = std::max(lev1, lev2);
00392
00393 ASSERT(pyr1[largeLev].getDims() == pyr2[largeLev].getDims());
00394 ASSERT(pyr1[smallLev].getDims() == pyr2[smallLev].getDims());
00395
00396
00397 const CudaImage<float> limg = pyr1[largeLev]-pyr2[largeLev];
00398 const CudaImage<float> simg = pyr1[smallLev]-pyr2[smallLev];
00399
00400 if (clipPyr != 0 && clipPyr->isNonEmpty())
00401 {
00402 ASSERT((*clipPyr)[largeLev].getDims() == limg.getDims());
00403 ASSERT((*clipPyr)[smallLev].getDims() == simg.getDims());
00404
00405 return ::cudaCenterSurround(limg*(*clipPyr)[largeLev],
00406 simg*(*clipPyr)[smallLev],
00407 absol);
00408 }
00409 else
00410 return ::cudaCenterSurround(limg, simg, absol);
00411 }
00412
00413 void cudaCenterSurroundDiff(const CudaImageSet<float>& pyr1,
00414 const CudaImageSet<float>& pyr2,
00415 const int lev1, const int lev2,
00416 CudaImage<float>& pos, CudaImage<float>& neg,
00417 const CudaImageSet<float>* clipPyr)
00418 {
00419 ASSERT(lev1 >= 0 && lev2 >= 0);
00420 ASSERT(uint(lev1) < pyr1.size() && uint(lev2) < pyr1.size());
00421
00422 const int largeLev = std::min(lev1, lev2);
00423 const int smallLev = std::max(lev1, lev2);
00424
00425 ASSERT(pyr1[largeLev].getDims() == pyr2[largeLev].getDims());
00426 ASSERT(pyr1[smallLev].getDims() == pyr2[smallLev].getDims());
00427
00428
00429 const CudaImage<float> limg = pyr1[largeLev]-pyr2[largeLev];
00430 const CudaImage<float> simg = pyr1[smallLev]-pyr2[smallLev];
00431
00432 if (clipPyr != 0 && clipPyr->isNonEmpty())
00433 {
00434 ASSERT((*clipPyr)[largeLev].getDims() == limg.getDims());
00435 ASSERT((*clipPyr)[smallLev].getDims() == simg.getDims());
00436
00437 ::cudaCenterSurround(limg*(*clipPyr)[largeLev],
00438 simg*(*clipPyr)[smallLev],
00439 pos, neg);
00440 }
00441 else
00442 ::cudaCenterSurround(limg, simg, pos, neg);
00443 }
00444
00445
00446 CudaImage<float> cudaCenterSurroundDiffSingleOpponent(const CudaImageSet<float>& cpyr1,
00447 const CudaImageSet<float>& cpyr2,
00448 const CudaImageSet<float>& spyr1,
00449 const CudaImageSet<float>& spyr2,
00450 const int lev1, const int lev2,
00451 const bool absol,
00452 const CudaImageSet<float>* clipPyr)
00453 {
00454 ASSERT(lev1 >= 0 && lev2 >= 0);
00455 ASSERT(uint(lev1) < cpyr1.size() && uint(lev2) < cpyr1.size());
00456
00457 const int largeLev = std::min(lev1, lev2);
00458 const int smallLev = std::max(lev1, lev2);
00459
00460 ASSERT(cpyr1[largeLev].getDims() == cpyr2[largeLev].getDims());
00461 ASSERT(cpyr1[smallLev].getDims() == cpyr2[smallLev].getDims());
00462 ASSERT(spyr1[largeLev].getDims() == spyr2[largeLev].getDims());
00463 ASSERT(spyr1[smallLev].getDims() == spyr2[smallLev].getDims());
00464
00465
00466 const CudaImage<float> limg = cpyr1[largeLev]-cpyr2[largeLev];
00467 const CudaImage<float> simg = spyr1[smallLev]-spyr2[smallLev];
00468
00469 if (clipPyr != 0 && clipPyr->isNonEmpty())
00470 {
00471 ASSERT((*clipPyr)[largeLev].getDims() == limg.getDims());
00472 ASSERT((*clipPyr)[smallLev].getDims() == simg.getDims());
00473
00474 return ::cudaCenterSurround(limg*(*clipPyr)[largeLev],
00475 simg*(*clipPyr)[smallLev],
00476 absol);
00477 }
00478 else
00479 return ::cudaCenterSurround(limg, simg, absol);
00480 }
00481
00482
00483 void cudaCenterSurroundDiffSingleOpponent(const CudaImageSet<float>& cpyr1,
00484 const CudaImageSet<float>& cpyr2,
00485 const CudaImageSet<float>& spyr1,
00486 const CudaImageSet<float>& spyr2,
00487 const int lev1, const int lev2,
00488 CudaImage<float>& pos, CudaImage<float>& neg,
00489 const CudaImageSet<float>* clipPyr)
00490 {
00491 ASSERT(lev1 >= 0 && lev2 >= 0);
00492 ASSERT(uint(lev1) < cpyr1.size() && uint(lev2) < cpyr1.size());
00493
00494 const int largeLev = std::min(lev1, lev2);
00495 const int smallLev = std::max(lev1, lev2);
00496
00497 ASSERT(cpyr1[largeLev].getDims() == cpyr2[largeLev].getDims());
00498 ASSERT(cpyr1[smallLev].getDims() == cpyr2[smallLev].getDims());
00499 ASSERT(spyr1[largeLev].getDims() == spyr2[largeLev].getDims());
00500 ASSERT(spyr1[smallLev].getDims() == spyr2[smallLev].getDims());
00501
00502
00503 const CudaImage<float> limg = cpyr1[largeLev]-cpyr2[largeLev];
00504 const CudaImage<float> simg = spyr1[smallLev]-spyr2[smallLev];
00505
00506 if (clipPyr != 0 && clipPyr->isNonEmpty())
00507 {
00508 ASSERT((*clipPyr)[largeLev].getDims() == limg.getDims());
00509 ASSERT((*clipPyr)[smallLev].getDims() == simg.getDims());
00510
00511 ::cudaCenterSurround(limg*(*clipPyr)[largeLev],
00512 simg*(*clipPyr)[smallLev],
00513 pos, neg);
00514 }
00515 else
00516 ::cudaCenterSurround(limg, simg, pos, neg);
00517 }