NoMoSmooth YV12

 

NoMoSmooth permet de faire du "motion-adaptive spatio-temporal smoothing".

SansGrip (son concepteur) a voulu faire un filtre puissant qui préserve tout de même les détails d'une vidéo.

Pour cela, le filtre commence par déterminer si un pixel a besoin d'être filtré. (c'est le cas s'il est "fluctuant", cf. explications en dessous du tableau)

Ensuite le filtre sépare les zones en mouvement des zones statiques.

Et pour finir, il filtre différemment ces zones en calculant les moyennes des valeurs des pixels spacialement ou temporellement.

Ah oui, il faut savoir que NoMoSmooth ne travaille que sur la luminance.

 

En voilà un filtre qu'il est bien ... ☺

 

 

      NoMoSmooth(motion_threshold = 40 , temporal_radius = 1, temporal_threshold = 6, spatial_radius=1,

 spatial_threshold=3, show=false)

 Valeurs possibles

Valeurs raisonnées

motion_threshold

Seuil du mouvement.

Contrôle la sensibilité de la détection du mouvement.

 

valeur faible → très sensible au mouvement.

40     → par défaut

valeur élevée → moins sensible au mouvement.

 

de 0 à ~2000 

défaut = 40

filtrer dès que ça bouge

1 à 50

filtrage normal

50 à 100

ne filtrer sue les mvt forts

100 à 300 (et +)

temporal_radius

Rayon temporel.

 

Détermine sur combien de frames le filtre va travailler.

1 → 1 frame de chaque "côté" de la frame courante va être examinée → soit 3 au total

5 → 5 frames de chaque "côté" de la frame courante vont être examinées → soit 11 au total

...

Attention, si vous augmentez trop ce rayon vous risquez des effets de ghosting et surtout de réduire considérablement la vitesse d'encodage.

de 0 à

défaut = 1

1 à 2

temporal_threshold

Seuil temporel.

 

NoMoSmooth n'inclura dans la moyenne que les pixels ayant une différence de valeurs avec le pixel courant ne dépassant pas ce seuil.

 

de 0 à 0

défaut = 6

 2 à 20

spatial_radius

Rayon spatial.

 

Détermine combien de pixels autour du pixel courant sont pris en compte.

1 → le pixel courant + les 8 pixels voisins → soit 9 pixels en tout.

2 → le pixel courant + les 24 pixels voisins → soit 25 pixels en tout.

...

 

Attention, si vous augmentez trop ce rayon vous risquez de perdre trop de détails et surtout de réduire considérablement la vitesse d'encodage.

 

de 0 à 0

défaut = 1

1 à 4

spatial_threshold

Seuil spatial.

 

NoMoSmooth n'inclura dans la moyenne que les pixels ayant une différence de valeurs avec le pixel courant ne dépassant pas ce seuil.

 

de 0 à 0

défaut = 3

2 à 20

show

Affichage.

 

Si ce paramètre est activé, le filtrage ne se fera pas. Par contre, les zones de mouvement détectées sont grisées. (ceci pour percevoir l'influence de la précision de l'algo défini par motion_threshold)

 

True / False

défaut = False

 False

 

 Filtrage léger

NoMoSmooth(60,1,4,2,2,false)

 

 Filtrage standard

NoMoSmooth(40,2,6,2,6,false)

 

 Filtrage plus poussé

NoMoSmooth(30,2,8,2,8,false)

 

 

 

 

 

FONCTIONNEMENT DE NOMOSMOOTH :

 

 

1) Pixel fluctuant ou non ? :

 

Imaginez 3 images consécutives :

 

 

 

 

 

 

 

 

 

 

 

 

 

X1

 

 

X2

 

 

X3

 

 

 

 

 

 

 

 

 

 

 

Si la valeur du pixel X2 est soit plus grande que celle de X1 et de X3 ou soit plus petite que les deux, le pixel est considéré comme fluctuant.

Cette idée se base sur le principe que les pixels "fluctuants" sont du bruit puisque n'évoluant pas dans le même sens que leurs pixels voisins temporellement.

 

1a) X2 n'est pas "fluctuant" → X2 ne sera pas filtré

1b) X2 est "fluctuant" → X2 sera filtré → 2)

 


 

2) Différenciation des zones en mouvement et des zones statiques :

 

NoMoSmooth dispose d'un algorithme de détection de mouvement. Il est assez simpliste et peut causer des artefacts lorsque des objets de la même couleur bougent l'un sur l'autre ou quand il y a des différence temporelle alors qu'il n'y a pas de mouvement. Mais il est peut quand même donner de bons résultats.

 

Frame précédente

 

Frame en cour

pprevt[-2]

.

pprevt[0]

.

pprevt[+2]

pcurrt[-2]

.

pcurrt[0]

.

pcurrt[+2]

pprevc[-2]

.

pprevc[0]

.

pprevc[+2]

pcurrc[-2]

.

pcurrc[0]

.

pcurrc[+2]

pprevb[-2]

.

pprevb[0]

.

pprevb[+2]

pcurrb[-2]

.

pcurrb[0]

.

pcurrb[+2]

 

La détection se fait de cette façon :

 

(pprevt[-2] - pcurrt[-2]) +(pprevt[0] - pcurrt[0]) +(pprevt[2] - pcurrt[2]) +(pprevc[-2] - pcurrc[-2]) +(pprevc[0] - pcurrc[0]) +(pprevc[2] - pcurrc[2]) + (pprevb[-2] - pcurrb[-2]) +(pprevb[0] - pcurrb[0]) +(pprevb[2] - pcurrb[2])

 

Si le résultat de l'opération (en valeur absolue) est inférieur au seuil (motion_threshold), NoMoSmooth filtrera le pixel spatialement 3)

                                                 si par contre il est supérieur, NoMoSmooth filtrera le pixel temporellement 4)

 


 

3) Filtrage spatial des zones en mouvement :

 

 

Frame "symbolisée" par 81 pixels

 

Le rayon spatial :

1

2

3

4

5

6

7

8

9

 

4

4

4

4

4

4

4

4

4

10

11

12

13

14

15

16

17

18

4

3

3

3

3

3

3

3

4

19

20

21

22

23

24

25

26

27

4

3

2

2

2

2

2

3

4

28

29

30

31

32

33

34

35

36

4

3

2

1

1

1

2

3

4

37

38

39

40

41

42

43

44

45

4

3

2

1

0

1

2

3

4

46

47

48

49

50

51

52

53

54

4

3

2

1

1

1

2

3

4

55

56

57

58

59

60

61

62

63

4

3

2

2

2

2

2

3

4

64

65

66

67

68

69

70

71

72

4

3

3

3

3

3

3

3

4

73

74

75

76

77

78

79

81

81

4

4

4

4

4

4

4

4

4

 

 

NoMoSmooth est un filtre moyenneur et n'applique aucune "matrice-poids" lors de ses calculs.

La valeur de sortie du pixel 41 est ainsi déterminée à partir des valeurs des pixels spatialement voisins :   (32 + 32 + 33 + 40 + 41 + 42 + 49 + 50 + 51)  / 9

 

• Ne sont pas inclus dans la moyenne les pixels dont la différence de valeur dépasse le seuil fixé par spatial_threshold

 

• Le nombre de pixel spatialement voisins pris en compte dans les moyenne dépend du spatial_radius   (cf. tableau de droite)

 


 

4) Filtrage temporel des zones statique :

 

2 frames avant

 

Frame précédente

 

Frame en cour

 

Frame suivante

 

2 frames après

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

A

 

 

B

 

 

C

 

 

D

 

 

E

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

NoMoSmooth est un filtre moyenneur et n'applique aucune "matrice-poids" lors de ses calculs.

La valeur de sortie du pixel C est ainsi déterminée à partir des valeurs des pixels temporellement voisins :   ( A + B + C + D + E )  / 5

 

• Ne sont pas inclus dans la moyenne les pixels dont la différence de valeur dépasse le seuil fixé par temporal_threshold

 

• Le nombre de pixels temporellement voisins pris en compte dans les moyenne dépend du temporal_radius   

si le rayon est de 0 :  valeur de C en sortie =  C /1

si le rayon est de 1 :  valeur de C en sortie =  ( B + C + D ) /3

si le rayon est de 2 :  valeur de C en sortie =  (A +  B + C + D + E ) /3

......

 

 

 

DIFFERENCES  ENTRE FLUXSMOOTH ET NOMOSMOOTH :

 

 

Souvent confondus, car du même programmeur, FluxSmooth et NoMoSmooth ne sont pourtant pas exectement similaires. En résumé, on peut dire que :

 

NoMoSmooth applique une simple moyenne (sans matrice de poids) à chaque pixel fluctuant et intègre un algo (assez simpliste) de détection du mouvement qui permet au filtre de lisser temporellement les zones statiques et de lisser spatialement les zones en mouvement.

 

FluxSmooth, quand à lui, applique de façon spatio-temporel une simple moyenne (sans matrice de poids) à chaque pixel fluctuant.

 

 

 

REMERCIEMENTS

 

Merci à Sigmatador pour avoir actualisé une partie du code de NoMoSmooth et pour les explications qu'il m'a gentiment fournis.

 

 

 

 

~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~Ctrl-Alt-Suppr~~~~~~~~~~~~~~~~~