// Copyright (c) the JPEG XL Project Authors. All rights reserved. // // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file.
int Mode() const {
size_t max_idx = 0; for (size_t i = 0; i < kBins; i++) { if (bins[i] > bins[max_idx]) max_idx = i;
} return max_idx;
}
double Quantile(double q01) const { const int64_t total = std::accumulate(bins, bins + kBins, int64_t{1}); const int64_t target = static_cast<int64_t>(q01 * total); // Until sum >= target:
int64_t sum = 0;
size_t i = 0; for (; i < kBins; ++i) {
sum += bins[i]; // Exact match: assume middle of bin i if (sum == target) { return i + 0.5;
} if (sum > target) break;
}
// Next non-empty bin (in case histogram is sparsely filled)
size_t next = i + 1; while (next < kBins && bins[next] == 0) {
++next;
}
// Linear interpolation according to how far into next we went constdouble excess = target - sum; constdouble weight_next = bins[Index(next)] / excess; return ClampX(next * weight_next + i * (1.0 - weight_next));
}
for (size_t y = 0; y + block_s <= opsin.ysize(); y += block_s) { for (size_t x = 0; x + block_s <= opsin.xsize(); x += block_s) { float sad_sc = GetScoreSumsOfAbsoluteDifferences(opsin, x, y, block_s);
sad_scores[block_index++] = sad_sc;
sad_histogram->Increment(sad_sc * num_bin);
}
} return sad_scores;
}
float GetSADThreshold(const NoiseHistogram& histogram, constint num_bin) { // Here we assume that the most patches with similar SAD value is a "flat" // patches. However, some images might contain regular texture part and // generate second strong peak at the histogram // TODO(user) handle bimodal and heavy-tailed case constint mode = histogram.Mode(); returnstatic_cast<float>(mode) / NoiseHistogram::kBins;
}
// loss = sum asym * (F(x) - nl)^2 + kReg * num_points * sum (w[i] - w[i+1])^2 // where asym = 1 if F(x) < nl, kAsym if F(x) > nl. struct LossFunction { explicit LossFunction(std::vector<NoiseLevel> nl0) : nl(std::move(nl0)) {}
Status GetNoiseParameter(const Image3F& opsin, NoiseParams* noise_params, float quality_coef) { // The size of a patch in decoder might be different from encoder's patch // size. // For encoder: the patch size should be big enough to estimate // noise level, but, at the same time, it should be not too big // to be able to estimate intensity value of the patch const size_t block_s = 8; const size_t kNumBin = 256;
NoiseHistogram sad_histogram;
std::vector<float> sad_scores =
GetSADScoresForPatches(opsin, block_s, kNumBin, &sad_histogram); float sad_threshold = GetSADThreshold(sad_histogram, kNumBin); // If threshold is too large, the image has a strong pattern. This pattern // fools our model and it will add too much noise. Therefore, we do not add // noise for such images if (sad_threshold > 0.15f || sad_threshold <= 0.0f) {
noise_params->Clear(); returnfalse;
}
std::vector<NoiseLevel> nl =
GetNoiseLevel(opsin, sad_scores, sad_threshold, block_s);
OptimizeNoiseParameters(nl, noise_params); for (float& i : noise_params->lut) {
i *= quality_coef * 1.4;
} return noise_params->HasAny();
}
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.