Files
@ 06da5db2fafe
Branch filter:
Location: light9/web/calibrate/FindSafeExposure.ts - annotation
06da5db2fafe
2.3 KiB
video/MP2T
rewrite ascoltami to use the graph for more playback data
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;
}
}
|