960 Commits
Author SHA1 Message Date
Harry Chen dcab26f00d fixes #135 2026-10-01 11:28:25 -04:00
viridivn 62be4bbe74 add cstdint includes for gcc16 compat (#134) 2026-10-01 11:12:04 -04:00
Harry Chen 2de49a1e89 fix unnecessary reruns in dataset creation 2026-10-01 00:51:06 -04:00
Harry Chen 01763fd6c2 update workflows to auto release binaries 2026-09-30 23:54:11 -04:00
Harry Chen a82d9263d1 speed up depth/normal estimation for 360 camera 2026-09-30 23:17:08 -04:00
Harry Chen e40a26f627 use kRigDofAxial for dual-fisheye rig by default 2026-09-30 21:51:17 -04:00
Harry Chen 70478ff2b1 support tiff image format (fixes #127) 2026-09-30 21:36:23 -04:00
Debashish SahuandHarry Chen 2a19c6887f sfm: DJI Avata 360 telemetry, attitude and factory lens calibration (#128)
* telemetry: read the Avata 360 djmd with its own field numbers

read_dji applied the Osmo 360 field numbers to dvtm_AVATA360. That printed
an IMU rate of 2^64 (1.10.1 is an int64 -555 on the Avata), put every
quaternion of a frame on one time (sensor fps was read from 1.11, which is
not it), and found no GPS (the Avata writes it at 3.4.4, in degrees, with no
unit field).

A DjiLayout table now carries the numbers per proto:

- clip rate 1.8, fps 1.9, no focal, no per-frame accelerometer
- GPS at 3.4.4.1.{2,3} in degrees, altitude at 3.4.4.2 (mm)
- relative altitude at 3.4.5.1 (f32 mm, new TelemetryGps::rel_alt)
- per-frame exposure: ISO 3.2.3.1 (f32), shutter 3.2.4.1 (two varints n, d,
  n/d seconds), colour temperature 3.2.6.1 (varint K)

The Osmo keeps its numbers. An unknown proto keeps them too and is still
flagged as unverified. f-number and EV are not read: both SRTs carry one
constant value on every frame, so no field can be told apart. Nothing
downstream consumes the exposure yet.

The clip note no longer prints "focal 0.0 px" when the clip has no focal
field. The report gains an exposure line and a relative altitude range on
the GPS line, each only when present, so Osmo reports are unchanged.
docs/notes/imu-gps-for-sfm.md has the field map.

Tests in sfm_telemetry_test: synthetic Avata frames, an Osmo frame carrying
Avata numbers, and an unknown proto. Two more run on real clips when
SS_TEST_AVATA_OSV, SS_TEST_AVATA_OSV_HOVER and SS_TEST_AVATA_LRF_HOVER name
them, and print SKIP otherwise.

The test helper near() becomes close_to() in sfm_telemetry_test. near is a
Windows macro and check_winmacro flags the file otherwise.

Checked against the SRT of a 139 s flight (8354 frames, packet p is FrameCnt
p+1): lat/lon within 5e-7 deg, altitudes within 1 mm, ISO and colour
temperature exact, shutter within the SRT's 1/3-stop rounding, 0 misses.
Shifted by one frame the same comparison misses 2695 colour temperatures
and 662 altitudes, so the alignment is real. A hover clip's .LRF proxy,
read as an oracle, pairs 317 frames by exact time and matches bit for bit.
The oracle shares the reader, so the SRT comparison is the independent one.

An Osmo 360 clip's report is byte-identical before and after.

Written by Claude (Sonnet 5.5), with review by a second Claude session.

* sfm: attitude sense and vertical without an accelerometer (Avata 360)

The Avata 360 writes a 4 kHz fused attitude and no accelerometer. With no
accelerometer, telemetry_check never measures which way the quaternion maps,
and the timeline conjugated it by default. On a real flight that is the wrong
sense: the hand-eye fit gives sig_rot 5.37 deg against 0.315 deg for the
quaternion itself. The eigen gap is 2.0 against 620, and the old refit also
comes out mirrored (det -1). So every run logged that the gyro and the poses
disagree, and no rotation prior was used.

- SensorTimeline: sign -1 conjugates an attitude whose sense no
  accelerometer settled (attitudeSenseOpen), in orientationAt and in upAt's
  attitude branch.
- ImuExtrinsic: the existing sign-hypothesis loop tries that conjugate
  instead of breaking, and recomputes the up votes per hypothesis. A source
  with an accelerometer keeps break-at-minus-one and its own votes.
- Telemetry::attitude_world_up: a carrier may declare the vertical of the
  attitude world. The DJI reader declares z-down for dvtm_AVATA360 only. With
  no accelerometer the timeline uses it as the up source, so hasUp() is true
  and the gravity refit, the up factors and the sensor gauge's up all run.
  An accelerometer-less attitude with no declaration now answers no up vote
  instead of guessing world +Z.

Tests:

- sfm_sensor_prior_test: no accelerometer, declared and undeclared; an
  accelerometer wins over a declared vertical; attitudeSenseOpen() is open
  exactly when there is no accelerometer.
- sfm_sensor_gauge_test T8 and T8b.
- sfm_telemetry_test: the declaration is set for the Avata and not for the
  Osmo or an unknown proto.
- sfm_attitude_replay_test, gated on SS_TEST_AVATA_MODEL and SS_TEST_AVATA_OSV
  (SKIP when unset): runs a finished sparse model and its clip's telemetry
  through the pair calibration, the factors, the registration check and the
  gauge, so the fix is checked without mapping again. It requires det(X) +1
  on every refit, which is what catches a flipped declared vertical: the fit
  settles X's sign by agreement with the up votes, so a flip leaves the up
  consensus at 0.227 deg and mirrors X instead.

On a 2090-image GPS-levelled model of one flight: sig_rot 0.315 deg, up
0.227 deg from the model's +Z, 2090 of 2090 images get a prior, 10 held.
With the old sense restored the gate rejects the pair set. One flight and
one clip only.

Osmo 360 is unchanged: attitudeSenseOpen() is false, hasUp() is true through
the accelerometer, and the declared vertical is never read.

Written by Claude (Sonnet 5.5), with review by a second Claude session.

* sfm: factory lens calibration from the Avata 360 OSV, through #119's params

The Avata 360 clip header carries each lens's calibration at StreamMeta.5
(PanoDewarpParams). Entry 4 (native_refine_far_master) is video track 0 and
entry 3 (slave) is track 1. The model is Kannala-Brandt with five radial
terms (k5 at field 15), tangential p1 p2 at field 20 on the equidistant
coordinates, in pixels of the 3840x3840 frame, lens_model 8.

- Telemetry: LensCalibration, djmd_lenses, video_lenses.
- LensCalibration.h: refits the five-term curve to the fisheye models' four
  (1.97 px worst on the master lens, 1.22 px on the slave, +0.1 px median on
  real matches), and appends one CameraOverride with params per lens folder
  (camN, under the capture prefix), unless a setting a person gave already
  covers it: a per-folder or bare --focal or --distortion, manifest params,
  or a dataset-wide focal, distortion or params. A model-only entry keeps its
  model.
- Pipeline: applied in `auto` before the match signature. The [run] lines
  say which lens got what, or why not. `--sensor-gauge none` does not turn
  it off.
- 7 messages in 13 languages.

Measured on real frames (docs/notes/imu-gps-for-sfm.md section 2.3). Against
DJI Studio's equirect export of a hover clip, the master lens on track 0 fits
at 0.55 px median and the slave's set at 2.2 px. Lens to lens on a flight,
0.88 and 0.90 px, swapped 6.2 and 8.4 px, without p 2.0 to 2.2 px, without k5
unusable (the four-term polynomial turns over before 90 deg).

Tests: sfm_telemetry_test (decoding, and real clips when SS_TEST_AVATA_OSV and
SS_TEST_AVATA_OSV_HOVER are set), and the new sfm_lens_calib_test (the refit
against an independent five-term projection, the bearing() round trip, which
is shown able to fail, precedence, folder sizing).

No accuracy gain over a hand-set focal was measured on one flight (median
distance to GPS 0.77 m with the factory calibration, 0.66 m with a hand
focal, one run each, so not shown to differ from run-to-run noise). What it gives is no
hand-tuned focal and a faster match stage (4:06 against 6:07).

Written by Claude (Sonnet 5.5), with review by a second Claude session.

* sfm: a person's lens setting at any prefix beats the factory calibration

applyLensPlans read only the longest matching override. A focal, extra or
params given for the capture was ignored as soon as a longer override named
one of its lenses with only a model. With `--focal clip=900` and
`--camera-model clip/cam0=opencv-fisheye`, clip/cam0 got the factory
calibration and the person's focal was overridden. The model had the same
flaw: it came from the longest match only, even when that entry set none.

It now reads every matching override. Any that sets a focal, extra or params
makes the lens a person's own. The model is the longest one that names a
model, and is also written into an existing entry for the lens folder, so the
params are read in the model they were cut for.

Tests, each run against the old code first:

- a capture focal with a model-only entry for one lens: the lens kept by the
  person (fails on the old code), and the other lens, which the old code
  already handled
- a capture calibration with a model-only entry for one lens (fails on the
  old code)
- a capture model with a nearer entry that names none: the params are cut in
  the capture's model, and buildCameras builds that lens in it (both fail on
  the old code)
- a dataset-wide manifest calibration, and a frame size that differs in only
  one of width and height. Both pin behaviour the old code already had, so
  they pass on it. They fail on a build with the dataset-wide params check
  removed, and with either size comparison removed.

Written by Claude (Sonnet 5.5), with review by a second Claude session.

* rebuild telemetry wasm module

---------

Co-authored-by: Harry Chen <harry7557558@gmail.com>
2026-09-30 20:35:03 -04:00
Harry Chen d6b6aad78d mask editor zoom (#100) and draw outside boundary 2026-09-30 19:50:17 -04:00
Harry Chen 19fd3296d7 support path picker in train config UI 2026-09-30 19:06:45 -04:00
Niloux3dandNiloux3d b5b8588425 Add external PLY seed clouds for training (#126)
* Add external seed point cloud initialization

* Clarify seed point cloud controls and initialization source

---------

Co-authored-by: Niloux3d <1400621898@qq.com>
2026-09-30 18:27:48 -04:00
Harry Chen c8aaa2e382 add HEIC support (#104) 2026-09-30 15:59:09 -04:00
Harry Chen 9f7ab0d697 masking: hide sky and cloud from features in 360-camera preset 2026-09-30 12:54:48 -04:00
Harry Chen 09de422c80 address occasional training divergence 2026-09-30 12:02:09 -04:00
Harry Chen 1943edaf83 bump version to 2026.9.30 v2026.9.30 2026-09-29 20:53:45 -04:00
Jeffrey PowersandJeff Powers 35e84b0f76 sfm: Support complete calibrated camera intrinsics (#119)
Manifest camera settings previously supplied a shared focal length and distortion, losing independent focal lengths and off-center principal points from calibrated cameras.

Accept full model-specific COLMAP parameters, validate their shape and values, preserve CLI override precedence, and include calibration in stage cache signatures. Document the input format and test serialization, camera setup, match persistence, and invalid inputs.

Validation: added calibration checks pass on macOS. The manifest suite retains two existing dual-fisheye rig expectation failures: upstream leaves all rig degrees of freedom enabled while those checks expect axial refinement.

Co-authored-by: Jeff Powers <jeff@arcturus.vision>
2026-09-29 20:01:36 -04:00
Harry Chen 316c57f15c speed up SIFT feature detection 2026-09-29 19:51:17 -04:00
Harry Chen a0d8c8e427 fixes #121 2026-09-29 17:52:12 -04:00
Harry Chen 282c41bee7 masking: pen tool, separate areas for each camera (#100), drop masking with separate script 2026-09-29 17:43:53 -04:00
Harry Chen d91821148d Merge remote-tracking branch 'refs/remotes/origin/master' 2026-09-29 14:41:35 -04:00
Harry Chen 0d32bd11f6 CLI: support ffmpeg fallback when extracting frames from video (#118) 2026-09-29 14:41:23 -04:00
Harry Chen 5d4d5dc8df training forecasting: fix ETA underestimate + display OOM risk 2026-09-29 14:35:21 -04:00
Harry Chen 737161db45 fixes #116 2026-09-28 23:04:39 -04:00
Niloux3dandNiloux3d c8c95c58a4 Allow wider fisheye border adjustment and manual ellipse correction (#112)
* Allow wider fisheye border adjustment and editable ellipse correction

* Define GL_STREAM_DRAW for Windows OpenGL headers

---------

Co-authored-by: Niloux3d <1400621898@qq.com>
2026-09-28 22:39:05 -04:00
Harry Chen 08adec2a4b debug macOS packaging failure 2026-09-28 20:22:51 -04:00
6d070edc34 fix: set Wayland app ID for GUI window (#107)
* fix: set Wayland app ID for GUI window

* make GUI register on Linux at startup

---------

Co-authored-by: Frank <zhongyuanguo@foxmail.com>
Co-authored-by: Harry Chen <harry7557558@gmail.com>
2026-09-28 20:16:21 -04:00
Harry Chen 0b0d7a547e fix winmacro check failure 2026-09-28 16:08:29 -04:00
Harry Chen b4db20437b fix Windows build error/warning + better keyboard support 2026-09-28 16:02:08 -04:00
Harry Chen ddba66a209 GUI enhancement for scene partitioning 2026-09-28 10:07:42 -04:00
Harry Chen 52cfb6a772 scene partitioning rework 2026-09-28 09:00:26 -04:00
Harry Chen 96948e4dc8 try more scene partitioning and ROI training methods 2026-09-27 23:42:21 -04:00
Harry Chen adf2f5c413 update partition heuristics + better ROI visualization 2026-09-27 19:40:07 -04:00
Harry Chen 7ff6836a1e gui: fix tilted view caused by skip-when-scale-is-1 mode 2026-09-27 15:18:38 -04:00
Harry Chen 7281ae4fea fix outliers and missing images in colmap parser 2026-09-27 14:51:36 -04:00
Harry Chen d8e6a267f9 wip: partition reconstruction to train separately and merge + ROI training 2026-09-27 02:00:24 -04:00
Harry Chen ee7f5409c6 fix #102 2026-09-26 15:26:05 -04:00
Harry Chen 5bf415f0ed masking: support lang-sam and BiRefNet models 2026-09-26 15:08:58 -04:00
Harry Chen d56882ad7f sfm: telemetry in the loop (wip) 2026-09-26 00:12:15 -04:00
Harry Chen e1d7e47847 support relative path for dataset parsers (#78) 2026-09-25 18:47:04 -04:00
Harry Chen 4e9849161c sfm: speed up mapper / BA solver 2026-09-25 18:03:34 -04:00
Harry Chen caee88fa71 SfM: fix VK_ERROR_DEVICE_LOST in BA solver 2026-09-25 09:23:44 -04:00
Harry Chen 6b70e20770 guard gpu submit budget to reduce chance of VK_ERROR_DEVICE_LOST on slow GPUs 2026-09-25 00:20:22 -04:00
Harry Chen 73e6c0f6c4 auto enable vulkan video decoding/encoding on Mesa driver 2026-09-24 21:38:36 -04:00
Harry Chen a089101a8c video decoding fixes (#98) 2026-09-24 21:28:04 -04:00
Harry Chen d61301853b rebuild web viewers 2026-09-24 19:56:52 -04:00
Harry Chen 183b2c6df7 bump version to 2026.9.24 v2026.9.24 2026-09-23 23:56:06 -04:00
Harry Chen 763e611257 hdr: support explicit control of color space of input seed points 2026-09-23 23:45:49 -04:00
Harry Chen 75923ca1b6 mask editor: #96 follow up 2026-09-23 23:35:37 -04:00
Debashish Sahu 6fa5b746f7 Mask correction editor (#96) 2026-09-23 19:40:23 -04:00
Harry Chen b0ff19d926 fix test failures 2026-09-23 19:09:51 -04:00