JOVANA
Explore Library Glossary Getting Started Three Levels Fields How it works Mission
Join the mission
All guides

Dense Video: Segmentation, Interpolation, and Beyond

Reach the master tier — per-pixel masks that persist across frames, inventing brand-new frames between real ones, and the single idea that unifies the whole track.

Dense prediction over time: the frontier

Welcome to the top of the ladder. Look back at the climb. In Guide 1 we noticed that something moved — a coarse, binary signal. In Guide 2 we measured that motion densely, assigning a velocity arrow to every pixel with optical flow. In Guide 3 we stopped caring about pixels and started following whole objects, keeping their identity alive across frames. In Guide 4 we zoomed all the way out and asked a single question of an entire clip: *what is happening here?* Each rung traded a little spatial detail for a little more semantic ambition.

This final guide refuses that trade-off. We now demand both at once: a label or a value for every location in every frame, and — most boldly — frames that never existed in the original footage. We will study the two flagship tasks of dense video. The first is video object segmentation (VOS): producing a clean per-pixel mask of an object — not a box, the exact silhouette — and keeping that mask correct frame after frame. The second is frame interpolation: synthesising brand-new in-between frames, literally inventing moments of time that the camera never captured.

Let us be honest from the start, because this is the research frontier. These systems are genuinely impressive and genuinely brittle. They lean heavily on the motion machinery you already learned — flow gives a strong prior — but they fail in predictable, instructive ways at occlusions, fast motion, and over long durations. The goal of this guide is not to sell you a solved problem; it is to give you the conceptual map of why these tasks are hard, how the best methods attack them, and where they still break.

Video object segmentation: masks that persist

You already know image segmentation: a network reads one picture and labels every pixel — this pixel is 'dog', that one is 'background'. Video object segmentation is that same per-pixel labelling, but it must hold together along a fourth axis: time. The backbone that produces the mask in each frame is the image-segmentation machinery you met earlier; the new problem is making the masks across hundreds of frames refer to the same object, with edges that move smoothly rather than crawl and shimmer.

Per-pixel labelling in a single frame — the spatial backbone of VOS. The hard part is repeating this consistently for every frame of a clip.

A diagram showing an input image and an output where each pixel is coloured according to its class label.

There are two task settings, and the difference is what help you get on frame zero. In semi-supervised VOS, you are handed a ground-truth mask for the first frame (a human, or another model, outlines the target once) and your job is to propagate that mask through every later frame. In unsupervised VOS, you get no hint at all: the system must itself discover the salient, primary moving object and segment it throughout. Semi-supervised is 'follow this exact thing'; unsupervised is 'figure out what matters and follow it'. They sound similar but the second is far harder because you must also solve the question of which object.

Why not just run a great image segmenter independently on each frame and be done? Because each frame is decided in isolation, the result flickers: an edge that the network draws slightly differently from frame to frame, or a pixel that flips class for one frame, looks like visual noise. Worse, with multiple similar objects (three identical zebras), a per-frame model has no notion of identity — it might swap which zebra is 'object 1' between frames. That is exactly the failure that object tracking was invented to fix. So the honest one-line definition is: VOS = pixel-accurate segmentation + tracking. We need the spatial precision of segmentation and the temporal identity of tracking, fused.

Semantic vs instance segmentation. VOS usually needs instance-level identity — telling apart two objects of the same class and keeping each one's label fixed across the whole clip.

A comparison showing semantic segmentation colouring all objects of a class the same, versus instance segmentation giving each separate object its own colour.

The paradigm that currently dominates semi-supervised VOS is the memory network (think STM and its efficient descendant XMem). The idea is beautifully simple: as you process the video, keep a memory — a growing collection of past frames paired with the masks you produced for them. To segment the new frame, you treat its pixels as queries and the stored frames as keys and values: for each location in the current frame, you ask 'which stored regions look most like me?' and pull their mask information across. This is attention over time — the very mechanism from Guide 4's video models, now used to retrieve appearance rather than to classify. Because the memory holds the actual first-frame mask (the trustworthy ground truth) plus many recent frames, the model can re-anchor to the true object even after it temporarily looks odd.

Real videos have several objects, and they hide each other. Multi-object VOS handles this by keeping a separate mask channel per target and resolving competition at each pixel with a softmax-style 'which object owns this pixel?' decision — so two masks cannot claim the same pixel. Occlusion is the brutal case: when object A passes behind a pillar it may vanish for fifty frames. A pure per-frame method loses it; a memory method survives because, when A reappears, its earlier stored appearance in memory still matches, and the mask is recovered. This robustness to disappearance-and-return is precisely what separates a toy segmenter from a usable one — and it is why 'segmentation + tracking + memory', not segmentation alone, defines the modern approach.

Propagation with optical flow, and the consistency idea

Before memory networks, the most natural way to make a mask persist was to let optical flow carry it. Recall from Guide 2 that dense optical flow gives, for every pixel, an arrow saying where that bit of the scene went between frames. If a pixel was labelled 'object' in frame t−1 and we know which pixel it became in frame t, we can simply move the label along the arrow. Flow is the glue between frames: it tells us the correspondence, and a label is just a passenger riding the motion vector to its new seat.

Dense optical flow: a motion vector at every pixel. Warping uses these vectors to drag last frame's mask, image, or features into the current frame.

A field of small arrows over an image, each arrow showing the direction and speed a pixel moves to the next frame.

This operation has a name — warping — and a precise formula. Read it as 'the predicted mask at this frame is the previous mask, sampled at where this pixel came from':

\hat{M}_t(x) = M_{t-1}\!\left(x - f_{t-1\to t}(x)\right)

Flow-based warping: drag last frame's labels along the motion arrows.

Let us define every symbol. x is a pixel location in the current frame t — say the point (100, 50). M_{t-1} is a known quantity: the mask we already have for the previous frame (a 1 where the object is, 0 elsewhere). f_{t-1\to t}(x) is the optical-flow vector at that location — the arrow telling us how much the scene there moved from t−1 to t. The hat on \hat{M}_t marks it as a prediction, our guess for the current mask. The key move is the subtraction: to fill in pixel x now, we 'look backward' to the source location x - f. Concretely: if at x=(100,50) the flow is f=(4,0) — the object drifted four pixels right — then \hat{M}_t(100,50) = M_{t-1}(96,50). We copy the label from where this stuff used to be. Do that for every pixel and last frame's whole mask slides bodily into its new position. That single subtraction is the entire intuition: drag yesterday's labels along today's motion arrows.

import numpy as np

def warp_mask(mask_prev, flow):
    """mask_prev: (H, W) labels at frame t-1.
       flow:      (H, W, 2) vectors f_{t-1->t} for each pixel.
       returns:   (H, W) predicted mask for frame t."""
    H, W = mask_prev.shape
    ys, xs = np.mgrid[0:H, 0:W]          # grid of current-frame coords
    # 'look back' to the source location each pixel came from
    src_x = xs - flow[..., 0]
    src_y = ys - flow[..., 1]
    # x - f can land off-grid -> round/interpolate; clip to stay in bounds
    src_x = np.clip(np.round(src_x).astype(int), 0, W - 1)
    src_y = np.clip(np.round(src_y).astype(int), 0, H - 1)
    return mask_prev[src_y, src_x]       # sample the source labels
Nearest-neighbour backward warping. Real systems use bilinear sampling for sub-pixel flow and add a validity check to mark pixels with no real source.

Now the honest master-level caveat — because warping is not magic. First, x - f rarely lands exactly on an integer pixel, so we must interpolate between neighbours (the code above just rounds; better systems do bilinear sampling). Second, and far worse, are occlusion and disocclusion. When something becomes hidden, two current pixels can trace back to the same source, and the mask folds onto itself. When a region is newly revealed (a disocclusion — the floor behind a walking person), there is simply no source pixel to copy from: the formula points to a location that, for this object, did not exist last frame. Those holes have to be invented. Third, errors accumulate: warp frame 1→2, then 2→3, then 3→4, and every small flow mistake compounds, so a pure chain of warps inevitably drifts off the object.

This is exactly why the memory/attention methods of the previous section outperform pure flow-propagation: attention can re-match the true object from a trustworthy stored frame, healing the drift that warping cannot. But flow is far from obsolete. The modern view is a partnership: flow supplies a strong motion prior — a confident first guess of where everything went — and a learned network corrects its mistakes, filling disocclusion holes and rejecting bad correspondences. So optical flow, and especially the dense optical flow of Guide 2, is not a relic; it is the motion engine that makes video object segmentation tractable. This is where Guide 2's dense flow pays its final dividend.

Video frame interpolation: inventing time

Every task so far analysed video. Now we generate it. Video frame interpolation takes two real, consecutive frames and synthesises one or more brand-new frames in between them — moments the camera never recorded. Why bother? Smooth slow-motion (turn 30 real frames per second into a silky 240 by inserting seven invented frames between each pair), frame-rate up-conversion (make 24 fps film play fluidly on a 120 Hz display), and smoother playback or video compression. This is the most generative — and arguably the most magical — task in the entire track.

The dominant recipe is, once again, built on motion. The intuition: if a pixel travels in a roughly straight line at roughly constant speed between the two real frames, then its position at an in-between moment is just a point part-way along that straight path — a linear interpolation along the flow vector. So we estimate the flow between the two frames, scale it to reach the target moment, warp both neighbours toward that moment, and blend the two warped views.

  1. Estimate optical flow both ways between the two real frames: forward f(0→1) and backward f(1→0).
  2. Pick a target time t in (0,1) — e.g. t=0.5 for the exact middle frame.
  3. Scale each flow by t (or 1−t) and warp each real frame to the in-between moment.
  4. Blend the two warped frames with weights that favour the nearer original frame.
  5. Refine: a network predicts soft visibility/occlusion masks and fixes holes and ghosts.
Interpolation reuses the very same flow field — but now to move pixels partway to a synthetic in-between time, rather than to analyse motion.

A field of motion arrows between two frames, with a midpoint marked partway along each arrow indicating the interpolated position.

\hat{I}_t(x) \;\approx\; (1 - t)\, I_0\!\left(x - t\, f_{0\to 1}(x)\right) \;+\; t\, I_1\!\left(x - (1 - t)\, f_{1\to 0}(x)\right)

Linear flow-based interpolation for an intermediate time t in (0,1).

Symbol by symbol. I_0 and I_1 are the two real frames (start and end). t \in (0,1) is the fractional moment we want — t=0.5 is halfway. f_{0\to 1} is the forward flow (how pixels move from I_0 to I_1) and f_{1\to 0} the backward flow. \hat{I}_t is the synthesised in-between frame. Look at the first term: x - t\,f_{0\to 1}(x) takes only a fraction t of the full motion, so it warps I_0 partway toward the middle — a pixel that would travel 10 px to frame 1 is moved only 5 px when t=0.5. The second term does the mirror image from I_1, moving back (1-t) of the way. Finally the weights (1-t) and t blend the two warped views, leaning toward whichever real frame is nearer in time: at t=0.5 they average 50/50; at t=0.1 the result is 90% the start frame, which is right because we are barely past it.

Now the hard parts that keep this a live research problem — and notice each is a failure of one of the assumptions above. Occlusion: if a region is visible in only one of the two frames (a wall hidden behind a moving car in I_0 but exposed in I_1), naively averaging both warps mixes in garbage from the frame where it does not exist — so the blend should not be 50/50 there; it should take the pixel only from the frame that can actually see it. Non-linear / fast motion: the straight-line, constant-speed assumption breaks for a bouncing ball or a fast turn, so the linear warp lands the pixel in the wrong place. Blending artifacts: even with good flow, averaging two slightly misaligned warps produces ghosting — a faint double image. This is why modern deep interpolators do not stop at the formula: they predict task-specific flow, output soft visibility (occlusion) masks so each pixel is drawn from the frame that truly sees it, and run a synthesis network to refine the blend and hallucinate plausible content where neither warp is trustworthy. The whole edifice rests on motion estimation as its engine, exactly as frame interpolation demands — but learning is what cleans up where optical flow alone fails.

Evaluation, artifacts, and honest limits

A master does not just build these systems — they know how to judge them, and a number can lie. Start with VOS. We score two complementary things. The region measure \mathcal{J} is the Intersection-over-Union (IoU) of the predicted mask against the ground-truth mask: the overlap area divided by the union area, which is 1 for a perfect match and 0 for no overlap — it asks 'did you cover the right pixels overall?' The boundary measure \mathcal{F} instead scores contour accuracy: how well your mask's edge lines up with the true edge, which catches a blobby mask that has decent area overlap but sloppy, ragged borders. The standard headline number is their average, \mathcal{J}\&\mathcal{F}, so a method cannot win by being good at only one.

For interpolation we compare the synthesised frame against the held-out real frame. The classic pixel-fidelity metrics are PSNR and SSIM. PSNR (defined below) measures raw error; SSIM (Structural Similarity) is a bit smarter, comparing local luminance, contrast, and structure rather than bare pixel differences. Here is the formula every video researcher knows:

\mathrm{PSNR} = 10\,\log_{10}\!\left(\frac{\mathrm{MAX}^2}{\mathrm{MSE}}\right), \qquad \mathrm{MSE} = \frac{1}{N}\sum_{i=1}^{N}\bigl(I_{\text{pred},i} - I_{\text{gt},i}\bigr)^2

Peak Signal-to-Noise Ratio, measured in decibels — higher is better.

Unpack it. \mathrm{MSE} — mean squared error — is the average, over all N pixels, of the squared difference between the predicted pixel I_{\text{pred},i} and the true pixel I_{\text{gt},i}; it is large when the reconstruction is far off and zero for a perfect copy. \mathrm{MAX} is the largest possible pixel value (255 for 8-bit images), so \mathrm{MAX}^2 is the strongest signal the image could carry. The ratio \mathrm{MAX}^2/\mathrm{MSE} is therefore 'true signal strength relative to reconstruction error', and 10\log_{10} turns that ratio into decibels — a compressed scale where bigger means better. A quick number: a tiny average error of \mathrm{MSE}=1 on 8-bit images gives 10\log_{10}(255^2/1) \approx 48 dB (excellent); a larger \mathrm{MSE}=100 gives \approx 28 dB (visibly degraded). Intuition: PSNR asks *how strong is the real signal compared to the error you introduced?*

Catalogue the characteristic artifacts, and trace each back to a root cause we already named. Flicker in VOS — a mask that shimmers frame to frame — comes from per-frame decisions lacking temporal binding (Section 2). Ghosting in interpolation — faint double images — comes from blending two misaligned warps (Section 4). Blur at fast motion comes from flow that is wrong when motion is large or non-linear, plus the MSE-blur incentive above. Holes at occlusion/disocclusion come from warping having no valid source pixel for newly revealed regions (Section 3). Notice the pattern: every artifact is the visible fingerprint of a specific broken assumption.

Finally, two honest realities. Compute: dense video means doing per-pixel work for thousands of frames, and memory networks must store and attend over a growing history — so memory and latency, not just accuracy, decide whether a method is deployable (this is precisely why XMem's efficient memory mattered). Open failure modes: these systems still lose thin structures (hair, bicycle spokes), confuse near-identical objects after long occlusion, drift over very long videos, and hallucinate when asked to interpolate motion too fast or too non-rigid for flow to track. State this plainly. The frontier is real, the progress is real, and so are the cliffs.

The unifying thread: motion is the signal

Stand back and look at the whole track at once, and one idea is woven through every single guide: motion estimation is the connective tissue of video understanding. It detected change in Guide 1. It became the explicit, dense field of optical flow in Guide 2. In Guide 3 it drove the Kalman filter's predict step and powered the data-association that links detections into tracks. In Guide 4 it fed the temporal stream — the 'motion view' — that lets a network recognise an action rather than just a pose. And in this guide it both propagated labels (warping masks forward in VOS) and synthesised pixels (warping frames toward an invented moment in interpolation). The same arrow, reused at every rung.

Look forward, honestly. The field is moving from task-specific pipelines toward video foundation models — large networks pre-trained on oceans of video that can be adapted to detection, segmentation, video classification, and more. Space-time transformers extend the attention you saw used for VOS memory and action recognition into a single architecture that reasons jointly over where and when. And diffusion-based video generation pushes synthesis far past interpolation, generating whole clips from text or a single image — the same generative ambition as frame interpolation, scaled up enormously.

But keep your hard-won skepticism. The open challenges are exactly the ones this guide taught you to see: long-range temporal coherence (staying consistent over hundreds of frames, not just a few), compute (video is enormous, and quadratic attention over space-time is brutal), and evaluation (we still lack metrics that reliably match human judgement of a video — PSNR's blur problem, scaled to whole generated clips). These are not footnotes; they are the live research questions.

That is the master tier of motion and video. You can now reason about a video at every granularity — a flicker of change, a dense field of arrows, a tracked identity, a recognised action, a per-pixel mask that persists, and an invented frame — and, just as importantly, you can say precisely why each method works and where it breaks. You have the conceptual map and the honest caveats. The frontier is open; go watch it move.