- 10 Jul, 2026 8 commits
-
-
Andrey Filippov authored
The RECTILINEAR nadir pass multiplied sampling coordinates by getRByRDist() (distorted->ideal), but sampling positions must be moved to where the ideal ray lands in the distorted image - the FORWARD distortion getRDistByR(), same direction as GeometryCorrection.getImageCoordinates(). The old code ADDED the common radial distortion to the output instead of removing it. Evidence (graveyard ref 1763232420_274928, flat constant-disparity terrain where translation flow must be uniform for a true pinhole image): - plain NADIR-MERGED edge/center flow ratio 0.965 (expected 0.954 from the calibration polynomial: ~4.8 px barrel at the edge), - old RECTILINEAR 0.952 - worse than uncorrected, - COLMAP self-calibrated f=1003/k1=-0.385 on the old rectilinear stack. Co-authored-by:Claude <claude@elphel.com>
-
Andrey Filippov authored
Analysis of the -NADIR-SCENE-PXPYD[-NULLCAM] dumps (graveyard ref 1763232420_274928) showed the transformFromVirtual() refinement output is accurate to <0.3 px in the interior, but produces garbage coordinates (5..100 px off) in a rim band at the edge of the valid region, where the interpolation works one-sided over NaN-filled disparity. Rendered, those tiles put wrong content in a border strip: COLMAP fit it as fake barrel distortion (f=1000, k1=-0.38) and image-based rotation measurements were contaminated (apparent ~0.6x roll). A correct scene-frame grid position is the tile center + small ERS displacement, so tiles straying more than 4 px are nulled and render as NaN instead of wrong content, slightly shrinking the usable FOV at the rim. Co-authored-by:Claude <claude@elphel.com>
-
Andrey Filippov authored
Second per-scene grid computed with scene_QuadClt=null - the exact camera model used inside Cuas.transformFromVirtual()'s refinement loop. Its non-uniformity isolates the refinement residual; its difference from -NADIR-SCENE-PXPYD isolates the scene-ERS-instance effect. Saved only on the first (non-undistorted) pass. Context: 2026-07-10 analysis of the first -NADIR-SCENE-PXPYD dump showed the sampling grid contains rotation ~0.31x scene roll (R2=0.77) plus correlated scale (~0.955) and shift_y (to -24 px) concentrated in the high-roll-rate half of the graveyard segment - explaining the ~0.6x in-plane content rotation and COLMAP's f=1000/k1=-0.38 self-calibration. Co-authored-by:Claude <claude@elphel.com>
-
Andrey Filippov authored
Save the actual scene-frame pXpYD fed to renderGPUFromDSI (after transformToScenePxPyD and optional undistort) as a pX/pY/D hyperstack at tile resolution, one frame per scene, suffix -NADIR-SCENE-PXPYD[-RECTILINEAR]. For offline verification of the nadir render geometry: the grid should be near-uniform (tile centers + ERS displacement); any residual rotation proportional to scene roll would explain the halved in-plane rotation observed in the 2026-07-10 graveyard COLMAP test. Co-authored-by:Claude <claude@elphel.com>
-
Andrey Filippov authored
getNadirDisparityMaps() returns pXpYD in the SEGMENT REFERENCE frame (Cuas.transformFromVirtual() output), but renderNadirSequence() passed it to renderGPUFromDSI() with ZERO3 pose and the scene as its own reference, so each scene image was sampled at reference-frame coordinates. Each nadir frame thus carried an extra ref->scene terrain warp: effective camera poses vs the segment reference were ~doubled (ground translation 2x, small rotations ~2x), and the identity transform also canceled ERS compensation. On flat terrain the extra plane homography mimics a valid pose change, so COLMAP converged self-consistently but disagreed with the exported poses (Sim(3)/free monocular scale absorbs the 2x translation; rotations do not scale, explaining the large angular residuals, worst on high-rotation-rate sequences). Now transformToScenePxPyD() maps the reference-frame pXpYD into each scene's own frame (pose + ERS, same machinery as the verified frozen-terrain path) before rendering with ZERO3/self, where the identity pass is an exact pass-through. Output becomes a global-shutter virtual view at each scene's nominal pose. Also converts disparity to the scene frame for 16-sensor parallax compensation, and drops the defensive clone (the transform returns new arrays). Docs updated to state the frame conventions. Co-authored-by:Claude <claude@elphel.com>
-
Andrey Filippov authored
-
Andrey Filippov authored
Kills the manual raw-import papercut: dims come from manifest.txt, TD buffers (trailing 256) render as tile grids with presentCltData quadrant placement, per-tile planes as tilesX x tilesY images, generic fallback otherwise. viewCase/viewResults/showAll; verified shapes on the avg_td round-trip case (80x64 x16 TD grid, 5x4 counts). Co-Authored-By:Claude Fable 5 <noreply@anthropic.com>
-
Andrey Filippov authored
New package com.elphel.imagej.gpu.testdata implementing the Java side of tile_processor_gpu/src/tests/testdata_format.md: - TestDataWriter: raw little-endian arrays + manifest.txt (prm/buf records) - TestDataReader: parse manifest or C++ results back for ImageJ comparison - AvgTdExport: full clt_average_sensors test case (per-sensor TD from GpuQuad, CuasTD.consolidateSensorsTD expected outputs + counts, optional TpTask per-sensor XY for the OOB stage) + compareResults round-trip check Round-trip verified bit-exact (max|diff|=0): TestDataWriter -> CUDA test_avg_td on GPU -> TestDataReader. Co-Authored-By:Claude Fable 5 <noreply@anthropic.com>
-
- 08 Jul, 2026 5 commits
-
-
Andrey Filippov authored
Andrey's correction: the eroded average left a wide NaN frame (and all its descendants - EVAL diffs). The average virtual image must be defined wherever ANY scene provides (a single bad first/last row/col at most): combine ALL available contributors, let the count taper naturally near the edges, and reject junk providers per pixel as OUTLIERS vs the MEDIAN with an IQR-based robust sigma (immune to heavy contamination, unlike mean/sigma). Fewer than 4 providers - plain mean; zero - NaN. Geometric erosion (erodeDefined/erodedMasks/AVG_EDGE_ERODE) removed. Next (Andrey): per-TILE outlier rejection in the 16-sensor TD consolidation, anticipating the GPU migration (candidate indicator: CC(0,0) flux, possibly + quadrant energy). Co-Authored-By:Claude Fable 5 <noreply@anthropic.com>
-
Andrey Filippov authored
New evaluation product with the RT render (replaces the manual run-UM-in-ImageJ workflow): merged component only, z = robust all-scenes average + each scene, t ordered for ImageJ auto-range: 1) pixel LoG (the pre-DNN kernel, LINEAR) of the image, 2) LoG of (scene - average), 3) plain (scene - average); t2/t3 are 0 for the average frame. The average is the new robust one (edge-eroded + outlier-rejected), extracted into shared helpers (erodedMasks/robustAverage) used by both saveRenderHyper and the EVAL builder. Co-Authored-By:Claude Fable 5 <noreply@anthropic.com>
-
Andrey Filippov authored
The temporal averages accumulated per-scene edge junk into stable margin artifacts (ROWCOL-04: worst columns x=12,20,28 = 8-px tile pitch - partially covered virtual tiles at the warped-coverage edge; the wobble sweeps which tiles are partial). For the two AVERAGE slices only (individual scenes stay liberal/untouched): each scene's contribution is box-eroded 24 px (3 tile pitches, AVG_EDGE_ERODE - clears the partial-tile ring) and outlier-rejected (3 sigma vs the first-pass mean when >= 4 providers, per Andrey's >1-non-NaN-provider rule); zero eroded providers -> honest NaN. Co-Authored-By:Claude Fable 5 <noreply@anthropic.com>
-
Andrey Filippov authored
ROWCOL-04 localization: RT rows regression (18.0 vs 10.6 pre-rework) is CONTENT BIAS, zero in the sky and +10..22 counts in terrain rows - with dense high-contrast content nearly every |UM residual| exceeds max_abs, all pixels get the outlier weight and the weighted mean degenerates to the row's content mean (the small weights cancel), stamping bias bands. lineAverage now zeroes a line's correction when its inlier fraction is below rowcol_min_inlier (default 0.33 - content-dominated lines cannot yield a line-noise measurement) or when |estimate| > max_abs (line noise cannot physically exceed the gate scale). Both guards are no-ops with the gate off (max_abs INF - every pixel is an inlier). Co-Authored-By:Claude Fable 5 <noreply@anthropic.com>
-
Andrey Filippov authored
ROWCOL-03 QC FAIL (rms 52.9 unchanged by erosion) proved the junk edge columns are FULLY covered with DEFINED-BUT-WRONG back-projection values (left-edge convert_direct artifact class) - erosion cannot see them: - exclude a 16px frame-edge band from the content-excluded estimator by geometry (ROWCOL_BP_EDGE_MARGIN); those lines take the legacy fallback; - physical cap in the per-line merge: a content-excluded line value over max_abs cannot be line noise - use legacy (also blunts any future ROWCOL-01-class estimator failure). RT conditioning: profile HPF now applies ONLY when rowcol_um_sigma==0. Stacking it on the UM measurement double-high-passed the row-offset estimate ((1-G10)(1-G8)): removed fraction at period ~20 rows dropped 96% -> 91%, residual mid-band line noise x2 - measured merged RT-RENDER rows metric 10.60 (ROWCOL-02, pre-rework) -> 18.73 (ROWCOL-03). Single sigma-10 high-pass removes strictly more noise at every period than the old sigma-8-only path and protects the LoG band at least as well. Co-Authored-By:Claude Fable 5 <noreply@anthropic.com>
-
- 07 Jul, 2026 13 commits
-
-
Andrey Filippov authored
Where a small foreground object (the 3-tile roadside sign, disp ~22) stands in front of a distant background both disparities are legitimate, but for CUAS the background matters: a drone flying exactly behind the sign must stay detectable. conditionDisparityCuas now detects connected clusters of local near-outliers (disparity above the local 7x7 median by curt.disp_fg_over, default 2 px) up to curt.disp_fg_tiles (default 8, 0 = off) tiles and re-fills them with zero-curvature background disparity (TileProcessor.fillNaNs Laplacian relaxation). All three RT call sites (render, pose, appropriation) share the one conditioned source as before. Co-Authored-By:Claude Fable 5 <noreply@anthropic.com>
-
Andrey Filippov authored
1. calculateRowColBackProject: ERODE the coverage mask (blurred mask >= ROWCOL_BP_ERODE=0.95 ~ 16px inside at sigma 10) before the masked UM and averaging - the back-projection is unreliable near its own boundary and boundary garbage dominated the partially-covered EDGE columns in v013-ROWCOL-02 (per-x maxima ~1000 for x<14, interior clean at 13-39 counts). Excluded edge lines drop below MIN_COVER and take the legacy per-line fallback. 2. RT conditioning row/col (problem 2, borrowed from the oracle path, /jp4/ input unchanged): - REORDER: row/col now AFTER photometric+FPN. Measuring on raw captured the FPN's static line structure (rms ~6/12 counts) which the later FPN subtraction removed AGAIN - negative FPN line structure was injected into the output. - UM before averaging (new curt.rowcol_um_sigma, default 10, 0=off): profiles measured on an unsharp-masked copy, subtracted from the original - content no longer biases the averages and the max_abs gate acts on residual counts. - rowcol_max_abs default 50 (calibrated counts; configs saved before this change carry 0 = no gate - set 50 to enable). 3. CuasQC (Andrey's regression-protection design): per-product health statistics with sequence-independent pass bands, appended per run to <center>-QC.json; FAIL prints loudly, never aborts. Increment 1: ROWCOL vectors (rms<=25, scene-max p95<=500 - both of today's defects would have failed) + FPN (rms, row/col line-structure energy), hooked after calculation AND reuse in CorrectionFPN. Co-Authored-By:Claude Fable 5 <noreply@anthropic.com>
-
Andrey Filippov authored
The first calculateRowColBackProject mixed two baselines in one image: content-excluded residual (~0, regression baseline) inside the back-projection coverage, full raw-level image-FPN outside it. Whole lines fell outside the max_abs gate and the outlier-weighted average degenerated to the content mean: vectors reached ~2300 counts (legacy ~340) and stamped junk bands at the coverage-window margins into all per-sensor images (v013-ROWCOL-01 MERGED-DBG slices 141/408 etc). Now the two baselines never mix: masked UM (blur(value*mask)/blur(mask)) high-passes the residual within coverage only; NaN-aware line averages use covered pixels only (getLineAvgNaN); lines with under 10% coverage (ROWCOL_BP_MIN_COVER) fall back to the pure legacy UM+gating estimate per line (mergeLineProfiles). Console reports the line-fallback share. Co-Authored-By:Claude Fable 5 <noreply@anthropic.com>
-
Andrey Filippov authored
The registry entry is cleared by submitCurrent() (and again by showDialog()) BEFORE applyCltDialog() runs the getNext*() reads, so getValueOrDefault() - which looked the session up via the registry - always saw null and fell back to every field's default: any value set via POST /mcp/dialog/values was silently lost and OK re-applied the loaded config. The dialog now keeps its OWN session reference for the reads and the await; the registry cleanup clears only its own session (covers the timeout path without clobbering a newer dialog). Co-Authored-By:Claude Fable 5 <noreply@anthropic.com>
-
Andrey Filippov authored
Delete-the-file rule (Andrey): FPN and row/col noise recalculate ONLY when <center>-FPN.tiff / <center>-ROWCOL.tiff are missing in the model directory. The two force-recalc checkboxes are removed from the dialog and the config (stale _cuas_calc_* keys in old corr-xml are ignored on load). Reuse printlns name the exact file to delete; the dialog shows addMessage() notes in place of the removed checkboxes. Co-Authored-By:Claude Fable 5 <noreply@anthropic.com>
-
Andrey Filippov authored
CLAUDE: Row/Col correction (RT step 2): curt rowcol_* dialog params + content-excluded noise calculation 2a: CuasConditioning rowcol_* Config now dialog-driven (curt.rowcol_en/ rowcol_hpf/rowcol_hpf_sigma/rowcol_max_abs/rowcol_outlier, "CUAS RT" tab) via CuasConditioning.configFromCurt(); RT Row/Col is optional/bypassable (turn rowcol_en OFF when the FLIR internal correction is verified OK). Defaults reproduce the previous hardcoded Config bit-exactly (rowcol_max_abs 0 = the old INFINITY no-gate). 2b: new CorrectionFPN.calculateRowColBackProject() (gated by NEW imp.cuas_backprop_rowcol, default ON): subtract the back-projected (pose-transformed, photometric-matched) virtual center from each scene BEFORE the UM + line averaging, so bright content no longer biases the row/col averages (the dark horizontal/vertical line artifact). Falls back to (image - FPN) where the back-projection is undefined; serial scene loop (GPU back-projection per scene) - borrowed/non-RT path only. Co-Authored-By:Claude Fable 5 <noreply@anthropic.com>
-
Andrey Filippov authored
value
-
Andrey Filippov authored
CLAUDE: test 7 - windowed-LoG TD product (correlation machinery): broadband exact, crease bands UNCHANGED Andrey's separate-LoG proposal prototyped on the CPU oracle: LoG as a windowed 16x16 DATA tile (taps pre-divided by the sine window AND cosAtten so the effective filter is the exact flux-normalized LoG), full 16-mult quad product per tile (GPU correlateAccumulateTiles table == convolve_tile(conj(data),k) - verified term-by-term), dttt_iie back (mode-TRANSPOSED = GPU dttii_2d), corr_unfold_tile, windowed OLA with sum(w^2) normalization. RESULT: impulse fidelity 2.0e-3 (no aberration-kernel cross-term - a separate pass), but the ramp crease bands are IDENTICAL to the per-bin fold (+/-0.546): the DTT symmetric-extension reflection is only attenuated by the window, not removed - the crease is BASIS-INHERENT to any single-tile TD product. The per-bin fold is the degenerate (symmetric-kernel) case of this same product. Band-free LoG requires pixel-domain convolution on the assembled image. Calibrated conventions along the way (documented in code): correlation product table, dttii mode transpose, corr_unfold patch mapping (+1 offset, no flip), global gain 4.000, window and cos tap precompensation. Co-Authored-By:Claude Fable 5 <noreply@anthropic.com>
-
Andrey Filippov authored
Same ramp, same chain: identity 0.000; aberration-like kernel 0.624 counts (band/output 0.18% - present in every render, invisible under content); pure LoG 0.547 (176% of its near-zero output); folded 0.682. The aberration kernels DO band identically in absolute counts - the LoG only unmasks them by removing the content. Corollary: the CURRENT pixel-LoG conditioning also reveals the render's own crease bands (the oracle product bands too, with a different pattern). Co-Authored-By:Claude Fable 5 <noreply@anthropic.com>
-
Andrey Filippov authored
CLAUDE: test 6 - sky-band root cause reproduced: symmetric-extension crease response to LINEAR content Constant -> exactly 0; ramp 5/row -> 8-row-periodic band pattern (0,-0.008,-0.297,-0.547,+0.547,+0.297,+0.008,0) = the LOG-01 run's measured sky bands scaled by the gradient (2.5/row -> -0.14,-0.30,+0.35,+0.16). Pure double CPU chain -> not float32, not GPU, not a kernel coefficient: pixel LoG of a ramp is 0 (odd symmetry) but the per-tile symmetric convolution sees the mirrored extension's slope crease at tile boundaries. Inherent to any per-bin TD multiply (present under aberration kernels too, masked by content - Andrey's LPF-era artifact class, confirmed in substance). Co-Authored-By:Claude Fable 5 <noreply@anthropic.com>
-
Andrey Filippov authored
Andrey's discriminator for the fold-vs-kernel-interaction question: with rend_test + new 'RT render LoG isolation (identity krnl)' ON, saves -CUAS-RT-RENDER-ID (identity kernels: q0=1, q1..3=0, CltExtra=0 - aberration correction AND fractional offsets skipped), -ID-LOG-ORACLE (pixel LoG of -ID), and -LOG-ONLY (pure-LoG kernels, CuasLogFold.uniformKernels(log_td)). If -LOG-ONLY vs -ID-LOG-ORACLE residual persists, the fold/L0 is wrong; if it collapses to the wrap floor, the aberration-kernel interaction is responsible. Refactor: pixel-LoG application extracted to applyPixelLog(); log_test and log_ident share the kernel fetch/restore (finally). Evidence so far (offline, this evening's run): per-sensor high-bin tilt varies s07 +1.3% .. s01 +2.4% with identical scene content => kernel-dependent; per-quadrant deviation maps identical (no single-coefficient signature); kx=0 column regionally incoherent (row-structure channel, separate issue). Co-Authored-By:Claude Fable 5 <noreply@anthropic.com>
-
Andrey Filippov authored
t (channels): merged FIRST then s00..s15; z (frames): 'average' (all scenes) + 'average-f:l' (middle-half, renderSceneSequence default range) then scenes - same dimensions as -CUAS-INDIVIDUAL-CUAS-DBG (17 x 499 x H x W) so ImageJ can subtract the stacks directly. NaN-tolerant per-pixel averages. Applies to all three products (RT-RENDER, -LOG-ORACLE, -LOG-FOLDED). Per Andrey 07/06/2026. Co-Authored-By:Claude Fable 5 <noreply@anthropic.com>
-
Andrey Filippov authored
With 'CUAS RT render' + new 'RT render LoG A/B (folded kernels)' checkboxes ON, testRenderSequence saves two more hyperstacks comparable to -CUAS-RT-RENDER: - -CUAS-RT-RENDER-LOG-ORACLE: the product convolved with the EXISTING pre-DNN pixel-domain LoG (same CuasRTUtils.convolve2DLReLU instance construction as CuasDetectRT.detectTargets, LINEAR alpha=1); - -CUAS-RT-RENDER-LOG-FOLDED: the same render chain re-run with the LoG folded into the GPU aberration kernels (CuasLogFold.getLogTd tap-precompensated + foldKernels, setConvolutionKernels force re-upload) - NO pixel convolution; original kernels restored in a finally block. Render loop extracted verbatim into renderPass(), hyperstack save into saveRenderHyper() so both passes share the exact chain. Offline verdict: attic/CLAUDE/compare_cuda_versions.py --only LOG- Co-Authored-By:Claude Fable 5 <noreply@anthropic.com>
-
- 06 Jul, 2026 10 commits
-
-
Andrey Filippov authored
CLAUDE: CuasLogFold - LoG-into-kernel fold + synthetic impulse/grating self-test (roadmap RT-seed step 1) Findings (all validated to stated precision by the self-test, exit 0): - Per-bin TD quad-multiply == pixel convolution with cos(pi*dx/16)*cos(pi*dy/16) ATTENUATED taps (matches norm_sym_weights in calculateCLTKernel; shift-tap error exactly 1-cos(pi/16) before compensation). getLogTd() therefore pre-compensates LoG taps by 1/cosAtten so the EFFECTIVE filter is the true pixel LoG (machine-exact at non-bin gratings). - Residual floors: symmetric-extension wrap ~0.5-2.5% (inherent to the lapped structure); folded-vs-pixel-LoG A/B cross-term ~7% on a pessimistic spread kernel (test 5 - predicts the full-run A/B floor). - clt_symmetrize_kernel quadrant-3 (AA) sign pattern looks like a latent copy-paste of the AS expression: pure-AA kernel test - math sign 2.6e-3, code sign 1.9e-1. Production kernel files likely carry the wrong AA sign. Co-Authored-By:Claude Fable 5 <noreply@anthropic.com>
-
Andrey Filippov authored
POSE-13 forensics (from files, run 02:18-02:24): the iteration executed but dG came out defined on only 5% of the frame (right-edge strip + terrain patches), so fpn2 = fpn1 over 95% - the ghost survived. Chain: rebuild accumulation was healthy (494/494 scenes, ~75% per scene, ~85% union) but a single-sequence new-average center keeps NaN holes in the weak sky (no parent cumulative, no fillNewGaps), and convert_direct of a NaN-holed center image NaN-poisons nearly all back-projected tiles (task inversion + overlap spread). Fix: composite before the second back-propagation - keep rebuilt values where defined, fall back to the original center in the holes. There dG measures the pass-1 residual (~0), so it degrades to "no correction where not rebuilt" instead of NaN. Adds a coverage printout and a cuas_debug save of the composited center (-FPN-CENTER2-ITERn) so the next run is file-verifiable. Co-Authored-By:Claude Fable 5 <noreply@anthropic.com>
-
Andrey Filippov authored
FPN = mean(scene - backProject(center)) is a fixed point that preserves the center's own content residual (the rotating ghost): recomputing against the same contaminated center reproduces the same ghost regardless of rot_period or photometric vintage (POSE-12 confirmed: 43.1/92.0 unchanged). Iterate per Andrey's design (internal handoff 2026-07-06): 1. subtract fpn_k from scenes in memory (setApplyFPN, delta-aware) 2. rebuild the center IMAGE from the corrected scenes over integer rotations - new Cuas.rebuildCenterImageInMemory(): new-average only (no parent cumulative fold), NOTHING persisted, center_clt and image_center untouched (the .cuas cumulative is upstream state) 3. back-propagate against the rebuilt center image (swapped in/restored around the measurement) -> residual dG = the ghost 4. fpn_{k+1} = fpn_k + dG in NEW arrays (scenes hold fpn_k references as applied-FPN for delta re-apply); prints |dG| RMS/max per iteration 5. cuas_debug saves per-iteration -FPN-DG-ITERn Gated by new dialog field "FPN back-propagation iterations" next to "Rotation period"; default 1 keeps the POSE-12 baseline bit-reproducible. Verify by RT-RENDER horizon/sky pk-pk (43.1/92.0 -> temporal-noise floor). Data path verified: applyFPN sets hasNewImageData, honored by both GpuQuad.setBayerImages and GpuQuadJna, so corrected pixels reach the GPU for the rebuild and the second back-propagation. Co-Authored-By:Claude Fable 5 <noreply@anthropic.com>
-
Andrey Filippov authored
Andrey's clutter rule: calibration force-rerun = erase the file, not a config checkbox. pose_recalc removed everywhere (field/dialog/properties/ copy; old configs' leftover key is ignored harmlessly), poseSequencePass lost its allow_recalc parameter. Every file-gated reuse now prints the delete-to-recalculate hint: - TILE-CALIB: 'reusing ... delete <name>-POSE-RT-TILE-CALIB.tiff to recalculate' - RT-STATE dc_center: 'delete <name>-RT-STATE.json (or its dc_center field)' - FPN (CorrectionFPN): 'reusing saved <name>-FPN.tiff - delete it to recalculate (verify Rotation period first - a mismatch bakes an azimuth-sector content ghost into the FPN)' Co-Authored-By:Claude Fable 5 <noreply@anthropic.com>
-
Andrey Filippov authored
Andrey's ruling: the pose stage normally ALWAYS runs (it is part of the RT cycle, not a mutually-exclusive test) - the last run had rend_test ON which silently skipped the pose stage (old precedence) and left TILE-CALIB unbuilt. Now: pose_test runs FIRST, rend_test render follows when also ON, cond_test stays standalone (only when nothing else ran). Dialog/tooltips updated ('CUAS RT render (full product)'). Verified meanwhile (POSE-11 renders): frozen per-sequence DC cut the RT-RENDER horizon wobble 234 -> 42.4 counts pk-pk (5.5x), exactly to the oracle DBG floor - the residual at 1-rev period is the shared FPN ghost; FPN.tiff still Jun-1 vintage because cuas_calc_fpn was OFF (the '(Re)calculate FPN' checkbox) - the rot_period=164.9 recompute has not actually run yet. Co-Authored-By:Claude Fable 5 <noreply@anthropic.com>
-
Andrey Filippov authored
POSE-10 forensics: RT-RENDER merged horizon pk-pk 234 counts (sky 187) with the dominant period 165.7 scenes = EXACTLY one camera revolution (21.83 rpm @ 60 fps -> 164.9); POSE-RT-COMPOSITE real slices the same. Cause: the per-SCENE zero-DC sky median (Config.dc_level=NaN auto) oscillates with azimuth as warm terrain sweeps through the sky half; downstream temporal averages convert the wobble into content-correlated residuals - the faint rotating ghost ('real image treated as FPN'). Oracle MERGED-DBG shows a separate, 3-6x smaller wobble at the same period (pre-existing, prepared path - not addressed here). Fix (Andrey's rule: one constant per sequence, from the average scene): - CuasRT.sequenceDcLevel(): manual curt.dc_center override when nonzero, else the RT-STATE value derived by appropriateCenter() from the borrowed center (= the sequence average) - scenes and center shift by the IDENTICAL constant. - CuasPoseRT (A2 ingest) + CuasRender (render test) now pass a Config with that dc_level instead of null; NaN fallback (per-scene) kept but warns loudly. Config.dc_level doc updated. Co-Authored-By:Claude Fable 5 <noreply@anthropic.com>
-
Andrey Filippov authored
New checkbox 'Save oracle DBG renders (11GB)' (default ON - current behavior preserved): gates the EXTRA per-sensor -CUAS-INDIVIDUAL-CUAS-DBG render pass and the -CUAS-MERGED-CUAS-DBG save in CuasRanging.prepareFpixels (the merged render itself stays - it is the production imp_targets input). Turn OFF to save render time and disk once -CUAS-RT-RENDER (rend_test, the RT-chain full render) is the trusted full product. Also refreshed the stale dc_center GUI tooltip (RT-STATE.json semantics). Co-Authored-By:Claude Fable 5 <noreply@anthropic.com>
-
Andrey Filippov authored
Missing-file rule (Andrey): calibrations are FILE-gated; missing -> rebuild (slow first run), present -> reuse, erase -> force. Config keeps parameters only. - TILE-CALIB bootstrap: testPoseSequence = wrapper over poseSequencePass; missing -POSE-RT-TILE-CALIB (or pose_recalc ON) -> FULL pass generates and saves it, then AUTOMATICALLY re-runs filtered (~150 cluster tiles) - first run on a v013_min copy ends in the warmed-system state, per sequence (mixed-state batches self-serve). Bootstrap re-run ignores pose_recalc; pose_full still never reads/writes the calibration. - NEW CuasRtState (-RT-STATE.json, Gson): per-sequence RT-only persistent variables in the CENTER model dir; global params stay with quadCLT_main / corr-xml (GUI save + compare/combine). Data-pure (paths, no QuadCLT), forward-compatible, failure-safe load. First tenant: dc_center - AUTO now reuses/derives-and-stores per sequence; the corr-xml config is never mutated (nonzero = manual override). - INTERFRAME is QuadCLT-workflow/POSES ONLY (Andrey): rtPhotometricCalibration no longer writes the ref INTERFRAME; photometric persists via the explicit corr-xml save after a calib-ON run (quadCLT_main carries the values). Co-Authored-By:Claude Fable 5 <noreply@anthropic.com>
-
Andrey Filippov authored
- NEW cuas/rt/CuasRT.java: the ENTIRE CUAS RT mode moved out of OpticalFlow.buildSeries (curt_en branch) into one readable top method: 1. INITIALIZATION (ingest, photometric calibration, center appropriation) 2. DIAGNOSTICS (rend/pose/cond tests - exclusive, never grow the top) 3. PRODUCTION (detection; the MVP per-scene jp4 loop will replace the bulk oracle ingest without changing this structure). - Borrow boundary (Andrey ruling): all transforms of borrowed QuadCLT data happen at CuasRT initialization ONLY. appropriateCenter() zeroes the center CLT IN MEMORY (setCenterClt; -CLT-UPDATED is saved upstream, so the zeroed copy never persists) - the pose test drops its per-run GPU appropriation and uploads an already-zeroed reference. The pure math is CuasConditioning.zeroDcClt(fclt, pattern, level) - knows no QuadCLT. - FIX (POSE-09 silent no-op): the DC-pattern uniform image must be set on gpuQuad.getQuadCLT() - what both backends actually read (GpuQuadJna setBayerImages(center=true), JCuda base, CorrectionFPN recipe) - not on center_CLT; plus an all-zero-pattern guard (warn loudly, never fake-offset). - FIX (POSE-09 1470-count per-sensor sky spread vs 17 calibrated): rtPhotometricCalibration applies the fit to the ALREADY-SPAWNED per-scene instances too (created by ingest before the calib step). The recalibrated photometric persists only via ref INTERFRAME + a config save after a calib-ON run - all current configs still carry the stale values. Co-Authored-By:Claude Fable 5 <noreply@anthropic.com>
-
Andrey Filippov authored
getCenterAverage() is null in the pose flow, so the auto DC level silently no-op'd (composite virtual sky stayed at -4511). Derive the level from the reference buffer render itself - perSensorImagesFromTD(gpuQuad, true)[0] sky-half median - i.e. the exact data being zeroed, right after setReferenceGPU uploads it. Failure-safe warnings preserved; explicit curt.dc_center and adoption/persistence semantics unchanged. Verify: pose run -> console 'AUTO center DC level', composite virtual sky ~0. Co-Authored-By:Claude Fable 5 <noreply@anthropic.com>
-
- 05 Jul, 2026 4 commits
-
-
Andrey Filippov authored
Three coupled improvements from tonight's design discussion with Andrey: 1. ZERO-DC in CuasConditioning (Config default ON): LWIR microbolometers are ADDITIVE (fixed tau=8ms exposure, F#~1 for NETD, ~100 counts/K) - day/night and seasons SHIFT the level, never scale it; the MCLT has no clean DC/AC separation, so a large DC (current ~-3500 counts under ~300 counts AC) spreads over many TD points and costs float32 mantissa bits. Subtract ONE common constant from all 16 sensors (pure shift, never rescale). AUTO level = MEDIAN OF THE TOP (SKY) HALF, robust to the snowy-ground-vs-summer- calibration mismatch and to targets. 2. RT-DECOUPLED FAT ZERO (curt.fz_inter=10000, curt.fz_intra=2000 reserved): the lean code erroneously used the INTRA getGpuFatZero (2000) instead of the INTER value - Andrey's FZ sweep (200/1000/3000/10000: corrRMS .54/.39/.37/.31, roll bias +.80/+.62/+.50/+.39) independently rediscovered the oracle's INTER operating point (10000). RT now owns its FZ pair, no AUX switch; legacy gpu_fatz*/FOPEN configs untouched. Sweep recorded as characterization: FZ tolerant over a broad range; revisit only together with the argmax method redesign (sharp peaks starve the centroid). 3. BORROWED-CENTER APPROPRIATION (curt.dc_center, 0=auto): the restored CenterClt reflects its own footage vintage - offset it ONCE at the borrow boundary (firewall: never re-compensate downstream) to match the zero-sky scenes. Auto level = sky-half median of the borrowed center average, ADOPTED into curt.dc_center (persisted with the config - borrowable later like the photometric calibration). Mechanics: DC pattern = CLT of a uniform image via the existing back-propagation convert (setImageCenter + no_kernels + use_center_image, the CorrectionFPN recipe); failure-safe (any missing piece leaves the reference unchanged, with a warning). Roadmap recorded: per-pixel offset (recalibrated per-sensor + FPN) and per-pixel scale maps to the GPU; the average stored in TD AFTER LoG (aberration+LoG combined kernels) for fpixels subtraction - possibly for poses too; center-average window length trades reference stability vs extremely-slow-target detectability. Verified: mvn -DskipTests clean package OK. Co-Authored-By:Claude Fable 5 <noreply@anthropic.com>
-
Andrey Filippov authored
Per Andrey: restore the pose test using the new (certified) data. - Disparity: ONE source for all of RT - the plain DSI slice through CuasRender.conditionDisparityCuas (defined for ALL tiles, sky=infinity, negatives clamped). The use_lma_dsi gate removed from the pose test (the LMA slice is NaN over the sky and silently shrank the usable set). - leanMeasure/leanFitScene: MB compensation (lean v2) - the same certified machinery as CuasRender: setInterTasksMotionBlur two task sets + the erase-first interCorrTDMotionBlur double convert (undefined tiles NaN for the consolidation), gated by imp.mb_en, vectors from the existing per-scene getMotionBlur block (previously computed but unused by lean). - pose_stored branch gets the same MB treatment. Expected in the next lean run (LMA, 150-cluster selection, mb_en ON): az/tilt wobble (v*tau, 0.5 px rotating) collapses toward the MBEN oracle (0.029/0.021 mrad), corr RMS toward ~0.08; roll bias = the remaining open question (FPN-mask lead). Verified: mvn -DskipTests clean package OK. Co-Authored-By:Claude Fable 5 <noreply@anthropic.com>
-
Andrey Filippov authored
Per Andrey: the sky has nothing to match but is the BACKGROUND FOR DRONES - it must render (at infinity), NaN acceptable only outside the image. Root of the NaN tiles in -CUAS-RT-RENDER: use_lma_dsi=true selected the LMA DSI slice, which is NaN wherever the LMA did not fit (the whole sky) -> tiles dropped from the task list. The plain slice has no NaN but carries garbage (crazy < -1 tiles in the sky, negatives near the sign post). Fix: NEW static QuadCLT-free conditionDisparityCuas() (the legacy conditionInitialDS takes a QuadCLT instance - out per the RT rules): plain slice 0, NaN -> 0.0 (infinity), negatives -> 0.0. testRenderSequence now uses it unconditionally (not gated by use_lma_dsi - that gate is for the pose measurement, not rendering). Verified: mvn -DskipTests clean package OK. Co-Authored-By:Claude Fable 5 <noreply@anthropic.com>
-
Andrey Filippov authored
Per Andrey: undefined tiles (= not in the task list; the fixed-length 5120 arrays represent them as nulls) must be handled by the channel consolidation - weighted-by-existing average, all-NaN tile when no sensor has it (now Java CuasTD.consolidateSensorsTD, later the CUDA clt_average_sensors kernel). The consolidation detects missing by NaN, but the MB double convert ran with erase=-1, leaving STALE (valid-looking) data at undefined tiles. - ImageDtt.interCorrTDMotionBlur: new erase-capable overload (erase_clt_first: >0 NaN, 0 zeros, <0 legacy no-erase) - erases before the FIRST (SET) convert only; the SECOND (negative-scale SUBTRACT) never erases. Legacy signature delegates with -1: oracle/SfM callers byte-identical. - CuasRender MB path uses erase_clt_first=1: the GPU TD buffer's NaN pattern now mirrors the task-list membership, so consolidation + renders see undefined tiles as NaN - never the previous scene. Verified: mvn -DskipTests clean package OK. Co-Authored-By:Claude Fable 5 <noreply@anthropic.com>
-