diff --git a/server-trainer/Camera_Identification_VitesseRoadSign-ModelTraining.py b/server-trainer/Camera_Identification_VitesseRoadSign-ModelTraining.py new file mode 100644 index 0000000..ee8a039 --- /dev/null +++ b/server-trainer/Camera_Identification_VitesseRoadSign-ModelTraining.py @@ -0,0 +1,208 @@ +import tensorflow as tf +from tensorflow.keras import layers, models +import numpy as np +from sklearn.utils import shuffle +from sklearn.model_selection import train_test_split +import cv2 +import os +import time +import dataset + +size=42 +dir_images_panneaux="server-trainer/images/road_sign_speed_trainers/panneaux" +dir_images_autres_panneaux="server-trainer/images/road_sign_speed_trainers/autres_panneaux" +dir_images_genere_sans_panneaux="server-trainer/images/road_sign_speed_trainers/genere_sans_panneaux" + +batch_size=128 +nbr_entrainement=1 #20 + +def panneau_model(nbr_classes): + model=tf.keras.Sequential() + + model.add(layers.Input(shape=(size, size, 3), dtype='float32')) + + model.add(layers.Conv2D(128, 3, strides=1)) + model.add(layers.Dropout(0.2)) + model.add(layers.BatchNormalization()) + model.add(layers.Activation('relu')) + + model.add(layers.Conv2D(128, 3, strides=1)) + model.add(layers.Dropout(0.2)) + model.add(layers.BatchNormalization()) + model.add(layers.Activation('relu')) + + model.add(layers.MaxPool2D(pool_size=2, strides=2)) + + model.add(layers.Conv2D(256, 3, strides=1)) + model.add(layers.Dropout(0.3)) + model.add(layers.BatchNormalization()) + model.add(layers.Activation('relu')) + + model.add(layers.Conv2D(256, 3, strides=1)) + model.add(layers.Dropout(0.4)) + model.add(layers.BatchNormalization()) + model.add(layers.Activation('relu')) + + model.add(layers.MaxPool2D(pool_size=2, strides=2)) + + model.add(layers.Flatten()) + model.add(layers.Dense(512, activation='relu')) + model.add(layers.Dropout(0.5)) + model.add(layers.BatchNormalization()) + model.add(layers.Dense(nbr_classes, activation='sigmoid')) + + return model + +def lire_images_panneaux(dir_images_panneaux, size=None): + tab_panneau=[] + tab_image_panneau=[] + + if not os.path.exists(dir_images_panneaux): + quit("Le repertoire d'image n'existe pas: {}".format(dir_images_panneaux)) + + files=os.listdir(dir_images_panneaux) + if files is None: + quit("Le repertoire d'image est vide: {}".format(dir_images_panneaux)) + + for file in sorted(files): + if file.endswith("png"): + tab_panneau.append(file.split(".")[0]) + image=cv2.imread(dir_images_panneaux+"/"+file) + if size is not None: + image=cv2.resize(image, (size, size), cv2.INTER_LANCZOS4) + tab_image_panneau.append(image) + + return tab_panneau, tab_image_panneau + +tab_panneau, tab_image_panneau=lire_images_panneaux(dir_images_panneaux, size) + +tab_images=np.array([]).reshape(0, size, size, 3) +tab_labels=np.array([]).reshape(0, len(tab_image_panneau)) + +id=0 +for image in tab_image_panneau: + lot = [] + for _ in range(120): + lot.append(dataset.modif_img(image)) + lot = np.array(lot) + tab_images=np.concatenate((tab_images, lot)) + tab_labels=np.concatenate([tab_labels, np.repeat([np.eye(len(tab_image_panneau))[id]], len(lot), axis=0)]) + id += 1 + + +files=os.listdir(dir_images_autres_panneaux) +if files is None: + quit("Le repertoire d'image est vide:".format(dir_images_autres_panneaux)) + +nbr=0 +for file in files: + lot = [] + if file.endswith("png"): + path=os.path.join(dir_images_autres_panneaux, file) + image=cv2.resize(cv2.imread(path), (size, size), cv2.INTER_LANCZOS4) + for _ in range(700): + lot.append(dataset.modif_img(image)) + lot = np.array(lot) + tab_images=np.concatenate([tab_images, lot]) + nbr+=len(lot) + +tab_labels=np.concatenate([tab_labels, np.repeat([np.full(len(tab_image_panneau), 0)], nbr, axis=0)]) + +nbr_np=int(len(tab_images)/2) + +id=1 +nbr=0 +tab=[] +for cpt in range(nbr_np): + file=dir_images_genere_sans_panneaux+"/{:d}.png".format(id) + if not os.path.isfile(file): + break + image=cv2.resize(cv2.imread(file), (size, size)) + tab.append(image) + id+=1 + nbr+=1 + +tab_images=np.concatenate([tab_images, tab]) +tab_labels=np.concatenate([tab_labels, np.repeat([np.full(len(tab_image_panneau), 0)], nbr, axis=0)]) + +tab_panneau=np.array(tab_panneau) +tab_images=np.array(tab_images, dtype=np.float32)/255 +tab_labels=np.array(tab_labels, dtype=np.float32) #.reshape([-1, 1]) + +train_images, test_images, train_labels, test_labels=train_test_split(tab_images, tab_labels, test_size=0.10) + +train_ds=tf.data.Dataset.from_tensor_slices((train_images, train_labels)).batch(batch_size) +test_ds=tf.data.Dataset.from_tensor_slices((test_images, test_labels)).batch(batch_size) + +print("train_images", len(train_images)) +print("test_images", len(test_images)) + +@tf.function +def train_step(images, labels): + with tf.GradientTape() as tape: + predictions=model_panneau(images) + loss=my_loss(labels, predictions) + gradients=tape.gradient(loss, model_panneau.trainable_variables) + optimizer.apply_gradients(zip(gradients, model_panneau.trainable_variables)) + train_loss(loss) + train_accuracy(labels, predictions) + +def train(train_ds, nbr_entrainement): + for entrainement in range(nbr_entrainement): + start=time.time() + for images, labels in train_ds: + train_step(images, labels) + message='Entrainement {:04d}: loss: {:6.4f}, accuracy: {:7.4f}%, temps: {:7.4f}' + print(message.format(entrainement+1, + train_loss.result(), + train_accuracy.result()*100, + time.time()-start)) + train_loss.reset_states() + train_accuracy.reset_states() + test(test_ds) + +def my_loss(labels, preds): + labels_reshape=tf.reshape(labels, (-1, 1)) + preds_reshape=tf.reshape(preds, (-1, 1)) + result=loss_object(labels_reshape, preds_reshape) + return result + +def test(test_ds): + start=time.time() + for test_images, test_labels in test_ds: + predictions=model_panneau(test_images) + t_loss=my_loss(test_labels, predictions) + test_loss(t_loss) + test_accuracy(test_labels, predictions) + message=' >>> Test: loss: {:6.4f}, accuracy: {:7.4f}%, temps: {:7.4f}' + print(message.format(test_loss.result(), + test_accuracy.result()*100, + time.time()-start)) + test_loss.reset_states() + test_accuracy.reset_states() + +optimizer=tf.keras.optimizers.Adam() +loss_object=tf.keras.losses.BinaryCrossentropy() +train_loss=tf.keras.metrics.Mean() +train_accuracy=tf.keras.metrics.BinaryAccuracy() +test_loss=tf.keras.metrics.Mean() +test_accuracy=tf.keras.metrics.BinaryAccuracy() +model_panneau=panneau_model(len(tab_panneau)) +checkpoint=tf.train.Checkpoint(model_panneau=model_panneau) + +print("Entrainement") +train(train_ds, nbr_entrainement) +checkpoint.save(file_prefix="server-ia/data/modeles/road_sign_speed_trainers/modele_panneau") + +quit() + +for i in range(len(test_images)): + prediction=model_panneau(np.array([test_images[i]])) + print("prediction", prediction[0]) + if np.sum(prediction[0])<0.6: + print("Ce n'est pas un panneau") + else: + print("C'est un panneau:", tab_panneau[np.argmax(prediction[0])]) + cv2.imshow("image", test_images[i]) + if cv2.waitKey()&0xFF==ord('q'): + break diff --git a/server-trainer/RoadSigns-ModelTraining_MobileNetV2.py b/server-trainer/RoadSigns-ModelTraining_MobileNetV2.py new file mode 100644 index 0000000..dceda31 --- /dev/null +++ b/server-trainer/RoadSigns-ModelTraining_MobileNetV2.py @@ -0,0 +1,99 @@ +import os +import tensorflow as tf +from tensorflow.keras.preprocessing.image import ImageDataGenerator +from tensorflow.keras.applications import MobileNetV2 +from tensorflow.keras.layers import AveragePooling2D, Dropout, Flatten, Dense, Input +from tensorflow.keras.models import Model +from tensorflow.keras.optimizers import Adam +from sklearn.model_selection import train_test_split +from sklearn.metrics import classification_report +from imutils import paths +import numpy as np + +# Définir les chemins des données d'entraînement et de validation +train_data_dir = "server-trainer/images/road_sign_trainers/train_speed" +valid_data_dir = "server-trainer/images/road_sign_trainers/test_speed" + +# Initialiser les hyperparamètres +INIT_LR = 1e-4 +EPOCHS = 1 +BS = 32 + +# Charger et prétraiter les images +train_datagen = ImageDataGenerator( + rescale=1.0 / 255, + rotation_range=20, + zoom_range=0.15, + width_shift_range=0.2, + height_shift_range=0.2, + shear_range=0.15, + horizontal_flip=True, + fill_mode="nearest" +) + +valid_datagen = ImageDataGenerator(rescale=1.0 / 255) + +train_generator = train_datagen.flow_from_directory( + train_data_dir, + target_size=(224, 224), + batch_size=BS, + class_mode='categorical' +) + +valid_generator = valid_datagen.flow_from_directory( + valid_data_dir, + target_size=(224, 224), + batch_size=BS, + class_mode='categorical' +) + +# Générer le fichier class_names.txt +class_names_file = os.path.join("server-ia/data/modeles/RoadSign", "class_names.txt") +with open(class_names_file, "w") as f: + # Utiliser le générateur class_indices pour récupérer les noms de classe et les écrire dans le fichier + for class_name, class_index in train_generator.class_indices.items(): + f.write(f"{class_name}\n") + +# Charger le modèle pré-entraîné MobileNetV2 sans la couche supérieure +base_model = MobileNetV2( + weights="imagenet", + include_top=False, + input_tensor=Input(shape=(224, 224, 3)) +) + +# Construire le modèle de tête qui sera placé au-dessus du modèle de base +head_model = base_model.output +head_model = AveragePooling2D(pool_size=(7, 7))(head_model) +head_model = Flatten(name="flatten")(head_model) +head_model = Dense(128, activation="relu")(head_model) +head_model = Dropout(0.5)(head_model) +head_model = Dense(len(train_generator.class_indices), activation="softmax")(head_model) + +# Combiner le modèle de base avec le modèle de tête +model = Model(inputs=base_model.input, outputs=head_model) + +# Geler les couches du modèle de base +for layer in base_model.layers: + layer.trainable = False + +# Compiler le modèle +opt = Adam(learning_rate=INIT_LR) +model.compile(loss="categorical_crossentropy", optimizer=opt, metrics=["accuracy"]) + +# Entraîner le modèle +history = model.fit( + train_generator, + steps_per_epoch=len(train_generator), + validation_data=valid_generator, + validation_steps=len(valid_generator), + epochs=EPOCHS +) + +# Sauvegarder le modèle +model.save("server-ia/data/modeles/RoadSign/modele_signaux_routiers.h5") + +# Évaluer le modèle +print("[INFO] Évaluation du modèle...") +predictions = model.predict(valid_generator, steps=len(valid_generator), verbose=1) +predictions = np.argmax(predictions, axis=1) +print(classification_report(valid_generator.classes, predictions, target_names=valid_generator.class_indices.keys())) diff --git a/server-trainer/RoadSigns-ModelTraining_Yolovv3.py b/server-trainer/RoadSigns-ModelTraining_Yolovv3.py new file mode 100644 index 0000000..27c3ef9 --- /dev/null +++ b/server-trainer/RoadSigns-ModelTraining_Yolovv3.py @@ -0,0 +1,31 @@ +import os + +# Assurez-vous d'être dans le répertoire Darknet +os.chdir("chemin/vers/votre/darknet") + +# Entraînement du modèle YOLOv3 pour les panneaux de signalisation routière +# Utilisation du CPU uniquement + +# Chemin vers les données d'entraînement et de validation +train_data = "server-trainer/images/road_sign_trainers/train_speed" +valid_data = "server-trainer/images/road_sign_trainers/test_speed" + +# Paramètres d'entraînement +batch_size = 64 +subdivisions = 16 +num_epochs = 1000 + +# Commande d'entraînement +train_command = f"./darknet detector train data/obj.data cfg/yolov3_custom_train.cfg yolov3.weights -map -dont_show -gpus 0" + +# Boucle d'entraînement +for epoch in range(num_epochs): + print(f"Epoch {epoch+1}/{num_epochs}") + + # Entraînement sur les données d'entraînement + os.system(train_command) + + # Validation sur les données de validation + os.system(f"./darknet detector map data/obj.data cfg/yolov3_custom_test.cfg backup/yolov3_custom_train_{epoch+1}.weights") + +print("Entraînement terminé!") diff --git a/server-trainer/UsersIdentification-ModelTraining.py b/server-trainer/UsersIdentification-ModelTraining.py new file mode 100644 index 0000000..37eb7d0 --- /dev/null +++ b/server-trainer/UsersIdentification-ModelTraining.py @@ -0,0 +1,33 @@ +import cv2 +import os +import numpy as np +import pickle + +image_dir="server-trainer/images/avatars/" +current_id=0 +label_ids={} +x_train=[] +y_labels=[] + +for root, dirs, files in os.walk(image_dir): + if len(files): + label=root.split("/")[-1] + for file in files: + if file.endswith("jpg"): + path=os.path.join(root, file) + if not label in label_ids: + label_ids[label]=current_id + current_id+=1 + id_=label_ids[label] + image=cv2.imread(path, cv2.IMREAD_GRAYSCALE) + x_train.append(image) + y_labels.append(id_) + +with open("server-ia/data/modeles/camera_identification_user/labels.pickle", "wb") as f: + pickle.dump(label_ids, f) + +x_train=np.array(x_train) +y_labels=np.array(y_labels) +recognizer=cv2.face.LBPHFaceRecognizer_create() +recognizer.train(x_train, y_labels) +recognizer.save("server-ia/data/modeles/camera_identification_user/trainner.yml") diff --git a/server-trainer/dataset.py b/server-trainer/dataset.py new file mode 100644 index 0000000..d83c49e --- /dev/null +++ b/server-trainer/dataset.py @@ -0,0 +1,82 @@ +import numpy as np +import cv2 +import multiprocessing +import random +# dataset pour train_panneau.py +def bruit(image_orig): + h, w, c = image_orig.shape + n = np.random.randn(h, w, c) * random.randint(5, 30) + return np.clip(image_orig + n, 0, 255).astype(np.uint8) + +def change_gamma(image, alpha=1.0, beta=0.0): + return np.clip(alpha * image + beta, 0, 255).astype(np.uint8) + +def modif_img(img): + h, w, c = img.shape + + r_color = [np.random.randint(255), np.random.randint(255), np.random.randint(255)] + img = np.where(img == [142, 142, 142], r_color, img).astype(np.uint8) + + if np.random.randint(3): + k_max = 3 + kernel_blur = np.random.randint(k_max) * 2 + 1 + img = cv2.GaussianBlur(img, (kernel_blur, kernel_blur), 0) + + M = cv2.getRotationMatrix2D((int(w / 2), int(h / 2)), random.randint(-10, 10), 1) + img = cv2.warpAffine(img, M, (w, h)) + + if np.random.randint(2): + a = int(max(w, h) / 5) + 1 + pts1 = np.float32([[0, 0], [w, 0], [0, h], [w, h]]) + pts2 = np.float32([[0 + random.randint(-a, a), 0 + random.randint(-a, a)], [w - random.randint(-a, a), 0 + random.randint(-a, a)], [0 + random.randint(-a, a), h - random.randint(-a, a)], [w - random.randint(-a, a), h - random.randint(-a, a)]]) + M = cv2.getPerspectiveTransform(pts1,pts2) + img = cv2.warpPerspective(img, M, (w, h)) + + if np.random.randint(2): + r = random.randint(0, 5) + h2 = int(h * 0.9) + w2 = int(w * 0.9) + if r == 0: + img = img[0:w2, 0:h2] + elif r == 1: + img = img[w - w2:w, 0:h2] + elif r == 2: + img = img[0:w2, h - h2:h] + elif r == 3: + img = img[w - w2:w, h - h2:h] + img = cv2.resize(img, (h, w)) + + if np.random.randint(2): + r = random.randint(1, int(max(w, h) * 0.15)) + img = img[r:w - r, r:h - r] + img = cv2.resize(img, (h, w)) + + if not np.random.randint(4): + t = np.empty((h, w, c), dtype=np.float32) + for i in range(h): + for j in range(w): + for k in range(c): + t[i][j][k] = (i / h) + M = cv2.getRotationMatrix2D((int(w / 2), int(h / 2)), np.random.randint(4) * 90, 1) + t = cv2.warpAffine(t, M, (w, h)) + img = (cv2.multiply((img / 255).astype(np.float32), t) * 255).astype(np.uint8) + + img = change_gamma(img, random.uniform(0.6, 1.0), -np.random.randint(50)) + + if not np.random.randint(4): + p = (15 + np.random.randint(10)) / 100 + img = (img * p + 50 * (1 - p)).astype(np.uint8) + np.random.randint(100) + + img = bruit(img) + + return img + +# NOT WORKING ERREUR +def create_lot_img(image, nbr, nbr_thread=None): + if nbr_thread is None: + nbr_thread = multiprocessing.cpu_count() + lot_original = np.repeat([image], nbr, axis=0) + p = Pool(nbr_thread) + lot_result = p.map(modif_img, lot_original) + p.close() + return lot_result \ No newline at end of file diff --git a/server-trainer/genere_images_panneaux.py b/server-trainer/genere_images_panneaux.py new file mode 100644 index 0000000..2c17c7d --- /dev/null +++ b/server-trainer/genere_images_panneaux.py @@ -0,0 +1,85 @@ +import tensorflow as tf +from tensorflow.keras import layers, models +import numpy as np +from sklearn.utils import shuffle +import os +import cv2 +import dataset +###GENERE DES IMAGES AVEC PANNEAUX DEPUIS UN MEDIA### +# Tuto25[OpenCV] Lecture des panneaux de vitesse p.1 (houghcircles) 28min +# Taille des images +size = 42 +# Chemin vers le répertoire contenant les images de panneaux +dir_images_panneaux = "server-trainer/images/road_sign_speed_trainers/panneaux" +dir_images_genere_panneaux = "server-trainer/images/road_sign_speed_trainers/genere_panneaux" + +# Fonction pour lire les images de panneaux à partir du répertoire spécifié +def lire_images_panneaux(dir_images_panneaux, size=None): + tab_panneau = [] + tab_image_panneau = [] + + # Vérifie si le répertoire existe + if not os.path.exists(dir_images_panneaux): + quit("Le repertoire d'image n'existe pas: {}".format(dir_images_panneaux)) + + # Liste tous les fichiers dans le répertoire + files = os.listdir(dir_images_panneaux) + + # Quitte si le répertoire est vide + if files is None: + quit("Le repertoire d'image est vide: {}".format(dir_images_panneaux)) + + # Parcours des fichiers dans le répertoire + for file in sorted(files): + # Vérifie si le fichier est un fichier PNG + if file.endswith("png"): + # Ajoute le nom du fichier (sans l'extension) à tab_panneau + tab_panneau.append(file.split(".")[0]) + + # Lit l'image et redimensionne si une taille est spécifiée + image = cv2.imread(dir_images_panneaux + "/" + file) + if size is not None: + image = cv2.resize(image, (size, size), cv2.INTER_LANCZOS4) + tab_image_panneau.append(image) + + return tab_panneau, tab_image_panneau + +# Appel de la fonction pour lire les images de panneaux +tab_panneau, tab_image_panneau = lire_images_panneaux(dir_images_panneaux, size) + +# Initialisation des tableaux pour les images et les labels +tab_images = np.array([]).reshape(0, size, size, 3) +tab_labels = [] + +# Génération des données d'entraînement +id = 0 +for image in tab_image_panneau: + lot = [] + for _ in range(100): + lot.append(dataset.modif_img(image)) + lot = np.array(lot) + tab_images = np.concatenate([tab_images, lot]) + tab_labels = np.concatenate([tab_labels, np.full(len(lot), id)]) + id += 1 + +# Conversion des tableaux en type approprié et normalisation des images +tab_panneau = np.array(tab_panneau) +tab_images = np.array(tab_images, dtype=np.float32) / 255 +tab_labels = np.array(tab_labels).reshape([-1, 1]) + +# Mélange des données +tab_images, tab_labels = shuffle(tab_images, tab_labels) + +# Boucle pour sauvegarder les images générées dans le répertoire de sortie +for i in range(len(tab_images)): + # Générer un nom de fichier unique en fonction de l'ID et du nom du panneau + file_name = "{:d}_{}.png".format(i, tab_panneau[int(tab_labels[i])]) + # Enregistrer l'image dans le répertoire de sortie + cv2.imwrite(os.path.join(dir_images_genere_panneaux, file_name), tab_images[i] * 255.0) # Retour à l'échelle 0-255 + +# Affichage des images avec leur label +for i in range(len(tab_images)): + cv2.imshow("panneau", tab_images[i]) + print("label", tab_labels[i], "panneau", tab_panneau[int(tab_labels[i])]) + if cv2.waitKey() & 0xFF == ord('q'): + quit() \ No newline at end of file diff --git a/server-trainer/genere_images_sans_panneaux.py b/server-trainer/genere_images_sans_panneaux.py new file mode 100644 index 0000000..c7d76c6 --- /dev/null +++ b/server-trainer/genere_images_sans_panneaux.py @@ -0,0 +1,39 @@ +import cv2 +import numpy as np +import random +import os +###GENERE DES IMAGES SANS PANNEAUX DEPUIS UN MEDIA### +#YT:Tuto25[Tensorflow2] Lecture des panneaux de vitesse p.2 - 4min30 + +size=42 +video="server-trainer/videos/autoroute.mp4" +dir_images_genere_sans_panneaux="server-trainer/images/road_sign_speed_trainers/genere_sans_panneaux" + +if not os.path.isdir(dir_images_genere_sans_panneaux): + os.mkdir(dir_images_genere_sans_panneaux) + +if not os.path.exists(video): + print("Vidéo non présente:", video) + quit() + +cap=cv2.VideoCapture(video) + +id=0 +nbr_image=1500 + +nbr_image_par_frame=int(1500/cap.get(cv2.CAP_PROP_FRAME_COUNT))+1 + +while True: + ret, frame=cap.read() + if ret is False: + quit() + h, w, c=frame.shape + + for cpt in range(nbr_image_par_frame): + x=random.randint(0, w-size) + y=random.randint(0, h-size) + img=frame[y:y+size, x:x+size] + cv2.imwrite(dir_images_genere_sans_panneaux+"/{:d}.png".format(id), img) + id+=1 + if id==nbr_image: + quit() \ No newline at end of file