Eyldebrandt Michel de Hurlevent | II - Avisynth
Voilà l'outil du délit.
A la fois complexe et surpuissant, destiné à l'origine à l'encodage vidéo, la puissance des PC modernes a permis au fil du temps de l'utiliser en temps réel, d'abord sur des sources DivX et DVD puis, depuis quelques années, sur des sources 720p, 1080p et Blu-ray.
A la question, que peut, concrètement, faire Avisynth, on répondra absolument tout. Seule la puissance du processeur limite ses fonctions.
Et sur ce plan, Avisynth est incroyablement gourmand.
Pour de la lecture en temps réel, sur des sources DivX, DVD, 720p, 1080p et Blu-ray (ou HD-DVD hein, ça marche aussi), et compte-tenu que nous utilisons madVR, il est inutile de s'encombrer avec des fonctions trop exotiques.
Nous n'utiliserons, dans tous les cas, que des fonctions de sharpen, de denoiser, et des algorithmes de redimensionnement. Pour ceux qui veulent expérimenter, ou juste s'amuser, je rajouterais un petit filtre de blur bien sympa, ainsi qu'un script d'ajout de grain.
Tout d'abord, veuillez télécharger ce dossier de plugins, déjà présent en début de tutoriel, et qui contient tout le nécessaire pour faire fonctionner tous les scripts et plugins que je vais vous proposer.
http://www.mediafire.com/?opkmequ1j758iy4
Sources Blu-ray et 1080p
J'ai longtemps été tenté de proposer 4 filtres, mais comme 3 d'entre eux reposent sur la même base, j'ai préféré proposer celui des 3 qui offrait le meilleur rapport qualité/puissance requise, à savoir LimitedSharpenFasterHC, une version dépoussiérée et plus rapide de LSF, par Emmanuel Piat.
Le 2e sharpener n'est autre que FineSharp, par didée, l'auteur de LimitedSharpen, Seesaw et tellement d'autres scripts géniaux, et dont je n'étais pas particulièrement fan avant de comprendre comment il fonctionnait (je lui reprochais un piqué trop appuyé, des arrières-plans déstructurés et un aliasing omniprésent), et qui est aujourd'hui, sans aucune espèce de contestation possible, le meilleur sharpen pour la haute définition.
LimitedSharpenFasterHC
Citation :
function LimitedSharpenFasterHC( clip clp, float "strength" )
{
ox = clp.width
oy = clp.height
strength = default( strength, 40 )
overshoot = 1
undershoot= 1
soft = 0
clp.isYV12() ? clp : clp.converttoyv12()
tmp = last
edge = mt_logic( tmp.mt_edge(thY1=0,thY2=255,"8 16 8 0 0 0 -8 -16 -8 4" )
\ ,tmp.mt_edge(thY1=0,thY2=255,"8 0 -8 16 0 -16 8 0 -8 4" )
\ ,"max" ) .mt_lut("x 128 / 0.86 ^ 255 *" ) #.levels(0,0.86,128,0,255,false)
tmpsoft = tmp.removegrain(11,-1)
dark_limit = tmp.mt_inpand()
bright_limit = tmp.mt_expand()
minmaxavg = mt_average(dark_limit, bright_limit)
Str=string(strength/100.0)
normsharp = mt_lutxy(tmp,minmaxavg,yexpr="x x y - "+Str+" * +" )
OS = string(overshoot)
US = string(undershoot)
mt_lutxy( bright_limit, normsharp, yexpr="y x "+OS+" + < y x y x - "+OS+" - 1 2 / ^ + "+OS+" + ?" )
mt_lutxy( dark_limit, last, yexpr="y x "+US+" - > y x x y - "+US+" - 1 2 / ^ - "+US+" - ?" )
mt_clamp(normsharp, bright_limit, dark_limit, overshoot, undershoot)
AMNT = string(soft)
AMNT2 = string(100-soft)
sharpdiff=mt_makediff(tmp,last)
sharpdiff2=mt_lutxy(sharpdiff,sharpdiff.removegrain(19,-1),
\ "x 128 - abs y 128 - abs > y "+AMNT+" * x "+AMNT2+" * + 100 / x ?" )
ex=blankclip(last,width=ox,height=oy,color=$FFFFFF).addborders(2,2,2,2).coloryuv(levels="TV->PC" )
\.removegrain(mode=19).mt_inpand().removegrain(mode=19).spline36resize(ox,oy,1.0,.0)
tmp = clp.spline36resize(ox,oy)
clp.isYV12() ? tmp.mergeluma(last) : tmp.mergeluma(last.converttoyuy2())
return last
}
|
Le call de base est celui-ci :
- LimitedSharpenFasterHC(strenght=23.5)
Ici, seule la fonction strength nous intéresse, et elle impacte uniquement la puissance du sharpening.
FineSharp
Citation :
function FineSharp(clip c, int "mode", float "sstr", float "cstr", float "xstr", float "lstr", float "pstr", float "ldmp" )
{
mode = default(mode, 1 ) # 1 to 3, weakest to strongest. When negative -1 to -3, a broader kernel for equalisation is used.
sstr = default(sstr, 2.0 ) # strength of sharpening, 0.0 up to ??
_cstr = spline(sstr, 0,0, 0.5,0.1, 1.0,0.6, 2.0,0.9, 2.5,1.00, 3.0,1.09, 3.5,1.15, 4.0,1.19, 8.0,1.249, 255.0,1.5)
_cstr = (mode>0) ? _cstr : pow(_cstr,1./1.25)
cstr = default(cstr, _cstr) # strength of equalisation, 0.0 to ? 2.0 ? (recomm. 0.5 to 1.25, default AUTO)
xstr = default(xstr, 0.19 ) # strength of XSharpen-style final sharpening, 0.0 to 1.0 (but, better don't go beyond 0.249 ...)
# Viscera parameters
lstr = default(lstr, 1.49 ) # modifier for non-linear sharpening
pstr = default(pstr, 1.272) # exponent for non-linear sharpening
ldmp = default(ldmp, sstr+0.1) # "low damp", to not overenhance very small differences (noise coming out of flat areas)
str1 = sstr
str2 = cstr
SSTR = string(sstr)
CSTR = string(cstr)
LSTR = string(lstr)
PSTR = string(pstr)
LDMP = string(ldmp)
rg=mode>0?11:20
b = (abs(mode)==1) ? c.removegrain(11,-1).removegrain(4,-1)
\ : (abs(mode)==2) ? c.removegrain(4,-1).removegrain(11,-1)
\ : (abs(mode)==3) ? c.removegrain(4,-1).removegrain(11,-1).removegrain(4,-1) : c
shrpD = mt_lutxy(c,b,"x y - abs "+LSTR+" / 1 "+PSTR+" / ^ "+SSTR+" * x y - x y - abs 0.001 + / * x y - 2 ^ x y - 2 ^ "+LDMP+" + / * 128 +" )
shrp = (str1<0.01) ? c : c.mt_adddiff(shrpD,U=2,V=2)
shrp = (str2<0.01) ? shrp : shrp.mt_makediff(shrpD.mt_lut("x 128 - "+CSTR+" * 128 +" ).removegrain(rg,-1),U=2,V=2)
shrp = (xstr<0.01) ? shrp
\ : mt_lutxy(shrp,shrp.removegrain(20,-1),"x x y - 9.9 * +",U=2,V=2).repair(shrp,12,0).mergeluma(shrp,1.0-xstr)
return(shrp)
}
|
La ligne FineSharp dans le call sera, de base, celle-ci :
Ici, sstr est la force du sharpen intelligent et xstr la force du sharpen dit final, qui agit sur toute la surface de l'image, notamment l'arrière-plan (et qui peut faire opérer la magie dans certains cas, mais aussi, et le plus souvent, créer les pires atrocités). Personnellement, je le désactive, mais vous pouvez l'activer si vous aimer. Maximum 0.2
D'autres options peuvent s'avérer intéressantes, comme le choix du mode, qui va de -3 à 3. Par défaut c'est le mode 1, et c'est très bien. Les modes négatifs sont, à mon goût, beaucoup trop "artificiels".
Le cstr aussi est intéressant, mais comme nous allons utiliser un denoiser indépendant, la fonction est inutile et il est donc préférable de le laisser en auto, ou de le désactiver.
Je n'ai pas terminé les tests sur les autres options, donc pour le moment, faisons comme si elles n'existaient pas, mais si vous vous sentez d'expérimenter, ma foi, ne vous privez pas
Comparaison
=> http://screenshotcomparison.com/comparison/153425 <=
LimitedSharpenFasterHC
FineSharp
Voici, dans un ordre de qualité et de gourmandise croissant, les 4 denoisers que je vous propose. 3 d'entre eux sont des plugins.
J'en ai viré plusieurs, SMDegrain, SMDegrainHD, RemoveGrainHD, pour cause de gourmandise exagérée, et d'une qualité moindre que le plugin de la vie
RemoveGrain
Un grand classique, utilisé plus ou moins directement par la plupart des sharpeners pour limiter l'aliasing et l'apparition du grain.
Il a l'avantage d'être extrêmement rapide, et assez efficace.
Son gros défaut est la perte de piqué très importante.
Les 2 calls qui vont bien :
- RemoveGrain(mode=1).RemoveGrain(mode=5).RemoveGrain(mode=22).RemoveGrain(mode=21)
- RemoveGrain(21,19,19).RemoveGrain(22)
Le 1er call est un poil moins rapide, mais un poil meilleur.
FluxSmoothT
Un Temporal Denoiser, qui agit essentiellement sur les pixels fluctuants (donc plus efficace sur le bruit que sur le grain). Une version Spatial est possible, mais inutile en HD.
Le dosage doit être bien mesuré, parce que le plugin peut-être extrêmement destructeur.
Le résultat est à la hauteur, mais le filtre est assez gourmand.
Le call de base
On agit sur la puissance, mais mieux vaut ne pas dépasser 8
5 est très bien aussi.
CalmGrain
Le seul script du lot, qui utilise en partie le plugin FluxSmooth, en lui rajoutant quelques fonctions, par le biais de RedAverage.
Le résultat, si bien dosé, est un poil plus précis, mais un peu plus gourmand en performances.
Citation :
tstr = Default(tstr, 58)
mskstr = Default(mskstr, 0)
mskbias = Default(mskbias, -32)
a = clp.IsYV12() ? clp : clp.ConvertToYV12()
noise = a.RemoveGrain(21,19,19).RemoveGrain(22) # You can replace this line with whatever denoiser you want.
# I recommend you to make said denoiser only denoise luma, as that's faster, and provides usable masks anyway.
msk = RAverageW(noise,19+mskstr,a,-18-mskstr,mode=8,u=0,v=0,bias=mskbias) # Set u & v to 3 to include chroma differences.
# It's faster to just do it with luma, and the default denoising is set to luma only. (* luma,-1 chroma)
RMerge(a,FluxSmoothT(a,tstr),msk,mode=255)
}
|
On peut appuyer un peu plus, mais on y va doucement.
On peut rajouter la fonction msktr=15. Pas fan, mais certains aiment bien.
DeGrainMedian
La vie.
Plugin que j'ai découvert récemment, que je ne connaissais que de nom. Peu utilisé dans le monde de l'encodage au profit de SMDegrain notamment.
Mais il s'avère qu'en HD, l'engin fait de véritables merveilles. A la fois incroyablement performant, très peu destructeur, une perte de piqué minimale. Ce plugin est magique.
Evidemment, il est assez lourd à l'usage
Les 2 meilleures variantes à mon avis.
Le 1er denoise de manière plus poussée que le 2e :
- DeGrainMedian(limitY=3,limitUV=5,mode=1,interlaced=false)
- DeGrainMedian(limitY=6,limitUV=8,mode=3,interlaced=false)
Comparaison
- Original vs RemoveGrain => http://screenshotcomparison.com/comparison/153432 <=
- Original vs FluxSmooth => http://screenshotcomparison.com/comparison/153434 <=
- Original vs CalmGrain => http://screenshotcomparison.com/comparison/153435 <=
- Original vs DeGrainMedian => http://screenshotcomparison.com/comparison/153436 <=
Original
RemoveGrain
FluxSmooth
CalmGrain
DeGrainMedian
- Algorithme de redimensionnement
Vous le savez, l'une des bases de ce tuto est d'envoyer à madVr une image préalablement upscalée pour bénéficier de ses capacités de downscaling et ainsi générer une image la plus précise et la plus propre possible.
pour cela, nous allons utiliser un algorithe de redimensionnement pour upscaler l'image en 2560 x 1440.
L'algo est le Spline, et vous devrez choisir en différentes variantes, le spline 32, le spline 64, le spline 100, le spline 144.
ss=1.333
spline32resize(round(ss*last.width/8)*8,last.height)
spline32resize(last.width,round(ss*last.height/8)*8)
ss=1.333
spline64resize(round(ss*last.width/8)*8,last.height)
spline64resize(last.width,round(ss*last.height/8)*8)
ss=1.333
spline100resize(round(ss*last.width/8)*8,last.height)
spline100resize(last.width,round(ss*last.height/8)*8)
ss=1.333
spline144resize(round(ss*last.width/8)*8,last.height)
spline144resize(last.width,round(ss*last.height/8)*8)
Pour ma part, ma préférence va très largement au Spline 100 et au Spline 144.
Les différences sont toutefois marquées. Le spline 100 propose un grain réduit, mais un piqué en retrait, tandis que le Spline 144 lui, propose l'inverse, un piqué plus appuyé, en contrepartie d'une plus grande présence de grain.
Des deux, mon préféré est le spline 144.
Comparaison
Spline 100 vs Spline 144 => http://screenshotcomparison.com/comparison/153439 <=
Spline 100
Spline 144
Quels que soient vos choix concernant le sharpen, le denoiser ou l'ago que vous allez utiliser, l'ordre du call devra toujours être le même.
Le voici :
Citation :
SetMemoryMax(2048)
SetmtMode(5,0)
ffdshow_source()
Denoiser
ss=1.333
algoresize(round(ss*last.width/8)*8,last.height)
algoresize(last.width,round(ss*last.height/8)*8)
Sharpen
GetMTMode(false) > 0 ? distributor() : last
|
Sachez que vous pouvez rajouter des lignes "fictives" dans le call, pour nommer la chaîne vidéo, par exemple, ou pour inclure des scripts/plugins non actifs, pour faciliter les tests.
Pour cela, la ligne doit être précédée de #.
Pour faciliter la tâche des moins aventuriers, voici 3 calls, du plus léger au plus lourd (du moins bon rendu au meilleur aussi ).
Call 1 #QuadCore (4 Threads)
Citation :
#Blu-ray
#Call LimitedSharpenFaster * RemoveGrain
#Upscaling WQHD by Spline 100
#Chroma Upscaling ................
#Downscaling 1080p ............... SetMemoryMax(512)
SetmtMode(5,0)
ffdshow_source()
RemoveGrain(21,19,19).RemoveGrain(22)
ss=1.333
spline100resize(round(ss*last.width/8)*8,last.height)
spline100resize(last.width,round(ss*last.height/8)*8)
LimitedSharpenFasterHC(Strength=30)
GetMTMode(false) > 0 ? distributor() : last
|
Call 2 #QuadCore (4 Threads) + o/c
Citation :
#Blu-ray
#Call FineSharp * FluxSmoothT
#Upscaling WQHD by Spline 144
#Chroma Upscaling ................
#Downscaling 1080p ............... SetMemoryMax(1024)
SetmtMode(5,0)
ffdshow_source()
FluxSmoothT(5)
ss=1.333
spline144resize(round(ss*last.width/8)*8,last.height)
spline144resize(last.width,round(ss*last.height/8)*8)
FineSharp(sstr=2.0,xstr=0)
GetMTMode(false) > 0 ? distributor() : last
|
Call 3 #QuadCore (8 Threads)
Citation :
#Blu-ray
#Call FineSharp * DeGrainMedian
#Upscaling WQHD by Spline 144
#Chroma Upscaling ................
#Downscaling 1080p ............... SetMemoryMax(1024)
SetmtMode(5,0)
ffdshow_source()
DeGrainMedian(limitY=3,limitUV=5,mode=1,interlaced=false)
ss=1.333
spline144resize(round(ss*last.width/8)*8,last.height)
spline144resize(last.width,round(ss*last.height/8)*8)
FineSharp(sstr=2.0,xstr=0)
GetMTMode(false) > 0 ? distributor() : last
|
Comparaison
Call 1 vs Call 2 => http://screenshotcomparison.com/comparison/153440 <=
Call 1 vs Call 3 => http://screenshotcomparison.com/comparison/153441 <=
Call 2 vs Call 3 => http://screenshotcomparison.com/comparison/153442 <=
Call 1
Call 2
Call 3
Sources 720p
A venir...
Sources DVD & DivX
A venir... |