Determine if a point is in a camera’s field of view (3D)

3dgeometry

I have a camera that is present at some coordinate, say, $(x,y,z)$ and a point which is present in space at some coordinate, say, $(x', y',z')$. All the properties of the camera like focal length, sensor size are known to me.

I want to check if this object would be visible in the field of view of the camera or not. Something like, if the point is present in the pyramid-like shape which can be drawn with the tip at the lens. My question is – how do I go about doing that?

Going through the information given here in this Wikipedia article on angle of view, it says that a camera's angle of view can be measured horizontally, vertically, or diagonally. There are formulas that give the horizontal, vertical and diagonal angle which can be calculated via the parameters of the camera.

Assuming that the the horizontal angle is $\alpha$, vertical angle is $\beta$, would it suffice to check if the angle between $(x,y,z)$ and $(x',y',z')$ horizontally and vertically falls within that range of horizontal and vertical angles? Or would I be missing any cases with this formulation?

If the question is unclear, I'd be happy to elaborate further.

EDIT: Here's the image from Wikipedia which depicts the angle of view

enter image description here

Best Answer

The most efficient way I've found, is to project the point to an arbitrary projection plane (corresponding to the view frustum, or camera field of view), and check that the projected point is within the rectangular boundaries of the visible projection plane.


Let the focal point of the camera be at origin. The view from the camera is a bipyramid, with apex at the focal point. We can ignore the pyramid on the other side of the focal point (there's just the image sensor there).

Choose an arbitrary projection plane, at a distance $d \gt 0$ from the focal point. (You normally already have such a projection plane, for describing the scene in 2D; if you do not, choose $d = 1$ for simplicity.)

Let $\hat{n}$ be the unit vector along the sight line, i.e. from the focal point to the projection plane, perpendicular to the projection plane, with length $1$. Usually that point is at the center of the projection plane, but it is quite possible to choose a skewed camera frustum (frustum being the portion of the pyramid in front of the camera that is projected to the projection plane).

Let $\hat{u}$ be the unit vector "right" along the projection plane, and $\hat{v}$ the unit vector "up" along the projection plane. Let the projection plane be $w$ wide (in world units, not projection plane units), and $h$ tall.

An arbitrary point $\vec{p}$ must be in front of the camera, $$\vec{p} \cdot \hat{n} \gt 0 \tag{1a}\label{G1a}$$for it to be visible. Usually, we use $$\vec{p} \cdot \hat{n} \gt d \tag{1b}\label{G1b}$$ i.e. only consider points at or beyond the projection plane, ignoring points between the focal point and the projection plane. Choose which one is appropriate for you.

Next, calculate $$\begin{aligned} \vec{p}^\prime &= \frac{d \, \vec{p}}{\hat{n} \cdot \vec{p}} - d \hat{n} \\ u^\prime &= \vec{p}^\prime \cdot \hat{u} \\ v^\prime &= \vec{p}^\prime \cdot \hat{v} \\ \end{aligned} \tag{2a}\label{G2a}$$ where $\vec{p}^\prime$ is the relative vector from origin of projection plane, to where the ray along vector $\vec{p}$ intersects the projection plane. Its first term is $\vec{p}$ projected to the projection plane, and the second term ($d \hat{n}$) is the origin of the projection plane. $u^\prime$ and $v^\prime$ are the coordinates on the projection plane. If the projection plane is centered, then the limits for $u^\prime$ and $v^\prime$ are $$\left\lbrace \begin{aligned} -\frac{w}{2} \le u^\prime & \le \frac{w}{2} \\ -\frac{h}{2} \le v^\prime & \le \frac{h}{2} \\ \end{aligned} \right. \tag{2b}\label{G2b}$$ otherwise the projected point is outside the projection plane visible to the camera.


To recap, in step-by-step algorithm form:

  1. Calculate $$d^\prime = \vec{p} \cdot \hat{n}$$ If $$d^\prime \lt 0$$ then point $\vec{p}$ is behind the camera, and outside the field of view.

    Otherwise,

  2. Calculate $$\vec{p}^\prime = d \left( \frac{1}{d^\prime}\vec{p} - \hat{n} \right)$$

  3. Calculate $$u^\prime = \vec{p}^\prime \cdot \hat{u}$$ If $$u^\prime \gt u_\max$$ or $$u^\prime \lt u_\min$$ the point is outside the camera field of view.

    Note that when the view is centered, $u_\min = -w/2$, and $u_\max = w/2$.

    Otherwise,

  4. Calculate $$v^\prime = \vec{p}^\prime \cdot \hat{v}$$ If $$v^\prime \gt v_\max$$ or $$v^\prime \lt v_\min$$ the point is outside the camera field of view.

    Note that when the view is centered, $v_\min = -h/2$, and $v_\max = h/2$.

    Otherwise, point $\vec{p}^\prime$ is within the bounds on the projection plane, and therefore point $\vec{p}$ within the field of view.

The maximum cost of this test, ignoring setting $d$, $w$, $h$, $\hat{n}$, $\hat{u}$, and $\hat{v}$ that only change if the camera direction changes, is three vector dot products, one vector-scalar product and one division of vector by a scalar, one vector subtraction, two scalar absolute values, two multiplications by two, and three comparisons. This is very cheap and very efficient.

You can make it even more efficient by using an additional vector $\vec{o}$ pointing to the negative corner of the projection plane, and $\vec{p}^\prime = \frac{d\,\vec{p}}{\hat{n}\cdot\vec{p}} - \vec{o}$, and $\vec{u} = \hat{u}/w$ and $\vec{v} = \hat{v}/h$ instead of $\hat{u}$ and $\hat{v}$ above. Then, the valid range is $0 \le u^\prime \le 1$ and $0 \le v^\prime \le 1$, and you shave off a couple of (scalar) operations.

Related Question