Menu

Home_it

Kickaha

English version / Versione italiana



Benvenuti nella wiki di QMtrim!
(Questa documentazione è un libero adattamento della guida originale in italiano di HoHoHo. --KICKAHA)

Introduzione

Ottimizzare la compressione video

Uno degli obiettivi della compressione video è quello di ottenere la massima qualità nel minimo spazio possibile. A tal fine sono stati sviluppati diversi componenti software che vengono utilizzati durante la compressione. Tra questi:

  • il decoder, per la decompressione dello stream originale affinché possa essere elaborato,
  • il frameserver, che gestisce l'elaborazione dello stream dalla decodifica iniziale alla ricodifica finale,
  • i filtri, che elaborano le immagini prima della ricompressione,
  • i codec, responsabili della compressione con cui si ottiene il file finale.

AviSynth è un frameserver con un potente linguaggio di scripting che permette di elaborare e ricomprimere i video con logiche molto articolate. Attorno ad AviSynth si è sviluppata una voluminosa libreria di filtri che consente di effettuare ogni sorta di elaborazione sulle immagini.

Uno dei possibili usi di AviSynth è quello di dividere il flusso video in diverse parti con la funzione trim, applicare ad ogni sequenza un filtro diverso e riunire infine le sequenze prima della ricompressione. Questo modo di processare gli stream video consente di applicare ad ogni parte del video i filtri che si ritengono più adatti a comprimere meglio quella particolare sequenza.

QMtrim nasce per sfruttare questa idea applicando filtri più "pesanti" (che quindi fanno perdere più dettaglio a vantaggio della compressione) laddove le immagini sono maggiormente in movimento (e l'occhio non percepisce i dettagli in modo accurato) e filtri più "leggeri" per le immagini più statiche (di cui l'occhio percepisce meglio i dettagli). In questo modo si perde dettaglio dove serve meno e rimane più spazio da dedicare alle immagini che vengono osservate in modo più scrupoloso, ottenendo una qualità percepita maggiore.

La misura del movimento e le complicazioni

Per realizzare questo tipo di elaborazione video è indispensabile innanzitutto avere una misura del movimento. Esistono filtri per AviSynth che fanno questo tipo di misurazione: uno di questi è MVAnalyse delle librerie MVtools di Manao & Fizick che, confrontando ogni frame col successivo, applica un algoritmo di motion-compensation simile a quello dei codec e valuta la somma dello spostamento di ogni blocco di pixel.
Per il sistema di filtri si potrebbe pensare ad un algoritmo ideale che misura il movimento di ogni singola immagine e le applica un filtro su misura, ma questo vuol dire che se una sequenza video diventa repentinamente più movimentata, si applicherebbero in breve tempo filtri sempre più grossolani e l'occhio si accorgerebbe del calo della qualità.
Inoltre la misura del movimento non è un dato preciso né una curva continua; tipicamente i valori sono affetti da errore (come un rumore di fondo) e sono presenti "picchi" di movimento che vanno ignorati perché troppo brevi per essere notati dall'occhio: classico il caso del cambio scena che viene misurato come se fosse un grosso movimento di un singolo frame seguito magari improvvisamente da immagini statiche.

QMtrim

L'approccio che fa uso di QMtrim è quello di pensare ad una serie di filtri fissi, ognuno leggermente più pesante del precedente: il primo si userà per le immagini quasi immobili, l'ultimo per quelle con molto movimento. Con un numero di filtri sufficientemente alto si nota poca differenza tra un filtro e quello successivo, e l'effetto che si ottiene è quello che si avrebbe con l'applicazione di un insieme continuo di filtri, ognuno calibrato molto bene sul movimento di quella particolare immagine.
Il problema è poi suddividere il video in spezzoni tutti più o meno con lo stesso movimento per applicare a ciascuno il suo filtro. AviSynth fa uso della funzione trim per ottenere gli spezzoni ma, al crescere del numero di filtri che si vogliono applicare, questi spezzoni diventano brevi e numerosi, e pensare di scriverli a mano diventa un compito impossibile da realizzare. Per ultimo è necessario evitare che i filtri scelti diventino grossolani troppo rapidamente.
QMtrim cerca di risolvere questi problemi.

Passo 1: la generazione dello statfile

Innanzitutto QMtrim ha bisogno della misura del movimento per ogni singolo frame. In questo il tool è pensato per essere indipendente dal metodo che si vuole usare e dalla logica che si vuole dare ai filtri; data una libreria che misuri, ad esempio, quanto è rossa un'immagine, si potrebbe usare QMtrim per decidere che filtro usare per eliminare la componente rossa o altro ancora. In questa guida discutiamo del metodo descritto sopra: applicare filtri più o meno pesanti a seconda del movimento presente in ciascun frame.
Quello che importa a QMtrim è di avere in ingresso un file da analizzare (statfile) con queste caratteristiche:

  • formato testo;
  • due valori numerici per ogni riga: il numero del frame e la misura del movimento (o altro valore da analizzare);
  • ogni riga descrive un frame, in ordine, a partire dal frame numero 0;
  • le coppie di valori devono essere separate da spazi o tab;
  • il numero del frame deve essere intero;
  • il secondo numero può essere decimale (il separatore decimale è il punto).

Innanzitutto è necessario procurarsi le MVtools a questo indirizzo (http://avisynth.org.ru/mvtools/mvtools.html) e installarle assieme alle altre librerie di AviSynth in modo che siano utilizzabili dagli script (negli esempi che seguono si suppone che la DLL sia installata nel path "C:\Programs\AviSynth 2.5\plugins\").
Per agevolare l'analisi, assieme a QMtrim viene fornito uno script per AviSynth (QMlib.avsi) che genera lo statfile facendo uso di queste librerie.
Per creare lo statfile, serve uno script per AviSynth che decodifichi il flusso video da analizzare, lo filtri il minimo indispensabile per la misura del movimento e infine invochi la funzione che genera lo statfile.
Dal sito delle MVtools si legge che sono ammessi solo stream progressivi con formato colore YV12/YUY2 e QMlib.avsi ammette solo il YV12 quindi il filtraggio minimo prevede tipicamente:

  • eventuale deinterlace;
  • crop/resize dell'immagine;
  • eventuale conversione al formato colore YV12.

In questa fase non è necessario applicare altri filtri, a meno che non siano funzionali ad una più corretta misurazione del movimento.
Uno script di esempio:

LoadPlugin("DGDecode.dll")
LoadPlugin("C:\Programs\AviSynth 2.5\plugins\MVtools.dll")
Import("QMlib.avsi")
Mpeg2Source("VTS_01.d2v")
Spline16Resize(576,432,10,4,-20,-2)


In coda allo script va aggiunta la chiamata alle funzioni fornite in QMlib.avsi che sono QMwritesub(), QMstack() e QMwritefile().

  • QMwritesub mostra in sovrimpressione il valore di movimento su ciascun frame, utile a verificare la corretta valutazione del movimento;
  • QMstack genera un frame di due immagini: quella in alto è l'immagine originale col valore del movimento sovrimpresso (come quella generata da QMwritesub), quella in basso è la mappa dei vettori di movimento (a linee più lunghe corrispondono movimenti più veloci);
  • QMwritefile genera lo statfile per QMtrim.

L'analisi si intende eseguita rispetto al frame successivo, quindi per il frame 0 viene indicato il movimento misurato tra frame 0 e frame 1.

La sintassi per l'invocazione delle funzioni è la seguente:

  • QMwritesub(clip c, bool "chroma", int "Ysc", int "thSCD1", int "thSCD2")
  • QMstack(clip c, bool "chroma", int "Ysc", int "thSCD1", int "thSCD2")
  • QMwritefile(clip c, string "statfile", bool "chroma", int "Ysc", int "thSCD1", int "thSCD2")

I parametri sono:

  • chroma (default true) da mettere a false per video in bianco e nero;
  • Ysc (default 255) valore di movimento da usare quando due frame sono troppo diversi (es: cambi scena); idealmente dovrebbe essere un valore superiore al massimo misurato in tutto il video, ma è irrilevante per QMtrim che smorza i picchi;
  • thSCD1 (default 600) durante la ricerca di ciascun blocco di pixel nel frame successivo, è la massima differenza ammessa per considerare i potenziali blocchi come candidati all'analisi del movimento; se non vengono trovati candidati entro questa soglia, il blocco viene conteggiato come scorrelato;
  • thSCD2 (default 130) è la frazione (su 255) di blocchi scorrelati, oltre la quale due frame successivi sono considerati troppo diversi e viene restituito il valore di movimento Ysc (il default 130 corrisponde al 51% dell'immagine);
  • statfile (parametro obbligatorio) è il nome dello statfile per QMtrim.

Nella maggior parte dei casi i valori di default dei parametri Ysc, thSCD1 e thSCD2 sono adeguati. Si faccia riferimento anche alla documentazione delle MVtools per ulteriori informazioni sui parametri descritti.

Lo script che produce lo statfile per QMtrim nel nostro esempio sarà quindi qualcosa del tipo:

LoadPlugin("DGDecode.dll")
LoadPlugin("C:\Programs\AviSynth 2.5\plugins\MVtools.dll")
Import("QMlib.avsi")
Mpeg2Source("VTS_01.d2v")
Spline16Resize(576,432,10,4,-20,-2)
QMwritefile(statfile="StatFile.txt")


Per generare lo statfile sarà necessario permettere ad AviSynth di processare il video per intero, a partire dall'inizio e fino alla fine. Quindi, se usate ad esempio VirtualDubMod, avviate l'elaborazione dal primo frame e lasciate completare il processo fino al termine; è molto facile corrompere lo statfile scorrendo parti diverse di video anche solo per pochi frame. Al termine chiudete l'applicazione e prelevate lo statfile ottenuto.
QMtrim a questo punto ha le informazioni che servono per produrre la sequenza di trim.

Passo 2: usare QMtrim

QMtrim nasce come utility da linea di comando e continua a mantenerne la modalità di utilizzo. In più ora è possibile utilizzare la modalità grafica. I parametri inseriti al momento del lancio saranno presentati nella GUI per eventuali modifiche; se il lancio avviene senza parametri la GUI conterrà i valori di default.

Linea di comando

Questa è la lista dei parametri da linea di comando:

  • -v o --version mostra le informazioni sulla versione di QMtrim ed esce
  • -h o --help mostra una videata di istruzioni sulla sintassi per il lancio di QMtrim ed esce
  • -i statfile o --input statfile indica il nome dello statfile da analizzare
  • -o trimfile o --output trimfile indica il nome del file in cui salvare la sequenza di trim generata
  • -u unsaw_val o --unsaw unsaw_val larghezza (in frame) della finestra di dati da usare per smorzare i picchi (default 0)
  • -c cxrest_val o --cxrest cxrest_val parametro che rallenta l'incremento del livello di filtraggio, in frame (default 50)
  • -t o --thresholds interpreta la distribuzione di livelli come soglie assolute, invece che come quote di presenza
  • -f levels o --flat-distrib levels genera una distribuzione di levels filtri con pari quota di presenza
  • -q o --quiet incluso per compatibilità con le versioni precedenti, viene ignorato
  • -d o --debug mostra nella GUI alcune informazioni di debug
  • distribution sequenza di valori, uno per livello di filtro, da interpretare come quota di presenza o soglia assoluta (default: 1,1,1,1,1,1,1,1,1,1)

Innanzitutto è necessario decidere quanti livello di filtraggio si vogliono applicare: con 3-4 livelli si possono ottimizzare gran parte dei video, AvsOptimizer ne utilizza 10, ottimizzazioni più fini si hanno con 32 livelli di filtro. QMtrim supporta fino a 250 livelli di filtro.

Stabilito il numero dei livelli, si può partire da due tipi di distribuzione: per quote o per soglie.

La distribuzione per soglie richiede una sequenza crescente di valori che hanno corrispondenza diretta con quelli presenti nello statfile, ovvero saranno valori di movimento. Ogni frame sarà quindi assegnato al livello corrispondente a seconda del suo valore di movimento. Ogni livello n comprenderà i frame con movimento compreso tra il valore n-1 della distribuzione e il valore n. In particolare il primo livello comprenderà i valori di movimento inferiori al primo valore della distribuzione e i frame con valore superiore all'ultimo livello saranno comunque assegnati all'ultimo livello. Segue un esempio:

Livello Valore di soglia Frame assegnati a questo livello
0 10 Quelli con movimento da 0 a 10 incluso
1 20 Quelli con movimento oltre 10 e fino a 20
2 50 Quelli con movimento oltre 20 e fino a 50
3 80 Quelli con movimento oltre 50

La distribuzione per quote richiede una sequenza di valori che indica quale frazione dei frame si vuole far cadere in ciascun livello. Sarà compito di QMtrim determinare quali sono i valori di soglia da dare a ciascun livello per ottenere questa ripartizione. Non importa quale sia il valore assoluto delle quote, ma solo il valore che hanno una rispetto all'altra. Tre esempi di quote del tutto equivalenti:

Livello Es. 1 Es. 2 Es. 3 Frame assegnati a questo livello
0 1 0.125 3 Il 12.5% dei frame totali
1 2 0.25 6 Il 25% dei frame totali
2 3 0.375 9 Il 37.5% dei frame totali
3 2 0.25 6 Il 25% dei frame totali

Quindi la distribution della linea di comando potrà contenere valori di movimento in presenza del flag -t (o --thresholds) e quote in assenza del flag.
I valori vanno forniti in ordine di livello crescente e devono essere separati da virgola (,) punto e virgola (;) o spazio, e usano sempre il punto (.) come separatore delle cifre decimali.
Il valore di default della distribuzione (1,1,1,1,1,1,1,1,1,1) è di 10 quote identiche che faranno assegnare il 10% dei frame totali a ciascun livello di filtro. È possibile similmente ottenere una distribuzione piatta, ma con un numero di livelli diverso da 10, se si fa seguire all'opzione -f (o --flat-distrib) il numero di livelli desiderato (levels).

Esistono infine due parametri che servono a raffinare l'analisi: unsaw e cxrest.

Il parametro unsaw agisce sulla distribuzione dei valori in ingresso con lo statfile e serve ad attenuare i picchi. In pratica QMtrim analizza una finestra di dati pari a unsaw_val frame e pone un limite pari al massimo valore presente a uno dei due estremi della finestra; tutti i valori contenuti all'interno di questa finestra che sono superiori a questo limite vengono resi pari al limite stesso. Più unsaw_val è grande e più la finestra si allarga attenuando i picchi. Un algoritmo simile viene comunque applicato ai dati anche con unsaw_val pari a 0: ogni dato superiore sia al frame che lo precede che a quello che lo segue viene ridotto al valore ottenuto dalla media dei due frame vicini.

Il parametro cxrest agisce invece come attenuatore sulla sequenza di trim per mitigare cambi di filtro troppo repentini. In pratica cxrest_val indica per quanti frame il livello di filtro non può aumentare, per evitare che l'occhio noti il peggioramento dell'immagine. Invece l'applicazione di filtri via via più fini non viene limitata.

GUI

Innanzitutto l'interfaccia visuale riporta tutti i parametri necessari all'elaborazione descritti sopra, poi visualizza informazioni più precise sulla distribuzione e relativa assegnazione dei frame, e infine prevede la possibilità di eseguire una serie di operazioni.

Screenshot thumbnail
QMtrim prototype

Viene mostrato il nome dello statfile, seguito dai pulsanti per aprire un altro file e per ricaricare il file nel caso fosse stato modificato (QMtrim evita di rileggere il file ad ogni generazione di trim, è quindi necessario ricaricarlo esplicitamente).
Seguono i parametri unsaw, cxrest e l'indicazione se si sta fornendo un elenco di soglie (thresholds) o di quote.

La tabella della distribuzione è del tutto simile a quella che veniva mostrata a linea di comando nelle versioni precedenti di QMtrim. Si possono aggiungere/togliere livelli, preparare una distribuzione piatta con un numero di livelli a scelta (opzione -f o --flat-distrib) o eseguire la ridistribuzione delle quote con un algoritmo automatico(*).
In tabella sono disponibili le seguenti informazioni:

  • Cx, il numero del livello (al livello n corrisponde la sezione Cn della sequenza dei trim);
  • Weight, il valore di riferimento per il livello (quota o soglia);
  • Frames, il numero di frame effettivamente assegnato al livello; anche se si imposta una distribuzione piatta, non è detto che il numero di frame sia prevedibile perché i parametri unsaw, cxrest e l'eliminazione dei picchi produrranno alla fine uno sbilanciamento dei livelli;
  • Quote, la percentuale di frame assegnate al livello;
  • Threshold, la soglia che è stata usata per fare la suddivisione dei livelli; permette di conoscere la soglia utilizzata da QMtrim per suddividere i livelli allo scopo di ottenere le quote richieste;
  • Density, la percentuale di frame rapportata alla frazione di valori di movimento del livello; questo valore misura l'affollamento dei frame in ciascun livello e permette di farsi un'idea di quanto è lento o veloce un video; il valore è più significativo con valori nulli di unsaw_val e cxrest_val.

Sotto la distribuzione sono presenti i pulsanti che permettono di copiare il contenuto della tabella in serie di valori separati dal carattere di tabulazione, il pulsante che copia nella clipboard la linea di comando da eseguire per ripartire dalla stessa distribuzione e il pulsante per generare la stringa di trim.
Segue la stringa di trim generata e i campi per salvare il risultato: nome del trimfile, pulsante per scegliere il trimfile e pulsante di salvataggio.

La barra di stato in fondo alla finestra fornisce informazioni sull'esecuzione, indica i dati mancanti per poter valutare il trim e da suggerimenti sulle funzioni della maschera.

(*) La ridistribuzione automatica delle quote permette di ottenere una distribuzione migliore dei livelli e si opera in questo modo:

  1. si impostano i parametri per usare una distribuzione piatta col numero di livelli desiderato;
  2. (la generazione della sequenza di trim viene eseguita automaticamente;)
  3. si usa il pulsante "Auto-redistribute quotes" che copia le soglie calcolate nella colonna "Weight" per usarle a loro volta come quote;
  4. (la generazione della sequenza di trim viene eseguita automaticamente;)
  5. si procede a raffinare tipicamente il primo e ultimo livello che tendono a rimanere comunque poco bilanciati.
Passo 3: lo script finale

La sequenza di trim ha una forma del tipo:

C0.Trim(0,10)+C1.Trim(11,16)+C2.Trim(17,23)\
+C3.Trim(24,29)+C4.Trim(30,32)+C3.Trim(33,33)\
+C4.Trim(34,39)+C5.Trim(40,45)+C6.Trim(46,49)


Perché sia possibile utilizzarla devono essere stati definiti in precedenza i filtri per ciascun livello e il risultato deve essere chiamato con un nome nella forma Cn, dove n è il numero del livello. La sequenza di trim generata da QMtrim può essere inserita manualmente nello script copiandola dalla casella di testo o più semplicemente includendo nello script il trimfile salvato. Un esempio che riporti i filtri e l'uso della sequenza di trim è il seguente:

# filtri
C0 = clip.Spline36Resize(XRES,YRES,X0,Y0,X1,Y1)
C1 = clip.Spline16Resize(XRES,YRES,X0,Y0,X1,Y1)
C2 = clip.GaussResize(XRES,YRES,X0,Y0,X1,Y1,p=80)
C3 = clip.GaussResize(XRES,YRES,X0,Y0,X1,Y1,p=70)
C4 = clip.GaussResize(XRES,YRES,X0,Y0,X1,Y1,p=60)
C5 = clip.GaussResize(XRES,YRES,X0,Y0,X1,Y1,p=50)
C6 = clip.GaussResize(XRES,YRES,X0,Y0,X1,Y1,p=40)
C7 = clip.GaussResize(XRES,YRES,X0,Y0,X1,Y1,p=30)
C8 = clip.GaussResize(XRES,YRES,X0,Y0,X1,Y1,p=20)
C9 = clip.GaussResize(XRES,YRES,X0,Y0,X1,Y1,p=10)

# trim generato da QMtrim
Import("C:\qmtrim\QMtrim\trim.avsi")


È tutto!

Supporto

Su SourceForge sono disponibili:

  • il servizio di ticketing per notificare i bug, cercando di descrivere ed allegare tutto ciò che pensate possa servire per riprodurli (ad esempio: lo statfile);
  • questa wiki come manuale di riferimento utente;
  • il forum per le richieste di aiuto, per raccontare la vostra esperienza e discutere di nuove funzionalità.

Prossimi sviluppi

L'obiettivo del prototipo (0.7.7) era di aggiungere una GUI al programma originale e correggere eventuali problemi senza troppa cura di come è stato sviluppato il codice.

La prossima versione (0.8) sarà una vera beta da cui partire.
Al momento sto riscrivendo tutto per avere:
- una GUI standard;
- tutte le funzioni della v0.7.7;
- (se possibile) rilasciare una versione GNU/Linux.

Successivamente (non è una promessa!) si potranno aggiungere alcune di queste funzionalità:
- internazionalizzazione;
- supporto per elaborare parti diverse di video con distribuzioni differenti (incluso l'uso di un filtro statico);
- salvare/ricaricare la configurazione;
- help/documentazione;
- suggerimenti per guidare l'utente alle prime armi.

--KICKAHA


Related

Wiki: Home_en
Wiki: Home_it