You want to create a new view by linearly blending corresponding pixels from two images using
It=(1−t)I0+tI1. This is the simplest form of image-based view interpolation: instead of rendering a 3D scene, you directly operate on pixels from captured images and interpolate their colors over time/position between views.
This works visually when:
- The cameras are close and have small baseline.
- Scene depth variation is small (little parallax), or objects are far away.
In more challenging setups (large viewpoint change, strong parallax, occlusions), simple per-pixel blending fails (ghosting, double edges) and you need depth-based warping / 3D geometry to align content before blending.
1. Background Knowledge (Key Concepts)
- Image as a function
Treat an image as a function I(x,y) mapping pixel coordinates to color values (e.g., RGB vectors). Linear blending forms a convex combination of two such functions:
It(x,y)=(1−t)I0(x,y)+tI1(x,y)
for each pixel (x,y). This is done independently at every pixel.
- View interpolation vs. morphing vs. rendering
- View interpolation: generate intermediate viewpoints from real images with minimal geometry (your task, simplest case is direct blending).
- Image morphing: often involves both geometric warping and color blending.
- 3D rendering: uses explicit geometry and camera models to render new views.
Your problem uses no warping, just blending, which assumes corresponding structures lie at the same pixel coordinates in both images.
2. Algorithm / General Approach
The core pattern:
- Input: two images I0 and I1 (same size, same alignment), and a scalar t∈[0,1].
- For each pixel location (x,y):
- Read color c0=I0(x,y) and c1=I1(x,y).
- Compute blended color:
ct=(1−t)c0+tc1
- Store ct at (x,y) in output image It.
This is a per-pixel, per-channel linear interpolation (often called “lerp”) applied uniformly over the whole image.
3. Step-by-Step Strategy
Assume both images are the same height, width, and number of channels.
- Validate inputs
- Check that I0 and I1 have identical shape: (H,W,C).
- Ensure t is clamped or validated in [0,1].
- Choose numeric type
- Internally, use a floating-point representation (e.g., float32) to avoid rounding too early.
- If images are in uint8 [0, 255], convert to float first.
- Compute blend
- Vectorized (preferred in NumPy/PyTorch):
I_t = (1.0 - t) * I0 + t * I1
for y in range(H):
for x in range(W):
I_t[y, x, :] = (1 - t) * I0[y, x, :] + t * I1[y, x, :]
- Clamp and cast back
- If working with integer images:
I_t = np.clip(I_t, 0, 255)
I_t = I_t.astype(np.uint8)
- For normalized floats in [0,1], clamp to [0,1] instead.
- Return or display result
- Optionally generate multiple views by looping over several t values (e.g., t = 0.0, 0.1,..., 1.0).
4. Common Pitfalls
-
Mismatched image sizes or formats
-
Different resolutions, aspect ratios, or channel counts will break simple per-pixel blending.
-
Always resize / align beforehand if necessary.
-
Incorrect data types
-
Doing (1 - t)I0 + tI1 on uint8 can cause overflow or truncation.
-
Convert to float before blending, then back to integer.
-
Not normalizing t
-
If t is outside [0,1], you get extrapolation, which may be unintended:
-
t<0: go “before” I0.
-
t>1: go “beyond” I1.
-
For this problem, clamp to [0,1].
-
Expecting good results with large viewpoint changes
-
Without depth/warping, you will see ghosting and blur when objects move significantly between views (parallax, occlusions).
-
That is a limitation of this simple method, not a bug in your code.
5. Time & Space Complexity
Let N=H×W×C be the number of pixel values.
- Time complexity
- You perform a constant amount of work per pixel (a few multiplications and additions).
- Overall:
O(N)=O(H⋅W⋅C)
- Space complexity
- You need space for the output image It of size H×W×C.
- Input images are given, so extra space (besides inputs) is O(N).
- Total additional space:
O(N)
This linear complexity is efficient and scales proportionally with image size, which is why linear blending is often used as a baseline or starting point in view interpolation.