Files
@ 26f84fc67ab1
Branch filter:
Location: light9/web/calibrate/FindSafeExposure.ts - annotation
26f84fc67ab1
2.3 KiB
video/MP2T
start 2024 show
e3af0ac507c8 e3af0ac507c8 e3af0ac507c8 e3af0ac507c8 e3af0ac507c8 e3af0ac507c8 e3af0ac507c8 e3af0ac507c8 e3af0ac507c8 e3af0ac507c8 e3af0ac507c8 e3af0ac507c8 e3af0ac507c8 e3af0ac507c8 e3af0ac507c8 e3af0ac507c8 e3af0ac507c8 e3af0ac507c8 e3af0ac507c8 e3af0ac507c8 e3af0ac507c8 e3af0ac507c8 e3af0ac507c8 e3af0ac507c8 e3af0ac507c8 e3af0ac507c8 e3af0ac507c8 e3af0ac507c8 e3af0ac507c8 e3af0ac507c8 e3af0ac507c8 e3af0ac507c8 e3af0ac507c8 d5750b2aaa9e e3af0ac507c8 e3af0ac507c8 e3af0ac507c8 e3af0ac507c8 e3af0ac507c8 e3af0ac507c8 e3af0ac507c8 e3af0ac507c8 e3af0ac507c8 e3af0ac507c8 e3af0ac507c8 e3af0ac507c8 e3af0ac507c8 e3af0ac507c8 e3af0ac507c8 e3af0ac507c8 e3af0ac507c8 e3af0ac507c8 e3af0ac507c8 e3af0ac507c8 e3af0ac507c8 e3af0ac507c8 e3af0ac507c8 e3af0ac507c8 e3af0ac507c8 e3af0ac507c8 e3af0ac507c8 e3af0ac507c8 e3af0ac507c8 e3af0ac507c8 e3af0ac507c8 e3af0ac507c8 e3af0ac507c8 e3af0ac507c8 e3af0ac507c8 e3af0ac507c8 e3af0ac507c8 e3af0ac507c8 e3af0ac507c8 e3af0ac507c8 e3af0ac507c8 e3af0ac507c8 e3af0ac507c8 e3af0ac507c8 e3af0ac507c8 e3af0ac507c8 e3af0ac507c8 e3af0ac507c8 e3af0ac507c8 | import { clamp } from "lodash";
import { sleep } from "./Light9Calibrate";
import { Light9Camera } from "./Light9Camera";
import { XyPlot } from "./XyPlot";
export class FindSafeExposure {
expoMin: number;
expoMax: number;
expo: number;
expoStep: number;
sameStateSteps: number;
constructor(public cam: Light9Camera, public plot: XyPlot) {
const fixedSteps = 5;
this.plot.clear();
this.expoMin = 1;
this.expoMax = 800;
this.expo = this.expoMin;
this.expoStep = (this.expoMax - this.expoMin) / fixedSteps;
this.sameStateSteps = 0;
}
async run() {
while (true) {
const currentOverexposed = await this.gatherSample();
this.step(currentOverexposed);
if (this.plot.data.length > 50 || Math.abs(this.expoStep) < 1) {
this.expo = this.expoMin;
await this.gatherSample();
break;
}
}
return this.expo;
}
step(currentOverexposed: number) {
const maxAllowedOverexposedPixels = 5;
const turnaroundScale = 0.6;
const stepsPerSide = 3;
const overexposed = currentOverexposed > maxAllowedOverexposedPixels;
if (this.expoStep > 0) {
if (overexposed) {
this.sameStateSteps += 1;
}
} else {
if (!overexposed) {
this.sameStateSteps += 1;
}
}
this.plot.setXMarklines([
{ txt: "min", x: this.expoMin },
{ txt: "max", x: this.expoMax },
{ txt: "expo", x: this.expo },
]);
const nextExpo = clamp(this.expo + this.expoStep, this.expoMin, this.expoMax);
if (this.sameStateSteps > stepsPerSide || nextExpo <= this.expoMin || nextExpo >= this.expoMax) {
if (this.expoStep > 0) {
this.expoMax = this.expo;
} else {
this.expoMin = this.expo;
}
this.expoStep = this.expoStep * -1 * turnaroundScale;
this.sameStateSteps = 0;
}
this.expo = clamp(this.expo + this.expoStep, this.expoMin, this.expoMax);
}
async gatherSample() {
const settleMs = 200;
await this.cam.set("exposureTime", this.expo);
const settleUntil = Date.now() + settleMs;
let miny = this.cam.saturatedPixelCount!;
while (Date.now() < settleUntil) {
await sleep(1000 / this.cam.videoSettings.frameRate);
miny = Math.min(miny, this.cam.saturatedPixelCount!);
}
this.plot!.insertPoint(this.expo, clamp(miny, 0, 100));
return miny;
}
}
|