-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathpreprocess.py
More file actions
144 lines (127 loc) · 5.31 KB
/
preprocess.py
File metadata and controls
144 lines (127 loc) · 5.31 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
import numpy as np
import sys
import time
from PIL import Image
import warnings
try:
from scipy.ndimage import convolve as scipy_convolve
scipy_available = True
except ImportError:
scipy_available = False
warnings.warn("""\033[93m\nScipy n'est pas disponible. Le paramètre fast est automatiquement corrigé en False.
Si pip est installé, exécutez 'pip install scipy', '!pip install scipy' ou 'py -m pip install scipy' pour pouvoir utiliser fast=True.\033[0m""", category=UserWarning)
def progress_bar(iteration: int, total: int, timing: float, length=80):
"""
Affiche une barre de progression pour permettre à l'utilisateur de savoir où il en est.
Parameters
----------
iteration : int
Numéro de la tache qu'on est en train de faire
total : int
Nombre total d'itérations pour compléter la tâche
timing : float
Heure de début
length : int, optional
Longueur de la barre dans la console, par défaut 80
"""
percent = (iteration / total) * 100
filled_length = int(length * iteration // total)
bar = '█' * filled_length + '-' * (length - filled_length)
sys.stdout.write(f'\r|{bar}| {percent:.2f}% ({time.time()-timing}s)')
sys.stdout.flush()
def read_image(image_path: str) -> np.ndarray:
"""
Ouvre l'image et la convertit en niveaux de gris et en np.ndarray.
Parameters
----------
image_path : str
Chemin vers l'image.
NOTE : Attention, sur VSCode, il faut mettre le chemin par rapport au dossier ouvert, pas pas rapport au fichier. Sur IDLE,
le chemin relatif suffit.
Returns
-------
np.array
L'image convertie en niveaux de gris
"""
print("Importation de l'image...")
timing = time.time()
img = Image.open(image_path).convert("L") # Convertit en niveaux de gris
progress_bar(1, 1, timing)
print()
return np.array(img)
def convolve(image: np.ndarray, kernel: np.ndarray, debug=True, fast=True) -> np.ndarray:
"""
Applique une convolution sur l'image avec un calcul optimisé si `fast=True`.
Parameters
----------
image : np.ndarray
L'image avec 1 canal sous-entendu et 2 dimensions (i.e. image.shape == (height, width)).
kernel : np.ndarray
La matrice de convolution à appliquer.
debug : bool, optional
Affiche une barre de progression si True, par défaut True.
fast : bool, optional
Utilise une convolution rapide avec scipy.ndimage.convolve si True, par défaut True.
Returns
-------
np.ndarray
L'image convoluée.
"""
if fast and not scipy_available:
fast = False # Bascule automatiquement si scipy est absent
if fast:
image = image.astype(np.float32)
return scipy_convolve(image, kernel, mode='nearest', cval=0.0) # type: ignore # noter que la convolution manuelle utilise le mode constant
kernel_height, kernel_width = kernel.shape
pad_height, pad_width = kernel_height // 2, kernel_width // 2
padded_image = np.zeros((image.shape[0] + 2 * pad_height, image.shape[1] + 2 * pad_width))
for i in range(image.shape[0]):
for j in range(image.shape[1]):
padded_image[i + pad_height, j + pad_width] = image[i, j]
output = np.zeros(image.shape)
if debug==True:
print("Convolution de l'image...")
timing = time.time()
for i in range(image.shape[0]):
for j in range(image.shape[1]):
region = padded_image[i:i + kernel_height, j:j + kernel_width]
output[i, j] = np.sum(region * kernel) # "Produit" matriciel
if debug==True: progress_bar(i + 1, image.shape[0], timing) # type: ignore
if debug==True:
print()
return output
def calculate_max_gradient(image: np.ndarray) -> tuple:
"""
NOTE : cette version devrait être renommée calculate_mean_gradient.
Calcule la moyenne des gradiants dans l'image de bords donnée.
Parameters
----------
image : np.ndarray
L'image à traiter. A priori une petite partie d'une grande image
Returns
-------
list
Les moyennes des normes et arguments des gradiants de l'image
"""
sobel_x = np.array([[1, 0, -1],
[2, 0, -2],
[1, 0, -1]])
sobel_y = np.array([[1, 2, 1],
[0, 0, 0],
[-1, -2, -1]])
x = convolve(image, sobel_x, False)
y = convolve(image, sobel_y, False)
magnitudes = np.sqrt(x**2 + y**2)
gradient_magnitude = np.mean(magnitudes)
test = np.arctan2(y, x) * 180 / np.pi
indices = magnitudes != 0
try: # marche mais on a quand même le warning. Pasla priorité mais regarder comment corriger ça.
gradient_angle = np.mean(test[indices] % 180)
except RuntimeWarning:
gradient_angle = -1 # Valeur arbitraire qui sera de toute façon ignorée par le fait que la magnitude est nulle
"""
angles_positive = test[np.where(test > 157.5)] - 180
angles_negative = test[np.where(test < -22.5)] + 180
gradient_angle = np.mean(np.concatenate((angles_positive, angles_negative, angles_in_range)))
"""
return (gradient_magnitude, gradient_angle)