| 233 | // function and its callees do not modify any data that is not on the stack. |
| 234 | |
| 235 | void ClassicDescSearch( // search along whisker for best profile match |
| 236 | double& x, // io: (in: old posn of landmark, out: new posn) |
| 237 | double& y, // io: |
| 238 | const Image& img, // in: the image scaled to this pyramid level |
| 239 | const Shape& inshape, // in: current posn of landmarks (for whisker directions) |
| 240 | int ipoint, // in: index of the current landmark |
| 241 | const MAT& meanprof, // in: mean of the training profiles for this point |
| 242 | const MAT& covi) // in: inverse of the covar of the training profiles |
| 243 | { |
| 244 | const int proflen = NSIZE(meanprof); |
| 245 | CV_Assert(proflen % 2 == 1); // proflen must be odd in this implementation |
| 246 | |
| 247 | // fullprof is the 1D profile along the whisker including the extra |
| 248 | // elements to allow search +-CLASSIC_MAX_OFFSET pixels away from |
| 249 | // the current position of the landmark. |
| 250 | // We precalculate the fullprof for efficiency in the for loop below. |
| 251 | |
| 252 | const int fullproflen = proflen + 2 * CLASSIC_MAX_OFFSET; |
| 253 | CV_Assert(fullproflen % 2 == 1); // fullprof length must be odd |
| 254 | const VEC fullprof(FullProf(img, inshape, ipoint, fullproflen)); |
| 255 | |
| 256 | // move along the whisker looking for the best match |
| 257 | |
| 258 | int bestoffset = 0; |
| 259 | double mindist = FLT_MAX; |
| 260 | for (int offset = -CLASSIC_MAX_OFFSET; |
| 261 | offset <= CLASSIC_MAX_OFFSET; |
| 262 | offset += CLASSIC_SEARCH_RESOL) |
| 263 | { |
| 264 | // Get the profile distance. That is, get the image profile at the given |
| 265 | // offset along the whisker, and return the Mahalanobis distance between |
| 266 | // it and the model mean profile. Low distance means good fit. |
| 267 | |
| 268 | const VEC prof(SubProf(offset, proflen, fullprof)); |
| 269 | |
| 270 | // The following code is equivalent to |
| 271 | // dist = (prof - meanprof).t() * covi * (prof - meanprof) |
| 272 | // but is optimized for speed. |
| 273 | |
| 274 | prof -= meanprof; // for efficiency, use "-=" not "=" with "-" |
| 275 | const double dist = xAx(prof, covi); |
| 276 | |
| 277 | if (dist < mindist) |
| 278 | { |
| 279 | mindist = dist; |
| 280 | bestoffset = offset; |
| 281 | } |
| 282 | } |
| 283 | // change x,y to the best position along the whisker |
| 284 | |
| 285 | double xstep, ystep; |
| 286 | WhiskerStep(xstep, ystep, inshape, ipoint); |
| 287 | x = inshape(ipoint, IX) + (bestoffset * xstep); |
| 288 | y = inshape(ipoint, IY) + (bestoffset * ystep); |
| 289 | } |
| 290 | |
| 291 | } // namespace stasm |
no test coverage detected