L’objectif de ce mini-projet est la manipulation d’images 2D en java, en abordant par la même occasion différents algorithmes de détection de mouvement (motion detection).

Cahier des charges simplifié :

1.fonctionne sous GNU/linux Ubuntu
2.upload des images d’infraction par ftp
3.ajout facile de différents algo de motion detection en respectant simplement une interface Java.

Java ne semble pas être le langage idéal pour la video surveillance, la lenteur des opérations de traitement d’images risquant d’altérer l’ensemble du programme. Qu’en est-il vraiment ?

Ubuntu

Après quelques heures de recherches et d’essais, il me semble que JMF n’est pas le bon candidat. Trop obsolète.

Je me suis donc tourné vers un projet open source nommé : v4l4j.

Installation sans soucis sur mon fixe en ubuntu 8.10 et mon umpc en ubuntu 9.04.
Upload des images d’infraction via FTP

Je me suis inspiré du projet timcam. Comme lui j’utilise les sources de jFtp de Bea Petrovicova. L’objectif étant la découverte d’algo de détection de mouvement et pas FTP en soit.
Ajout facile de différents algo de motion detection en respectant simplement une interface Java

package kaerith.securecam.movedetector;

import java.awt.image.BufferedImage;

public interface IMotionDetector {

/**

* Alerte en fonction des 2 imges en parametre

* @param oldImage image de référence

* @param currentImage image actuelle

* @return boolean l’alerte est déclanchée

*/

public boolean bMoveAlert(BufferedImage oldImage, BufferedImage currentImage);

/**

* Accessor pour le nom du detecteur

* @return nom du detecteur

*/

public String getName();

}

Algorithme moyenne des pixels

Cet algorithme, qui s’est au final révélé fort peu intéressant fait la moyenne pour chaque image des différentes couleurs rouge, vert et bleu des pixels.

Pour cela on récupère dans chaque image tous les pixels :

PixelGrabber grabber = new PixelGrabber(image, 0, 0, -1, -1, false);

int[] data = (int[]) grabber.getPixels();

Puis, pixel par pixel on récupère sa valeur R, puis G puis B :

Color c = new Color(pixels[i]);

blue = blue + c.getBlue();

red = red + c.getRed();

green = green + c.getGreen();

Il ne reste plus qu’a faire une moyenne, en ajoutant ou non un certain degré de tolérance.

Algorithme soustraction simple


Cet algorithme pourtant plus simple donne de meilleurs résultats que le précédant, du moins tant que la luminosité ne change pas trop vite.

Son principe est simple : récupérer les valeurs des différents pixels de chaque images et les soustraire un à un. La encore en se laissant une tolérance paramétrable.

Pour récupérer un tableau de toutes valeurs de pixels d’un image :

int[] BufferedImage.getRGB(int x, int y)

Puis soustraire :

int[] tImgRef = imgRef.getRGB(0, 0, w, h, null, 0, w);

int[] tImgNew = imgNew.getRGB(0, 0, w, h, null, 0, w);

int[] tRet = new int[tImgRef.length];

for(int i = 0; i < tRet.length; i++) {

int diff = tImgNew[i] – tImgRef[i];

if( diff >= tolerance) {

nbRet++;

}

}

Variante : transformer les images en niveaux de gris, afin d’atténuer légèrement les problèmes de fausses détection à cause des changements de luminosité.

Algorithme soustractions multiple


La soustraction de deux images montre elle aussi rapidement ses limites en cas de brusque changement de luminosité.

Comment limiter au maximum l’influence de la luminosité ?

Au cours de différents essais, j ‘ai pu me rendre compte qu’il est très improbable que la luminosité chute d’un seul coup de façon importante. La nuit ne tombe pas si vite, pas vrai ? A l’inverse, si entre 2 images la luminosité à énormément variée, c’est certainement parce que quelqu’un est passé entre une source lumineuse et la caméra. Dans ce dernier cas, lever une alerte reste légitime.

Par contre, en condition de faible variation de luminosité il est fort probable qu’une petite zone de l’image changeant fortement sera susceptible de lever une alerte.

L’algorithme de découpage puis soustraction est une amélioration de celui de simple soustraction. Il permet de modérer les alertes non seulement sur les écarts entre les pixels de deux images mais aussi sur le nombre de zones modifiées.

Le principe est simple, les 2 images à comparer sont découpées en carrés. Chaque carré est soustrait de son supposé jumeaux, la tolérance de soustraction s’appliquant là aussi.
Pour chaque carré différent un compteur est incrémenté ; la position du carré est mémorisée.
Dès que tous les carrés ont été comparés, si le nombre de carrés différent dépasse le seuil fixé, l’alerte est donnée.

Les sources de Meduse 0.1 (alias SecureCam).

Prochaine version :
– gestion de plusieurs webcam