Filtre de Deriche

Principe

Le filtre de Deriche est un filtre de lissage (passe-bas) qui a été conçu pour détecter, associé à un opérateur de dérivation, de manière optimale les contours d'une image (optimisation des critères de Canny). Par ailleurs, comme il est très similaire à un filtre gaussien, mais beaucoup moins complexe à implémenter, car fondé sur de simples filtres RII du premier ordre, il est très utilisé pour du filtrage en général.

En effet, contrairement au filtrage gaussien qui est souvent implémenté sous la forme de filtre RIF (à réponse finie), et dont la complexité dépend donc du niveau de filtrage souhaité (écart-type), pour un filtre RII du premier ordre, d'équation : y[n] = a*x[n] + (1-a)*y[n-1], la complexité est constante et très modeste (2 multiplications par pixel), et le niveau de filtrage peut être arbitrairement modifié via le coefficient d'oubli a.

Néanmoins, ce filtre n'est pas symétrique, ce qui est problèmatique en traitement d'image. Heureusement, pour le rendre symétrique, il suffit de l'appliquer une deuxième fois dans le sens inverse (filtre anti-causal). Enfin, pour se rapprocher encore plus d'un filtre gaussien, cette séquence filtrage causal + filtrage anti-causal est appliquée deux fois. Voilà ce que cela donne en terme de réponse impulsionnelle 1D :

Au total, on fait donc appel à quatre filtrages dans le sens horizontal, puis quatre filtrages dans le sens vertical (le filtre est séparable), soit une complexité fixe d'environ 16 multiplications / pixel, et ce indépendemment du niveau de filtrage souhaité. A titre de comparaison, pour un filtre gaussien, la complexité devient supérieure dès lors que le noyau a une largeur supérieure à 9 pixels.

Comparaison des réponses impulsionnelles d'un filtre gaussien et d'un filtre de Deriche

API C++

int DericheBlur(const cv::Mat &I, cv::Mat &O, float gamma)

Où :

  • I et O sont respectivement les images d'entrée et de sortie de la fonction. Les types supportés sont les suivants : CV_32F, CV_8U, CV_16S, avec un nombre de canaux (couleurs) arbitraires.
  • Et gamma est le facteur d'oubli entre 0 (pas de filtrage) et 1 (filtrage maximal).

Application au calcul de gradient

Lors du calcul d'un gradient (c'est-à-dire le calcul des dérivées partielles d'une image suivant les deux axes), le bruit à haute fréquence est naturellement amplifié ; c'est pourquoi il est très important de pré-filtrer l'image avant la dérivation. On utilise pour cela communément un filtre gaussien (par exemple dans l'algorithme de Canny), mais son approximation par le filtre Deriche peut aussi être utilisée.

La fonction suivante réalise successivement les deux opération de pré-filtrage (Deriche) et de calcul de gradient (masque de Sobel) :

int DericheGradient(const cv::Mat &I, 
                    cv::Mat &gx, cv::Mat &gy, 
                    float gamma)

Pour se convaincre de la nécessité du préfiltrage avant calcul du gradient, regardez ci-dessous les gradients calculés sur une image modéremment bruitée (dans la pratique, le bruit peut être encore plus important, notamment dans les situations de faible éclairage) :

Gradients d'une image (en haut à gauche) : sans pré-filtrage (en haut à droite), avec pré-filtrage de Deriche (en bas).

Comme on peut s'y attendre, le pré-filtrage de Deriche donne des résultats assez similaires par rapport à un pré-filtrage gaussien (mais avec une complexité moindre), et meilleure qu'avec une simple moyenne mobile, comme les figures ci-dessous le montrent :

Gradient de Sobel (sans pré-filtrage). La couleur (teinte) indique la direction du gradient.

Gradient de Canny (pré-filtrage gaussien, noyau 15x15)

Gradient de Deriche (pré-filtrage exponentiel, a = 0.6)

Gradient (pré-filtrage moyenne mobile, noyau 11x11)