Port the SAR3D background gate, CLEAN and object boxes from Multi_depthnorm_clean

- BG_GATE_ENABLE: frame peak over its median background (sar3d_background); the
  GUI scales the frame with bg_gate_gain and its cloud threshold.
- SAR_CLEAN_ENABLE: CLEAN of a one-frame aperture on a 4x10x4 cm search grid over
  the whole scene; objects in their own scale (sar3d_objects).
- SAR_MARK_ENABLE: boxes by class around object groups (sar3d_marks), with the
  legend under the views.
- SAR_VOXEL_M as three steps X/Y/Z with the notebook defaults 0.025/0.02/0.02.
- GPU backend: image/download/load/project API, per-plane block reduction for the
  maximum, depth gate without FMA; sar3d host code built with -ffp-contract=off.
- References regenerated from notebook cells 1 and 5, with new CLEAN scenes and a
  synthetic box-rule case; docs updated.
This commit is contained in:
Ayzen
2026-10-16 12:08:57 +03:00
parent 9a9b8ce5c7
commit b88d704126
26 changed files with 1895 additions and 407 deletions
+38 -13
View File
@@ -71,13 +71,13 @@ controls, processing settings and a copy of the live plot through an embedded we
- **gpr** — coherent back-projection on the ground plane, as in `Horns_motion_4x4_ground.py`,
with object detection. Radar height and look angle define the slice in radar X/Z axes;
the wave speed is 3×10⁸ m/s (air).
- **sar3d** — 3D SAR of the reference notebook `Multi_antenna_demonstrate_depthnorm.ipynb`
- **sar3d** — 3D SAR of the reference notebook `Multi_depthnorm_clean.ipynb`
on an NVIDIA GPU through CUDA: front (X-Y), side (Z-Y), top (X-Z)
and oblique maximum projections of the imaged
volume. Its settings carry the notebook's parameter names; the scene window is
set by the selected antennas with a 2 m X margin and height −0.5…2 m above the ground; its range extent follows
`MIN_DEPTH`/`MAX_DEPTH`, and the voxels are cubes with edge `SAR_VOXEL_M`
(default 2 cm). The radar motion is corrected from each trace's capture
`MIN_DEPTH`/`MAX_DEPTH`, and the voxel steps `SAR_VOXEL_M` X, Y and Z default to the
notebook's 2.5, 2 and 2 cm. The radar motion is corrected from each trace's capture
timestamps, so the sweep timing needs no parameters.
Both coherent GPR and SAR apply `PAIR_DEPTH_EQUALIZE` (on by default) before the
@@ -100,7 +100,27 @@ redraw the existing result without recalculating it. Tx/Rx markers appear on the
front, side and top projections in ground coordinates. A hollow square marks the
peak; its size follows the contiguous half-maximum width along the volume axes
(FWHM, at least one voxel). This measures the imaged response rather than the
reflector's physical dimensions.
reflector's physical dimensions. The square is left out when CLEAN objects are shown
or when the background gate empties the frame.
**BG_GATE_ENABLE** shows a frame relative to its background, the median of the volume
over its working voxels: below 6 backgrounds the frame is empty, at 6 its maximum
appears at the cloud threshold, and from 8.5 the scale is full. **SAR_CLEAN_ENABLE**
runs the notebook's CLEAN on a one-frame aperture: always with `SAR_FRAME_RADIUS` 0,
otherwise while no previous frame is available, as after Start. It subtracts the strongest point response
from the A-scans of every pair, step by step on a 4 × 10 × 4 cm grid over the whole scene
region, until the residual is background. The search ignores `SAR_X_SIZE_M` and
`SAR_Z_SIZE_M`, so reflectors just outside a narrowed scene are subtracted too. Each object is then imaged apart and drawn in its own 0–1
scale over the residual, so a weak object is not hidden by the sidelobes of a strong
one. **SAR_MARK_ENABLE** draws boxes around groups of CLEAN objects: red for very low
objects (like a mine), orange on the ground, blue above it, dashed grey at the scene
boundary, where the response may lie partly outside. The legend is in the title of the
3D view. Without boxes the objects are numbered with their level in backgrounds. All
three switches are on by default, like in the notebook, and the status line reports the
background ratio and the CLEAN result. The gate and CLEAN are processing settings; boxes
only redraw. Their thresholds and rules are the notebook's fixed values. Both cost time:
on a GTX 1060 with the default scene of 10 million voxels, the gate adds about 0.1 s per
frame and CLEAN about 0.4 s more.
The desktop uses a light theme with white plot canvases. **Mode** stays below the
**Actions** buttons while the settings sections scroll; the settings panel and
@@ -222,7 +242,7 @@ The preprocessor still requires S21 calibration/reference sets. Start the GUI:
Open **Preprocessing…**, use **Create Neutral S21 Sets**, then **Start**. This makes
identity calibration + zero reference, preserving the simulated S21 samples.
Finer voxels increase SAR3D work as 1/`SAR_VOXEL_M`³. Increase the voxel size when
SAR3D work grows inversely with the product of the three `SAR_VOXEL_M` steps. Increase them when
a faster preview matters more than spatial resolution. Processing failures appear
above the plots and a failed single capture
finishes with its explanation while retaining the acquired data.
@@ -469,19 +489,24 @@ physical timing. Real devices, GPIO and the CUDA backend need their own hardware
`check-sar3d` runs the real CUDA processor (`data_acq_and_processing/tests/test_backprojection.py`).
It compares it with `sar3d_reference.npz`: compact float32/complex64 inputs, the three
maximum projections of the notebook's volume, its joint peak/level and response
widths for six compensation/normalization, equalization, background, scene and
timing cases. The expected values come from unchanged functions in cells 1 and 14
maximum projections of the notebook's displayed volume, its peak/level, response
widths and background ratio for ten cases. Six cover compensation/normalization,
equalization, background, scene and timing. Four are frames of point reflectors in noise
for CLEAN, which also compare the objects and their boxes: with and without the background
gate, with a scene where the stop at each range's background adds steps, and with a
narrowed scene. The box rules are also checked
one by one on synthetic objects. The expected values come from unchanged functions in cells 1 and 5
of the original notebook, with each frame's previous-collection mean subtracted
from its input spectra by NumPy. The same test checks the published
status for invalid input, a result too large for the ring slot, an empty and a very weak
signal. Without a usable GPU it checks only the CUDA warning and skips the rest; the
notebook itself is not needed to run it. To regenerate the reference, pass the
original notebook (it is kept outside the repository):
status for invalid input, a volume beyond float32, a result too large for the ring slot,
an empty and a very weak signal, and that the views are normalized at their peak on
finer grids. Without a usable GPU it checks only the CUDA warning and the box rules and
skips the rest; the notebook itself is not needed to run it. To regenerate the references,
pass the original notebook and the Horns script (both are kept outside the repository):
```bash
.venv/bin/python data_acq_and_processing/tests/generate_backprojection_reference.py \
--notebook /path/to/Multi_antenna_demonstrate_depthnorm.ipynb \
--notebook /path/to/Multi_depthnorm_clean.ipynb \
--gpr-script /path/to/Horns_motion_4x4_ground.py
```