Simplify and generalize Helmert logic#390
Conversation
|
@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 :). |
Glad to hear it's working as expected! This is definitely the right way to fit a model.
Done, now we've passed -100 ∆ lines! |
|
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 |
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 orifstatements needed.This also fixes a bug where
_calculate_scaleonly considered the first two GCPs but the other methods considered all of them. I made_get_helmert_paramsreturn a dataclass with the parameters. The test passes without much modification, just anassertEqual->assertAlmostEqualfor the rotation.