:Video Composition and Enhancement Pipeline with FFmpeg and OpenCV

Processing cryptic video sources requires a multi-stage pipeline to reveal hidden visual information. This walkthrough demonstrates a practical approach using command-line tools and computer vision libraries.

Initial Video Composition

Two source videos containing concealed countdown sequences were combined using FFmpeg's mixing filter. The direct composition produced a low-visibility result requiring significant enhancement.

import subprocess

subprocess.run([
    'ffmpeg', '-y',
    '-i', 'clips/source_a.mp4',
    '-i', 'clips/source_b.mp4',
    '-filter_complex', 'mix',
    'results/composite.mp4'
])

Contrast Amplification

The initially merged footage suffered from poor contrast. An FFmpeg equalization filter dramatically improved the luminance range, making the underlying numeric content partially recognizable.

subprocess.run([
    'ffmpeg', '-y',
    '-i', 'results/composite.mp4',
    '-vf', 'eq=contrast=8.5',
    'results/contrast_boosted.mp4'
])

Noise Reduction Strategy

Heavy sensor noise remained visible after contrast adjustment. A two-pass denoising approach proved necessary:

  1. Median filtering to eliminate salt-and-pepper artifacts
  2. Non-local means denoising to preserving edge details while smoothing

Processing order proved critical—applying denoising before contrast enhancement resulted in irreversible information loss and mosaic patterns.

import cv2

input_clip = 'results/contrast_boosted.mp4'
capture = cv2.VideoCapture(input_clip)

frame_rate = capture.get(cv2.CAP_PROP_FPS)
dimensions = (
    int(capture.get(cv2.CAP_PROP_FRAME_WIDTH)),
    int(capture.get(cv2.CAP_PROP_FRAME_HEIGHT))
)
codec = cv2.VideoWriter_fourcc(*'avc1')

output_file = 'results/denoised.mp4'
writer = cv2.VideoWriter(output_file, codec, frame_rate, dimensions, True)

while capture.isOpened():
    success, frame = capture.read()
    if not success:
        break
    
    filtered = cv2.medianBlur(frame, 5)
    filtered = cv2.fastNlMeansDenoising(filtered, None, 12, 7, 21)
    writer.write(filtered)

writer.release()
capture.release()

Alternative: FFmpeg's BM3D filter offers comparable noise reduction with GPU acceleration potential.

Edge Sharpening

Denoising inevitably introduced slight blurring. A convolution-based sharpening kernel restored digit boundaries and improved legibility.

import numpy as np

source_file = 'results/denoised.mp4'
capture = cv2.VideoCapture(source_file)

fps = capture.get(cv2.CAP_PROP_FPS)
frame_size = (
    int(capture.get(cv2.CAP_PROP_FRAME_WIDTH)),
    int(capture.get(cv2.CAP_PROP_FRAME_HEIGHT))
)
codec = cv2.VideoWriter_fourcc(*'avc1')

destination = 'results/sharpened.mp4'
writer = cv2.VideoWriter(destination, codec, fps, frame_size, True)

sharpen_kernel = np.array([
    [-1, -1, -1],
    [-1, 9, -1],
    [-1, -1, -1]
], dtype=np.float32)

while capture.isOpened():
    ret, frame = capture.read()
    if not ret:
        break
    
    sharpened = cv2.filter2D(frame, -1, sharpen_kernel)
    writer.write(sharpened)

writer.release()
capture.release()

Final Noise Suppression

Sharpening amplified residual high-frequency noise. A final median blur pass with a smaller kernel size eliminated these artifacts without compromising the newly enhanced edges.

final_input = 'results/sharpened.mp4'
capture = cv2.VideoCapture(final_input)

fps = capture.get(cv2.CAP_PROP_FPS)
resolution = (
    int(capture.get(cv2.CAP_PROP_FRAME_WIDTH)),
    int(capture.get(cv2.CAP_PROP_FRAME_HEIGHT))
)
codec = cv2.VideoWriter_fourcc(*'avc1')

final_output = 'results/final_output.mp4'
writer = cv2.VideoWriter(final_output, codec, fps, resolution, True)

while capture.isOpened():
    success, frame = capture.read()
    if not success:
        break
    
    cleaned = cv2.medianBlur(frame, 3)
    writer.write(cleaned)

writer.release()
capture.release()

Codec Configuration Note

OpenCV's MP4 encoding requires the AVC1 codec, which depends on the OpenH264 library. Missing this dependency produecs runtime errors:

Failed to load OpenH264 library: openh264-1.8.0-win64.dll
Please check environment and/or download library: https://github.com/cisco/openh264/releases

Place the appropriate platform-specific DLL in the working directory or system PATH before execution.

Jupyter Playback Utility

To iterative development, a simple HTML5 video renderer enables quick preview within notebook environments.

from IPython.display import HTML

def display_clip(file_path, width=480, height=360, extension='mp4'):
    video_tag = f'''
    <video width="{width}" height="{height}" controls>
        <source src="{file_path}" type="video/{extension}">
    </video>
    '''
    return HTML(video_tag)

This pipeline transforms initially unviewable source material into clean, decipherable output through careful sequencing of traditional image processing operations.

Tags: ffmpeg OpenCV video-processing computer-vision denoising

Posted on Sun, 17 May 2026 13:22:05 +0000 by bmw57