Files
Titano/Titano/Motion/FrameInterpolator.cs
T
Alby96andClaude Opus 5 cc1d040ac0 Titano: motore e interfaccia per time-lapse, senza dipendenze di terze parti
Applicazione desktop completa per creazione e ottimizzazione di time-lapse.
Il vincolo che ne definisce l'architettura è l'assenza totale di componenti
di terze parti: il progetto non ha alcun PackageReference e non invoca processi
esterni. Oltre alla libreria standard di .NET si usano solo API native di
Windows (WIC, Media Foundation, GDI+, DWM) richiamate via P/Invoke scritto a mano.

Sono in-house tutte le parti che di norma si delegherebbero a una libreria:
il parser binario EXIF/XMP, la misura di luminanza e la curva di deflicker,
il calcolo del campo vettoriale di movimento con il motion blur sintetico,
il multiplexer MP4 e ogni controllo dell'interfaccia.

Scelte algoritmiche che meritano una nota:
- il deflicker usa una regressione lineare locale pesata con seconda passata
  robusta, così le rampe reali di luce (alba, tramonto) sopravvivono mentre
  lo sfarfallio del diaframma viene rimosso; una media mobile semplice le
  appiattirebbe entrambe;
- la sfocatura mancante si compone in quadratura con quella già incisa nello
  scatto, perché sommarla linearmente renderebbe l'immagine troppo morbida;
- la luminanza si misura come media logaritmica troncata, invariante alla
  scala e insensibile a cieli bruciati e ombre chiuse.

L'elaborazione non produce file temporanei e mantiene un'occupazione di memoria
stazionaria: buffer poolati e canale a capacità limitata rendono i fotogrammi
vivi indipendenti dalla lunghezza della sequenza.

Verificato con "Titano.exe --selftest": 23 controlli su una sequenza sintetica
dalle proprietà note, incluse la struttura del contenitore prodotto e la sua
ri-decodifica con il lettore di sistema. Tutti superati.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-13 21:40:26 +02:00

49 lines
1.9 KiB
C#
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
using Titano.Imaging;
namespace Titano.Motion;
/// <summary>
/// Interpolazione temporale fra due fotogrammi guidata dal campo vettoriale.
///
/// Si usa il warping all'indietro bidirezionale: l'istante t viene ricostruito prelevando da
/// A lungo t·v e da B lungo +(1t)·v, poi i due contributi vengono miscelati con pesi
/// complementari. Il warping all'indietro non lascia buchi (a differenza di quello in avanti)
/// e la miscelazione incrociata attenua gli errori del campo nelle zone di occlusione.
/// </summary>
public static class FrameInterpolator
{
/// <summary>Genera il fotogramma all'istante <paramref name="t"/> ∈ [0,1] fra A e B.</summary>
public static void Interpolate(ImageBuffer a, ImageBuffer b, MotionField flowAtoB,
float t, ImageBuffer destination)
{
if (t <= 0f) { destination.CopyFrom(a); return; }
if (t >= 1f) { destination.CopyFrom(b); return; }
int width = a.Width;
int height = a.Height;
var srcA = a.Data;
var srcB = b.Data;
var dst = destination.Data;
float wa = 1f - t;
Parallel.For(0, height, y =>
{
int rowBase = y * width * ImageBuffer.Channels;
for (int x = 0; x < width; x++)
{
int index = rowBase + x * ImageBuffer.Channels;
flowAtoB.Sample(x, y, out float vx, out float vy);
MotionBlurRenderer.SampleBilinear(srcA, width, height, x - vx * t, y - vy * t,
out float ar, out float ag, out float ab);
MotionBlurRenderer.SampleBilinear(srcB, width, height, x + vx * wa, y + vy * wa,
out float br, out float bg, out float bb);
dst[index] = ar * wa + br * t;
dst[index + 1] = ag * wa + bg * t;
dst[index + 2] = ab * wa + bb * t;
}
});
}
}