Reputation: 3117
Assuming I have a 3D object. I have no detailed information about the form of the object, the only information I have is the ranges of the 3 axis coordinates (the min/max x-coordinate etc.).
Given a camera "direction" (so basically from which angle does the camera look at the object) how can I calculate how far away the camera has to be to allow viewing the whole object on a screen of a certain size.
So basically I have the following inputs:
And want to calculate the camera distance.
How can I solve this?
I found a lot of information about how to project a 3D point onto a 2D plane when knowing the camera position in 3D-coordinates, but I failed in adapting the formulas in a way to match my inputs/outputs.
Example inputs would be:
Thanks in advance!
Upvotes: 1
Views: 1595
Reputation: 1575
I am going to assume an orthogonal projection in the following answer, but extension to perspective projection should be easy enough. For smallish objects, orthogonal projection would look okay (since we are used to not seeing perspective effects on them).
For each point i
let x[i]
,y[i]
,z[i]
be the original coordinates in object space.
Let x'[i]
,y'[i]
,z'[i]
be the point rotated into camera space (this can be calculated by applying your rotation transformation to each point - I think this part will be easy for you).
The orthogonal projection will be:
X[i] = f*x'[i] + Cx
Y[i] = f*y'[i] + Cy
Where f
is some number, that we will calculate that deals with the scaling, and Cx
and Cy
are the centre of the image.
This could be made more complicated to allow for e.g. perspective projection, non-unity aspect ratios. See e.g. my answer to this other question: (( 3D points projected to form an image )) for something like this dealing with perspective projection.
Since we will solve for f
, we rearrange:
f = (X[i] - Cx)/x'[i]
f = (Y[i] - Cy)/y'[i]
let MaxX
be the biggest desirable X
point in pixel coordinates, MaxY
the biggest in Y
pixel coordinates, and MinX
and MinY
the smallest (we take the centre of the pixel).
For e.g.
MinX=0.5
MaxX=599.5
MinY=0.5
MaxY=599.5
We want to choose an f
just small enough so that the most extreme x'[i]
or y'[i]
point maps onto one of these pixels.
NOTE: I am assuming that the object is already centred: if it is not then we will also need to calculate a good Cx
and Cy
too (and a tighter fit to the image can be achieved like that).
Calculate the biggest and smallest rotated points in each of the X
and Y
directions (min_i(x[i])
means the smallest value of x[i]
over all possible values of i
):
minx = min_i(x[i])
maxx = max_i(x[i])
miny = min_i(y[i])
maxy = max_i(y[i])
Now solve for the focal length that will be necessary for each of the extreme pixels to map onto each of these extreme points:
f_1 = (MinX - Cx)/minx
f_2 = (MaxX - Cx)/maxx
f_3 = (MinY - Cy)/miny
f_4 = (MaxY - Cy)/maxy
And we choose the smallest of these in order to ensure the whole object fits on the screen.
Example
If we assume that the most leftwards point (post rotation) is at
minx = -1.2
The most rightwards point:
maxx = 1.5
The most upwards point (note that I am assuming the pixel coordiantes align with spatial coordinates):
miny = -1.3
The most downards point (note that I am assuming the pixel coordiantes align with spatial coordinates):
maxy = 1.3
We use your example of a 600x600
image.
For each of these we solve for f
:
f_1 = (0.5 - 300)/-1.2 = 249.6
f_2 = (599.5 - 300)/1.5 = 199.7
f_3 = (0.5 - 300)/-1.3 = 230.4
f_4 = (599.5 - 300)/1.3 = 230.4
Now we choose the smallest f
and so we get:
f=199.7
And the orthogonal projection would be:
X[i] = 199.7*x'[i] + 300
Y[i] = 199.7*y'[i] + 300
A reminder: You can make this more sophisticated in many ways, by adding in perspective projection, allowing a different image centre, scaling, and so forth. This approach is designed to be the simplest way of getting started.
Upvotes: 1