21 int const width =
image.getWidth();
22 int const height =
image.getHeight();
28 int const initialStride =
29 std::max(1,
static_cast<int>(
std::sqrt(width * height /
static_cast<double>(nSamples))));
31 for (
int stride = initialStride; stride >= 1; --stride) {
34 for (
int y = 0;
y < height;
y += stride) {
35 for (
int x = 0;
x < width;
x += stride) {
44 if (5 * vSample.
size() > 4 * nSamples) {
56 double sumz = 0, sumsq = 0;
57 for (
unsigned i = 0; i < vFlat.
size(); ++i) {
59 double const z = vFlat[i];
66 double const goodPix = nGoodPix;
75 std::vector<T> const& vSample,
double const nSigmaClip,
int const nGrow,
int const minpix,
78 double const xscale = 2.0 / (vSample.
size() - 1);
88 int nGoodPix = vSample.
size();
89 int nGoodPixOld = nGoodPix + 1;
95 for (
int iteration = 0; iteration < nIter; ++iteration) {
96 if (nGoodPix < minpix || nGoodPix >= nGoodPixOld) {
100 double sum = nGoodPix;
101 double sumx = 0, sumy = 0, sumxx = 0, sumxy = 0;
104 double const x = xnorm[i];
105 double const y = vSample[i];
114 double delta = sum * sumxx - sumx * sumx;
117 intercept = (sumxx * sumy - sumx * sumxy) / delta;
118 slope = (sum * sumxy - sumx * sumy) / delta;
123 for (
unsigned i = 0; i < vSample.
size(); ++i) {
124 vFlat.
push_back(vSample[i] - (xnorm[i] * slope + intercept));
128 double const sigma = computeSigma(vFlat, vBadPix, nGoodPix);
129 double const hcut =
sigma * nSigmaClip;
130 double const lcut = -hcut;
133 nGoodPixOld = nGoodPix;
136 for (
unsigned i = 0; i < vSample.
size(); ++i) {
137 double val = vFlat[i];
138 if (
val < lcut || hcut <
val) {
146 for (
unsigned x = 0;
x < vSample.
size(); ++
x) {
147 int imin = (
static_cast<int>(
x) > nGrow) ?
x - nGrow : -1;
149 for (
int i =
x; i > imin; --i) {
157 vBadPix = vBadPix_new;
161 *nGoodPixOut = nGoodPix;
170 getSample(
image, nSamples, vSample);
171 int nPix = vSample.
size();
173 if (vSample.
empty()) {
183 double const zmin = vSample.
front();
184 double const zmax = vSample.
back();
185 int const iCenter = nPix / 2;
186 T median = (nPix & 1) ? vSample[iCenter] : (vSample[iCenter] + vSample[iCenter + 1]) / 2;
189 const int maxRejectionRatio = 2;
190 const int npixelsMin = 5;
192 int minpix =
std::max(npixelsMin, nPix / maxRejectionRatio);
193 int nGrow =
std::max(1, nPix / 100);
195 const double nSigmaClip = 2.5;
196 const int nIterations = 5;
200 #if 0 // unused, but calculated and potentially useful
201 double const zstart = ret.first;
203 double const zslope = ret.second;
206 if (nGoodPix < minpix) {
210 double const slope = zslope / contrast;
212 z1 =
std::max(zmin, median - iCenter * slope);
213 z2 =
std::min(zmax, median + (nPix - iCenter - 1) * slope);
220 #define INSTANTIATE_GETZSCALE(T) \
221 template std::pair<double, double> getZScale(image::Image<T> const& image, int const nSamples, \
222 double const contrast)