Projet Python : Redressement d`images de tableau

publicité
Projet Python : Redressement d’images de tableau
P. Vanier, T. Kaced
Projet Python : Redressement d’images de tableau
Dernière modification : 28 septembre 2015
[email protected]
1
Consignes
— Date limite inscription groupes : 5 octobre
— Date limite rendu sur gitlab : 29 novembre
— Date de la soutenance : Semaine du 30 novembre.
Le projet est à faire par groupe d’au plus 2 personnes, vous devez inscrire le groupe sur la
page eprel avant le 5 octobre. Vous devez vous servir de git pour le rendu, l’interface gitlab est
http://git-etudiants.lacl.fret des slides d’initiation à git sont disponibles sur la page eprel du
cours de systèmes en L2.
Vous devez écrire un rapport (un simple fichier texte nommé rapport) que vous mettrez à
la racine de votre projet.
Seuls les projets rendus sur http://git-etudiants.lacl.frseront acceptés, vous devez faire des
commit régulièrement (un seul commit à la dernière minute entrainera une perte de plusieurs
points sur la note finale).
2
Le sujet
Le but de ce projet est d’écrire un package/module permettant à partir d’une photo de
tableau d’obtenir une image lisible et redressée, voir la figure 1.
Le projet peut être décomposé en plusieurs étapes intermédiaires :
1. Détection des bords du tableau
2. Découpage et redressement de l’image
3. Améliorations de l’image
Nous vous donnons ci-dessous une méthode pour faire chacune de ces étapes, celle-ci est
tirée de l’article Whiteboard Scanning and Image Enhancement de Zhengyou Zhang et Li-wei
He, que vous pouvez trouver dans le répertoire du projet sur éprel. Vous n’êtes pas obligés de
suivre cette méthode (vous pouvez l’améliorer si vous le souhaitez). Vous pouvez vous servir
de packages/modules python que vous voulez, y compris opencv (seule les versions 3.0 et
postérieures sont compatibles python 3) ou de scikit-image.
3
3.1
Détecter les bords
Détection de contours
La première étape pour détecter les contours est de prendre l’image convertie en niveaux
de gris. On utilise ensuite un filtre de Sobel pour calculer deux gradients pour chaque pixel :
M1 Python – Cours : P. Vanier
1/5
Projet Python : Redressement d’images de tableau
(a) Avant
P. Vanier, T. Kaced
(b) Après
Figure 1: Exemple d’image de tableau.




−1 0 1
−1 −2 −1




0
0  et le filtre en y : Gy = −2 0 2
Le filtre en x : Gx =  0




−1 0 1
1
2
1
Ces deux filtres sont les filtres horizontaux et verticaux par défaut pour le filtre de Sobel
d’opencv2 étant donné les paramètres
— dx = 1, dy = 0, ksize = 3 et
— dx = 0, dy = 1, ksize = 3 .
Il suffit alors de calculer le gradient total G = |Gx | + Gy pour chaque pixel. On peut alors
définir un seuil TG tel que tout pixel où G ≥ TG sera considéré comme faisant partie d’un
contour. On pourra prendre TG = 40.
On aurait également pu détecter les contours avec un filtre de Canny par exemple.
3.2
Détection de lignes
On a maintenant une image temporaire contenant uniquement du blanc et du noir : une
image binaire donc, où le blanc représente un contour et le noir le fond. On veut cependant
uniquement conserver les contours correspondant à notre tableau : on ne veut conserver que
les contours qui forment des segments. On va utiliser pour cela une transformation de Hough
(également disponible dans opencv). Cette transformée permet d’obtenir une liste de droites.
Il faut ensuite calculer pour chaque droite son orientation, ce qui peut se faire en prenant
atan2(G_y, G_x) pour n’importe quel point de cette droite où l’image binaire contenait
du blanc. Vous pouvez également réimplémenter la transformée de Hough
3.3
Détection de quadrilatère
Une fois que vous avez détecté les lignes, il faut déterminer lesquelles seront considérées
pour former le contour du tableau. Pour cela, on prendra des quadruples de droites qui vérifient les conditions suivantes :
M1 Python – Cours : P. Vanier
2/5
Projet Python : Redressement d’images de tableau
P. Vanier, T. Kaced
— Les lignes opposées doivent avoir des orientations opposées : 180 ± 30.
— Les lignes opposées doivent être relativement loin les unes des autres (par exemple la
différence entre les ρ est plus grande que 1/5 de la largeur/hauteur de l’image).
— L’angle entre deux lignes consécutives doit s’approcher de 90 ± 30
— Le quadrilatère ainsi formé doit être relativement grand (plus grand que (L + H)/4 par
exemple).
Les lignes renvoyées par la transformée de Hough ne disent cependant pas où se trouvaient
les segments correspondant, et si l’on peut, même en vérifiant toutes les conditions précédentes
se retrouver dans la situation suivante :
Pour éviter cette situation, il faut parcourir ces droites sur l’image en binaire et regarder si
le segment initial correspond bien à un bord du quadrilatère formé par les droites. On conservera le meilleur quadrilatère. On peut utiliser à ce stade diverses techniques pour raffiner le
quadrilatère (c’est mieux, mais ce n’est pas obligatoire), par exemple un line-fitting pour chaque
bord.
4
Redressement de l’image
Il faut déterminer la taille du rectangle dans lequel on mettra notre sous-image de tableau.
Supposons que les coordonnées des coins détectés du tableau soient m1 , m2 , m3 , m4 (où la troisième coordonnée est mise à 1), la figure ci-dessous est une vue schématique de la manière
dont la photo a été prise :
M1 Python – Cours : P. Vanier
3/5
Projet Python : Redressement d’images de tableau
P. Vanier, T. Kaced
On calcule le rapport de cadre (aspect ratio) du rectangle :
s
t n t A−1 A−1 n
2
2
r = w/h =
t n t A−1 n
3
3
— k2 =
(m1 ×m4 )·m3
(m2 ×m4 )·m3
(m1 ×m4 )·m2
(m3 ×m4 )·m2
— k3 =
— n2 = k2 m2 − m1
— n3 =k3 m3 − m1 
f 0 u0 


— A =  0 sf v0  où (u0 , v0 ) est le centre de l’image.


0 0 1
— f 2 = − n 1n (n21 n31 −(n21 n33 +n23 n31 )u0 +n23 n33 u02 +n22 n32 −(n22 n33 +n23 n32 )v0 +n23 n33 v02 )
23 33
où nij est la j-ème coordonnée de ni .
Une fois r calculé, on peut obtenir des dimensions pour notre nouvelle image :
Pour cela on définit W = max(W1 , W2 ) (où W1 et W2 sont les longueurs des bords horizontaux) et H = max(H1 , H2 ) (les longueurs des bords verticaux). On calcule alors un rapport
temporaire r = W /H et :
— Si r ≥ r alors W = W et H = W /r
— Sinon H = H et W = rH.
5
Correction de l’image
Il faut ensuite corriger l’image pour rendre l’arrière plan blanc uniforme se débarasser en
particulier des reflets et autres bruits non désirés. La technique est expliquée dans l’article sur
Eprel.
6
Améliorations
Vous pouvez améliorer le projet comme vous le souhaitez : interface graphique, reconstruction d’image de tableau à partir de plusieurs images partielles...
A
Installer opencv
Pour pouvoir utiliser opencv avec python 3, il faut que vous installiez la dernière version
d’opencv ainsi que numpy. Installer numpy est très simple : pip install numpy.
— Sous archlinux yaourt opencv-git
M1 Python – Cours : P. Vanier
4/5
Projet Python : Redressement d’images de tableau
P. Vanier, T. Kaced
— Sous gentoo emerge opencv-3.0.0
— Sous ubuntu/debian/mint des instructions sont disponibles : http://docs.opencv.org/
doc/tutorials/introduction/linux_install/linux_install.html
N’oubliez pas d’installer les paquets libavcodec-dev libavformat-dev libswscale-dev
libv4l-dev libjpeg8-dev libtiff4-dev libjasper-dev libpng12-dev build-essential
cmake git pkg-config
B
Installer scikit-image
Il suffit d’utiliser pip.
M1 Python – Cours : P. Vanier
5/5
Téléchargement