Connexion élèves

Choisir le(s) module(s) à installer :

Parcours de matrices

Principe

Comme pour le parcours d'un tableau "simple" il y a également deux méthodes, qui utilisent toutes les deux deux boucles imbriquées :

Parcours par valeur


matrice = [[0,1,2,3],[4,5,6,7],[8,9,10,11]]

for ligne in matrice :  # boucle sur les "lignes"
	for element in ligne : # boucles sur les éléments de chacune des "lignes"
		print(element, end =' ')	
	
>>> 0 1 2 3 4 5 6 7 8 9 10 11
			

On retrouve la même structure que pour la construction de matrices par compréhension :

Parcours par indice


matrice = [[0,1,2,3],[4,5,6,7],[8,9,10,11]]

lignes = len(matrice) # nombre d'éléments dans la matrice = nombre de "lignes"
colonnes = len(matrice[0])  # nombre d'éléments dans le premier sous-tableau = nombre de "colonnes" !

for l in range(lignes) :  # boucle sur les "lignes"
	for c in range(colonnes) : # boucles sur les "colonnes"
		print(matrice[l][c])	# affichage de l'élément à la ligne l et à la colonne c
	
>>> 0 1 2 3 4 5 6 7 8 9 10 11
			

La deuxième méthode semble plus compliquée, mais c'est la seule qui permette en plus de modifier les éléments de la matrice ( c'est impossible avec la première méthode ).

Exercices

Affichages multiples

Pour cet exercice, on travaillera avec une matrice quelconque, par exemple celle ci-dessous :


m = [[0, 1, 2, 3], [4, 5, 6, 7], [8, 9, 10, 11],[12, 13, 14, 15]]			
			
			

On rappelle que pour afficher des éléments sur une même ligne, il faut rajouter un argument dans la fonction print() :


print(x, end =' ') # affiche la valeur de x sans revenir à la ligne				
				

Pour sauter une ligne, il suffit d'un print() sans aucun argument :


print() # saute une ligne			
				

A partir de la matrice créée à la deuxième question de l'exercice 2.4.1 :

  1. afficher la matrice ligne par ligne
    
    [0, 1, 2, 3]
    [4, 5, 6, 7]
    [8, 9, 10, 11]
    [12, 13, 14, 15]
    					
  2. afficher la matrice élément par élément mais en les présentant en lignes et en colonnes
    
    0 1 2 3
    4 5 6 7
    8 9 10 11
    12 13 14 15
    					
  3. afficher la matrice colonne par colonne ( plus dur ! )
    
    0 4 8 12
    1 5 9 13
    2 6 10 14
    3 7 11 15
    					
m = [[0,1,2,3],[4,5,6,7],[8,9,10,11],[12,13,14,15]]

Lien vers les RÉPONSES

Inverser les zéros et les uns

Dans cet exercice, une fonction doit muter une matrice, c'est à dire qu'elle la prend en paramètre, la modifie, mais n'a pas besoin de la renvoyer puisque la modification "perdure" en dehors de la fonction une fois la modification faite; c'est le problème des "effets de bord" évoqués dans la page sur les tableaux en paramètre de fonction.
Normalement, ces effets de bord sont à éviter, mais on s'en sert au contraire ici...

Parcours par valeur ou par indice dans ce cas ?

Compléter la fonction inverser_0_et_1 qui :

  • prend en paramètres une matrice mat d'entiers égaux à 0 ou à 1,
  • mute mat afin d'en inverser toutes les valeurs : les 0 sont transformés en 1, et les 1 sont transformés en 0.

[[0, 1, 1, 0],				[[1, 0, 0, 1],	
[1, 0, 1, 0],		=>		[0, 1, 0, 1],
[0, 0, 0, 1]]				[1, 1, 1, 0]]	
			
def inverser_0_et_1(mat: list): pass

Lien vers les RÉPONSES

Maximum/Minimum d'une matrice

Objectif : adapter l'algorithme de la recherche du maximum/minimum dans un tableau, à la recherche dans une matrice.

Parcours par valeur ou parcours par indice ??

  1. écrire une fonction maximum_matrice() qui prend en paramètre une matrice m d'entiers, et renvoie la valeur du maximum dans cette matrice.
  2. écrire une fonction minimum_matrice() qui prend en paramètre une matrice m d'entiers, et renvoie la valeur du minimum dans cette matrice.
  3. tester les fonctions avec le jeu de test suivant :
    	
    mat_a = [[0,  7,  8,  9,  5,  3,  2,  12], 
             [13, 6,  7,  8,  3,  15, 16, 4], 
             [-2, 6,  8,  21, 5,  6,  8,  4]]
    maximum_matrice(mat_a) == 21
    minimum_matrice(mat_a) == -2
    
    mat_b = [[2, 3, 4], 
             [5, 6, 7], 
             [8, 9, 8], 
             [7, 6, 5]]
    maximum_matrice(mat_b) == 9
    minimum_matrice(mat_b) == 2
    
    mat_c = [[-5, -7, -8],
             [-4, -2, -9],
             [-1, -2, -7]]
    maximum_matrice(mat_c) == -1	
    maximum_matrice(mat_c) == -9	
    					
def maximum_matrice(m: list)->int: pass def minimum_matrice(m: list)->int: pass

Lien vers les RÉPONSES

Manipulation d'images plus poussées

Il va s'agir maintenant d'utiliser de "vraies" images ( des photos, quoi...), pour les manipuler comme on le ferait avec un logiciel de retouche d'images.

Choisissez une image quelconque ( mais pas trop grande ! ) en couleur au format .jpg ou .png.

Pour manipuler les images facilement, vous pourrez utiliser le module images.py, qui s'appuie aussi sur le module PIL.

Une fois importé, ce module propose deux fonctions :

  • get_pixels(nom_fichier) qui permet d'ouvrir un fichier image et de renvoyer la matrice de ses pixels codés sous forme de tuples (R,V,B).
  • show_image(data) qui permet d'afficher une image en lui passant comme argument une matrice de tuples (R,V,B).

Par exemple, pour ouvrir et afficher une image à partir d'un fichier image :


from images import *

data = get_pixels("fichier_image.jpg")

show_image(data)				
				

Attention, la fonction get_pixels renvoie toujours une matrice de tuples (R, V, B), que l'image soit en niveau de gris ou en couleurs.

  • avec Pyzo, pensez à enregistrer les fichiers images et le module images.py dans le même répertoire que les scripts que vous allez écrire.
  • avec les éditeurs de la page, pensez à installer le module PIL, et à placer dans le système de fichiers virtuel le module images.py et les fichiers images.

Vous écrirez les fonctions qui permettront de transformer la matrice des valeurs de pixels pour obtenir l'effet recherché.

Le programme principal de votre script devra :

La fonction devra au préalable faire une copie de la matrice des pixels d'origine, et ne travailler ensuite que sur cette copie. On évitera ainsi les effets de bord et on ne perdra pas les données de l'image de départ.

Revoir la page expliquant comment faire une "vraie" copie de tableau/matrice.


from images import *
import copy

def ma_fonction(matrice: list)->list:
	'''
		Fonction qui modifie une matrice de pixels pour obtenir un certain effet
		
		Entrée :
			la matrice des valeurs de pixels de l'image
			d'autres paramètres si besoin...
		Sortie :
			une matrice des valeurs de pixels modifiées	
	'''
	
	copie = copy.deepcopy(matrice) # copie de la matrice d'origine
	....... # modification de la matrice des valeurs de pixels
	.......
	.......
	
	return copie
	

data = get_pixels("fichier_image") # récupération des données de l'image ( nom à adapter ! )

data2 = ma_fonction(data) # appel de la fonction et récupération de la matrice modifiée

show_image(data2) # affichage de la nouvelle image		
			

Le négatif

Effet très populaire dans les années 70 et 80 : les pixels blancs de l'image sont transformés en pixels noirs, et vice et versa; de manière générale, toutes les valeurs de pixels sont remplacées par leur complément à 255 :

  • 0 devient 255
  • 255 devient 0
  • donc, de manière générale, une valeur quelconque est remplacée par 255 - valeur

Sur une image en couleurs, il faut donc remplacer chaque tuple (R, V, B) codant un pixel, par le tuple (255-R, 255-V, 255-B).

Chat normal
Chat normal
Chat inversé
Chat inversé
from images import * import copy def image_negatif(mat: list)->list: copie = copy.deepcopy(mat) for ... in ...: for ... in ... : pixel = ... R = ... V = ... B = ... nv_pixel = ... ... = nv_pixel return copie ## Programme principal data = get_pixels("fichier_image") data2 = image_negatif(data) show_image(data2)

Lien vers les RÉPONSES

Le seuil

Effet qui revient à transformer une image en niveaux de gris ou en couleurs en une image en noir et blanc ou en 2 couleurs : tous les pixels en dessous d'une certaine valeur ( appelée "seuil" ) sont transformés en pixels noirs ( valeur = 0 ), et tous les pixels de valeur supérieure au seuil sont transformés en pixels blancs ( valeur = 255 ). Il n'y a donc effectivement plus que deux "couleurs" dans l'image.
Selon la valeur du seuil ( que l'on passera en argument à la fonction ), on obtient des effets différents :

Chat normal
Chat normal
Chat seuil 50
Seuil à 50
Chat seuil 150
Seuil à 150
Chat seuil 200
Seuil à 200
from images import * import copy def image_seuil(mat: list, seuil: int)->list: copie = copy.deepcopy(mat) for ... in ...: for ... in ... : pixel = ... R = ... if R > seuil: R = ... else: R = ... V = ... if V > seuil: V = ... else: V = ... B = ... if B > seuil: B = ... else: B = ... nv_pixel = ... ... = nv_pixel return copie ## Programme principal data = get_pixels("fichier_image") data2 = image_seuil(data, 100) # valeur du seuil à expérimenter ! show_image(data2)

Lien vers les RÉPONSES

L'image retournée

Ou comment faire pivoter l'image de 180° ?

Chat normal
Chat normal
Chat renversé
Chat renversé
from images import * import copy def image_180(matrice: list)->list: pass ## Programme principal data = get_pixels("fichier_image") data2 = image_180(data) show_image(data2)

Lien vers les RÉPONSES

Noir et blanc

Comment transformer une image en couleur en image en niveaux de gris ?

Singe en couleurs
Singe en couleurs
Singe monochrome
Singe gris

Indication : il faut remplacer dans chaque tuple les valeurs (R,V,B) par un nombre identique, égal à la moyenne pondérée de ces trois valeurs, selon la formule suivante :
Gris = 0,2126 × Rouge + 0,7152 × Vert + 0,0722 × Bleu.

from images import * import copy def couleurs_gris(matrice: list)->list: pass ## Programme principal data = get_pixels("fichier_image") data2 = couleurs_gris(data) show_image(data2)

Lien vers les RÉPONSES

Application

Sur la base de l'algorithme de parcours de tableau, nous pouvons également travailler maintenant avec les matrices.

Nous allons utiliser un exemple concret de recherche dans une matrice contenant "beaucoup" de données.
Pour cela téléchargez le fichier liste-des-communes-2019.csv. Il contient la liste des communes françaises, ainsi que leur population en 2019 et leur rang dans le classement des populations, sans ex-æquo.
Le code ci-dessous permet de transférer toutes ces données dans une matrice ( un tableau de tableaux ).


import csv

liste = []
with open("liste-des-communes-2019.csv", 'r', encoding='utf-8') as f:
    lecteur = csv.reader(f, delimiter = ';')
    for ligne in lecteur:
        liste.append([int(ligne[0]), ligne[1], int(ligne[2])])				
				

Chaque "ligne" de la matrice correspond à une ville; les données sont classées dans cet ordre : rang, nom de commune, population.
Un affichage d'un extrait de la matrice donnera :


[11, 'Rennes', 216268]
[12, 'Reims', 183113]
[13, 'Saint-Étienne', 171924]				
				

Vous avez a votre disposition une grande série de données et vous avez vu les algorithmes permettant de calculer une moyenne un maximum (ou un minimum...).
Vous devez coder un programme qui répondra aux questions suivantes :

  1. Quelle est la commune ayant le plus grand nombre d'habitants ?
  2. Quelle est la commune ayant le plus petit nombre d'habitants ?
  3. Quelle est la moyenne d'habitants par commune en France ?

Votre programme devra être structuré en fonctions.

import csv liste = [] with open("liste-des-communes-2019.csv", 'r', encoding='utf-8') as f: lecteur = csv.reader(f, delimiter = ';') for ligne in lecteur: liste.append([int(ligne[0]), ligne[1], int(ligne[2])])

Question :

Quelle est la complexité de la recherche d'une valeur dans une matrice ?

Lien vers les RÉPONSES