fwt_software/include/fgc/ExposurePolicy.h

52 lines
2.1 KiB
C++

#pragma once
#include "fgc/ImageQuality.h"
#include <string>
namespace fgc {
// The exposure/gain control law: given what an image turned out like, decide
// whether to keep it and what to change if not. Pure (no camera, no I/O, no
// clock) so the whole correction strategy is unit-testable.
struct CaptureSettings {
double exposure_us = 0.0;
double gain_db = 0.0;
};
struct PolicyParams {
double target_mean = 110.0; // desired mean luma, 0..255
double mean_tolerance = 12.0; // accept within +-this of the target
double clip_max_fraction = 0.005; // 0.5% blown pixels is the ceiling
double exposure_min_us = 50.0;
double exposure_max_us = 20000.0; // doubles as the motion-blur budget
double gain_max_db = 12.0;
double damping = 0.8; // <1 damps the correction, preventing oscillation
// Blur is judged RELATIVE to the same angle's own history: a foggy horizon is
// legitimately low-detail, so an absolute threshold would retry forever on it.
double blur_relative_floor = 0.5; // retry below this fraction of the reference
double blur_absolute_floor = 0.0; // 0 disables the catastrophic-blur backstop
};
struct Verdict {
bool accept = false;
std::string reason; // "ok" / "clipped" / "dark" / "bright" / "blur" / "saturated"
CaptureSettings next; // settings to use for the next attempt (== current if accepting)
};
// Judge one attempt. `reference_sharpness` is this angle's recent sharpness; pass
// 0 when unknown, which skips the relative blur check.
//
// Precedence matters: clipping outranks the mean, because a bright sky can blow
// out while the average still looks perfectly reasonable - and blown highlights
// are unrecoverable, whereas a slightly dark frame is not.
Verdict evaluate(const ImageMetrics& m, const CaptureSettings& current, const PolicyParams& p,
double reference_sharpness = 0.0);
// Rank attempts so "best so far" is well defined: sharpness discounted by how far
// the exposure strayed. Higher is better.
double score(const ImageMetrics& m, const PolicyParams& p);
} // namespace fgc