• Aucun résultat trouvé

TP2 TRAITEMENT D IMAGE : CAMERA THERMIQUE ET SUIVI DE TRAJECTOIRE

N/A
N/A
Protected

Academic year: 2022

Partager "TP2 TRAITEMENT D IMAGE : CAMERA THERMIQUE ET SUIVI DE TRAJECTOIRE"

Copied!
6
0
0

Texte intégral

(1)

TP2 T RAITEMENT D IMAGE :

C AMERA THERMIQUE ET S UIVI DE TRAJECTOIRE

1. P

RELIMINAIRES

Pour faciliter la suite du projet et afin que tout le monde aie la même trame, voici quelques fonctions qui seront utiles :

import numpy as np form pylab import * def Gris(tabPix):

"""Convertit en niveau de gris"""

tabPix1=tabPix.copy()

tabPix1=tabPix1.astype(int)

tabPix1[:,:,0]=(tabPix1[:,:,0]+tabPix1[:,:,1]+tabPix1[:,:,2])/3#moyenne des 3 couleurs

tabPix1[:,:,0]=tabPix1[:,:,0]

tabPix1[:,:,1]=tabPix1[:,:,0]

tabPix1[:,:,2]=tabPix1[:,:,0]

tabPix1=tabPix1.astype('uint8') return tabPix1

def Seuillage(im,seuil) :

"""retourne un tableau seuillé """

tmp=im.copy()

tmp[:,:,0]=(im[:,:,0]>seuil) tmp[:,:,1]=(im[:,:,1]>seuil) tmp[:,:,2]=(im[:,:,2]>seuil) return tmp*255

Q1. Copier/coller ces deux fonctions au début de votre programme. Expliquer leur role.

Quelques petites remarques sur les tableaux images :

Pour créer une image à partir de rien, on créé une matrice numpy pleine de zéros que l’on remplira ensuite.

tabPix = np.zeros((ligne,colonne,3),dtype=np.int32)

Attention, (ligne,colonne) est à l’envers de (largeur,hauteur).

Il faut que le type de données soit toujours des entiers non signés sur un octet (uint8).

Cependant afin de pouvoir faire du traitement de l’image en toute liberté, le type sera un entier sur 4 octets (int32). Il faudra prendre la précaution de revenir en uint8 avant l’affichage ou la sauvegarde.

tabPix = np.uint8(tabPix)

Pour créer une image, c’est aussi très simple.

NouvImage = im.fromarray(tabPix) ou tabPix.copy()

On peut sauvegarder sur le disque ou visualiser l’image. On enregistre sur le disque à côté du fichier python. On peut utiliser les formats « jpg » ou « png » ou d’autres nouvImage.save("image.jpg")

On visualise avec imshow(tabPix)

Pour la suite, vous pouvez alors importer directement ces fonctions précédentes dans votre fichier en prenant soin de bien vous placer dans votre répertoire de travail avec la commande (certaines versions de Python nécessitent quand même l’exécution du code dans fonctions.py avant de passer à la suite) :

import os

os.chdir ("C :\\votre chemin”)

(2)

2. C

AMERA THERMIQUE

On a récupéré l’image d’une maison, issue d’une caméra thermique, nommée « image-thermique.jpg ». On veut faire ressortir les parties les plus chaudes pour repérer d’éventuelles fuites thermiques. On souhaiterait ne garder que les 10% les plus chauds en couleur, le reste passant en niveau de gris.

Pour manipuler plus aisément l’échelle de température, il est préférable de couper l’image initiale qui fait 540*720 pixels en deux images « image-thermique_reduite.jpg » où on supprime toute la partie droite de la photo contenant l’échelle et « echelle_de_temperature.jpg » où on ne garde que le cadre échelle.

Q2. Ecrire la procédure qui permet de créer ces deux images.

Comme les pixels chauds sont rouges voire blancs, on peut effectuer un travail de seuillage sur les différents canaux (R-V-B) : on garde tels quels les pixels dont les canaux appartiennent à un certain intervalle, les autres sont passés en niveau de gris. Il faudra faire attention au violet qui est constitué de rouge et de bleu …

La méthode utilisée pour le niveau de gris tient compte du fait que l’œil est plus sensible au vert et utilise la recommandation ITU-RBT601 pour les écrans 4:3 et 16:9 dans laquelle la couleur RVB est remplacée par Y=0.299∗R+0.587∗V+0.114∗B

Q3. Créer une fonction seuillageThermique(tabPix) et proposer les "bonnes" valeurs de seuil sur l’image «image-thermique_reduite.jpg ». On enregistrera le résultat de sortie dans un fichier nommé «points_chauds.jpg ».

3. F

LOUTAGE

On considère les matrices (

) et (

)

Pour chaque élément bij de B, on considère la matrice 3×3 Bij qui l’entoure, on calcule le produit de convolution de A par Bij (multiplication classique A*Bij) et on note cij la somme des coefficients de la matrice produit obtenue (fonction np.sum).

Si bij est un élément en bordure de B, on posera cij = bij. On forme ainsi une nouvelle matrice C dont les éléments intérieurs sont les cij (et les éléments au bord sont les bij).

On dit qu’on a filtré la matrice B par la matrice A, ou qu’on a appliqué le masque (filtre) A sur l’image B.

Q4. Créer la fonction filtrer1(filtreA,matB) qui prend en argument une matrice carrée filtreA de dimension taille×taille (taille est un entier impair ≥ 3) et une matrice quelconque matB de dimensions supérieures, et qui renvoie la matrice C (attention : si taille>3, la bordure devra être plus épaisse).

y=67

y=470

x=652 x=686

(3)

Vous pouvez tester votre fonction avec :

matA=np.array([[1,2,3],[-1,0,1],[-1,1,2]]) matB=np.array([[5,6,7,8,9,10],

[-5,-6,-7,-8,-9,-10], [1,1,1,1,1,1],

[2,2,3,3,4,4], [0,0,1,2,3,3]]) print(filtrer1(matA,matB))

On souhaite appliquer le filtre A aux 3 tableaux B[:,:,0], B[:,:,1], B[:,:,2] et enregistrer le résultat dans une matrice C de même format que B.

Voici la fonction filtrer(filtreA,matB) qui prend en argument une matrice carrée filtreA de dimension taille×taille et un tableau numpy matB de dimensions n×p×3,et qui renvoie le tableau C de dimensions identiques.

def filtrer(filtreA,matB):

taille=filtreA.shape[0] #matrice carree, donc shape[0]=shape[1]

bordure=taille//2

nb_lig,nb_col,nb_coul=matB.shape

matC=np.int32(np.copy(matB)) # forcer le type int32 for i in range(bordure,nb_lig-bordure):

for j in range(bordure,nb_col-bordure):

for k in range(3):

Bij=matB[i-bordure:i+bordure+1,j-bordure:j+bordure+1,k]

matC[i,j,k]=np.sum(filtreA*Bij) return matC

Pour des pixels, on applique le filtre A aux 3 tableaux B[:,:,0], B[:,:,1], B[:,:,2] et enregistrer le résultat dans une matrice C de même format que B.

Ces matrices réalisent un floutage par moyenne simple (coefficients tous égaux, de somme 1). Plus la taille du filtre est grande, plus le flou sera fort. On peut améliorer cette technique en utilisant un flou gaussien. Son principe est de calculer une moyenne pondérée en accordant plus de poids au pixel central et en diminuant le poids des pixels périphériques.

La matrice servant de filtre est calculée selon le modèle d’une courbe de Gauss (courbe en cloche) à 2 dimensions :

La fonction de Laplace-Gauss est ( )

A deux dimensions on utilise ( )

Plus l’écart type σ est grand, plus l’image sera floutée. En pratique, σ et la taille (impaire) du filtre étant fixés, on calcule chaque élément de la matrice filtre par la formule ( ) , où x et y sont le nombre de lignes et de colonnes qui séparent cet élément du centre, et k un coefficient constant tel que la somme de tous les éléments (de type float) ainsi calculés soit 1.

Par exemple, pour taille=5 et σ=0.9, le filtre est proche de :

(

)

Voici la fonction matriceFlouGaussien(taille,sigma) qui prend en argument la taille (impaire) de la matrice de floutage, sigma l’écart type de déviation standard et qui retourne la matrice filtre correspondant au niveau gaussien.

##resultat

[[ 5 6 7 8 9 10]

[ -5 38 44 50 56 -10]

[ 1 -32 -37 -42 -47 1]

[ 2 9 12 14 14 4]

[ 0 0 1 2 3 3]]

(4)

assert taille %2==1 # on verifie que taille est impaire mat = np. zeros ([ taille , taille ])

taille = taille // 2

for x in range (- taille , taille +1) : for y in range (- taille , taille +1) :

mat [x+ taille ,y+ taille ] = np.exp (-(x **2+ y **2) /(2*( sigma **2) )) return mat /np. sum ( mat )

Q5. Copier/coller les deux fonctions précédentes. Ecrire ensuite la fonction FloutageGaussien(tabPix,taille,sigma) qui utilise la fonction matriceFlouGaussien(taille,sigma) et filtrer(filtreA,matB) et qui renvoie la matrice tabPix qui a été floutée grâce au filtre défini dans la fonction matriceFlouGaussien

3. S

UIVI D

UNE BALLE

Vous trouverez dans le répertoire image les images issues d’une vidéo où une balle de golf blanche roule sur un plan incliné bleu. Sur la trajectoire de la balle, on trouve un obstacle modifiant ainsi la trajectoire suite au choc.

Une exportation a été faite afin de convertir cette vidéo en une série de 32 images. Cette opération simple a été faite grâce au logiciel « VirtualDub » accompagné du plug-in « DShowInput » (compatibilité de certains codecs). Afin de réduire, en masse, la taille des images, il a été ensuite utilisé « XnView ». Vous pouvez, si besoin, trouver aussi ces logiciels gratuits sur internet.

Nous sélectionnons, parmi ces images, l’image « trajectoire9.jpeg » comme étant pour nous une image représentative de l’ensemble des images à cause du flou de bougé de la balle, de la présence de la main et de la brique. (Le flou de bougé est le flou produit par le mouvement pendant l’exposition. L’exposition désigne la quantité totale de lumière reçue par la surface sensible (ici le capteur numérique) pendant la prise de vue.)

Q6. Charger l’image dans le tableau traj9. Pour la visualiser utiliser pl.imshow() Q7. Passer « l’image » en niveau de gris et afficher l’image.

Q8. Flouter « l’image » sur 9 pixels avec un écart type de 2.

On s’aperçoit que le temps de calcul est très long et cela peut être très préjudiciable pour traiter les 39 images. Nous allons donc définir une fonction optimisée floutageOptimise. Copier/coller la fonction suivante :

def floutageOptimise(tabPix,iteration):

"""floutage carré(moyenne avec les plus proche voisin, le nb d'iteration définie la puissance du floutage"""

flou=tabPix.copy() flou=flou.astype(float) for i in range(iteration):

flou[1:-1,1:-1]=(flou[2:,1:-1]+flou[:-2,1:-1]+flou[1:-1,2:]+flou[1:-1,:-2])/4 return flou.astype('uint8')

balle1flou=floutageOptimise(balle1,20) #il faut que balle1 soit l’objet grisé !!

pl.figure()

pl.imshow(balle1flou)

Q9. Définir une fonction Bordure(tabPix,taille) en convertissant en noir les pixels du bord de l’image, sur un nombre taille de pixels.

(5)

La fonction a comme paramètre tabPix un tableau de pixels en niveau de gris et taille la largeur en pixels de la bordure. Elle retourne un tableau de pixels en niveau de gris.

Q10. Convertir en noir le bord non flouté puis afficher l’image.

Q11. Seuiller « l’image » avec un seuil de 130 et afficher l’image.

Q12. Définir une fonction Centre(tabPix) qui retourne un tuple : les coordonnées du centre de la tâche blanche. La fonction a comme paramètre tabPix un tableau de pixels en niveau de gris.

Q13. Donner le centre de la tâche blanche puis tracer le point sur un graphique (Matplotlib.pyplot) en mettant en fond l’image (plt.imshow(np.uint8(tabPix))

Q14. Traiter les 32 images afin d’obtenir la trajectoire de la balle sur un graphique Matplotlib.pyplot avec les 32 centres uniquement. Fusionner ces centres sur un fond blanc ou sur un fond image, en faisant la moyenne sur un pixel des 32 images.

Voici le début de votre programme :

L = os.listdir('votre chemin') #On liste les images final[:,:,:]=255 #option fond blanc

#final=scm.imread(L[0])#option image 1 en arrière plan X=[]

Y=[]

for i in L:

#A vous de jouer : analyse de toutes les images

4. H

ISTOGRAMME

(

PARTIE INDEPENDANTE

)

Dans un nouveau fichier :

Q15. Charger l’image « trajectoire9.jpg » dans le tableau traj9. Puis passer « l’image » en niveau de gris

Q16. Flouter « l’image » sur 9 pixels avec un écart type de 2. Puis convertir en noir le bord non flouté

Q17. Faire un histogramme du niveau de gris.

(6)

A chaque fois que le seuil franchit un pic, on est susceptible d’effacer de l’image un ou des objets. Il peut être parfois utile d’effectuer un seuil juste sur une plage de valeurs.

Q18. Vérifier dans la mesure du possible cette affirmation.

Q19. Faire un choix sur le seuil à appliquer de façon à ne sélectionner que les pixels de la balle.

Q20. Seuiller « l’image » avec le seuil choisi et Afficher l’image.

Références

Documents relatifs

Ces nanocomposites hybrides organominéraux peuvent être utilisés comme filtre classique (absorption linéaire, pho- tochromisme) ou pour la protection laser (absorption non

Ces règles sont en fait autant d’instances différentes d’une seule et même règle qui associe à deux doublons de booléens un troisième doublon dont les coordonnées sont

Comme on le constate dans le diagramme de composi- tion CaO vs MgO (Figure 20), la composition des grenats du Diana correspond majo- ritairement aux Types I et II (avec

[r]

Combien faut-il examiner de malades pour verifier que le taux de reussite est bien de 70% avec la nouvelle mCthode, l'hypothkse alternative Ctant que ce taux n'atteint pas

MAUVE évite ce problème en utilisant des « Multiple Maximal Unique Matches » (multi-MUMs) de longueur minimum k comme ancres, c’est-à-dire des régions qui sont trouvées

Elle indique le sens dans lequel nous allons mettre nos données.. Fiche technique Réaliser

Pour faire cette comparaison le maraˆıcher pr´ el` eve, al´ eatoirement dans les semences de l’ann´ ee, un ´ echantillon de 200 graines qu’il met ` a germer1. Il constate que