Description
Problem
I'd like to be able to recreate the perspective-warping effects of changing focal length / FOV of a physical camera in matplotlib, for more fine-tuned camera control and for replicating real-world cameras in software.
Proposed solution
From this slide deck, we see how to generate a projection matrix:
This page has a nice derivation of the matrix.
The persp_transformation function in /lib/mpl_toolkits/mplot3d/proj3d.py implements this for a fixed focal distance of 1 (equivalent to a FOV of 90 deg):
def persp_transformation(zfront, zback):
a = (zfront+zback)/(zfront-zback)
b = -2*(zfront*zback)/(zfront-zback)
return np.array([[1, 0, 0, 0],
[0, 1, 0, 0],
[0, 0, a, b],
[0, 0, -1, 0]])
It should not be too hard to update this function to take in a focal length. I think the biggest question is the user interface. The focal_length
can be taken as fundamental and the current proj_type
arguments to the Axes3D constructor can be mapped to focal_length = 1
for proj_type == 'persp'
. To specify a custom focal length however, what should the user input?
Edit: I think the easiest thing would be a default focal_length = None
argument, which can be set by the user but otherwise gets set to 1 if proj_type == 'persp'
.