v9.1.1
Menu

Trajectory Smoothing Filter

mediumPROVideo StabilizationStabilizationCV: Motion Estimation

Implement camera trajectory smoothing for video stabilization. This task involves reducing the jitter in a video by smoothing the camera's motion trajectory between frames.

Video stabilization is crucial for enhancing the viewing experience, and it relies on accurately estimating the homography between consecutive frames, which describes the transformation of the camera's motion. The accumulation of these transformations yields the camera's trajectory over time. However, this trajectory is often noisy and needs to be smoothed to remove unwanted jitter.

Here are the key steps:

  1. Estimate the camera motion between frames using homography estimation techniques.
  2. Accumulate the transformations to obtain the camera trajectory.
  3. Apply a smoothing filter to the trajectory.
Tsmooth(t)=∑iwi⋅T(t+i)T_{smooth}(t) = \sum_i w_i \cdot T(t+i)

This technique is widely used in handheld camera recordings and action cameras to reduce shakiness.

Task

Implement smooth_trajectory(trajectory, window_size). The trajectory is already given (steps 1–2 are done for you); implement step 3 as a centred moving average:

  • Smooth each component (xx, yy, angle) independently.
  • For frame tt, average the frames from t−ht-h to t+ht+h with equal weights, where h=⌊window_size/2⌋h = \lfloor \text{window\_size} / 2 \rfloor.
  • Near the start and end, the window is truncated to the frames that exist, and the average is taken over only those frames.
  • Return a list with one (x, y, angle) tuple per input frame (same length as the input), each value rounded to 2 decimal places. The tests print the tuples, so the values are expected as NumPy float64 scalars, e.g. (np.float64(3.33), np.float64(0.0), np.float64(0.0)).

Example

Input
trajectory = [(0,0,0), (1,1,0.1), (0,2,0), (2,1,0.05), (1,2,0)]
window_size = 3
Output
Smoothed trajectory with reduced jitter
Reasoning
  • trajectory holds one camera pose (x,y,θ)(x, y, \theta) per frame, five frames here. With window_size = 3, each frame is averaged with h=1h = 1 neighbour on each side, all weighted equally.
  • Each component is smoothed on its own. Frame 2 uses frames 1, 2, 3: x=1+0+23=1.0x = \frac{1+0+2}{3} = 1.0, y=1+2+13≈1.33y = \frac{1+2+1}{3} \approx 1.33, θ=0.1+0+0.053=0.05\theta = \frac{0.1+0+0.05}{3} = 0.05.
  • Frame 1 uses frames 0–2: x=13≈0.33x = \frac{1}{3} \approx 0.33, y=1.0y = 1.0, θ=0.13≈0.03\theta = \frac{0.1}{3} \approx 0.03. Frame 3 gives (1.0,1.67,0.02)(1.0, 1.67, 0.02) the same way.
  • At the ends the window is cut short to two frames: frame 0 gives (0.5,0.5,0.05)(0.5, 0.5, 0.05) and frame 4 gives (1.5,1.5,0.025)(1.5, 1.5, 0.025). In binary, 0.0250.025 sits just under the halfway point, so it rounds to 0.020.02.
  • The result is a smoothed trajectory with reduced jitter: (0.5, 0.5, 0.05), (0.33, 1.0, 0.03), (1.0, 1.33, 0.05), (1.0, 1.67, 0.02), (1.5, 1.5, 0.02). That's one pose per input frame, rounded to 2 decimal places.
  • Notice that raw xx jumps 0,1,0,2,10, 1, 0, 2, 1 (swings of up to 2), while smoothed xx never moves more than 0.670.67 between frames.

Constraints

  • trajectory: List of (x, y, angle) camera positions per frame
  • window_size: Smoothing window
  • Return: Smoothed trajectory

Learn this in

More from CV: Motion Estimation

PRO

Editor locked

The code editor is locked for Pro problems. It is only available for free problems. Please upgrade to gain access to the code editor for all problems.

solution.py

Test results

Sign in to run your code against the test cases.