2419
|
1 import { clamp } from "lodash";
|
|
2 import { sleep } from "./Light9Calibrate";
|
|
3 import { Light9Camera } from "./Light9Camera";
|
|
4 import { XyPlot } from "./XyPlot";
|
|
5
|
|
6 export class FindSafeExposure {
|
|
7 expoMin: number;
|
|
8 expoMax: number;
|
|
9 expo: number;
|
|
10 expoStep: number;
|
|
11 sameStateSteps: number;
|
|
12
|
|
13 constructor(public cam: Light9Camera, public plot: XyPlot) {
|
|
14 const fixedSteps = 5;
|
|
15
|
|
16 this.plot.clear();
|
|
17 this.expoMin = 1;
|
|
18 this.expoMax = 800;
|
|
19 this.expo = this.expoMin;
|
|
20 this.expoStep = (this.expoMax - this.expoMin) / fixedSteps;
|
|
21 this.sameStateSteps = 0;
|
|
22 }
|
|
23
|
|
24 async run() {
|
|
25 while (true) {
|
|
26 const currentOverexposed = await this.gatherSample();
|
|
27 this.step(currentOverexposed);
|
|
28 if (this.plot.data.length > 50 || Math.abs(this.expoStep) < 1) {
|
|
29 this.expo = this.expoMin;
|
|
30 await this.gatherSample();
|
|
31 break;
|
|
32 }
|
|
33 }
|
2420
|
34 return this.expo;
|
2419
|
35 }
|
|
36
|
|
37 step(currentOverexposed: number) {
|
|
38 const maxAllowedOverexposedPixels = 5;
|
|
39 const turnaroundScale = 0.6;
|
|
40 const stepsPerSide = 3;
|
|
41
|
|
42 const overexposed = currentOverexposed > maxAllowedOverexposedPixels;
|
|
43 if (this.expoStep > 0) {
|
|
44 if (overexposed) {
|
|
45 this.sameStateSteps += 1;
|
|
46 }
|
|
47 } else {
|
|
48 if (!overexposed) {
|
|
49 this.sameStateSteps += 1;
|
|
50 }
|
|
51 }
|
|
52 this.plot.setXMarklines([
|
|
53 { txt: "min", x: this.expoMin },
|
|
54 { txt: "max", x: this.expoMax },
|
|
55 { txt: "expo", x: this.expo },
|
|
56 ]);
|
|
57 const nextExpo = clamp(this.expo + this.expoStep, this.expoMin, this.expoMax);
|
|
58 if (this.sameStateSteps > stepsPerSide || nextExpo <= this.expoMin || nextExpo >= this.expoMax) {
|
|
59 if (this.expoStep > 0) {
|
|
60 this.expoMax = this.expo;
|
|
61 } else {
|
|
62 this.expoMin = this.expo;
|
|
63 }
|
|
64 this.expoStep = this.expoStep * -1 * turnaroundScale;
|
|
65 this.sameStateSteps = 0;
|
|
66 }
|
|
67 this.expo = clamp(this.expo + this.expoStep, this.expoMin, this.expoMax);
|
|
68 }
|
|
69
|
|
70 async gatherSample() {
|
|
71 const settleMs = 200;
|
|
72
|
|
73 await this.cam.set("exposureTime", this.expo);
|
|
74 const settleUntil = Date.now() + settleMs;
|
|
75 let miny = this.cam.saturatedPixelCount!;
|
|
76 while (Date.now() < settleUntil) {
|
|
77 await sleep(1000 / this.cam.videoSettings.frameRate);
|
|
78 miny = Math.min(miny, this.cam.saturatedPixelCount!);
|
|
79 }
|
|
80 this.plot!.insertPoint(this.expo, clamp(miny, 0, 100));
|
|
81 return miny;
|
|
82 }
|
|
83 }
|