Created
August 7, 2024 14:40
-
-
Save GCBallesteros/ad0121c49134cfbe0cc5ab3cc97f669b to your computer and use it in GitHub Desktop.
Sample code for the MaxwellRules post "An unexpected matrix trick" showing how to reduce the dimension of a homography given a fixed coordinate along a dimension.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import numpy as np | |
DIM = 4 # Dimension of matrix which represents the homography | |
IGNORE_DIM = 2 # This would be t on the blog post example | |
# We can't remove the last dim of the homography because it's | |
# special. | |
assert 0 <= IGNORE_DIM <= (DIM - 2) | |
assert IGNORE_DIM | |
rng = np.random.default_rng(42) | |
def normalize_homography(h: np.ndarray) -> np.ndarray: | |
return h / h[-1, -1] | |
def normalize_vec(vec: np.ndarray) -> np.ndarray: | |
return vec / vec[-1] | |
def reduce_h_dim( | |
h: np.ndarray, ignored_component_value: float, ignored_dim: int | |
) -> np.ndarray: | |
# ASSUME: mat is a homography acting on a homogenous coordinates vector | |
new_col = ignored_component_value * np.delete(h[:, ignored_dim], ignored_dim) | |
reduced_h = np.delete(np.delete(h, ignored_dim, axis=1), ignored_dim, axis=0) | |
reduced_h[:, -1] = reduced_h[:, -1] + new_col | |
return reduced_h | |
def main(rng): | |
H = normalize_homography(rng.normal(3, 2, (DIM, DIM))) | |
vec = normalize_vec(rng.normal(2, 1, (DIM,))) | |
# Eliminate the dimension we didn't care about and | |
# normalize the homogenous vector | |
res = np.delete(normalize_vec(H @ vec), IGNORE_DIM) | |
reduced_H = reduce_h_dim(H, vec[IGNORE_DIM], IGNORE_DIM) | |
reduced_vec = np.delete(vec, IGNORE_DIM) | |
# No need to eliminate the dimension we didn't care about in the | |
# result as it was taken care of by reduced_H and reduced_ved | |
# then normalize the homogenous vector | |
reduced_res = normalize_vec(reduced_H @ reduced_vec) | |
assert np.allclose(reduced_res, res) | |
if __name__ == "__main__": | |
# Run a few times to check we weren't just lucky | |
for _ in range(2**8): | |
main(rng) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment