void ImageMean<T>::compute(int x, int y, T darkvalue) { // if the dark value is invalid, then the computed value // is also invalid if (darkvalue != darkvalue) { image->pixel(x, y) = darkvalue; var->pixel(x, y) = darkvalue; return; } // perform mean (and possibly variance) computation in the // case where //T m; T X = 0, X2 = 0; typename std::vector<PV>::const_iterator j; unsigned int counter = 0; for (j = pvs.begin(); j != pvs.end(); j++) { T v = j->pixelvalue(x, y); // skip this value if it is a NaN if (v != v) continue; if (v < darkvalue) { v = 0; } else { v = v - darkvalue; } X += v; if (enableVariance) { X2 += v * v; } counter++; } if (counter != pvs.size()) { debug(LOG_DEBUG, DEBUG_LOG, 0, "bad pixel values at (%d, %d): %d", x, y, counter); } T EX = X / counter; T EX2 = 0; if (enableVariance) { EX2 = X2 / counter; } // if we don't have the variance, we leave it at that if (!enableVariance) { image->pixel(x, y) = EX; return; } // if the variance is enabled, then we can do the computation // again, and ignore not only the bad values, but also the // ones that are more then 3 standard deviations away from // the mean X = 0, X2 = 0; counter = 0; T stddevk = k * sqrt(EX2 - EX * EX); if (stddevk < 1) { stddevk = std::numeric_limits<T>::infinity(); } for (j = pvs.begin(); j != pvs.end(); j++) { T v = j->pixelvalue(x, y); // skip NaNs if (v != v) continue; if (v < darkvalue) { v = 0; } else { v = v - darkvalue; } // skip values that are too far off if (fabs(v - EX) > stddevk) { continue; } X += v; X2 += v * v; counter++; } if (0 == counter) { image->pixel(x, y) = std::numeric_limits<T>::quiet_NaN(); var->pixel(x, y) = std::numeric_limits<T>::quiet_NaN(); return; } EX = X / counter; EX2 = X2 / counter; image->pixel(x, y) = EX; var->pixel(x, y) = EX2 - EX * EX; }