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
00040
00041
00042
00043
00044
00047
00048
00049
00050 #ifndef _LEVELSETFUNCTION_IMPLEMENTATION_H
00051 #define _LEVELSETFUNCTION_IMPLEMENTATION_H
00052
00053 #include <cmath>
00054
00055 namespace lsseg {
00056
00057
00058 double LevelSetFunction::gradientNorm2D(int x, int y) const
00059
00060 {
00061 const int xp = --x >= 0 ? x : 0; ++x;
00062 const int xn = ++x < dimx() ? x : dimx() - 1; --x;
00063 const int yp = --y >= 0 ? y : 0; ++y;
00064 const int yn = ++y < dimy() ? y : dimy() - 1; --y;
00065 const double Icp = operator()(x, yp);
00066 const double Icn = operator()(x, yn);
00067 const double Ipc = operator()(xp, y);
00068 const double Inc = operator()(xn, y);
00069
00070 const double x_diff = (xn - xp) == 2 ? 0.5 : 1;
00071 const double y_diff = (yn - yp) == 2 ? 0.5 : 1;
00072
00073 const double dx = (Inc - Ipc) * x_diff;
00074 const double dy = (Icn - Icp) * y_diff;
00075 return sqrt((dx*dx) + (dy*dy));
00076 }
00077
00078
00079 double LevelSetFunction::gradientNorm3D(int x, int y, int z) const
00080
00081 {
00082 const int xp = --x >= 0 ? x : 0; ++x;
00083 const int xn = ++x < dimx() ? x : dimx() - 1; --x;
00084 const int yp = --y >= 0 ? y : 0; ++y;
00085 const int yn = ++y < dimy() ? y : dimy() - 1; --y;
00086 const int zp = --z >= 0 ? z : 0; ++z;
00087 const int zn = ++z < dimz() ? z : dimz() - 1; --z;
00088 const double Icpc = operator()(x, yp, z);
00089 const double Icnc = operator()(x, yn, z);
00090 const double Ipcc = operator()(xp, y, z);
00091 const double Incc = operator()(xn, y, z);
00092 const double Iccp = operator()(x, y, zp);
00093 const double Iccn = operator()(x, y, zn);
00094
00095 const double x_diff = (xn - xp) == 2 ? 0.5 : 1;
00096 const double y_diff = (yn - yp) == 2 ? 0.5 : 1;
00097 const double z_diff = (zn - zp) == 2 ? 0.5 : 1;
00098
00099 const double dx = (Incc - Ipcc) * x_diff;
00100 const double dy = (Icnc - Icpc) * y_diff;
00101 const double dz = (Iccn - Iccp) * z_diff;
00102
00103 return sqrt((dx*dx) + (dy*dy) + (dz*dz));
00104 }
00105
00106
00107 double LevelSetFunction::curvature2D(int x, int y) const
00108
00109 {
00110 const double res = curvatureTimesGrad2D(x, y);
00111 return res / sqrt(cached_);
00112 }
00113
00114
00115 double LevelSetFunction::curvature3D(int x, int y, int z) const
00116
00117 {
00118 const double res = curvatureTimesGrad3D(x, y, z);
00119 return res / sqrt(cached_);
00120 }
00121
00122
00123
00124 double LevelSetFunction::curvatureTimesGrad2D(int x, int y) const
00125
00126 {
00127 const double EPS=1.0e-5;
00128 const int xp = --x >= 0 ? x : 0; ++x;
00129 const int xn = ++x < dimx() ? x : dimx() - 1; --x;
00130 const int yp = --y >= 0 ? y : 0; ++y;
00131 const int yn = ++y < dimy() ? y : dimy() - 1; --y;
00132 const double Icp = operator()(x, yp);
00133 const double Icn = operator()(x, yn);
00134 const double Ipc = operator()(xp, y);
00135 const double Inc = operator()(xn, y);
00136 const double dx = (Inc - Ipc) * 0.5;
00137 const double dy = (Icn - Icp) * 0.5;
00138 const double norm2 = (dx*dx) + (dy*dy);
00139 cached_ = norm2 > EPS ? norm2 : EPS;
00140
00141 if (norm2 < EPS) return 0;
00142
00143 const double Ipp = operator()(xp, yp);
00144 const double Inp = operator()(xn, yp);
00145 const double Icc = operator()(x,y);
00146 const double Ipn = operator()(xp, yn);
00147 const double Inn = operator()(xn, yn);
00148 const double dxx = Inc + Ipc - 2 * Icc;
00149 const double dyy = Icn + Icp - 2 * Icc;
00150 const double dxy = (dx * dy < 0) ?
00151 0.5 * (2 * Icc + Ipp + Inn - Ipc - Inc - Icp - Icn) :
00152 0.5 * (Ipc + Inc + Icp + Icn - 2 * Icc - Ipn - Inp);
00153 return (dy * dy * dxx - 2 * dx * dy * dxy + dx * dx * dyy) / norm2;
00154 }
00155
00156
00157 double LevelSetFunction::curvatureTimesGrad3D(int x, int y, int z) const
00158
00159 {
00160 const double EPS=1.0e-5;
00161 const int xp = --x >= 0 ? x : 0; ++x;
00162 const int xn = ++x < dimx() ? x : dimx() - 1; --x;
00163 const int yp = --y >= 0 ? y : 0; ++y;
00164 const int yn = ++y < dimy() ? y : dimy() - 1; --y;
00165 const int zp = --z >= 0 ? z : 0; ++z;
00166 const int zn = ++z < dimz() ? z : dimz() - 1; --z;
00167
00168 const double Icpc = operator()(x, yp, z);
00169 const double Icnc = operator()(x, yn, z);
00170 const double Ipcc = operator()(xp, y, z);
00171 const double Incc = operator()(xn, y, z);
00172 const double Iccp = operator()(x, y, zp);
00173 const double Iccn = operator()(x, y, zn);
00174
00175 const double x_diff = (xn - xp) == 2 ? 0.5 : 1;
00176 const double y_diff = (yn - yp) == 2 ? 0.5 : 1;
00177 const double z_diff = (zn - zp) == 2 ? 0.5 : 1;
00178
00179 const double dx = (Incc - Ipcc) * x_diff;
00180 const double dy = (Icnc - Icpc) * y_diff;
00181 const double dz = (Iccn - Iccp) * z_diff;
00182 const double norm2 = (dx*dx) + (dy*dy) + (dz*dz);
00183 cached_ = norm2 > EPS ? norm2 : EPS;
00184
00185 if(norm2 < EPS) return 0;
00186
00187 const double Ippc = operator()(xp, yp, z);
00188 const double Ipcp = operator()(xp, y, zp);
00189 const double Ipcn = operator()(xp, y, zn);
00190 const double Ipnc = operator()(xp, yn, z);
00191 const double Icpp = operator()( x, yp, zp);
00192 const double Icpn = operator()( x, yp, zn);
00193 const double Iccc = operator()( x, y, z);
00194 const double Icnp = operator()( x, yn, zp);
00195 const double Icnn = operator()( x, yn, zn);
00196 const double Inpc = operator()(xn, yp, z);
00197 const double Incp = operator()(xn, y, zp);
00198 const double Incn = operator()(xn, y, zn);
00199 const double Innc = operator()(xn, yn, z);
00200
00201 const double dxx = Incc + Ipcc - 2 * Iccc;
00202 const double dyy = Icnc + Icpc - 2 * Iccc;
00203 const double dzz = Iccn + Iccp - 2 * Iccc;
00204 const double dxy = (dx * dy < 0) ?
00205 0.5 * (2 * Iccc + Ippc + Innc - Ipcc - Incc - Icpc - Icnc) :
00206 0.5 * (Ipcc + Incc + Icpc + Icnc - 2 * Iccc - Ipnc - Inpc);
00207 const double dxz = (dx * dz < 0) ?
00208 0.5 * (2 * Iccc + Ipcp + Incn - Ipcc - Incc - Iccp - Iccn) :
00209 0.5 * (Ipcc + Incc + Iccp + Iccn - 2 * Iccc - Ipcn - Incp);
00210 const double dyz = (dy * dz < 0) ?
00211 0.5 * (2 * Iccc + Icpp + Icnn - Icpc - Icnc - Iccp - Iccn) :
00212 0.5 * (Icpc + Icnc + Iccp + Iccn - 2 * Iccc - Icpn - Icnp);
00213
00214
00215 return (dx * dx * (dyy + dzz) +
00216 dy * dy * (dxx + dzz) +
00217 dz * dz * (dxx + dyy) -
00218 2 * (dx * dy * dxy +
00219 dx * dz * dxz +
00220 dy * dz * dyz)
00221 ) / norm2;
00222 }
00223
00224
00225 void LevelSetFunction::curvature2D(Image<double>& target, Mask* mask) const
00226
00227 {
00228 assert(!mask || spatial_compatible(*mask));
00229 MESSAGE_IF(dimz() > 1, "Warning: applying 2D method on a grid with dim(z) > 1");
00230 const int X = dimx();
00231 const int Y = dimy();
00232 if (!size_compatible(target)) {
00233 target.resize(X, Y);
00234 }
00235 if (!mask) {
00236 for (int y = 0; y < Y; ++y) {
00237 for (int x = 0; x < X; ++x) {
00238 target(x, y) = curvature2D(x, y);
00239 }
00240 }
00241 } else {
00242 char* mptr = mask->begin();
00243 for (int y = 0; y < Y; ++y) {
00244 for (int x = 0; x < X; ++x) {
00245 if (*mptr++) {
00246 target(x, y) = curvature2D(x, y);
00247 }
00248 }
00249 }
00250 }
00251 }
00252
00253
00254 void LevelSetFunction::curvature3D(Image<double>& target, Mask* mask) const
00255
00256 {
00257 assert(!mask || spatial_compatible(*mask));
00258 const int X = dimx();
00259 const int Y = dimy();
00260 const int Z = dimz();
00261 if (!size_compatible(target)) {
00262 target.resize(X, Y, Z);
00263 }
00264 if (!mask) {
00265 for (int z = 0; z < Z; ++z) {
00266 for (int y = 0; y < Y; ++y) {
00267 for (int x = 0; x < X; ++x) {
00268 target(x, y, z) = curvature3D(x, y, z);
00269 }
00270 }
00271 }
00272 } else {
00273 char* mptr = mask->begin();
00274 for (int z = 0; z < Z; ++z) {
00275 for (int y = 0; y < Y; ++y) {
00276 for (int x = 0; x < X; ++x) {
00277 if (*mptr++) {
00278 target(x, y, z) = curvature3D(x, y, z);
00279 }
00280 }
00281 }
00282 }
00283 }
00284 }
00285
00286
00287 void LevelSetFunction::gradientNorm2D(Image<double>& target, Mask* mask) const
00288
00289 {
00290 assert(!mask || spatial_compatible(*mask));
00291 MESSAGE_IF(dimz() > 1, "Warning: applying 2D method on a grid with dim(z) > 1");
00292 const int X = dimx();
00293 const int Y = dimy();
00294 if (!size_compatible(target)) {
00295 target.resize(X, Y);
00296 }
00297 if (!mask) {
00298 for (int y = 0; y < Y; ++y) {
00299 for (int x = 0; x < X; ++x) {
00300 target(x, y) = gradientNorm2D(x, y);
00301 }
00302 }
00303 } else {
00304 char* mptr = mask->begin();
00305 for (int y = 0; y < Y; ++y) {
00306 for (int x = 0; x < X; ++x) {
00307 if (*mptr++) {
00308 target(x, y) = gradientNorm2D(x, y);
00309 }
00310 }
00311 }
00312
00313 }
00314 }
00315
00316
00317 void LevelSetFunction::gradientNorm3D(Image<double>& target, Mask* mask) const
00318
00319 {
00320 assert(!mask || spatial_compatible(*mask));
00321 const int X = dimx();
00322 const int Y = dimy();
00323 const int Z = dimz();
00324 if (!size_compatible(target)) {
00325 target.resize(X, Y, Z);
00326 }
00327 if (!mask) {
00328 for (int z = 0; z < Z; ++z) {
00329 for (int y = 0; y < Y; ++y) {
00330 for (int x = 0; x < X; ++x) {
00331 target(x, y, z) = gradientNorm3D(x, y, z);
00332 }
00333 }
00334 }
00335 } else {
00336 char* mptr = mask->begin();
00337 for (int z = 0; z < Z; ++z) {
00338 for (int y = 0; y < Y; ++y) {
00339 for (int x = 0; x < X; ++x) {
00340 if (*mptr++) {
00341 target(x, y, z) = gradientNorm3D(x, y, z);
00342 }
00343 }
00344 }
00345 }
00346 }
00347 }
00348
00349
00350
00351 void LevelSetFunction::curvatureTimesGrad2D(Image<double>& target, Mask* mask) const
00352
00353 {
00354 assert(!mask || spatial_compatible(*mask));
00355 MESSAGE_IF(dimz() > 1, "Warning: applying 2D method on a grid with dim(z) > 1");
00356 const int X = dimx();
00357 const int Y = dimy();
00358 if (!size_compatible(target)) {
00359 target.resize(X, Y);
00360 }
00361
00362 if (!mask) {
00363 for (int y = 0; y < Y; ++y) {
00364 for (int x = 0; x < X; ++x) {
00365 target(x, y) = curvatureTimesGrad2D(x, y);
00366 }
00367 }
00368 } else {
00369 char* mptr = mask->begin();
00370 for (int y = 0; y < Y; ++y) {
00371 for (int x = 0; x < X; ++x) {
00372 if (*mptr++) {
00373 target(x, y) = curvatureTimesGrad2D(x, y);
00374 }
00375 }
00376 }
00377 }
00378 }
00379
00380
00381 void LevelSetFunction::curvatureTimesGrad3D(Image<double>& target, Mask* mask) const
00382
00383 {
00384 assert(!mask || spatial_compatible(*mask));
00385 const int X = dimx();
00386 const int Y = dimy();
00387 const int Z = dimz();
00388 if (!size_compatible(target)) {
00389 target.resize(X, Y, Z);
00390 }
00391
00392 if (!mask) {
00393 for (int z = 0; z < Z; ++z) {
00394 for (int y = 0; y < Y; ++y) {
00395 for (int x = 0; x < X; ++x) {
00396 target(x, y, z) = curvatureTimesGrad3D(x, y, z);
00397 }
00398 }
00399 }
00400 } else {
00401 char* mptr = mask->begin();
00402 for (int z = 0; z < Z; ++z) {
00403 for (int y = 0; y < Y; ++y) {
00404 for (int x = 0; x < X; ++x) {
00405 if (*mptr++) {
00406 target(x, y, z) = curvatureTimesGrad3D(x, y, z);
00407 }
00408 }
00409 }
00410 }
00411 }
00412 }
00413
00414
00415 };
00416
00417 #endif // _LEVELSETFUNCTION_IMPLEMENTATION_H
00418