| ||
Ormai è parecchio tempo che si parla di risoluzione e "risoluzione effettiva" per discriminare i magici upscale che ci ritroviamo su BD, .ts, release di FranceBB ecc ecc... dalla risoluzione "di partenza" sulla quale è stato fatto l'upscale. Fino a qualche tempo fa questa risoluzione di partenza era sempre 720p, quindi la questione si approcciava con "debilinear a 720p e gg", mentre adesso si hanno sempre più spesso casi di anime con una risoluzione >720p.
Volevo aprire questa discussione per approfondire proprio questo aspetto in quanto, almeno per quanto mi riguarda, ultimamente mi ci sono ritrovato molto spesso a combattere, e suppongo che lo stesso sia capitato anche ad altri. In particolare volevo prendere in considerazione questo aspetto per quanto riguarda i BD, visto che per release TV/Crunchy, imho, è un aspetto marginale. Di solito il primo passo che si segue consiste nell'andare su anibin per vedere qual è la risoluzione effettiva che viene riportata per l'anime che ci interessa. Sinceramente, ignoro quale black magic venga utilizzata, o se sono dati ufficiali/ufficiosi, fattostà che in un paio di circostanze ho constatato che ha toppato, quindi non mi fido. Considerando questo, ho cercato di ricavare un metodo più o meno "empirico" per trovare quale fosse la risoluzione di partenza, in quanto se si vuole utilizzare debilinear a 720p bisogna essere sicuri che la risoluzione di partenza sia 720p, mentre invece se si vuole rellare con risoluzioni improbabili, o si vuole effettuare un resize basato sul "MightyUpscale" proposto da chibi, è necessario conoscere questa risoluzione di partenza con precisione. Per farla breve, riporto il procedimento che ho applicato agli ultimi 2 BD che mi sono ritrovato ad encodare (Henneko e Shingeki no Kyojin) i quali, entrambi, hanno una risoluzione effettiva >720p. Lo scopo sarebbe quello di approfondire il discorso con gente che ne sa più di me, in modo da ottenere una linea guida precisa da seguire in queste circostanze. Iniziamo con un .avsi che mi sono preparato per questi casi: CODICE ### Kernel [int] ### ------------------ ### 1 = Bilinear (Default) ### 2 = Bicubic MitchellNetravali (b=0.3333 c=0.3333) ### 3 = Bicubic CatmullRom (b=0 c=0.5) ### ### Mode [int] ### ------------------ ### 1 = Stack (Default) ### 2 = Plus Only ### 3 = Minus Only ### ### PARNum [float] ### PARDen [float] ### ------------------ ### per .ts 1440x1080 si usa un PAR = 4/3, quindi PARNum = 4 e PARDen = 3 function ResFinder(clip clp, int Res, int "Kernel", int "Mode", float "PARNum", float "PARDen") { PARNum = Default(PARNum, 1) PARDen = Default(PARDen, 1) Kernel = default(Kernel, 1) Mode = default(Mode, 1) Assert (Res%2 == 0, "Res must be Mod2") Assert (!(Kernel > 3 || Kernel < 1), "Kernel must be 1, 2 or 3.") Assert (!(Mode > 3 || Mode < 1), "Mode must be 1, 2 or 3.") ResWidth = Round((Res*clp.Width()/clp.Height())*PARNum/PARDen) ResWidth = (ResWidth > clp.Width()) && (Res < clp.Height()) ? clp.Width() : ResWidth return ResWidth%2 == 0 ? clp.GenerateClip(Res, ResWidth, Kernel).GenerateReport(Res, ResWidth, 1) : clp.Mod2Function(Res, ResWidth , Mode, Kernel) function Mod2Function(clip clp, int Res, int ResWidth, int Mode, int Kernel){ ResRemaining = ResWidth%2 return Mode == 1 ? StackVertical(clp.GenerateClip(Res, ResWidth + ResRemaining, Kernel).GenerateReport(Res, ResWidth + ResRemaining, 2), clp.GenerateClip(Res, ResWidth - ResRemaining, Kernel).GenerateReport(Res, ResWidth - ResRemaining, 3)) : \ Mode == 2 ? clp.GenerateClip(Res, ResWidth + ResRemaining, Kernel).GenerateReport(Res, ResWidth + ResRemaining, 2) : \ clp.GenerateClip(Res, ResWidth - ResRemaining, Kernel).GenerateReport(Res, ResWidth - ResRemaining, 3) } function GenerateClip(clip clp, int Res, int ResWidth, int Kernel) { return Kernel == 1 ? mt_makediff(clp, clp.debilinear(ResWidth,Res).BilinearResize(clp.Width(),clp.Height()),u=1,v=1) : \ Kernel == 2 ? mt_makediff(clp, clp.debicubic(ResWidth,Res, b=0.3333, c=0.3333).BicubicResize(clp.Width(),clp.Height(), b=0.3333, c=0.3333),u=1,v=1) : \ mt_makediff(clp, clp.debicubic(ResWidth,Res, b=0, c=0.5).BicubicResize(clp.Width(),clp.Height(), b=0, c=0.5),u=1,v=1) } function GenerateReport(clip clp, int Res, int ResWidth, int Mode) { turnback = 1 clp.Removegrain(1,-1).mt_lut("x 128 - 0 > x " + string(turnback) + " - 128 > x " + string(turnback) + " - 128 ? x " + string(turnback) + " + 128 < x " + string(turnback) + " + 128 ? ?",u=1,v=1).Histogram("luma").Greyscale() Mode == 1 ? WriteFile(".\output.txt",""" "=;" """ , string(Res), """ ";" """, "AverageLuma()") : \ Mode == 2 ? WriteFile(".\output.txt",""" "+;" """ , string(Res), """ ";" """, "AverageLuma()") : \ WriteFile(".\output.txt",""" "-;" """ , string(Res), """ ";" """, "AverageLuma()") ScriptClip(" Subtitle( String(AverageLuma())) ") Mode == 2 ? Subtitle("Plus", align=8) : \ Mode == 3 ? Subtitle("Minus", align=8) : last return Subtitle(String(ResWidth), align=9) } } Niente di nuovo, va a fare debilinear(risoluzione effettiva presunta)->bilinear(risoluzione di partenza) e il risultato di questo lo va a "confrontare" con la clip di partenza tramite un makediff. In questo modo vengono evidenziate le differenze tra le due clip. Ovviamente nel processo viene considerato solo il luma, in quanto il kernel inversion sul chroma non verrebbe comunque effettuato. In ingresso viene richiesta solo l'altezza, in quanto la larghezza se la va a ricavare da solo. Quello che viene visualizzato quando si richiede la preview della clip è la differenza vista in precedenza, con in alto a sinistra il valor medio del luma, in alto al centro un "plus" o "minus" e in alto a destra la "Width" considerata per la risoluzione effettiva. Quando si ha plus vuol dire che la width è stata ricavata approssimando all'intero pari più vicino verso l'alto, quando si ha minus invece è stata utilizzato quello più vicino verso il basso, se non si ha nulla vuol dire che è mod2 (senza considerare le frazioni di pixel). Nel caso in cui si sta considerando una risoluzione la cui corrispondente width non è mod2, viene visualizzato uno stack verticale con sopra la plus e sotto la minus. Ho messo anche un ulteriore intero che può essere passato alla funzione (mode) se si vuole visualizzare solo il plus o solo il minus per una determinata risoluzione (mode=1 stack, mode=2 plus, mode=3 minus, default = stack). Oltre a questo andrà a generare un file .txt chiamato output con le varie entry costituite da (+ -> Plus, - -> Minus, = -> Mod2);Risoluzione;ValorMedioDelLuma. EDIT1: Aggiunta la possibilità di selezionare tra 3 diversi kernel, cioè Bilinear, Bicubic MitchellNetravali e Bicubic CatmullRom. Inoltre lavora anche con input che hanno AR diversi da 16/9 EDIT2: Grazie a Chibi per aver riscritto in maniera dignitosa lo script e aver inserito il lut. Per i dettagli sulle modifiche clicca qui EDIT3: Aggiunti PARNum e PARDen, per i dettagli clicca qui e qui (thx sp) A questo punto direi di passare proprio ad un approccio pratico, cioè a cosa ho fatto quando mi sono ritrovato, ad esempio, a dover encodare i BD di SnK. Per prima cosa sono andato a vedere se la risoluzione fosse o meno di 720p: CODICE DGSource("Shingeki no Kyojin BD - 10 Index.dgi") Trim(0,34693) ResFinder(720) Un po' di grain è normale che resti, visto che viene aggiunto sempre a 1080p. Ma quando nella preview si riescono a distinguere i volti e le artline sicuramente la risoluzione è sbagliata, quindi in questo caso è evidente che la risoluzione non è 720p. Ok, stiamo nella merda, cosa si può fare? Andiamo a vedere su anibin quale risoluzione riporta: vediamo allora a 824p cosa abbiamo: CODICE ResFinder(824) Dal risultato direi che ancora non ci siamo, le artline sono troppo visibili. C'è da dire che anibin spessissimo ci prende, e se non ci prende con ogni probabilità la risoluzione effettiva starà vicino al valore che riporta. Supponiamo di non cagarlo e andiamo a fare la preview spostandosi di 2 in 2 per la risoluzione. Il txt generato dallo script è formattato in modo che importare i dati in excel è una fesseria, quindi riporto il valor medio del luma ottenuto per ogni risoluzione: Il valore del luma è molto indicativo, infatti più sarà basso e più il frame sarà "spento". Il fatto che all'aumentare della risoluzione ci sia una diminuzione di questo valore è normale, in quanto ci si sta avvicinando sempre dippiù alla risoluzione di partenza. Quello che deve insospettire è quando questo andamento non viene rispettato, cioè se si hanno dei punti dove il valore decresce per poi ricrescere subito, come appunto accade in corrispondenza della risoluzione 858p con width approssimata per difetto, quindi 1524x858. Questo non vuole assolutamente dire che quella sia la risoluzione effettiva al 100%, ma quantomeno deve destare un sospetto. Per verificarlo andiamo a vedere cosa si ottiene con 1524x858 e con 860p: CODICE ResFinder(858, Mode=3) CODICE ResFinder(860) Ok, a questo punto è più di un sospetto. Infatti a 1524x858 resta solo il grain e le artline grossomodo scompaiono, mentre a 860p ricompaiono. Quindi, per essere sicuri di averci preso, va fatto un riscontro sulla clip effettiva: CODICE #Resize input=Last DebilinearY(1524, 858) #e DebilinearY(1528, 860) turnright() nnedi3(1, dh=true,U=false,V=false,nsize=0,nns=2) turnleft() nnedi3(1, dh=true,U=false,V=false,nsize=0,nns=2) big=last Dither_convert_8_to_16() Dither_resize16(1920,1080,kernel="bilinear", invks=true,y=3, u=1, v=1,src_left=-0.5,src_top=-0.5, src_width=big.width(), src_height=big.height(),invkstaps=5) Mergechroma(input.Dither_convert_8_to_16()) DitherPost() 858p Vs. 860p inb4: ma sono uguali!!11!1 Fissate il volto di Mikasa, compare merda random a palate. Avevo un altro screen dove Eren diventava praticamente un panda, ma non lo trovo. Con 1524x858 invece molto meglio, c'è giusto un po' di haloing. A questo punto si è più o meno sicuri che la risoluzione sia quella, quindi basta decidere il resize. O si usa quello visto sopra (che sarebbe il MightyUpscale), oppure anche con RHQ per fare downscale dopo nnedi si ottengono buoni risultati: CODICE input=Last DebilinearY(1524, 858) nnedi3_rpow2(2,cshift="bicubicresize") resamplehq(1920,1080,"YV12","TV.709","TV.709",true,0,0,0,0,"Bicubic",0.4,1.0) Mergechroma(input) invks Vs. RHQ È un po' più blurrato di quello che si ottiene con invks (MightyUpscale), ma allo stesso tempo invks produce più haloing, tende a sminchiare il grain e bloata il filesize di brutto (soprattutto a 1080p). Inoltre si possono anche avere delle sequenze con risoluzione effettiva diversa, ma sono piuttosto rare di solito (nelle prime puntate di SnK purtroppo ce ne stavano parecchie). Nel caso in cui la risoluzione cambia di continuo conviene lasciare a 1080p e levare il poco blur dovuto all'upscale con uno sharpner tweakkato dignitosamente. Ma di questo /cares al momento, l'unica cosa che mi interessava qua era discutere della ricerca della risoluzione effettiva. In particolare troverei molto utile se qualcuno avesse qualche suggerimento o qualcosa da aggiungere per esperienza personale o, ancora meglio, se qualcuno vede qualche minchiata scritta :E Edited by Liquid Dr4k3 - 23/12/2013, 17:15 |