1. 15 Jun, 2026 1 commit
    • Andrey Filippov's avatar
      CLAUDE: DNN de-streak (subtract-avg), compute-window, and recurrent feed · 1f04cb6a
      Andrey Filippov authored
      - curt_subtract_avg (+ -SUBAVG filename tag): subtract the input per-pixel temporal
        mean before LoG. Removes the static treeline edge (and so its 8px tile-grid
        horizontal streak and the first-LReLU amplification of it); the moving target is
        not in the average, so it survives. Uses the whole sequence (not realtime; realtime
        would use a prior-run average).
      - DNN compute-window: the timing ROI (curt_time_from/to) now gates the DNN inference
        loop (only in-window scenes are inferred), not just the saved output - fast iteration
        on a target's few seconds.
      - DNN -> recurrent layer: feed the DNN field to runRecurrentLevel (per selected level,
        curt_recur_*). curt_dnn_recur_splat toggles feed-as-is vs bilinear splat of each
        pixel's velocity vector to its fractional (px+dx,py+dy) so neighbours reinforce in one
        sub-pixel bin (-SPLAT mark). curt_dnn_recur_scale (default 10) lifts the [0,1] field
        (peaks ~0.1) to the recurrent's tuned rs_min~1.0 scale. splatField() helper added.
      Co-authored-by: 's avatarClaude Opus 4.8 (1M context) <noreply@anthropic.com>
      1f04cb6a
  2. 14 Jun, 2026 5 commits
    • Andrey Filippov's avatar
      CLAUDE: CUAS-RT overhaul - real-base synthetic-grid injection, level/time... · ee86f0fc
      Andrey Filippov authored
      CLAUDE: CUAS-RT overhaul - real-base synthetic-grid injection, level/time ROIs, 3d3 bypass, DNN offset/stride/window
      
      Reworks the synthetic B-measurement and detector flow on the real pyramid base:
      
      - Load: the real -CUAS-MERGED-CUAS stack is always the pyramid base (full-length
        levels); when curt_synth_src, the synthetic grid is loaded separately (scaled,
        NOT LoG'd) and injected TILED into each selected pyramid level AFTER the pure
        pyramid is built - same grid at every level, real noise averaged (sqrt(2)/level,
        printed). Both file picks use newestFile(). The old load-time mixing and the
        curt_synth_bg_avg (N=) decimation are retired.
      - Level selection unified on curt_c5_levels for ALL heavy paths (3d3/conv5d,
        C5P-direct, DNN); cheap temporalAverage pyramid still builds up to the max
        selected level. Pyramid-depth guard stops building when a level would have <1
        frame (was NegativeArraySizeException on short sequences).
      - Timing ROI curt_time_from/to (timestamp seconds; last-4-of-seconds shortcut,
        rollover-aware, 3-decimal fixed display) clips saved RECT/HYPER/DNN/C5P stacks
        and gates the DNN inference (compute-window, not just save).
      - curt_3d3_en (default false) bypasses the 3d3 coarse-velocity path and its
        ~W*H*9 arrays. Full-velocities hyperstack render is guarded by a free-heap
        estimate (it is also an unfilled stub) and skipped if it would not fit.
      - DNN: curt_dnn_stride (1 testing / 4 production 50%-overlap), and -DNN-OFFSET
        visualization (dx, dy, s over the ROI) from the offset channels.
      Co-authored-by: 's avatarClaude Opus 4.8 (1M context) <noreply@anthropic.com>
      ee86f0fc
    • Andrey Filippov's avatar
      CLAUDE: Add velocity-count getters + DNN offset-channel overload · f2b3b3b5
      Andrey Filippov authored
      CuasRTUtils.getNumVout()/getSubDim() expose the 5D render dimensions for the
      full-velocity-hyperstack memory estimate. CuasDnnInfer adds an inferROI(...,
      double[][] offOut) overload that also returns the two offset channels
      {dx, dy, s} per pixel (the DNN's per-pixel sub-pixel position estimate); the
      existing 6-arg call delegates with offOut=null, so the field output is
      unchanged. Both are prerequisites used by the CUAS-RT overhaul that follows.
      Co-authored-by: 's avatarClaude Opus 4.8 (1M context) <noreply@anthropic.com>
      f2b3b3b5
    • Andrey Filippov's avatar
      CLAUDE: Add MAX-over-v locator slice to -HYPER-RECT · bf2ba914
      Andrey Filippov authored
      Prepend velocity index 0 = max over all velocities (per scene, per pixel) to
      showConvKernel5dHyperRect, and scale the display range to that slice instead
      of the fixed IMP_MINMAX, so the small (~0.1) maxima are visible on open. It is
      the first slice ImageJ shows - a quick map of non-empty pixels before scanning
      scenes (Z) and velocities (T). Applies to both -HYPER-RECT and -DNN-HYPER-RECT.
      Co-authored-by: 's avatarClaude Opus 4.8 (1M context) <noreply@anthropic.com>
      bf2ba914
    • Andrey Filippov's avatar
      CLAUDE: Fix synth bg_avg to do real pyramid-level decimation · 134a5bdb
      Andrey Filippov authored
      The bg_avg>1 path kept all n_synth frames and only added an averaged
      background, so AVG4 and AVG8 produced the same frame count and 1/fps
      timestamps. Now output frame i is the mean of bg_avg consecutive frames of
      BOTH the scaled synthetic target AND the real background (non-overlapping
      groups): the sequence is decimated by N (n_synth/N frames), the moving target
      is motion-averaged like a real pyramid level, and each timestamp is the last
      real frame of its group (N/fps increments).
      Co-authored-by: 's avatarClaude Opus 4.8 (1M context) <noreply@anthropic.com>
      134a5bdb
    • Andrey Filippov's avatar
      CLAUDE: Wire DNN front-end into CuasDetectRT (-DNN field, all scenes) · c899aa2b
      Andrey Filippov authored
      When curt_dnn_model is set, run the ONNX DNN per-pixel inference over
      curt_save_select across all available scenes (not just the first few),
      saving -DNN-RECT / -DNN-HYPER-RECT. Slice labels carry timestamp + absolute
      frame index for matching to real targets. New curt_dnn_thresh (6 sites in
      IntersceneMatchParameters) zeroes the (Vx,Vy,s) field below confidence s -
      display/FP-suppression only. inferROI tiles the ROI batch (CHUNK) to bound
      ONNX Runtime activation memory.
      Co-authored-by: 's avatarClaude Opus 4.8 (1M context) <noreply@anthropic.com>
      c899aa2b
  3. 13 Jun, 2026 2 commits
  4. 11 Jun, 2026 3 commits
  5. 10 Jun, 2026 2 commits
    • Andrey Filippov's avatar
      CLAUDE: Cluster energy normalization in recurrent buffer conditioning · 2eb14ba0
      Andrey Filippov authored
      Per Andrey's continuity requirement: a sub-pixel target shift switching
      between 1 and 2 surviving cells must not change the total injected energy
      (filterConv5dROI does not conserve energy - it zeroes weaker components).
      
      condition() now labels 4D-connected survivor clusters (3^4-1 connectivity,
      BFS) and applies three regimes:
      1. Single survivor: full 3x3x3x3 spread with fading peripherals (as before).
      2. Compact cluster (2..curt_recur_max_clust near-equal survivors): spread
         limited along resolved dimensions; cluster total output = cluster max M,
         shared proportionally (survivor i contributes M*m_i/sum(m_j)) - exactly
         continuous across the 1<->2 survivor transition.
      3. Cluster larger than curt_recur_max_clust (default 5): weak signal that
         passed the filter linearly - identity, no spreading/renormalization.
      
      New parameter curt_recur_max_clust plumbed through dialog/properties/copy;
      -RC<n> added to the -RECUR image titles.
      Co-Authored-By: 's avatarClaude Fable 5 <noreply@anthropic.com>
      2eb14ba0
    • Andrey Filippov's avatar
      CLAUDE: Add Layer 2 recurrent accumulation buffer (CuasRecurrentBuffer) · 079d4237
      Andrey Filippov authored
      Implements the recurrent 4D (px, py, vx, vy) accumulation buffer per the
      2026-06-09 design (cuas_rt_gpu-internal CONTINUE.md, Step 4):
      
      - Update rule: buf = leak*(1-w_eff)*shift(buf, v) + w_eff*conditioned(meas),
        applied every curt_recur_period (default 4) time units so the per-update
        pixel shift is integer-clean (1 px per minimum velocity step).
      - shift(): each 4D point moves by its own velocity; predictions leaving the
        ROI are dropped.
      - conditioned(): adaptive 4D spreading of filterConv5dROI survivors -
        dimensions spanned by adjacent survivors are "resolved" and not expanded;
        total spread weight per survivor is 1.
      - w_eff: fixed curt_recur_w, or per-pixel adaptive w*tanh(strength/wthresh)
        when curt_recur_wthresh > 0 (dark frames then decay by curt_recur_leak
        alone - blind prediction).
      - convolve3d() still runs at every time step with unchanged output files;
        the buffer consumes every curt_recur_period-th ROI output (level 0 only).
      - New params (curt_recur_en/period/w/leak/wthresh/spread) plumbed through
        IntersceneMatchParameters (dialog, get/set, properties, copy).
      - Buffer state snapshots saved as -RECUR-RECT and -RECUR-HYPER-RECT images.
      
      Single-threaded over the ROI for now; optimization deferred by design.
      Co-Authored-By: 's avatarClaude Fable 5 <noreply@anthropic.com>
      079d4237
  6. 09 Jun, 2026 6 commits
  7. 07 Jun, 2026 5 commits
  8. 05 Jun, 2026 1 commit
  9. 03 Jun, 2026 1 commit
  10. 31 May, 2026 1 commit
  11. 30 May, 2026 2 commits
    • Andrey Filippov's avatar
      CLAUDE: Fix getInterseqScale() to use integer corr_inc for BX/AX/BY/AY positions · b691e9f3
      Andrey Filippov authored
      getInterseqScale() was calling getCorrIncExact() which returns 0.5*corr_offset
      for half_step mode instead of the actual integer keyframe step getCorrInc()
      (= corr_offset/2 with integer division). For odd corr_offset (e.g. 5) with
      half_step=true these differ: getCorrIncExact()=2.5 vs getCorrInc()=2.
      
      This caused getHalfBeforeAfterPixXY() to compute:
        after - before = RSLT_VX * 0.5   (wrong; observed by user)
      instead of:
        after - before = RSLT_VX * corr_inc/corr_offset = RSLT_VX * 0.4  (correct)
      
      recalcOmegas() uses the same interseq_scale in the inverse direction, so it
      also reconstructed RSLT_VX/VY incorrectly from neighbouring keyframe positions.
      
      Fix: use getCorrInc() (integer) in getInterseqScale() so that BX/AX positions
      correspond to actual raw-frame midpoints and the velocity round-trip is exact.
      
      Also adds an unambiguous convention comment near RSLT_VX/RSLT_VY in
      CuasMotionLMA.java documenting all required scale conversions.
      
      The omega calculation (getFrameVelocityScale * ifov * fps_raw) is independent
      of corr_inc and was already correct.
      Co-authored-by: 's avatarClaude <claude@elphel.com>
      b691e9f3
    • Andrey Filippov's avatar
      Found but not yet fixed getHalfBeforeAfterPixXY() velocities to · 9196f324
      Andrey Filippov authored
      coordinates relation
      9196f324
  12. 27 May, 2026 6 commits
    • Andrey Filippov's avatar
      CLAUDE: fopen_pose_compare.py — add orientation comparison + cumulative rotation · cd4e13ef
      Andrey Filippov authored
      - parse_images_txt: store full R_cw (world→camera rotation) per frame
      - new compute_orientation_data(): per-frame COLMAP and ERS orientation
        in Sim(3)-aligned GPS frame; delta-rotation angle (convention-independent);
        cumulative rotation integrated from frame 0
      - new print_orientation_report(): per-frame RMSE + cumulative totals
      - ers_to_R(): guessed convention Rz(az)*Rx(tilt)*Ry(roll) — to be verified
      - CSV: adds colmap_yaw/pitch/roll, delta_colmap/ers/diff, cum_colmap/ers/diff
      
      Key finding for water-tower straight-flight (378 frames):
        COLMAP cumulative rotation = 120.81° (photogrammetric noise ~0.25°/frame)
        ERS cumulative rotation    =  14.10° (physically correct: 1.9° heading + vibration)
      → COLMAP orientation is dominated by pose-estimation noise for pure-nadir SfM
      → orientation comparison meaningful only for LARGE angular changes (turning sequences)
      → position comparison (Sim(3) RMSE) remains the primary validation metric
      Co-authored-by: 's avatarClaude <claude@elphel.com>
      cd4e13ef
    • Andrey Filippov's avatar
      CLAUDE: Add fopen_pose_compare.py — COLMAP vs egomotion Sim(3) pose alignment · e24bde9f
      Andrey Filippov authored
      Compares COLMAP camera centers (images.txt) with three imagej-elphel position
      columns (ERS x/y/z, IMS imsX/Y/Z, PIMU pimuX-C/Y-C/Z-C) using 7-DOF Sim(3)
      alignment (Umeyama 1991).  Reports scale, rotation (Euler angles), per-frame
      residuals in both COLMAP units and physical meters, and saves a CSV.
      
      Key results for water-tower scene (1763233718_057205, rect/PINHOLE, 378 frames):
        Scale ~0.054 (1 COLMAP unit ≈ 18.5 m; flight spans 225 m → 12.2 COLMAP units)
        ERS RMSE=8.3 m, max=19.6 m at trajectory endpoints
        Worst frames are at both ends of the 378-frame sequence — consistent with the
        SfM nadir doming artifact (camera orientations rotate outward from center)
        Two near-zero crossings at frames ~74 and ~296 confirm dome vs straight-line fit
      Co-authored-by: 's avatarClaude <claude@elphel.com>
      e24bde9f
    • Andrey Filippov's avatar
      CLAUDE: Add fopen_nadir_compare.py — tile-proc vs COLMAP nadir comparison · 4a8f21f6
      Andrey Filippov authored
      Generates a multi-slice float32 TIFF (NaN-padded, ImageJ-compatible):
        Slice 1: tile-processor disparity D scattered to nadir image pixels
                 (from *-NADIR-DISPARITY-MAPS.tiff, averaged across all scenes)
        Slice 2: COLMAP sparse Z_cam projected to the same nadir pixel grid
                 (optional --dense PLY for OpenMVS dense cloud)
        Slice 3: spatial superposition (tile-proc priority; COLMAP where missing;
                 average at overlapping pixels)
        Slice 4: tile-processor scene-count per pixel (--counts flag)
      
      Uses the COLMAP reference-image pose (auto-detected as centroid of camera
      centres, or specified via --ref-image) to project 3D points. Handles
      OPENCV lens distortion model (--no-distortion to skip).
      
      Intended for evaluating depth-fusion approaches (tile processor + SIFT):
        python3 scripts/fopen_nadir_compare.py \
            --disp   <ts>-NADIR-DISPARITY-MAPS.tiff \
            --colmap sparse/0_txt/ [--dense scene_dense.ply] \
            --out    nadir_compare.tif --counts
      Co-authored-by: 's avatarClaude <claude@elphel.com>
      4a8f21f6
    • Andrey Filippov's avatar
      CLAUDE: Dual-pass nadir rendering (original + rectilinear) · 00c33f1a
      Andrey Filippov authored
      Update calling code in OpticalFlow.java to compute nadir_pXpYD once and
      render two passes when either nadir_gen or nadir_undistort is enabled:
      - nadir_gen=true  → renderNadirSequence(..., false) → *-NADIR-MERGED
      - nadir_undistort=true → renderNadirSequence(..., true)  → *-NADIR-MERGED-RECTILINEAR
      
      The nadir_pXpYD array is deep-copied per scene for the undistort pass so
      the original sensor-coordinate data is preserved for the non-undistorted pass.
      Co-authored-by: 's avatarClaude <claude@elphel.com>
      00c33f1a
    • Andrey Filippov's avatar
      CLAUDE: Add nadir_undistort parameter — rectilinear nadir images for COLMAP PINHOLE · 09d21774
      Andrey Filippov authored
      Add nadir_undistort (boolean, default true) to IntersceneMatchParameters
      at all 6 required locations (field, dialog, read, save, load, clone).
      
      When enabled, renderNadirSequence() undistorts the pX,pY coordinates of
      each scene's nadir disparity map before calling renderGPUFromDSI(), so the
      rendered NADIR-MERGED TIFF images are rectilinear (pinhole projection)
      rather than retaining the sensor's native radial distortion.
      
      Analysis of the Boson 640 calibration (lwir16-06-72-00.calib-tiff) showed:
      - True distortion polynomial terms: < 1 px magnitude across the full image
      - The dominant issue was d = K0 = 1.00997 (a ~1% focal-length constant offset)
        which, when modeled as PINHOLE with the nominal focal length, curves the
        ground plane into the 'Little Prince planet' sphere effect seen in Blender
      - With nadir_undistort=true, COLMAP can use a pure PINHOLE model with the
        correct effective focal length (f * d = 1121.8 px instead of 1110.8 px)
      
      The undistortPxPy() helper mirrors getWorldCoordinates() in GeometryCorrection:
        rD_mm = ||(pX-cx, pY-cy)|| * pixelSize_mm
        factor = getRByRDist(rD_mm / distortionRadius)
        pX_rect = (pX - cx) * factor + cx
      Co-authored-by: 's avatarClaude <claude@elphel.com>
      09d21774
    • Andrey Filippov's avatar
      CLAUDE: Add nadir_um_en/sigma/weight parameters for SIFT-tuned UM on nadir renders · 11c8998d
      Andrey Filippov authored
      Add three dedicated unsharp-mask parameters to IntersceneMatchParameters:
        nadir_um_en     (boolean, default false) - enable UM on nadir images
        nadir_um_sigma  (double,  default 2.0)   - Gaussian sigma in pixels
        nadir_um_weight (double,  default 1.0)   - blend weight (1.0 = 100%)
      
      These are separate from the existing um_sigma/weight and terr_um_* / cuas_rng_um_*
      parameters so they can be independently tuned for SIFT feature extraction.
      LWIR nadir images with UM sigma=2 go from ~500 to ~5000 SIFT keypoints/frame.
      
      Updated all 6 required locations: field declarations, dialog, dialog-read,
      save, load, and clone.
      
      Applied the filter in renderNadirSequence() using the existing applyUM()
      helper, matching the renderSceneSequence() pattern.
      Co-authored-by: 's avatarClaude <claude@elphel.com>
      11c8998d
  13. 26 May, 2026 5 commits
    • Andrey Filippov's avatar
      CLAUDE: Add transposeJagged() utility to ShowDoubleFloatArrays; refactor getNadirDisparityMaps() · 2e1c69b0
      Andrey Filippov authored
      Add ShowDoubleFloatArrays.transposeJagged(double[][][], int n_comp, int n_inner)
      which converts the common [outer][inner][comp] layout (with null outer or inner
      entries) to [outer][comp][inner] substituting NaN for nulls.  This pattern
      appeared inline in getNadirDisparityMaps() and recurs in other tile-processing
      code.
      
      Refactor getNadirDisparityMaps() to replace the 12-line inline transpose loop
      with a single call to the new utility, keeping the same semantics.
      Co-authored-by: 's avatarClaude <claude@elphel.com>
      2e1c69b0
    • Andrey Filippov's avatar
      CLAUDE: Save NADIR-DISPARITY-MAPS hyperstack from getNadirDisparityMaps() · 72a8b1df
      Andrey Filippov authored
      After computing per-scene pXpYD arrays, saves a tile-resolution
      hyperstack <ts>-NADIR-DISPARITY-MAPS.tiff with:
        - frames = scenes (labelled by timestamp)
        - slices = pX, pY, D (3 channels)
        - NaN where scene has no pose or tile has no data
      
      Useful for verifying disparity transform coverage before feeding
      the rendered images into OpenMVS/COLMAP.
      Co-authored-by: 's avatarClaude <claude@elphel.com>
      72a8b1df
    • Andrey Filippov's avatar
      CLAUDE: Add getNadirDisparityMaps() and renderNadirSequence() for OpenMVS · f455f79f
      Andrey Filippov authored
      New methods in OpticalFlow.java:
      - getNadirDisparityMaps(): transforms SfM terrain disparity from the
        segment reference into each scene's own camera frame using
        Cuas.transformFromVirtual(). Returns double[][][nscene][ntiles][3].
      - renderNadirSequence(): renders each scene from its own position
        (scene_xyz/atr=ZERO3, ref_scene=scene itself) using per-scene
        pXpYD from getNadirDisparityMaps(). ERS rolling-shutter velocity
        corrections are still applied. Output: <ts>-NADIR-MERGED.tiff.
      
      Unlike renderSceneSequence() (TERRAIN-DISP), which warps all frames
      to the reference for zero ground parallax, renderNadirSequence() produces
      natural-parallax perspective images from each scene's own viewpoint —
      the correct input format for OpenMVS/COLMAP dense reconstruction.
      
      New parameter in IntersceneMatchParameters:
      - nadir_gen (boolean, default false): checkbox under 'Flat ground' tab,
        before fgnd_gen_optho. Enables nadir rendering in the existing
        TERRAIN-DISP pipeline block.
      Co-authored-by: 's avatarClaude <claude@elphel.com>
      f455f79f
    • Andrey Filippov's avatar
      several typos · 5477b6bc
      Andrey Filippov authored
      5477b6bc
    • Andrey Filippov's avatar
      CLAUDE: Update eclipse_project_setup/.project — add attic filter · 9812ffc0
      Andrey Filippov authored
      Adds filteredResources to the seed template:
      - regex filter for node_modules/.git/Java LS artifacts (existing on .137)
      - multiFilter to hide attic/ from Eclipse project explorer and build
      
      Copy this to .project on a new machine setup.
      Co-authored-by: 's avatarClaude <claude@elphel.com>
      9812ffc0