Plan 256 shades of grey 1 Du pixel au fichier Pixels Formats de fichiers image 2 Manipulations avec Python Trois niveaux d’abstraction Du fichier aux pixels Des pixels au fichier Un peu de technique 3 Quelques traitements d’image Gestion du contraste Éclaircissement Floutage Détection de contours [email protected] - http://blog.psi945.fr Lundi 9 janvier 2017 Stéphane Gonnord 256 shades of grey Année 2016/2017 1 / 16 Qu’est-ce qu’une image ? Stéphane Gonnord 256 shades of grey Année 2016/2017 2 / 16 Quelques formats d’image À l’écran/sur le papier : un rectangle/une matrice de pixels (PICture ELements). Chat : image 2048 × 1536 pixels ; poids en kilo-octets. Un pixel = nuance de gris (...) entre 0 et 255... ou entre 0 et 1. Ou bien (RGB) : trois niveaux Red/Green/Blue de 0 à 255. Stockage dans un fichier : � � pixel par pixel... ou par compression d’une image initiale. Compression : destructive ou non (avec ou sans perte d’information). Poids d’un fichier BitMaP (pixel par pixel sans compression) en RGB : 3 × L × H octets ; trois fois moins en noir et blanc ! Stéphane Gonnord 256 shades of grey Année 2016/2017 3 / 16 Ext. destr. compr. chat (RGB) chat (N&B) bmp png gif jpg NON NON NON OUI NON OUI OUI OUI 9437 4999 3336 400 3147 1533 3367 366 Stéphane Gonnord 256 shades of grey Année 2016/2017 4 / 16 Trois niveaux d’abstraction (via PIL) Du fichier aux pixels Le fichier, support « physique », sur le disque. Image.open : objet image à partir du fichier. L’objet Python « image » intermédiaire. Contient les informations sur l’encodage... et les données. numpy.array : tableau/matrice de pixels à partir de l’objet image. La matrice des pixels. Définition de l’objet et de la matrice >>> chat = im.open(’images_out/baroudeurBW.jpg’) >>> pixels_chat = np.array(chat) Fichier Objet Python Matrice de pixels ’baroudeur.bmp’ <PIL.BmpImage... ... image mode=RGB ...> <PIL.JpegImage... ... image mode=RGB ...> <PIL.JpegImage... ... image mode=L ...> array([[[ 12, 16, 25], ... [80, 86, 60]]], dtype=uint8) array([[[ 12, 16, 25], ... [80, 86, 60]]], dtype=uint8) array([[14, 15, 15, ..., ... ... 80, 80, 80]], dtype=uint8) ’baroudeur.jpg’ ’baroudeurBW.jpg’ Stéphane Gonnord 256 shades of grey Exemple : Année 2016/2017 Résultat >>> chat <PIL.JpegImagePlugin.JpegImageFile image mode=L size=2048x1536 at 0xB5F911AC> >>> pixels_chat array([[ 14, 15, 15, ..., 208, 212, 215], [ 14, 15, 15, ..., 211, 212, 214], ..., [208, 206, 203, ..., 80, 80, 80]], dtype=uint8) 5 / 16 Des pixels au fichier Stéphane Gonnord 256 shades of grey Année 2016/2017 6 / 16 Quelques points techniques Slicing : tableau[ a:b , c:d ] en lecture ou écriture. numpy.zeros( (a,b) ) et numpy.ones( (a,b) ) attention aux types. Conversion en niveaux (Levels) de gris : Image.fromarray : des pixels à l’objet image. Méthode save des objets image : pour sauver sous différents formats. Exemple : image.open(’image_couleur.jpg’).convert(’L’).save(’image_BW.png’) Que fais-je ? Appliquer une fonction aux pixels : deux approches pixels_chat = np.array( im.open(’baroudeurBW.jpg’) ) Appliquons f à M : pixels_chat[ 100:200 , 500:1500 ] = 255*np.ones((100, 1000),dtype=’uint8’) pixels1 = np.array(im.open(’baroudeur.jpg’)) im.fromarray(pixels_chat).save(’mystere.jpg’) (H, L, _) = pixels1.shape # hauteur * largeur * 3 pixels2 = np.copy(pixels1) Pixel par pixel ; 48 secondes for i in range( H ): for j in range( L ): pixels2[i][j] = contraste( pixels2[i][j] ) Par application d’une fonction « vectorisée » au tableau ; 3 secondes contraste_vecto = np.vectorize( contraste ) pixels2 = contraste_vecto( pixels1 ) # en fait : pixels2 = np.array( ... , dtype=’uint8’) im.fromarray(pixels2).save(’baroudeurBW2.jpg’) Stéphane Gonnord 256 shades of grey Année 2016/2017 7 / 16 Stéphane Gonnord 256 shades of grey Année 2016/2017 8 / 16 Fonction de contraste Que devient le chat ? On applique f : {0, 1, ..., 255} → {0, 1, ..., 255} à chaque pixel. Pour contraster/décontraster : f1 (x ) = 128 + 2 × (x − 128) f2 (x ) = 128 + (x − 128)/2 On revient à {0, 1, ..., 255} en cas de dépassement ! ��� � � �� ��� � � �� ��� � ��� ��� �� � � Stéphane Gonnord �� ��� � 256 shades of grey ��� ��� Année 2016/2017 9 / 16 Un goutte contrastée 5 fois Stéphane Gonnord 256 shades of grey Stéphane Gonnord 256 shades of grey Année 2016/2017 10 / 16 Année 2016/2017 12 / 16 Un autre, aux bords moins nets Année 2016/2017 11 / 16 Stéphane Gonnord 256 shades of grey Floutons πR 2 ! Éclaircissement ou assombrissement Fonction pour éclaircir/assombrir : f3 (x ) = 255 − (255 − x )/2 ��� Mi ,j ← f4 (x ) = x /2 1 9 (Mi −1,j −1 + · · · + Mi +1,j +1 ) � � �� ��� � � �� ��� � ��� ��� �� � � Stéphane Gonnord �� ��� � ��� ��� 256 shades of grey Année 2016/2017 13 / 16 Stéphane Gonnord Détection de contours C’est fini ! On noircit les pixels (i , j ) tels que : Merci de votre attention 256 shades of grey Année 2016/2017 14 / 16 256 shades of grey Année 2016/2017 16 / 16 (Pi −1,j − Pi +1,j )2 + (Pi ,j −1 − Pi ,j +1 )2 > s, avec un seuil... à fixer ! On contraste d’abord l’image Stéphane Gonnord 256 shades of grey Année 2016/2017 15 / 16 Stéphane Gonnord