Skip to content

Simplify and generalize Helmert logic#390

Merged
mradamcox merged 2 commits into
ohmg-dev:mainfrom
danvk:simplify-helmert
Jun 24, 2026
Merged

Simplify and generalize Helmert logic#390
mradamcox merged 2 commits into
ohmg-dev:mainfrom
danvk:simplify-helmert

Conversation

@danvk

@danvk danvk commented Jun 22, 2026

Copy link
Copy Markdown
Contributor

Follow-up to #385 and #388. See also #381.

This streamlines the Helmert calculations so that they all go through numpy's np.linalg.lstsq. Since Helmert is a fundamentally linear transformation, this is valid and will produce exact fits for two GCPs and least squares fits for more. No special-casing or if statements needed.

This also fixes a bug where _calculate_scale only considered the first two GCPs but the other methods considered all of them. I made _get_helmert_params return a dataclass with the parameters. The test passes without much modification, just an assertEqual -> assertAlmostEqual for the rotation.

Comment thread ohmg/georeference/georeferencer.py
@mradamcox

Copy link
Copy Markdown
Member

@danvk Thanks for this, it's definitely a more concise approach to generating these 4 params, and after testing it all out manually (I wasn't fully confident my unit tests would be sufficient) everything still works as expected. I hadn't really considered that scale would need to take into account more than two GCPs if they were present, but you're right that it does.

Can you go ahead and also remove the geometry.azimuth_from_coords() function? There is no need for it anymore, though I did enjoy figuring it out :).

@danvk

danvk commented Jun 23, 2026

Copy link
Copy Markdown
Contributor Author

@danvk Thanks for this, it's definitely a more concise approach to generating these 4 params, and after testing it all out manually (I wasn't fully confident my unit tests would be sufficient) everything still works as expected. I hadn't really considered that scale would need to take into account more than two GCPs if they were present, but you're right that it does.

Glad to hear it's working as expected! This is definitely the right way to fit a model.

Can you go ahead and also remove the geometry.azimuth_from_coords() function? There is no need for it anymore, though I did enjoy figuring it out :).

Done, now we've passed -100 ∆ lines!

@mradamcox mradamcox merged commit 9be55a4 into ohmg-dev:main Jun 24, 2026
@mradamcox

Copy link
Copy Markdown
Member

Great, thanks!

Unfortunately I've found there is still more work to do to bring the helmert transformation into the IIIF annotation output, as described here: #391

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants