English version / Versione italiana
Benvenuti nella wiki di QMtrim!
(Questa documentazione è un libero adattamento della guida originale in italiano di HoHoHo. --KICKAHA)
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:
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.
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.
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.
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:
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:
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().
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:
I parametri sono:
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.
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.
Questa è la lista dei parametri da linea di comando:
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.
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.
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:
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:
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!
Su SourceForge sono disponibili:
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