Files
@ d5750b2aaa9e
Branch filter:
Location: light9/web/calibrate/FindSafeExposure.ts - annotation
d5750b2aaa9e
2.3 KiB
video/MP2T
minor cam edits
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;
}
}
|