Recensubs HQ

Dr. StrangeAVS, Or: How I Learned to Stop Cropping and Love De Bilinear-ehr-The Bomb, COMING BACK TO YOU, CHIBI

« Older   Newer »
  Share  
view post Posted on 25/5/2013, 21:46     +1   +1   -1
Avatar

Bimbosp

Group:
Administrator
Posts:
9,780
Reputation:
+929
Location:
Gallarate (VA)

Status:


Nota iniziale: visto che non ho in mente di scrivere altre guide per un bel po', mi dilungherò inutilmente in paragrafi che potreste saltare a piè pari.

Ok, allora, partiamo dal presupposto che debilinear è più figo di invks perché è l'inversa precisa dell'upscale bilineare e quindi il risultato finale sarà più preciso, nitido e dettagliato.
Partiamo anche dal presupposto che se croppiamo dobbiamo dire addio o a debilinear o alla risoluzione "precisa", ché, mettiamo caso la sorgente sia 720p in origine, se dovessimo croppare e usare debilinear, portando a 720 non sarebbe l'inversa precisa per cui scaga, oppure ci dobbiamo accontentare di roba come 1276x716 o giù di lì, che mette un po' di tristezza.

Partiamo dal presupposto che, ammesso e non concesso che non abbiamo righe intere di pixel neri puri (ma anche lì a volte si potrebbe avere culo, poi ne parliamo), ma soltanto pixel c.d. "morti", sarebbe bello riportarli al loro aspetto originale e quindi poter usare debilinear per riportare a 720 (risoluzione ipotetica) senza croppare (parliamo comunque di pixel schiariti/scuriti, non vero e proprio luma junk stile VHS, eh).

Bene, è con questi presupposti che (non) mi sono trattenuto dall'inveire agli autori di JinTai e scrissi, ormai nel lontano settembre 2012, una prima, embrionale, versione di edgefix.
Il ragionamento c'era e le basi anche, ma era scomodo da usare. Così, qualche mese più tardi, decisi di provare ad apportare qualche modifica al funzionamento, nonché varie migliore ai lut, che hanno portato quindi dapprima a edgefix2 fino ad arrivare, un paio di mesi più avanti, a edgepp nonché alla revisione finale di edgefix2, nonstante lo scopo non fosse ancora raggiunto.

Fortunatamente, nei giorni in cui stavo apportando le ultime modifiche a edgefix2, i "nomi grossi" di darkhold (leggi: prunedtree, e twc per i port avs poi) hanno notato l'effettiva applicabilità del ragionamento e deciso di scrivere una dll vera e propria un po' più umanamente utilizzabile, ovvero una versione del filtro in grado di calcolare automaticamente e autonomamente il valore di threshold necessario per aggiustare un particolare frame.
In questo modo, al posto di dover lavorare a sezioni come con edgefix2, sarebbe bastato mettere il filtro e laversene le mani.
Restava, però, il problema di sorgenti in cui questo valore cambia in base alla zona dell'immagine, cosa che costringeva a svariati mask manuali con edgefix2. Fortunatamente in poche ore anche questo problema è stato risolto, per cui la versione di edgefixer era pronta.
Tuttavia ancora c'era un problema sostanziale in questa versione: lavora solo sul singolo pixel di bordo, quindi 1 per lato e basta.
Ciò ovviamente non è la soluzione ideale se il problema è il secondo pixel o se, come in alcuni casi, ci sono svariate righe problematiche.
Per aggirare questo problema, due approcci diversi sono stati scritti, sempre da prunedtree, e sempre con relativo port avs di thewebchat: continuityfixer e referencefixer.
Purtroppo questi due filtri hanno dei piccoli problemi, ma mi sono adoperato per arginarli, per cui restate sintonizzati.

Prima di spiegare il funzionamento dei tre filtri, vi faccio, giustamente, dono delle dll:
Download EdgeFixer, ContinuityFixer e ReferenceFixer

Ok.
Anzitutto spieghiamo il funzionamento dei filtri di per sé.
Partiamo dal più semplice
CODICE
edgefixer(clip, int "radius")

Il clip è il classico last che si tende a passare implicitamente salvo particolari necessità.
Il radius è la dimensione dell'area da tenere in conto per calcolare l'OLS (se ho capito come funziona edgefixer, onestamente è roba fuori dalla mia portata, fuck math) ─ di default usa il lato più corto come radius (quindi, generalmente, l'altezza), specificando valori alti avrete una compensazione con uno stesso valore stabile, ma in caso di aree piccole che necessitano di compensazioni diverse, probabilmente avreste il valore errato, viceverse, specificare valori bassi consente di avere una maggiore flessibilità di compensazione anche per le aree più piccole, ma diventa progressivamente meno preciso, fino a limitarsi a essere una semplice duplicazione di pixel col radius minimo. Valori indicativi di radius che possono tornare utili tendono a variare tra i 15 e 50, ma suggerisco di controllare sempre sorgente perché può dipendere molto da cosa avete per mano.

Come già detto, edgefixer è in grado di aggiustare solo le sorgenti con un singolo pixel problematico al bordo. Forse vi sembrerà idiota preoccuparsi in questi casi e volendo si potrebbe far finta di nulla e tenere il pixel leggermente più scuro, ma in caso di cross conversion, con debilinear, l'errore viene propagato per alcuni pixel: le scene cross convertite, dopo essere state aggiustate portandole a 720 con field shift, arrivano ad avere minimo 4-5 pixel di propagazione di quell'unico pixel a 1080, sia in alto, sia in basso, per qui sostanzialmente potreste ritrovarvi con una dozzina di pixel totali da dover croppare in verticale.

Sempre come anticipato, non contento di questo limite, prunedtree ha usato altri due approcci (che purtroppo non ho capito con precisione come funzionano dal punto di vista teorico, per cui non so dirvi altro).

Il primo dei due è continuityfixer:
CODICE
continuityfixer(clip, int "left", int "top", int "right", int "bottom", int "radius")

Stesso discorso di edgefixer per quanto riguarda clip e radius, mentre left, top, right e bottom, come potete intuire, sono la quantità di pixel problematici ad ogni rispettivo bordo. Non è come crop, quindi right e bottom vogliono valori positivi, non negativi.

Di per sé continuity fixer applica un'offset riga per riga/colonna per colonna. Questo comporta due cose:
1) se ci sono pixel neri puri o junk, ammesso che non siano troppi, è possibile che riesca a interpolare il bordo (i risultati non sono perfetti, ma in alcuni casi sono sufficientemente buoni da passare inosservati in playback o comunque accettabili se si tratta di piccole necessità in singole scene).
2) a volte, se ci sono piccoli dettagli ai bordi di colori visibilmente diversi rispetto a ciò che li circonda, è possibile che il chroma venga sovrascritto con il valore che continuity fixer ritenga corretto.
3) valori left/top/right/bottom elevati possono causare (e quasi sicuramente causeranno) uno scurimento o schiarimento progressivo dei bordi, con una sorta di effetto vignettatura. I valori elevati possono anche banalmente essere qualcosa più alto di 3 o 4 pixel, in realtà, dipende sempre da sorgente e scena specifica.

Insomma, è utile in determinate circostanze, in cui i valori ai bordi sembrano riparabili ma variano pesantemente tra loro per i motivi più disparati o che, ma prestate attenzione alle controindicazioni.

L'ultimo filtro che rimane da analizzare è referencefixer:
CODICE
referencefixer(clip, clip, int "left", int "top", int "right", int "bottom", int "radius")

Non è un typo, ci sono due clip. Il primo clip e gli altri valori già intuite cosa sono e come funzionano se non avete saltato nulla finora, quindi cosa sarà mai il secondo clip? È un clip blurrato.
Idealmente dovreste fare un blur gaussiano, sostanzialmente un blur(1.0) di avisynth è più che sufficiente a svolgere il ruolo che il clip che viene usato come riferimento ha.
L'idea è che in questo clip sfocato si è andata ad attenuare la differenza che risalta tra righe di pixel con sbalzi luma/chroma diversi, per cui è possibile ricavare grazie ad esso il valore che serve per compensare il pixel.
Vale quindi sempre il discorso che radius bassi portano progressivamente a risultati paragonati alla semplice duplicazione di pixel, ma nel caso di referencefixer i risultati possono essere anche più strani attorno ai bordi. Valori elevati, invece, causano spesso e volentieri schiarimenti o scurimenti nelle aree con colori piani, e continua a valore il discorso che left/top/right/bottom introducono un effetto simil-vignettatura, anche se generalmente a valori più elevati di quelli di continuityfixer.

Anche qui, con le dovute precauzioni è possibile che si riescano ad ottenere i risultati sperati.

E ora la parte veramente interessante della guida.

"Ma essepi, se io sono uno sfigato cronico, chiamato Maddo, a cui capitano tutte le sfighe del mondo quando si tratta di encode, e devo fare una sorgente con molti pixel (una decina, o forse più!) da aggiustare, la prendo dove ci teniamo la paglia di solito?"

Silly Maddo, ovvio che no!

Ci penso io a venire in tuo soccorso!
...Ma solo perché mi sono ritrovato pure io in questa situazione, altrimenti zero sbatta.

Il caso in esame è Nozoki Ana, per cui roba leggermente NSFW ─ chiedo scusa ma non ho trovato buoni esempi nelle scene 100% safe, sono comunque immagini PG-13 (immagini già downscalate a 720p con debilinear per comodità di visualizzazione):

2700srcqqbr5

Come vedete, ci sono svariati pixel da dover aggiustare in tutte e quattro le dimensioni. La quantità varia leggermente in alcune scene, ma il massimo di cui si può avere bisogno in tutto l'anime (da quanto ho potuto constatare nella sezione che ho fatto finora) è di circa 8 da sinistra, 6 dall'altro, 10 da destra e 6 dal basso.
Essendo valori elevati, sappiamo che continuityfixer è fuori discussione, in quanto c'è troppo rischio che dei dettagli ai bordi vengano sovrascritti, per cui dobbiamo necessariamente usare referencefixer, che come continuityfixer ha comunque il problema del pseudo-vignetting quando si comincia ad andare verso i 10 pixel per lato.
Facciamo comunque un tentativo:

CODICE
referencefixer(blur(1.0),8,6,10,6)

2700referenceryuss

Non male, ma notiamo che in alto e a destra ci sono dei veri e propri problemi residui. Proviamo a modificare il radius per risolvere:

CODICE
referencefixer(blur(1.0),8,6,10,6,15)

2700referenceradiusb5kyq

Ouch. Anche peggio, e il problema persiste. Dietrofront. Visto che si tratta solo di due pixel, potremmo affidarci a continuityfixer a questo punto:

CODICE
referencefixer(blur(1.0),8,6,10,6)
continuityfixer(2,2,2,2)

2700referencecontinuieulht

Pare andare. Sarà così su tutti i frame?

1218referencecontinuiusk3j

Ahia. Sulla destra. No, quello in alto è lo sfondo. Ma vedete quella riga bianca? È *introdotta* da referencefixer.

Non starò a tediarvi oltre con i ragionamenti e i tentativi che ho fatto, mi limiterò a darvi la funzione completa (warning: è lunga in orizzontale, parte lo stretch del post):

CODICE
function averagefixer(clip c, clip blurred, int "rleft", int "rtop", int "rright", int "rbottom", int "rradiusp", int "rradiuse", int "thr", int "cleft", int "ctop", int "cright", int "cbottom", int "cradius") {
rleft = default(rleft+2,6)
rtop = default(rtop+2,6)
rright = default(rright+2,6)
rbottom = default(rbottom+2,6)
rradiusp = default(rradiusp,5)
rradiuse = default(rradiuse,50)
thr = default(thr,1)
cleft = default(cleft,2)
ctop = default(ctop,2)
cright = default(cright,2)
cbottom = default(cbottom,2)
cradius = default(cradius,25)
c.addborders(2,2,2,2).fillmargins(2,2,2,2)
blurred = blurred.addborders(2,2,2,2).fillmargins(2,2,2,2)
mt_merge(mt_average(referencefixer(blurred,rleft,rtop,rright,rbottom,rradiusp),mt_invert().referencefixer(blurred.mt_invert(),rleft,rtop,rright,rbottom,rradiusp).mt_invert()),mt_average(referencefixer(blurred,rleft,rtop,rright,rbottom,rradiuse),mt_invert().referencefixer(blurred.mt_invert(),rleft,rtop,rright,rbottom,rradiuse).mt_invert()),tedgemask(threshy=thr).mt_inflate())
crop(2,2,-2,-2)
return mt_average(continuityfixer(cleft,ctop,cright,cbottom,cradius),mt_invert().continuityfixer(cleft,ctop,cright,cbottom,cradius).mt_invert())
}


Senza stare troppo a pensare ai parametri (i default sono semi-ragionati):
CODICE
averagefixer(blur(1.0),8,8,10,6)


2700averagefixerzuktq
1218averagefixerzdkuv

Deal? Deal.

I parametri che iniziano per r sono quelli di referencefixer, quelli che iniziano per c sono quelli di continuityfixer. Di valori "nuovi" ci sono rradiusp, che è il radius per le zone non di bordo, rradiuse, radius delle zone bordo, e thr, che serve a decidere cosa è bordo e cosa no. Sono i tre parametri "fondamentali" con cui probabilmente vi troverete a giocare in base alla sorgente. Forse vi ritroverete ancora a dover aggiustare in base alla scena, ma idealmente dovrebbe essere un'occorrenza molto più rara.

Ok, ora sono a pari con Chibi, per cui mi rimetto la paglia nel culo.

PS: In realtà ho barato perché Nozoki Ana non necessitava di un trattamento speciale di questo tipo, ma volevo scrivere un filtro per casi disperati.

Edited by mirkosp - 29/1/2016, 10:04
 
Web  Top
CRC32
view post Posted on 26/5/2013, 12:31     +1   -1




Complimenti per lo screen
 
Top
view post Posted on 26/5/2013, 12:42     +1   -1
Avatar

Bimbosp

Group:
Administrator
Posts:
9,780
Reputation:
+929
Location:
Gallarate (VA)

Status:


CITAZIONE (CRC32 @ 26/5/2013, 13:31) 
Complimenti per lo screen

Pensa che gli esempi migliori erano nelle scene strettamente R Rated... rotfl.

Sostanzialmente Nozoki Ana ha confermato l'assioma secondo cui più perverso è un anime, peggio è preso (infatti gli hentai veri e propri tendono ad essere le cose conciate peggio).
 
Web  Top
CRC32
view post Posted on 30/5/2013, 22:30     +1   -1




Quegli screen significano anche che stai preparando la versione BD di Nozoki Ana?
 
Top
view post Posted on 30/5/2013, 22:43     +1   -1
Avatar

Bimbosp

Group:
Administrator
Posts:
9,780
Reputation:
+929
Location:
Gallarate (VA)

Status:


Sì. Adesso sono in "pausa" perché non è l'unico encode a cui sto "lavorando" e ci sono una dozzina di minuti aggiuntivi da tradurre e typesettare in qualsiasi caso rispetto alla versione DVD.
 
Web  Top
view post Posted on 20/6/2013, 15:40     +1   -1
Avatar

Bimbosp

Group:
Administrator
Posts:
9,780
Reputation:
+929
Location:
Gallarate (VA)

Status:


Ok, andando avanti con Nozoki Ana mi sono reso conto che era un caso più disperato di quello che pensavo visto che mi costringe a beccarmi tutti i lati negativi di referencefixer.
Tuttavia, ho trovato una nuova soluzione.
Sostanzialmente, come sapete, referencefixer schiarisce/scurisce a caso alcune linee in base al contrasto dei bordi presenti. Questo comportamento è sempre presente ad ogni chiamata del filtro e, pertanto, chiamandolo più volte, viene accentuato.
Per questo motivo è possibile ripararlo in questa maniera:
CODICE
averagefixer(*parametri*)
mt_adddiff(mt_makediff(last,averagefixer(*parametri*)))

I parametri da usare devono essere ovviamente identici. Riapplicando la differenza che viene creata dopo aver fatto il primo aggiustamento, sostanzialmente togliamo l'errore che viene introdotto da edgefixer senza però andare ad intaccare le modifiche originali, visto che il confronto avviene con la sorgente già modificata.

Alcuni prima e dopo, sempre da nozoki ana (i prima usano solo averagefixer ed edgepp, i dopo anche la differenza):
CODICE
averagefixer(minblur(1),8,8,10,6,100,270,10)
mt_adddiff(mt_makediff(last,averagefixer(minblur(1),8,8,10,6,100,270,10)))
edgepp(1,8,8,-10,-6)


Sorgente: http://abload.de/img/ova001218srcsqp9g.png
Prima: http://abload.de/img/ova001218prima1vojz.png
Dopo: http://abload.de/img/ova001218dopo7fq1l.png

Sorgente: http://abload.de/img/ova027704srcaoqx0.png
Prima: http://abload.de/img/ova027704primaylqfy.png
Dopo: http://abload.de/img/ova027704dopoonrqt.png

Chiaramente il miglioramento è visibile, per quanto non sia perfetto. Più avanti valuterò di fare ulteriori prove per vedere se riesco a perfezionare.
 
Web  Top
view post Posted on 6/10/2013, 17:21     +1   -1
Avatar

Snobbery Inside

Group:
Utente abilitato
Posts:
2,197
Reputation:
+1,005
Location:
Favolandia

Status:


Preso da 5 minuti di scazzo ho scritto una funzioncina che forse potrebbe essere utile per fixare qualche bordo.
L'idea è quella di usare nnedi3 per interpolare i pixel rovinati/mancanti.

CODICE
function FixTopPx(clip c, int pixel)
{
clp=c.crop(0,pixel,0,32)
fixed = clp.nnedi3(field=1, dh=true).Spline36Resize(clp.width(),clp.height()).nnedi3(field=1, dh=true).Spline36Resize(clp.width(),clp.height()).nnedi3(field=1, dh=true).Spline36Resize(clp.width(),clp.height()).nnedi3(field=1, dh=true).Spline36Resize(clp.width(),clp.height())
return pixel > 2 ? FixTopPx(Stackvertical(fixed.crop(0,0,0,2).AddBorders(0, pixel -2, 0, 0, color=$000000), c.crop(0,pixel,0,0)),pixel -2) : Stackvertical(fixed.crop(0,0,0,2), c.crop(0,2,0,0))
}


nota 1: il valore pixel deve essere multiplo di 2
nota 2: interpola sempre e soli i pixel "top", per usarla su 4 pixel a sinistra e destra bisogna chiamare, per esempio, TurnRight().FixTopPx(4).TurnLeft().TurnLeft().FixTopPx(4).TurnRight()
nota 3: la funziona ha senso se i pixel di lato sono messi molto male (se c'è solo una differenza di luma è meglio usare altro, ovviamente)
nota 4: potrebbe più che altro essere interessante per cercare di "recuperare" il chroma e la saturazione, che in generale i vari filtri di continuity non fanno
 
Web  Top
view post Posted on 6/10/2013, 17:25     +1   -1
Avatar

Bimbosp

Group:
Administrator
Posts:
9,780
Reputation:
+929
Location:
Gallarate (VA)

Status:


Per chroma/saturazione si risolve usando continuity in ytouv, però per i pixel neri puri o ci si mette con l'inpaint (ed esce male, provato), o ci si limita a fillmargins (meh ma ok per 1-2 pixel), oppure sì, fixtoppx dovrebbe andar bene.
 
Web  Top
CRC32
view post Posted on 19/10/2013, 21:34     +1   -1




Grazie della rella, devo dire che questo OVA mi è piaciuto molto.
Sono previsti altri episodi in futuro?

Comunque inizio a pensare che la Cumpa dovrebbe dedicarsi più spesso agli hentai...
 
Top
Byakko
view post Posted on 31/3/2015, 23:19     +1   -1




[00:15:00] mirkosp: HO CROPPATO
[00:15:03] mirkosp: E NON HO COMPENSATO L'AR
[00:15:16] mirkosp: TUTTA LA VOSTRA VITA È UNA MENZOGNA

TL;DR prendete le sue guide e buttatele nel cesso.
 
Top
9 replies since 25/5/2013, 21:46   1882 views
  Share