lundi 10 janvier 2011

Étape 1 : Prendre une photo du Sudoku


Traitement pour trouver la grille et les chiffres

Dans l'étape 1, il y a 2 principales difficultés :
  • créer l'image avec la bonne taille
  • gérer la caméra
Pour obtenir une image avec la bonne taille,vous devez tenir compte de la dimension de la mémoire virtuelle du téléphone Android. Généralement, cette dimension est de 16 mégaoctets; certains téléphones Android avec un appareil photo de 8 mégapixels peuvent avoir 24 mégaoctets de mémoire virtuelle. Supposons que nous prenons une photo avec la taille 2048X1536 (largeur x hauteur) qui est souvent la taille par défaut définie par le téléphone Android lorsque vous ne spécifiez pas vous-même la taille requise. La mémoire occupée est 2048 X 1536 X 4 = 12 mégaoctets. Rapidement, votre programme est à court de mémoire.

Alors, quelle est la bonne taille pour l'image? Si cette taille est trop haute, il n'y a pas assez de mémoire et cela prend trop de temps pour extraire la grille et les chiffres. Si cette taille est trop petite, le programme ne prend pas beaucoup de mémoire, prend moins de temps, mais la taille n'est souvent pas assez grande pour capturer tous les chiffres. Après de nombreux essais, nous avons choisi 512 pour la largeur et la hauteur du de l'image.

Maintenant, la caméra. Nous pouvons modifier le comportement de la caméra avec la classe Parameters comme ceci :

camera = Camera.open();
Camera.Parameters parameters = camera.getParameters();
//  . . . modifier rotation, orientation, preview size, picture size, . . .
camera.setParameters(parameters);

Certains paramètres peuvent être définis de différentes manières lorsque le programme s'exécute sur les différentes versions de Android. Notre objectif est que notre programme doit s'exécuter sur la version Android 1.5 ou plus. Donc, nous ne voulons pas utiliser une méthode spécifique à une version. En outre, certains paramètres ne sont pas pris en charge par certains téléphones Android. Donc, nous avons décidé de ne pas définir de paramètres pour la caméra.

Le programme pourrait recevoir une photo avec la dimension 2048X1536, ce qui est trop élevée. Donc, avant de convertir une photo en une image, il faut interroger la dimension de la photo afin de diminuer la taille de l'image. Voici le code pour interroger la dimension de la photo et pour créer l'image en tenant compte de la largeur et de la hauteur de 512 pour l'image résultante :

BitmapFactory.Options options = new BitmapFactory.Options();
options.inJustDecodeBounds = true;
bitmap = BitmapFactory.decodeByteArray(data, 0, data.length, options);
options.inJustDecodeBounds = false;
options.inSampleSize = options.outHeight / 512;
bitmap = BitmapFactory.decodeByteArray(data, 0, data.length, options);

La dimension de l'image est maintenant de 1024X768  ce qui prend beaucoup moins de mémoire qui est maintenant dans l'ordre de 3 mégaoctets.

Voici 2 points concernant "options.outHeight / 512" :
  • nous utilisons options.outHeight au lieu de options.outWidth parce que la photo est encore en mode paysage; la photo sur le téléphone Android est toujours prise en mode paysage; nous devons donc faire pivoter l'image (voir plus loin)
  • le résultat de options.outHeight / 512 est 3 et la hauteur obtenue est 768; ça aurait du être 512; mais, Android choisit toujours un nombre immédiatement inférieur à une puissance de 2 qui est 2 dans notre cas

Ensuite, nous devons réduire l'image de 1024X768 à 512X512. Nous allons recadrer l'image  de 1024X768 à 768X768 et la redimensionner de 768X768 à 512X512. Voici le code pour ce faire :

int destWidth = 512;
int destHeight = 512;
int origWidth = bitmap.getHeight(); // pour recadrer
int origHeight = bitmap.getHeight();
Bitmap bmwork = Bitmap.createBitmap(destWidth, destHeight, Bitmap.Config.RGB_565);
Rect destRect = new Rect(0, 0, destWidth, destHeight);
Rect origRect = new Rect(0, 0, origWidth, origHeight);
Canvas canvas = new Canvas(bmwork);
canvas.drawBitmap(bitmap, origRect, destRect, null); // pour redimensionner

La dernière transformation est de pivoter l'image comme ceci :
Matrix matrix = new Matrix();
matrix.setRotate(90);
bitmap = Bitmap.createBitmap(bmwork, 0, 0, 512, 512, matrix, true);
L'image est maintenant prête. Nous démarrons une unité de traitement pour trouver la grille et les chiffres.

Afficher

Pendant ce temps, nous affichons l'image résultante donnant ainsi le temps à l'utilisateur de vérifier si la photo est à sa satisfaction

Voici les captures d'écran de quelques photos :




Aucun commentaire:

Enregistrer un commentaire