TP
This commit is contained in:
parent
53dfb79662
commit
0dc0134920
114
Chapitre 2 - Récursivité/C06_tp_pivoter_image.py
Normal file
114
Chapitre 2 - Récursivité/C06_tp_pivoter_image.py
Normal file
|
@ -0,0 +1,114 @@
|
||||||
|
# TP p 128
|
||||||
|
|
||||||
|
# 1. L'étape (ii) fait des appels récursifs
|
||||||
|
|
||||||
|
# 2. Pour une image de 2^n x 2^n pixels il y auras une profondeur de récurstion de n et il y auras 4^n appels récursifs
|
||||||
|
|
||||||
|
# 3. Oui, l'algorithme reste corect si l'on inverse l'ordre des étapes (i) et (ii).
|
||||||
|
|
||||||
|
# 4. Non, cet algorithme n'est pas facilement adaptable pour fonctionner avec
|
||||||
|
# des rectangles car il se base sur le fait de pouvoir diviser en 4 l'image.
|
||||||
|
|
||||||
|
# 5. L'algorithme peut transformer l'image sur place.
|
||||||
|
|
||||||
|
def echange_2blocs(m, x1, y1, x2, y2, w):
|
||||||
|
"""
|
||||||
|
Echange sur place (sans les pivoter) 2 blocs de w x w dans la matrice m,
|
||||||
|
le bloc 1 étant compris entre (x1, y1) et (x1 + (w-1), y1 + (w-1)) inclus,
|
||||||
|
et le bloc 2 étant de façon similaire entre (x2, y2) et (x2 + (w-1), y2 + (w-1)) inclus
|
||||||
|
Chaque pixel dans un bloc est échangé avec le pixel de même coordonnées dans le second bloc.
|
||||||
|
-------
|
||||||
|
Complexité : quadratique en w.
|
||||||
|
"""
|
||||||
|
for i in range(w):
|
||||||
|
for j in range(w):
|
||||||
|
m[x2+i][y2+j], m[x1+i][y1+j] = m[x1+i][y1+j], m[x2+i][y2+j]
|
||||||
|
|
||||||
|
|
||||||
|
def permuter_4blocs(m, x, y, w):
|
||||||
|
"""
|
||||||
|
Permute sur place (sans les pivoter) les 4 blocs d'un carré dans l'image m,
|
||||||
|
le carré de w x w pixels compris entre (x, y) et (x + (w-1), y + (w-1)) inclus.
|
||||||
|
-------
|
||||||
|
Suppose (entre autres) que w est pair.
|
||||||
|
-------
|
||||||
|
Complexité : quadratique en w.
|
||||||
|
-------
|
||||||
|
Attention, on adopte la convention "image" pour les matrices :
|
||||||
|
m[i][j] donne la i-ième ligne et j-ième colonne en partant du haut à gauche.
|
||||||
|
La permutation se fait en échangeant les quartiers 2 à 2:
|
||||||
|
- (imin, jmin) avec (imin, jmax)
|
||||||
|
- (imin, jmin) avec (imax, jmin)
|
||||||
|
- (imax, jmin) avec (imax, jmax)
|
||||||
|
où par exemple (imin, jmin) représente le bloc comportant les plus petites valeurs sur i et j.
|
||||||
|
"""
|
||||||
|
echange_2blocs(m, x, y, x, y + w // 2, w // 2)
|
||||||
|
echange_2blocs(m, x, y, x + w // 2, y, w // 2)
|
||||||
|
echange_2blocs(m, x + w // 2, y, x + w // 2, y + w // 2, w // 2)
|
||||||
|
|
||||||
|
|
||||||
|
def pivoter_rec(m, x, y, w):
|
||||||
|
"""
|
||||||
|
Pivote récursivement d'un quart de tour
|
||||||
|
le carré compris entre (x, y) et (x + (w-1), y + (w-1)) inclus
|
||||||
|
dans la matrice m.
|
||||||
|
-------
|
||||||
|
Suppose (entre autres) que w est une puissance de 2.
|
||||||
|
-------
|
||||||
|
Complexité : quadratique en w.
|
||||||
|
"""
|
||||||
|
if w > 1:
|
||||||
|
new_w = w//2
|
||||||
|
pivoter_rec(m, x, y, new_w)
|
||||||
|
pivoter_rec(m, x+new_w, y, new_w)
|
||||||
|
pivoter_rec(m, x+new_w, y+new_w, new_w)
|
||||||
|
pivoter_rec(m, x, y+new_w, new_w)
|
||||||
|
permuter_4blocs(m, x, y, w)
|
||||||
|
|
||||||
|
|
||||||
|
def pivoter(m):
|
||||||
|
"""
|
||||||
|
Pivote une image d'un quart de tour à droite en utilisant l'algorithme récursif
|
||||||
|
de type « diviser pour régner » présenté dans le manuel.
|
||||||
|
-------
|
||||||
|
Entrée:
|
||||||
|
- une matrice m, de dimensions 2^k x 2^k.
|
||||||
|
- m[0][0] représente le coin en haut à gauche de l'image, m[0][len(m)] le coin en haut à droite.
|
||||||
|
Modifie la matrice m sur place.
|
||||||
|
-------
|
||||||
|
Complexité: k x 2^k x 2^k.
|
||||||
|
"""
|
||||||
|
w = len(m)
|
||||||
|
assert (w & (w - 1) == 0) and w != 0
|
||||||
|
assert w == len(m[0])
|
||||||
|
pivoter_rec(m, 0, 0, w)
|
||||||
|
|
||||||
|
|
||||||
|
# Test:
|
||||||
|
m = [['a','b'],['d','c']]
|
||||||
|
pivoter(m)
|
||||||
|
print(m==[['d', 'a'], ['c', 'b']])
|
||||||
|
|
||||||
|
m = [[1,2,3,4],[5,6,7,8],[9,10,11,12],[13,14,15,16]]
|
||||||
|
pivoter(m)
|
||||||
|
print(m==[[13, 9, 5, 1], [14, 10, 6, 2], [15, 11, 7, 3], [16, 12, 8, 4]])
|
||||||
|
|
||||||
|
# Attention de choisir une image carrée (même nombre de pixels sur x et y) dont les dimensions soient une puissance de 2.
|
||||||
|
import matplotlib.pyplot as plt
|
||||||
|
import matplotlib.image as mpimg
|
||||||
|
|
||||||
|
|
||||||
|
m = [[.4,.1],[.8,.8]]
|
||||||
|
plt.imshow(m)
|
||||||
|
plt.show()
|
||||||
|
pivoter(m)
|
||||||
|
plt.imshow(m)
|
||||||
|
plt.show()
|
||||||
|
|
||||||
|
img = mpimg.imread('python256_couleur.png').tolist()
|
||||||
|
imgplot = plt.imshow(img)
|
||||||
|
plt.show()
|
||||||
|
|
||||||
|
pivoter(img)
|
||||||
|
plt.imshow(img)
|
||||||
|
plt.show()
|
|
@ -165,4 +165,3 @@ better_hanoi(4, [4, 3, 2, 1], [], [])
|
||||||
|
|
||||||
# Il faut faire du code simple sans utiliser goto, setjmp ou longjmp et ne pas utiliser de récursion directe ou indirecte.
|
# Il faut faire du code simple sans utiliser goto, setjmp ou longjmp et ne pas utiliser de récursion directe ou indirecte.
|
||||||
# Cela est utile car cela permet d'avoir un code plus clair et plus facilement analysable pour détécter des erreurs.
|
# Cela est utile car cela permet d'avoir un code plus clair et plus facilement analysable pour détécter des erreurs.
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue