Page 1 of 5

Post-traitement pour diffuseurs 2K

Posted: Sat Mar 03, 2012 8:51 pm
by emmanuel piat
Bonjour,

Voici pour information le post-traitement que j'ai utilisé pour mes captures en 2K qui sont dans le thread du test du projecteur 4K Sony 1000ES : http://hdfever.fr/forum/viewtopic.php?f=7&t=82

Ce post suppose que vous avez les connaissances nécessaires pour mettre en oeuvre dans MPC-HC un script Avisynth via ffdshow, que vous connaissez les shaders (GPU coding) ainsi que les renderers EVR Custom Pres ou madVR. Si ce n'est pas le cas, ces tutos sont de bons points d'entrée :
http://www.homecinema-fr.com/forum/view ... t=29900151
http://www.homecinema-fr.com/forum/view ... t=29935240

J'utilise un call Avisynth dans ffdshow qui fait un upscale x4/3 en spline32 à la réso 2560x1440. Ensuite un LSF. Le downsize en 1920x1080 est fait par la CG (shaders).

Le call avisynth a été optimisé pour être entièrement multithreadé. Ce qui permet de minimiser la conso CPU. J'ai aussi réécrit LSF pour virer tout ce qui ne me servait à rien (80% du code en fait) afin d'avoir une exécution plus efficace.

call Avisynth supposant qu'il y a 8 threads dispo :

Code: Select all

SetMemoryMax(768)
nbthreads=8
ss=1.333
MT("spline36resize(round(ss * last.width /8)*8,last.height)",nbthreads,16)
MT("spline36resize(last.width,round(ss * last.height /8)*8)",nbthreads,16,splitvertical=true)
MT("LimitedSharpenFasterHC(strength=23.5)",nbthreads)
Contrairement à LSF, ici strength peut être un réel. C'est nécessaire pour les ajustements fins et ça se voit sur les diffuseurs avec une bonne MTF (moniteur LCD entre autres). La valeur 23.5 convient en général aux diffuseurs avec une bonne MTF. Si la MTF est moins bonne il faut augmenter cette valeur (jusqu'à x2 environ). Si vous avez l'impression de voir la structure des pixels, il faut diminuer cette valeur.

Pour ceux qui aiment les effets 3D où en cas de MTF vraiment moyenne, on peut renforcer l'effet du LSF en ajoutant le filtre sharpen de ffdshow après le call Avisynth. Utilisez le filtre unsharp mask qui se marie bien avec LSF et pour strengh prendre 4 à 10 maxi.

Ensuite ds le dossier Plugins de Avisynth, il faut créer un fichier "LimitedSharpenFasterHC.avsi" avec pour contenu :

Code: Select all

    # LimitedSharpenHC()   ( a modded version, 29 Oct 2005 )
    #
    # A multi-purpose sharpener by Didée
    #
    #
    # Changes in this mod:
    #
    # - RemoveGrain >= v0.9  IS REQUIRED!!
    #   ==================================
    #
    # - a separate "undershoot" parameter, to allow for some line darkening in comic or Anime
    # - Lmode=3   / on edges, limited sharpening with zero OS & US. On not-edges, limited sharpening with specified OS + LS
    # - "soft" acts different now: no more boolean true/false, but instead integer 0 - 100  (or -1 -> automatic)
    #    instead of blurring before finding minima/maxima, it now softens the "effect-of-sharpening"
    # - edgemode=-1 now shows the edgemask. (scaling still not implemented :p )
    #
    ## - MODIFIED version using MaskTools 2.0

    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
    }
La mise en oeuvre du downsize dépend du renderer dans MPC-HC :

- si c'est EVR Custom Pres, alors je conseille de sortir en RGB32 de ffdshow (avec high quality YV12 to RGB conversion actif) puis dans MPC-HC choisir comme retailler: Bicubic A=-0.60 (PS 2.0). Si la MTF du diffuseur est moyenne, vous pouvez augmenter la valeur de A.

- si c'est madVR, alors sortir de ffdshow en YV12 et choisir comme luma downscaling soit Mitchell-Netravali (MTF moyen) ou bicubic 60 (MTF correct) ou SoftCubic 70 ou 80 (excellent MTF).

Le Dithering de chroma lors de la conv YCbCr -> RGB est en général nécessaire si votre diffuseur a un bon CR (disons à partir de 2000:1) et que vous avez une salle sombre. Voici la raison en qq mots : sur les BR et les DVD l'encodage du luma après la précompensation gamma (espace Y'CbCR) est fait en 8 bit, ce qui est normalement suffisant car le fait de travailler en espace de couleur non linéaire augmente la réso du luma de manière proportionnelle à la sensibilité de l'oeil. Le fait d'utiliser 8 bits a été calculé pour être suffisant en vidéo pour une visualisation en env. clair, donc lorsque le CR du diffuseur est mauvais (largement inférieur à 100:1). En env. noir et avec des diffuseurs à fort CR, la réso de 8 bit n'est clairement plus suffisante. Cela peut alors se traduire par des effets de pallier trop important qui engendre des phénomènes de banding ou de fourmillement disgracieux notamment ds les tons sombres. En général, le dithering de chroma permet de rémédier à ces problèmes. Il adoucit néanmoins légèrement l'image.

Un point d'entrée sur ces questions de contraste et de résolution (pas franchement évident à digérer) :
http://www.poynton.com/notes/Timo/Weber ... ratio.html

Re: Post-traitement pour diffuseurs 2K

Posted: Sat Mar 03, 2012 8:53 pm
by emmanuel piat
Si la MTF du projo est franchement moyenne, et si vous utilisez EVR CP comme renderer, il es possible d'ajouter en plus du post-traitement précédent le shader suivant que j'avais baptisé SuperRésolution (nota : madVR ne permet pas d'utiliser les shaders ds MPC-HC). Il a néanmoins l'inconvénient de faire un peu remonter le bruit de fond de l'image mais c'est efficace, notamment si le contraste interpixel du diffuseur est moyen ds les hautes fréquences ce qui se traduit par un manque de piqué. Avec une bonne MTF, je déconseille fortement ce shader.

Code: Select all

// SuperResolution - V1.0
// Emmanuel - 6/03/2010
// Filtre de super résolution à employer derrière un filtre de sharpen
// tel que unsharp mask de ffdshow ou LSF de avisynth.

#define FinesseRendu 0 // 0: très fin, 1: fin, 2: moyen, 3: grossier 

#define SeuilBruit 0.15	// pour éviter la remontée du bruit de fond et
					// l'accentuation de petits détails dans les textures
					// Entre 0.1 et 0.2

#define diff 0.49		// influe sur le rendu "3D-Like", typ :
					// 0.49 => 3D-Like + présent
					// 0.50 => 3D-Like présent
					// 0.51 => 3D-Like - présent 

#define ICG 0			// Intensité de la correction gamma, de 0 à 5 typ
				// 0: faible, 5: forte

#define IAT 3			// Intensité accentuation des textures, de 0 à 3 typ 
				// 0: forte (recommandée pour diffuseur 720p)
				// 3: faible (recommandée pour diffuseur 1080p)

sampler s0 : register(s0);
float4 p1 : register(c1);

#define dx (p1[0])
#define dy (p1[1])
 
float4 main( float2 tex : TEXCOORD0 ) : COLOR
{
	// pixels original, flouté, corrigé
	float4 ori = tex2D(s0, tex);
	float4 flou;
	float4 cori;
	float seuil = 0.82 + FinesseRendu/100;

	// récupération de la matrice de 9 points
	// [ 1, 2 , 3 ]
	// [ 4,ori, 5 ]
	// [ 6, 7 , 8 ]

	float4 c1 = tex2D(s0, tex + float2(-dx,-dy));
	float4 c2 = tex2D(s0, tex + float2(0,-dy));
	float4 c3 = tex2D(s0, tex + float2(dx,-dy));
	float4 c4 = tex2D(s0, tex + float2(-dx,0));
	float4 c5 = tex2D(s0, tex + float2(dx,0));
	float4 c6 = tex2D(s0, tex + float2(-dx,dy));
	float4 c7 = tex2D(s0, tex + float2(0,dy));
	float4 c8 = tex2D(s0, tex + float2(dx,dy));

	// détection des contours
	// par filtre de sobel
	float delta1,delta2,value;

	// Gradient horizontal
	//   [ -1, 0 ,1 ]
	//   [ -2, 0, 2 ]
	//   [ -1, 0 ,1 ]
	delta1 = (c3 + 2*c5 + c8)-(c1 + 2*c4 + c6);

	// Gradient vertical
	//   [ -1,- 2,-1 ]
	//   [  0,  0, 0 ]
	//   [  1,  2, 1 ]
	delta2 = (c6 + 2*c7 + c8)-(c1 + 2*c2 + c3);

	// calcul
	value =  sqrt(mul(delta1,delta1) + mul(delta2,delta2)) ;

	// Gamma adaptatif à proximité d'une transition
	cori = ori;
	if ((value >= seuil-diff*1.15)&&(value <= seuil)) cori = pow(ori,1./(1-value/(10.5-ICG/10)));
	//if ((value >= seuil-diff*1.15)&&(value <= seuil)) cori = float4(1,0,0,0);

	// Masque flou pour renforcer les textures

	// calcul image floue (filtre gaussien)
	// pour normaliser les valeurs, il faut diviser par la somme des coef
	// 1/(1+2+1+2+4+2+1+2+1) = 1/ 16 = .0625

	flou = (c1+c3+c6+c8 + 2*(c2+c4+c5+c7)+ 4*cori)*0.0625;

	// Accentuation des textures si on est loin d'un bord 
	if ((value > SeuilBruit) && (value < seuil-diff)) cori = (2-IAT/10)*cori - (1-IAT/10)*flou;
	//if ((value > SeuilBruit) && (value < seuil-diff)) cori = float4(0,0,1,0);

	return cori;
}

Re: Post-traitement pour diffuseurs 2K

Posted: Sun Mar 04, 2012 10:29 am
by ciccio1112
bonjour, Ok pour superrésolution mais le script:


Code:
SetMemoryMax(768)
nbthreads=8
ss=1.333
MT("spline36resize(round(ss * last.width /8)*8,last.height)",nbthreads,16)
MT("spline36resize(last.width,round(ss * last.height /8)*8)",nbthreads,16,splitvertical=true)
MT("LimitedSharpenFasterHC(strength=23.5)",nbthreads)


et toujours un shader ou avisinth script?

Je limitedsharpenHC.avsi Crato 's-je mettre dans le dossier plugins, puis avisinth .....

Je note aussi un fil 4-cpu alors comment puis-je tout changer.

merci.

Re: Post-traitement pour diffuseurs 2K

Posted: Sun Mar 04, 2012 11:02 am
by Kazuya
Salut Emmanuel,
J'ai fait l'essai, et je trouve qu'il y a une perte de détails avec l'upscale Spline36 avant le LSF.
Je n'ai jamais aimé ces SuperSampling et compagnie, et avec les mires que j'utilise maintenant c'est flagrant.
Regarde :

Avec uniquement ta ligne LSFHC à 23.5 :
Image

avec les 2 lignes de SS en plus en downscale lanczos 1 :

Image

avec les 2 lignes de SS en plus en downscale bicubic 0.6 (nettement mauvais d'ailleurs) :

Image

Re: Post-traitement pour diffuseurs 2K

Posted: Sun Mar 04, 2012 11:48 am
by ciccio1112
ok c'était une avisinth problème.

Re: Post-traitement pour diffuseurs 2K

Posted: Mon Mar 12, 2012 12:42 pm
by emmanuel piat
Merci Kaz pour ces résultats qui ne me surprennent pas.

J'essaye de faire d'ici mardi soir un petit topo sur les mires 1 pixel car je pense que beaucoup de choses sur ces mires sont mal comprises du point de vue de la théorie du signal.

@+
Emmanuel

Re: Post-traitement pour diffuseurs 2K

Posted: Mon Mar 12, 2012 6:54 pm
by emmanuel piat
Je vais commencer par une analogie avec l'audio pour rendre les choses + claires.

Un signal audio correspond à la variation continue d'une grandeur physique qui est une pression acoustique.

Si on capture cette grandeur physique à l'aide d'un convertisseur analogique-numérique en capturant la pression acoustique à l'aide d'un microphone puis en échantillonnant le signal délivré à 48 kHz, on peut montrer que la plus haute fréquence "capturable" numériquement est de 24 kHz. Et toutes les fréquences au delà de 24 Hz doivent préalablement être supprimées du signal si on veut que la capture se passe correctement (si on ne le fait pas, on a un repliement (aliasing) des fréquences au delà de 24 kHz dans la zone 0-24 kHz, ce qui crée des artefacts sonores). Une période de la plus haute fréquence capturée sera alors représentée numériquement par uniquement 2 points : un situé par exemple sur le plus haut sommet et un sur le plus bas sommet. Cette information très minimaliste sera suffisante pour que l'étage de sortie du convertisseur numérique-analogique soit capable de restituer l' *ensemble* des points de la sinusoïde à 24 kHz, ce qui je le concède semble un peu magique (ça c'est la théorie, en pratique, ce n'est pas totalement possible et il y a forcément une petite distorsion du signal).

En vidéo c'est pareil : la lumière capturée à un instant donné par la caméra se compose aussi de fréquences analogiques sauf que cette fois-ci ces fréquences sont spatiales : elles "s'étalent" de ce fait sur la surface des 3 capteurs CCD RGB et deviennent ainsi numériques puisqu'elles sont échantillonnées spatialement. La période de la plus grande fréquence capturable est aussi représentée par deux points (dont l'écartement spatial correspond aux pixels du CCD) et la répétition de ces 2 points donne typiquement les motifs qu'on voit sur les mires "1 pixel".

L'image numérique est consituée par la somme des fréquences spatiales capturées.

La différence avec l'audio, c'est que maintenant il n'y a plus de convertisseur numérique-analogique avec son étage de sortie pour reconstituer la nature physique *spatialement continue* de la lumière. Et donc la plus grande fréquence capturée ne sera *pas* restituée comme une belle sinusoïde continue comme en audio mais par un signal très laid qui a la forme d'un créneau. Autrement dit, la structure "pixel" se met à apparaître et les fréquences élevées capturées présentent alors une grosse distorsion qui se traduit par ce qu'on appelle communément la nature "numérique" de l'image. C'est clairement un défaut des diffuseurs numériques qui présentent une distorsion importante dans les hautes fréquences.

Les vieux TT 100% analogiques ou les 1er projecteurs ILA de JVC n'avaient pas ce défaut (ou il était minimisé). Mais ces technos trop complexes à mettre en oeuvre ont périclité (par exemple l'ILA de JVC est devenu le Digital ILA ou DILA).

Pour minimiser la distorsion dans les hautes fréquences, la 1ère idée qui vient à l'esprit est d'utiliser des matrices de plus grande dimension que la source. Par exemple à l'époque des projos 800x600 (dreamvision DL500 etc.) le nec plus ultra était d'acquérir un JVC DILA de résolution 1360x1024 ou plus. Et ce n'était pas pour passer des vidéos de résolution plus élevée que le DVD (la HD n'existait pas) mais pour faire de l'upscaling : l'interpolation créée par l'upscaling permet de minimiser la distorsion dans les hautes fréquences en créant des points intermédiaires : ces diffuseurs avait un rendu qui se rapprochait des diffuseurs analogiques de type TT.

A l'époque certaines personnes trouvaient que ces images interpolées sur de "grandes matrices" manquaient de "piquée" par rapport aux images non interpolées. C'est un ressenti subjectif qui est du au fait que la structure "pixel" qui introduit de la distorsion dans les hautes fréquences de l'image est elle-même constituée de très hautes fréquences (puisque les pixels sont des fronts), lesquelles renforcent l'illusion de piqué. Alors que sur les images interpolées, on se rapproche plus de la variation spatiale continue de la lumière issue de la scène capturée, et là le manque de piquée traduit simplement la pauvreté de la basse résolution. En effet, comme en audio, toutes les fréquences spatiales supérieures à la plus grande fréquence capturable sont supprimées lors de la capture sans quoi on a des phénomènes d'aliasing très moches. De ce fait, les détails ne sont pas présents et le manque de piqué ressort cruellement sur les images interpolées alors qu'il est "masqué" par la distorsion introduite par les pixels.

Pour compenser le manque de piqué, on recourt traditionnellement à du sharpen lors de l'opération d'upscaling. C'est une astuce assez efficace visuellement lorsqu'elle est correctement mise en oeuvre. Certaines personnes préfèrent alors le rendu obtenu de cette manière-là par rapport à la sensation de piquée due à la distorsion introduite par les pixels...

Quoi qu'il en soit, la manière la plus sûr pour qu'une image projetée n'ai pas un aspect "numérique" est de limiter les hautes fréquences présentes ds l'image. C'est pourquoi les BR 1080p ont souvent une résolution intrinsèque de l'ordre d'un 720p. En général, on ne pas plus loin que les 3/4 de la plus haute fréquence de la matrice. Comment serait une image qui exploiterait totalement la résolution 1080p ? C'est bien simple, sur toutes les transitions ou les détails très fin (cheveux, textures, etc.) elle ressemblerait à l'image qu'on a sur un jeux vidéo 3D lorsqu'on supprime l'anti-aliasing de la CG ! On verrait alors les transitions des pixels sur les lignes droites ou les courbes, les textures scintilleraient lorsqu'elles sont en mouvement, etc. Sur les jeux vidéo 3D, l'anti-aliasing a pour rôle de détruire les hautes fréquences ds les transitions en les rendant plus douces.

En pratique sauf exception très rare, les films n'ont pas de tel défauts car les hautes fréquences sont limitées soit lors de la capture vidéo, soit par post-traitements (filtrage passe bas de l'image, downsize 4K ou 8K->2K avec des filtres antialiasing qui coupent largement avant la plus haute fréquence du 2K). Par contre, sur des DA, on voit parfois des structures pixelisées dues à des fréquences trop elevées présentes sur les BR. Quand on veut trop en faire, on finit par mal faire ...

La conséquence de toute cela est qu'une mire 1 pixel est un objet très artificiel car à une fréquence bien au delà de celle qui donne une image "naturelle" sur un diffuseur numérique (par "naturelle" j'entends peu distordue par la nature numérique du diffuseur). Ce type de mire est utile par contre pour mesurer les capacités d'un diffuseur (notamment optique) mais elle n'est pas représentative de ce qu'on appelle communément une image "naturelle". A noter qu'une image "naturelle" peut sembler manquer de résolution, il y a généralement un compromis à trouver entre les deux (voir plus loin).

Il faut donc utiliser ce type de mire avec culture.

Les mires 2 pixels sur un diffuseur 2K sont bcp plus représentatives des images présentes sur les BR et ces dernières doivent être rendues le plus correctement possible.

D'après ce que j'ai pu déduire des tests fait par Nicolas sur le sony 1000ES, j'ai trouvé personnellement que ce projo 4K avait un potentiel qui semble très intéressant pour le 2K. Le fait de pouvoir interpoler du 2K en 4K limite la distorsion haute fréquence en 2K et ce même si la source 2K a des fréquences très élevée. C'est un excellent point car cela devrait permettre de mieux marier image naturelle et résolution accrue si les sources 2K gagnaient en contenu fréquentiel.

La perte de piqué qui peut survenir sur des sources 2K de qualité moindre (fréquences plus limitées) peut être compensée par le sharpen du projo qui semble performant (j'ai néanmoins un peu peur qu'il soit trop boosté pour mon goût perso).

Sa MTF fait que les mires 2 pixels (qui correspondrait a du 1 pixel sur un projo 2K) sont un poil atténuées mais déjà de très bonne qualité et donc respectueuses d'une source 2K. Tout cela est donc de bonne augure pour l'avenir en 2K.

Pour ce qui est du 4K je suis bcp plus réservé sur les capacités de ce projo comme j'ai déjà pu l'écrire.

Un mot sur la MTF pour finir. Une MTF de très bonne qualité fera beaucoup plus vite ressortir la distorsion introduite par les pixels. La aussi il y a un compromis à trouver entre piqué et "naturel" (qui dépend aussi du goût de l'utilisateur). Quoi qu'il en soit, plus un diffuseur à une MTF de bonne qualité et moins il faut le sharpeniser. Ou bien il faut utiliser des stratégies de sharpen un peu différente : c'est-là où l'upscaling suivi d'un sharpen puis d'un downscaling "soft" trouve tout son intérêt. Ce type d'approche sharpenise tout en adoucissant les plus hautes fréquences (donc il fait aussi du AA) comme le montré KAZ. C'est pourquoi personnellement je l'utilise sur des diffuseurs tel que mon moniteur LCD car cela limite bien les structures pixelisée que je vois sur certains DA tout en les sharpenisant. Mais là encore, c'est une affaire de goût...

Je terminerai par un témoignage. Le complexe Pathé de ma ville vient récemment de passer l'ensemble de ces salles en numérique. Qd on regarde de près les pixels sur l'écran, on constate que les panneaux DLP ne sont pas parfaitement alignés (écart de l'ordre du 1/2 pixel) alors qu'il est possible de le faire via des vis micrométriques sur ces projos pro. Alors ? Incompétence ou volonté délibérée ? Je penche plus pour la 2e solution... Vue la qualité des sources DCP en 2K, cette dégradation volontaire de la MTF permet de masquer la structure des pixels sur ces grandes bases d'écran. Et c'est efficace. L'image obtenue semble un poil plus piquée que sur les anciens projos 35mm mais n'a aucun aspect numérique. Le spectateur n'est pas dépaysé et gagne en stabilité d'image.

@+
Emmanuel

Re: Post-traitement pour diffuseurs 2K

Posted: Mon Mar 12, 2012 7:33 pm
by Kazuya
Superbe explication, merci Emmanuel ! :o

Re: Post-traitement pour diffuseurs 2K

Posted: Mon Mar 12, 2012 7:38 pm
by Yahoo MMCrawler [Bot]
Kazuya wrote:Superbe explication, merci Emmanuel ! :o
+1 merci beaucoup pour ces explications ;)

Re: Post-traitement pour diffuseurs 2K

Posted: Tue Mar 13, 2012 6:28 pm
by ciccio1112
Grande emmanuel!