Ultimamente Chibi sta facendo troppe guide, con quella di ieri ne ha di fatto il doppio delle mie in questa sezione, quindi mi pareva il caso di togliermi un po' di paglia dal culo [cit.] e portarmi alla pari con lui.
Pensando a guide potenzialmente utili su argomenti non troppo noti, come prima cosa mi è venuta in mente la Cross Conversion, visto che negli ultimi tempi ci ho avuto a che fare anche più del dovuto.
Nota iniziale: data la necessità di mantenere le immagini alla loro risoluzione ottimale e in png, sono tutte presentate come thumbnail nella guida.
La Cross Conversion, visivamente, si presenta come una sorta di ibrido tra interlacciamento e aliasing. Anche a occhi inesperti è palese che qualcosa sia fuori posto.
Esempio:
Sostanzialmente, viene introdotta quando c'è una necessità di upscalare l'immagine originale, ma, al posto di upscalare in progressivo (vuoi per contenuto interlacciato o comunque per incompetenza/distrazione/malafede di chi ci ha lavorato) l'immagine viene upscalata separatamente per i semicampi.
Questo comporta uno scompenso verticale durante il resize che quindi introduce l'artefatto che potete notare nell'immagine poco più sopra.
Uno potrebbe anche fregarsene e limitarsi a fare debilinear alla risoluzione originale, ma fidatevi che i risultati non sono il massimo della vita...
Posto quindi che una merda del genere è meglio risolverla, e ammesso che il buontempone che ha upscalato alla canis mentula non abbia avuto la brillante idea di postprocessare l'immagine in qualche maniera dopo l'upscale, e che quindi i semicampi siano ben distinti tra loro, è possibile ripristinare l'aspetto originale dell'immagine.
La prima e più importante cosa da fare è accertarsi della risoluzione originale dell'immagine. Potete tirare a indovinare, tanto tendenzialmente avrete per le mani contenuti upscalati da 720 a 1080, per cui potreste affidarvi a
CCC(), che non starò qui ad analizzare, perché questa è una guida che affronta il problema più in completezza e non solo un suo sottoinsieme.
È infatti possibile che la risoluzione originale non fosse 720 e, quindi, oltre a dover capire cosa fosse (480, 486, 540, 576, 810... di possibilità ce ne sono varie), dovete andare a correggerla manualmente, perché ccc() riesce a correggere solo il 720, e può comunque non essere la soluzione perfetta anche in quel caso.
Se avete occhio o intuito, potete semplicemente tirare a indovinare, ma, nei casi più complessi o se proprio non sapete neanche da dove cominciare, la cosa migliore è sfruttare
Shrinker.
Questo programmino, scritto da prunedtree, utilizza il codice originale di debilinear e analizza il risultato a varie risoluzioni per cercare di stabilire quale sia la risoluzione originale del fotogramma che gli date in pasto (nota: dovete fornirgli sempre un'immagine in formato BMP, non funziona con altri formati).
In genere, però, non è molto preciso, ma con la cross conversion c'è la grande eccezione, essendo upscalato in base ai field, c'è molto aliasing e, fornendo a shrinker un'immagine
di un singolo field anziché dell'immagine intera, riuscirà quindi a dirvi la risoluzione verticale originale con precisione quasi assoluta.
Prendendo quindi in esame l'immagine poco più sopra, in avisynth possiamo fare:
CODICE
separatefields()
selecteven()
E successivamente, da AvsPmod,"Video" -> "Save image as...", scegliendo come formato il BMP. Di seguito vi fornisco una PNG del risultato di ciò:
A questo punto, ora che abbiamo la nostra BMP del singolo field, ci basta semplicemente trascinarla su shrinker.exe. Si aprirà un cmd di windows. Quando shrinker avrà finito vi comunicherà il risultato che ha ottenuto e vi fornirà anche una bmp di output:
L'immagine di output potete bellamente ignorarla, anche perché, essendo shrinker basato su una versione iniziale di debilinear, ci sono ancora molti dei bug che in debilinear sono stati aggiustati solo dopo il port in avisynth, ma comunque vi può dare un'idea se ci ha effettivamente preso o no (se non ci sono scagate di ringing visibili vuol dire che probabilmente ci ha preso).
Come vedete, in questo caso ci dice che la risoluzione del singolo field è 1280x360. Ciò significa che, mettendo assieme i due field una volta ripristinati, otterremo 1280x720.
Ma forse potremmo non ottenere i risultati sperati, vediamo assieme.
Di base, per risolvere la cross conversion, il procedimento è il seguente:
- separare i field
- downscalarli
- rimetterli assieme
Che in codice avisynth si traduce in:
CODICE
separatefields()
even = selecteven().debilinear(1280,360)
odd = selectodd().debilinear(1280,360)
interleave(even,odd)
weave()
Riprendendo ancora una volta lo screen in esame dall'inizio, il risultato, facendo questo, è il seguente:
Già meglio del risultato originale fregandosene di tutto, ma gli occhi più esperti avranno notato che c'è comunque un po' di aliasing residuo. Ciò è dovuto al fatto che può capitare (non sempre e non saprei dire con che frequenza) che l'upscale field-based sia fatto dando anche uno shift in verticale separato per i due field.
Per ripristinare l'immagine, quindi, potremmo aver bisogno di applicare uno shift ad entrambi i field, in modo tale che, una volta riportati alla risoluzione originale, combacino alla perfezione.
Purtroppo, però, non c'è un metodo automatico per trovare questi valori e variano anche molto di sorgente in sorgente.
Dovrete quindi andare a tentativi fino a che il risultato non vi soddisfi. Nel caso in esame, è possibile risolvere coi valori che seguono:
CODICE
separatefields()
even = selecteven().debilinear(1280,360,src_top=-0.19,src_height=540-0.19)
odd = selectodd().debilinear(1280,360,src_top=+0.19,src_height=540+0.19)
interleave(even,odd)
weave()
Che danno il seguente risultato:
Tenete presente che tutti i codici di cui sopra sono ridotti ai minimi termini per questione di chiarezza esemplificativa. Nella pratica, per ottenere i risultati migliori, ci sono altri piccoli fattori di cui tenere conto.
Anzitutto, avendo a che fare con materiale con subsampling, e visto che ciò avviene dopo l'upscale, il chroma avrà subito un blend dopo la cross conversion. Ne consegue che il chroma è sostanzialmente "irreparabile", ma il blend ha già provveduto a nascondere il look aliasato per il chroma (e rimane il fatto che l'occhio umano non è in grado di percepire il chroma sufficientemente a dovere per notare questa differenza). Perciò, nei casi più comuni, avrete bisogno di correggere solo il luma.
Sempre connesso a questo c'è il fatto che restando a 4:2:0, se fate debilinear diretto sul chroma, avrete artefatti vari, che possono essere più o meno evidenti in base alla scena, visto che il dettaglio presente nel chroma è comunque più elevato della risoluzione a cui lo state portando.
Infine, è buona abitudine fare resize a 16bit per massimizzare la qualità e ridurre gli errori di arrotondamento di debilinear.
La differenza è spesso e volentieri minima, ma è bene dire tutto con precisione. Sempre con l'esempio più sopra, un esempio di codice che tiene conto di tutto questo e fa un resize a 4:4:4 sarebbe il seguente:
CODICE
dither_convert_8_to_16()
even = separatefields().selecteven().debilineary(1280,360,src_top=-0.19,src_height=540-0.19,lsb_inout=true)
odd = separatefields().selectodd().debilineary(1280,360,src_top=+0.19,src_height=540+0.19,lsb_inout=true)
ly = interleave(even,odd).weave()
lu = utoy().dither_resize16(1280,720,kernel="spline16",invks=true,invkstaps=6,src_left=0.25,u=1,v=1)
lv = vtoy().dither_resize16(1280,720,kernel="spline16",invks=true,invkstaps=6,src_left=0.25,u=1,v=1)
ytouv(lu,lv,ly)
INB4 fuck you and your 4:4:4.
Giusto per completezza porto esempi di metraggi con altre risoluzioni. In particolare, risoluzioni che originariamente non sono mod4 e, pertanto, richiedono di ripristinare field che hanno una risoluzione verticale dispari.
Come primo esempio extra vi porto Pokémon. Non sarei io se non riuscissi a infilare i Pokémon da qualche parte, no?
A occhio si nota che la cross conversion è meno palese che nello screen di Jintai che abbiamo analizzato finora.
Se proviamo a dare a shrinker un singolo field:
Scopriamo che infatti Pokémon è 810.
Ma visto che i singoli field sono quindi a 405, è necessario processare il luma separatamente dal chroma per poter utilizzare i numeri dispari. Soluzione semplice a 8bit:
CODICE
even = separatefields().selecteven()
even = mergergb(even,even,even,"RGB24").debilinear(1440,405)
odd = separatefields().selectodd()
odd = mergergb(odd,odd,odd,"RGB24").debilinear(1440,405)
luma = interleave(even,odd).weave().showred("yv12")
chroma = spline36resize(1440,810)
mergechroma(luma,chroma)
Notate il mergergb e lo showred. Questo è dovuto al fatto che debilinear (quantomeno per il momento) non supporta y8 o yv24 come colorspace, per cui per poter lavorare con risoluzioni dispari bisogna usare colorspace rgb. Sfruttando mergergb e showred (o showgreen o showblue, è indifferente) si aggira il problema della conversione di colorspace.
Altro esempio, questa volta da Agriculture Girls.
Con questo esempio notiamo che shrinker non è infallibile:
Se provate a fare un esperimento con la risoluzione suggerita, vedrete che i risultati sono disastrosi.
Nella realtà dei fatti, possiamo sicuramente notare che la cross conversion qui è parecchio evidente, molto più che da 720, quindi possiamo dedurre che originariamente la risoluzione fosse inferiore a 720. Non ci resta che tentare varie risoluzioni papabili, fino a trovare quella in cui tutto combacia alla perfezione (se la risoluzione è sbagliata il risultato sarà chiaramente sfasato in alcuni punti). Nel caso specifico la risoluzione è 486, quindi 243 per field:
CODICE
even = separatefields().selecteven()
even = mergergb(even,even,even,"RGB24").debilinear(864,243)
odd = separatefields().selectodd()
odd = mergergb(odd,odd,odd,"RGB24").debilinear(864,243)
luma = interleave(even,odd).weave().showred("yv12")
chroma = spline36resize(864,486)
mergechroma(luma,chroma)
Di sicuro combaciano, ma quei bordi sono mostruosi! Dobbiamo lavorare sullo shift...
CODICE
even = separatefields().selecteven()
even = mergergb(even,even,even,"RGB24").debilinear(864,243,src_top=0.25,src_height=540+1)
odd = separatefields().selectodd()
odd = mergergb(odd,odd,odd,"RGB24").debilinear(864,243,src_top=0.25,src_height=540+1)
luma = interleave(even,odd).weave().showred("yv12")
chroma = spline36resize(864,486)
mergechroma(luma,chroma)
Molto meglio.
Come avete visto con quest'ultimo esempio, non ci sono regole fisse né certezze quando si ha a che fare con la cross conversion. Shrinker si rivela spesso utile, ma può sbagliare. Ma soprattutto, quando il risultato non vi convince appieno, provate a shiftare un po' a caso fino a che il risultato non vi torna. Purtroppo non è possibile dare consigli più precisi di così, al riguardo.
Beh, spero che la guida sia stata utile. Divertitevi.
EDIT: Aggiustato lo shift di Jintai.
Edited by mirkosp - 8/5/2013, 22:25