def improve_ia(root): """Hyperparameter tuning""" mt = MyTools() imshow = 1 # Création du dossier weights si besoin mt.create_directory(os.path.join(root, 'weights')) size = 40 # fixe for gray in GRAY: print("gray", gray) for blur in BLUR: print("blur", blur) # resize blur rb = ResizeBlur(root, size, blur, imshow) rb.batch() del rb # compression sc = ShotsCompression(root, TRAIN, TEST, size, gray, imshow) sc.create_semaphore_npz() del sc for learningrate in LEARNINGRATE: print("learningrate", learningrate) failed = 0 for k in range(NOMBRE_DE_PASSE): sia = SemaphoreIA(root, TRAIN, learningrate, failed, imshow) weight_list = sia.training() resp = sia.testing() print("Result:", resp) save_test(root, resp, weight_list, gray, blur, learningrate)
def create_directories(): """ Création de n dossiers un fichier = ./semaphore/shot/shot_0/shot_a_0.png """ # Dossier d'enregistrement des images gl.shot_directory = os.path.join(gl.root, 'training_shot') print("Dossier des shots:", gl.shot_directory) # Si le dossier n'existe pas, je le crée mt = MyTools() mt.create_directory(gl.shot_directory) # Nombre de dossiers nécessaires n = int(gl.nombre_shot_total / gl.nombre_de_fichiers_par_dossier) + 1 for i in range(n): directory = os.path.join(gl.shot_directory, 'shot_' + str(i).zfill(3)) mt.create_directory(directory)
class CreateShot: def __init__(self, size, video, number=1000): """ letters = {'a': image de a, ' ': image de ' ', etc ...} """ self.size = size self.number = number self.tools = MyTools() self.create_directories() self.letters = self.get_letters_images() self.numero_lettre = 0 self.capture = cv2.VideoCapture(video) self.width = int(self.capture.get(cv2.CAP_PROP_FRAME_WIDTH)) self.height = int(self.capture.get(cv2.CAP_PROP_FRAME_HEIGHT)) print("Taille Video:", self.width, self.height) self.get_shots() def create_directories(self): """Un dossier root=shot, un sous dossier par lettre""" self.tools.create_directory("./shot") for l in LETTRES: if l == " ": l = "space" self.tools.create_directory("./shot/shot_" + l) def get_letters_files(self): letters_files = self.tools.get_all_files_list("lettre_epaisse_alpha", ".png") print("Nombre de letters =", len(letters_files)) return letters_files def get_letters_images(self): """Récupère toutes les images de lettres""" letters = {} for l_file in self.get_letters_files(): # lettre/shot_10_j.png l = l_file[:-4][-1] img = cv2.imread(l_file, -1) img = delete_gray(img) letters[l] = img return letters def frame_resize(self, frame): """Pour 1024: resize puis coupe des 2 cotés de 398 pour 416: 1280x720 devient 739x416 """ # Largeur a = int(self.width * self.size / self.height) # Hauteur b = self.size # Resize frame = cv2.resize(frame, (a, b), interpolation=cv2.INTER_AREA) # Coupe x = int((a - b) / 2) y = 0 w, h = self.size, self.size frame = frame[y:y + h, x:x + w] return frame def aspect_change(self, lettre): """Couleur, flou, rotation lettre est l'image de la lettre """ bg_color = lettre[0][0] R = random.randint(0, 100) G = random.randint(0, 50) B = random.randint(100, 255) lettre[np.all(lettre == [0, 0, 0, 255], axis=2)] = [R, G, B, 255] mask = np.all(lettre == bg_color, axis=2) lettre[mask] = [0, 0, 0, 0] # Rotation some = random.randint(-3, 3) lettre = rotateImage(lettre, some) # Flou de 0 à 4 flou = random.randint(0, 4) if flou != 0: lettre = cv2.blur(lettre, (flou, flou)) return lettre def lettre_image_change(self, lettre): """Adapte une lettre, calcule taille, position, flou, couleur lettre est l'image de la lettre """ # Modification de l'aspect lettre = self.aspect_change(lettre) # Variation sur la taille du sémaphore semaphore_mini = int(self.size / 7) w, h = lettre.shape[1], lettre.shape[0] # Set de la hauteur, puis largeur y_size = random.randint(semaphore_mini, int(self.size * 0.8)) x_size = int(w * y_size / h) # Maxi de taille de lettre < self.size y_size = min(y_size, self.size) x_size = min(x_size, self.size) lettre = cv2.resize(lettre, (x_size, y_size), interpolation=cv2.INTER_CUBIC) # Position posible x = random.randint(0, self.size - x_size) y = random.randint(0, self.size - y_size) return lettre, x_size, y_size, x, y def overlay(self, frame): """Trouve une lettre, supperpose à la frame""" # Lecture des lettres de l'alphabet en boucle l = LETTRES[self.numero_lettre] self.numero_lettre += 1 if self.numero_lettre == 27: self.numero_lettre = 0 # lettre est l'image de lettre lettre = self.letters[l] # Adaptation lettre, x_size, y_size, x, y = self.lettre_image_change(lettre) # Overlay img = over_transparent(frame, lettre, x, y) return img, l, x_size, y_size, x, y def save(self, img, lettre, x_size, y_size, x, y, n): """Enregistrement dans le dossier ./shot/shot_a/ de shot_0_a.jpg et shot_0_a.txt class position(x y) taille(x y) x, y position du coin haut gauche s = taille de la lettre """ # Get indice avant modif liste indice = LETTRES.index(lettre) # pour avoir dossier clair if lettre == " ": lettre = "space" # Avec sous dossiers fichier = "./shot/shot_" + lettre + "/shot_" + str(n) + "_" + lettre # Enregistrement de l'image cv2.imwrite(fichier + ".jpg", img) # Enregistrement des datas # Taille relative de l'image lettre tx = x_size / self.size ty = y_size / self.size # Origine = top left xc = (x + (x_size / 2)) / self.size yc = (y + (y_size / 2)) / self.size # class-position du centre-taille data = (str(indice) + " " + str(xc) + " " + str(yc) + " " + str(tx) + " " + str(ty)) self.tools.write_data_in_file(data, fichier + ".txt", "w") def get_shots(self): n, m = 0, 0 self.loop = 1 while self.loop: ret, frame = self.capture.read() if ret: # pour enregistrer 1 frame sur 10 et varier les fonds if n % 10 == 0: frame = self.frame_resize(frame) # Overlay d'une lettre img, l, x_size, y_size, x, y = self.overlay(frame) print("Shot numéro", m, "Lettre", l) # Enregistrement de l'image et du fichier txt self.save(img, l, x_size, y_size, x, y, m) m += 1 cv2.imshow("image", img) # Jusqu'à number n += 1 if m == self.number: self.loop = 0 # Echap et attente k = cv2.waitKey(10) if k == 27: self.loop = 0 else: # Reset si la video est terminée self.capture = cv2.VideoCapture(video) print("Nombre d'images crées:", m) cv2.destroyAllWindows()
class BlurAndConvert: def __init__(self): self.mt = MyTools() self.blur_mini = CONF["letters_shot_jpg"]["blur_mini"] self.blur_maxi = CONF["letters_shot_jpg"]["blur_maxi"] self.size = CONF["letters_shot_jpg"]["shot_size"] # Dossiers self.shot = shot_dir print("Dossier shot:", self.shot) self.create_shot_jpg() self.create_sub_directories() # Images png self.all_png_files = self.mt.get_all_files_list(self.shot, '.png') print("Nombre de fichiers à convertir:", len(self.all_png_files)) if len(self.all_png_files) == 0: print("\n\nPas d'images à convertir") print("Créer les images avant !") os._exit(0) # Exécution du script flou puis save self.save_to_jpg() def create_shot_jpg(self): self.shot_jpg = shot_jpg print("Dossier shot_jpg:", self.shot_jpg) # Si le dossier n'existe pas, je le crée self.mt.create_directory(self.shot_jpg) def create_sub_directories(self): """Création de 100 dossiers.""" # Répartition dans 100 sous dossiers for l in range(100): directory = os.path.join(self.shot_jpg, str(l)) self.mt.create_directory(directory) def blur(self, img): # Flou k = random.randint(self.blur_mini, self.blur_maxi) if k != 0: img = cv2.blur(img, (k, k)) return img def save_to_jpg(self): n = 0 for png in self.all_png_files: if n % 100 == 0 and n != 0: a = len(self.all_png_files) print("Nombre de fichiers convertis:", n, "sur", a) n += 1 # Lecture de png img = cv2.imread(png) # Flou img = self.blur(img) # Retaillage avec size de letters.ini img = cv2.resize(img, (self.size, self.size), interpolation=cv2.INTER_AREA) # On travaille avec Path png_path = Path(png) jpg_path = self.get_jpg_name(png_path) # PosixPath # Ecriture de l'image jpg, cv2 prend seulement path en str cv2.imwrite(str(jpg_path), img, [int(cv2.IMWRITE_JPEG_QUALITY), 100]) # Copie du fichier txt de png dans jpg txt, dst = self.get_txt_dst(png_path, jpg_path) copyfile(txt, dst) # On prend son temps sleep(0.01) print("Nombre de fichiers convertis:", n) def get_jpg_name(self, png_path): """ png = str png = str(self.shot) + /25/shot_4126.png = str jpg = str(self.shot_jpg) + /25/shot_4126.jpg = str """ # Soustraction du chemin de shot_dir a = str(png_path).replace(str(shot_dir), "") # Ajout du chemin de jpg_dir b = Path(str(shot_jpg) + a) # Changement de l'extension jpg_path = b.with_suffix(".jpg") return jpg_path def get_txt_dst(self, png_path, jpg_path): txt_path = png_path.with_suffix(".txt") dst_path = jpg_path.with_suffix(".txt") return txt_path, dst_path
class AnalyseMidi: """Analyse le fichier midi, trouve le nombre et le nom des instruments. Retourne la liste des notes sur une time lapse de chaque instrument. save_midi_json enregistre le midi en json partitions = liste des partitions instruments = liste des instruments soit objet avec .program et .name L'enregistrement des json avec chemins absolus ne marche que pour letters Sous répertoires et sous sous répertoires possible dans /music """ def __init__(self, midi_file, FPS, volume=""): """Un seul fichier midi FPS de 10 à 1000, 50 ou 100 est bien Plus le FPS est élevé, plus le temps de calcul est long ! """ print("\n\nAnalyse de", midi_file.split('/')[-1], "\n") self.midi_file = midi_file self.FPS = FPS self.volume = volume self.end_time = 0 self.instruments = None self.instruments = [] self.partitions = [] self.mytools = MyTools() # Pour gérer les threads dans blender self.end = 0 def get_instruments(self): """instruments = [Instrument(program=71, is_drum=False, name="Grand Piano"), ...] """ # Récupération des datas avec pretty_midi midi_pretty_format = my_pretty_midi.PrettyMIDI(self.midi_file) # Supprime les notes avec fin avant le début ! midi_pretty_format.remove_invalid_notes() # Time de fin, instruments du fichier self.end_time = midi_pretty_format.get_end_time() self.instruments_without_drums = midi_pretty_format.instruments # Correction des intruments pour avoir le program des drums self.get_instruments_with_drums() return self.instruments def get_instruments_with_drums(self): """"De: [Instrument(program=25, is_drum=False, name="Bass"), Instrument(program=0, is_drum=True, name="Drums"), Instrument(program=0, is_drum=True, name="Drums2")] pour une liste de tuple: [((0, 25), False, "Bass"), ((0, 116), True, "Drums"), ((8, 115), True, "Drums2")] Pour le dict du json "instruments": [[(0, 25), false], [(0, 116), true], [(8, 116), true]]} """ for instrument in self.instruments_without_drums: program = instrument.program is_drum = instrument.is_drum name = instrument.name if is_drum: bank, bank_nbr = self.get_drum_program() else: bank = 0 bank_nbr = int(program) self.instruments.append(((bank, bank_nbr), is_drum, name)) def get_drum_program(self): """ Cas possible: 0 114 Steel Drums 0 115 Woodblock 0 116 Taiko Drum 0 117 Melodic Tom 0 118 Synth Drum 0 119 Reverse Cymbal 8 116 Concert Bass Drum 8 117 Melo Tom 2 8 118 808 Tom """ drums = [(0, 112), (0, 113), (0, 114), (0, 115), (0, 116), (0, 117), (0, 118), (0, 119), (8, 116), (8, 117), (8, 118)] c = choice(drums) return c[0], c[1] def get_partitions_and_instruments(self): """Fait les étapes pour tous les instruments, retourne les instruments et leurs partitions. """ # Si fichier midi anormal try: self.get_instruments() except: print("Instruments non récupérable dans le fichier midi\n") self.instruments_without_drums = [] # Si nombre d'instrument > 10 pour IA if len(self.instruments) > 10: return None, None for instrument in self.instruments_without_drums: if instrument.is_drum: drum = "Drum" else: drum = "" print(" Analyse de l'instrument: {:>2} {:>6} Name: {:>24}".\ format(instrument.program, drum, instrument.name)) # Array de 128 x nombre de frames instrument_roll = self.get_instrument_roll(instrument) # Conversion dans une liste de listes python partition = self.get_partition(instrument_roll, instrument) self.partitions.append(partition) print() return self.partitions, self.instruments def get_partition(self, instrument_roll, instrument): """entrée: une ligne du array = (0.0 0.0 0.0 ... 89 ... 91 ... 0.0) 89 est à la position 54 91 est à la position 68 sortie: une ligne de la liste: 2 notes du même instrument 54 et 68 [(54, 89), (68, 91)] = [(note=54, volume=89), (note=68, volume=91)] """ partition = [] # Parcours de toutes les lignes for n in range(instrument_roll.shape[1]): # Analyse des lignes pour ne garder que les non nuls non_zero = np.flatnonzero(instrument_roll[:,n]) notes = [] if non_zero.size > 0: note = int(non_zero[0]) volume = int(instrument_roll[:,n][note]) if note: notes.append((note, volume)) partition.append(notes) # velocity maxi entre 0 et 127 partition = normalize_velocity(partition) if self.volume == "flat": partition = flatten_partition(partition) return partition def get_instrument_roll(self, partition): """Retourne un np.array de (128, FPS*durée du morceau en secondes)""" # La méthode get_piano_roll marche pour tous les instruments instrument_roll = partition.get_piano_roll(self.FPS, np.arange(0, self.end_time, 1/self.FPS)) return instrument_roll def save_midi_json(self): """Commence par analyser le midi, puis enregistre. partitions = liste des partitions = [partition_1, partition_2 ...] instruments = [Instrument(program=71, is_drum=False, name="mélodie"), ...] json_data = {"partitions": [partition_1, partition_2 ......], "instruments": [instrument_1.program, instrument_2.program, ...] instrument is not JSON serializable = objet pretty_midi midi dans /media/data/3D/projets/darknet-letters/letters/midi/music sous dossiers possible json dans /media/data/3D/projets/darknet-letters/letters/midi/json_fps et sous dossiers """ # Analyse du midi self.get_partitions_and_instruments() if len(self.instruments) < 11: # Création du json json_data = {} json_data["partitions"] = self.partitions json_data["instruments"] = self.instruments # Save du json json_name = self.get_json_name() with open(json_name, 'w') as f_out: json.dump(json_data, f_out) f_out.close() print('Enregistrement de:', json_name) # Pour Blender self.end = 1 return self.instruments def get_json_name(self): """Le fichier midi_file est le chemin relatif du fichier dans : ./midi/music/ ou ./midi/music/non_git/ Le json sera dans le dossier ./midi/json_60/ ou ./midi/json_60/non_git/ """ # Remplacement de l'extension .midi en .json filename = Path(self.midi_file).with_suffix(".json") filename = str(filename) # Remplacement de music par json json_name = filename.replace("music/", "json_" + str(self.FPS) + "/") print("Nom du fichier json", json_name) # Crée les dossiers et sous dossiers self.create_directories(json_name) return json_name def create_directories(self, json_name): """ json_name converti en absolu pour valable ici ou dans blender json_name = /med/da/3D/pr/dark/let/midi/json_fps_17/toto.json 5 json_fps = /med/da/3D/pr/dark/let/midi/json_fps_17/oui/toto.json 7 """ json_name_abs = Path(json_name).absolute() # json_17 doit toujours exister, si existe on passe index_midi = json_name_abs.parts.index("midi") # Bidouille pour agréger les parts a = Path(json_name_abs.parts[0]) b = json_name_abs.parts[1:index_midi + 2] json_fps = a.joinpath(*b) # json_fps = Chemin absolu de json_fps self.mytools.create_directory(json_fps) # Sous répertoires if len(json_name_abs.parts) - index_midi == 4: sd_fin = json_name_abs.parts[1:index_midi + 3] sd = a.joinpath(*sd_fin) print("Sous dossier", sd) self.mytools.create_directory(sd) # Sous sous répertoires if len(json_name_abs.parts) - index_midi == 5: # Création du sous répertoire sd_fin = json_name_abs.parts[1:index_midi + 3] sd = a.joinpath(*sd_fin) print("Sous dossier", sd) self.mytools.create_directory(sd) # Création des sous sous répertoires ssd_fin = json_name_abs.parts[1:index_midi + 4] ssd = a.joinpath(*ssd_fin) print("Sous sous dossier", ssd) self.mytools.create_directory(ssd)
class ResizeTrainingShot: def __init__(self, root, size): self.root = root # soit ..../semaphore self.size = int(size) # Mes outils personnels self.tools = MyTools() # Renommage de training_shot en training_shot_copy self.rename_training_shot() # Re-création des dossiers self.create_training_shot_dir() self.create_sub_folders() # Liste des images self.shot_list = self.get_shot_list() def rename_training_shot(self): ori = os.path.join(self.root, "training_shot") dest = os.path.join(self.root, "training_shot_copy") os.rename(ori, dest) def create_training_shot_dir(self): directory = os.path.join(self.root, "training_shot") print("Dossier training_shot:", directory) self.tools.create_directory(directory) def create_sub_folders(self): """Création de n dossiers shot_000""" # Nombre de dossiers nécessaires d = os.path.join(self.root, "training_shot_copy") n = len(self.tools.get_all_sub_directories(d)) - 1 print("Nombre de sous répertoires", n) for i in range(n): directory = os.path.join(self.root, 'training_shot', 'shot_' + str(i).zfill(3)) self.tools.create_directory(directory) print("Sous répertoires créés") def get_shot_list(self): """Liste des images""" # Liste shot = os.path.join(self.root, "training_shot_copy") shot_list = self.tools.get_all_files_list(shot, ".png") print("Dossier des images NB:", shot) print("Nombre d'images:", len(shot_list)) return shot_list def change_resolution(self, img, x, y): """Une image peut-être ratée""" try: res = cv2.resize(img, (x, y), interpolation=cv2.INTER_AREA) except: res = np.zeros([self.size, self.size, 1], dtype=np.uint8) return res def get_new_name(self, shot): return shot.replace("/training_shot_copy/", "/training_shot/") def create_training_shot_resized_dir(self): directory = os.path.join(self.root, "training_shot_resized") print("Dossier training_shot_resized:", directory) self.tools.create_directory(directory) def batch(self): """Lecture, resize, save""" i = 0 # Pour chaque image for shot in self.shot_list: # Lecture img = cv2.imread(shot, 0) # Resize img_out = self.change_resolution(img, self.size, self.size) i += 1 # Save new_shot = self.get_new_name(shot) print(new_shot) cv2.imwrite(new_shot, img_out)
class ResizeBlur: def __init__(self, root, size, blur, imshow=1): """ root = dossier semaphore size = taille des images pour l'ia blur = 0 à 10 pour flouter les images pour l'ia imshow = 0 ou 1 pour affichage d'image ou non pendant l'exécution """ self.root = root # soit ..../semaphore self.size = int(size) self.size = max(20, self.size) self.size = min(800, self.size) self.blur = blur self.imshow = imshow # Mes outils personnels self.tools = MyTools() # Le terrain de jeu self.create_training_shot_resized_dir() # Liste self.shot_list = self.get_shot_list() self.create_sub_folders() def create_training_shot_resized_dir(self): directory = os.path.join(self.root, "training_shot_resized") print("Dossier training_shot_resized:", directory) self.tools.create_directory(directory) def create_sub_folders(self): """Création de n dossiers shot_000""" # Nombre de dossiers nécessaires d = os.path.join(self.root, "training_shot") n = len(self.tools.get_all_sub_directories(d)) - 1 print("Nombre de sous répertoires", n) for i in range(n): directory = os.path.join(self.root, 'training_shot_resized', 'shot_' + str(i).zfill(3)) self.tools.create_directory(directory) def get_new_name(self, shot): """ de /media/data/3D/projets/semaphore/training_shot/shot_000/shot_0_a.png à /media/data/3D/projets/semaphore/training_shot_resized/shot_000/shot_0_a.png j'ai /media/data/3D/projets/semaphore/training_shot_resized/shot_000/shot_3921_h.png """ t = shot.partition("training_shot") # t = ('/media/data/3D/projets/semaphore/', 'training_shot', # '/shot_000/shot_1054_s.png') name = os.path.join(self.root, "training_shot_resized", t[2][1:]) return name def change_resolution(self, img, x, y): """Une image peut-être ratée""" try: res = cv2.resize(img, (x, y), interpolation=cv2.INTER_AREA) except: res = np.zeros([self.size, self.size, 1], dtype=np.uint8) return res def apply_blur(self, img, k): """TODO: Utiliser GaussianBlur img = cv2.GaussianBlur(img, (5, 5), 0) """ if self.blur: img = cv2.blur(img, (k, k)) return img def random_noise(self, img): """Entre 0 et 20 pixels au hasard""" nb = random.randint(0, 10) for i in range(nb): x = random.randint(0, 39) y = random.randint(0, 39) img[x][y] = 1 return img def some_dirty(self, img): """0 à 3 paquets de 4 pixels 0 1 0 1 1 1 0 1 0 """ nb = random.randint(0, 2) for i in range(nb): x = random.randint(0, 34) y = random.randint(0, 34) # 1ère ligne a = x + 1 b = y + 0 img[a][b] = 1 # 2ème ligne for u in range(3): a = x + u b = y + 1 img[a][b] = 1 # 3ème ligne a = x + 1 b = y + 2 img[a][b] = 1 return img def batch(self): """Liste des images, lecture, conversion, save""" i = 0 if self.imshow: cv2.namedWindow('Image In') cv2.namedWindow('Image Out') # Pour chaque image for shot in self.shot_list: # Lecture img = cv2.imread(shot, 0) # ResizeBlur img_out = self.change_resolution(img, self.size, self.size) # Flou img_out = self.apply_blur(img_out, self.blur) # Noise # L'ajout de bruit est appris par le réseau et va dégrader la # reconnaissance, mais Jo dit que non, ça dépend de ??? # #img_out = self.random_noise(img_out) # #img_out = self.some_dirty(img_out) # ## Affichage if self.imshow: if i % 500 == 0: #print(i) imgB = self.change_resolution(img_out, 600, 600) cv2.imshow('Image In', img) cv2.imshow('Image Out', imgB) cv2.waitKey(1) i += 1 # Save new_shot = self.get_new_name(shot) cv2.imwrite(new_shot, img_out) cv2.destroyAllWindows() def get_shot_list(self): """Liste des images""" # Liste shot = os.path.join(self.root, "training_shot") shot_list = self.tools.get_all_files_list(shot, ".png") print("Dossier des images NB:", shot) print("Nombre d'images:", len(shot_list)) return shot_list
class YOLO: def __init__(self, images_directory, essai, save, test=0, weights=""): """ essai = numéro del'eaasi dans ini save = sauvegarde des notes en json test = bidouilles pour passer une série de weights """ # Mes outils self.mt = MyTools() self.lp = LettersPath() self.CONF = self.lp.conf self.essai = essai self.save = save self.test = test self.weights = weights if self.weights: print("Fichier de poids utilisé:", self.weights) self.get_weights_file_indice() if self.weights: self.create_test_subdir() # Paramètres de la conf # Avec ou sans GPU self.gpu = self.CONF['play_letters']['gpu'] # Résolution de l'écran ou du VP: x, y self.screen = self.CONF['play_letters']['screen'] # Boucle opencv self.loop = 1 self.fps = 0 # Récup des images self.images_directory = images_directory self.shot_list = self.get_sorted_shot_list() self.all_shot = self.get_all_shot() # nom du morceau self.filename = self.images_directory.split("/")[-1] # Initialisation de la détection self.set_darknet() # Paramètres de détections self.thresh = int(self.CONF['play_letters']['thresh']) self.hier_thresh = int(self.CONF['play_letters']['hier_thresh']) self.nms = int(self.CONF['play_letters']['nms']) # Windows self.create_windows() # Trackbars self.create_trackbar() self.set_init_tackbar_position() # Midi self.fonts = self.CONF['music_and_letters']['fonts'] self.instruments = [] self.get_instruments() self.notes_en_cours = [] self.players = {} self.set_players() self.all_notes = [] def create_windows(self): cv2.namedWindow('Reglage') cv2.moveWindow('Reglage', 0, 25) self.fullscreen = self.CONF['play_letters']['fullscreen'] if self.fullscreen: cv2.namedWindow('Letters', cv2.WND_PROP_FULLSCREEN) cv2.setWindowProperty('Letters', cv2.WND_PROP_FULLSCREEN, cv2.WINDOW_FULLSCREEN) else: cv2.namedWindow('Letters') cv2.moveWindow('Letters', 0, 25) self.titre = 0 b = int(416 * self.screen[0] / self.screen[1]) self.black_image = np.zeros((416, b, 3), np.uint8) def get_weights_file_indice(self): """Uniquement pour test weightpath = ../darknet/data_22/backup/yolov3-tiny_3l_22_best.weights début = ../darknet/data_22/backup/yolov3-tiny_3l_22_ fin = .weights """ a = len( "/media/data/projets/darknet-letters/letters/darknet/data_22/backup/yolov3-tiny_3l_22_" ) b = len(".weights") indice = str(self.weights[a:-b]) return indice def create_test_subdir(self): doss = "/media/serge/BACKUP/play_letters_shot/pl_shot_14_jpg/test/" for i in range(43): directory = doss + str((i + 1) * 1000) self.mt.create_directory(directory) def set_darknet(self): """Si weight_influence_test, teste tous les yolov3-tiny_3l_22_xxxxxxx.weights du dossier backup free_network = lib.api_free_network free_network.argtypes = [c_void_p] adapté à ce script: free_network = darknet.lib.api_free_network free_network.argtypes = [c_void_p] """ configPath = self.CONF['play_letters']['configpath'] if not self.test: weightPath = self.CONF['play_letters']['weightpath'] else: weightPath = self.weights metaPath = self.CONF['play_letters']['metapath'] self.netMain = darknet.load_net_custom(configPath.encode("ascii"), weightPath.encode("ascii"), 0, 1) self.metaMain = darknet.load_meta(metaPath.encode("ascii")) with open(metaPath) as metaFH: metaContents = metaFH.read() match = re.search("names *= *(.*)$", metaContents, re.IGNORECASE | re.MULTILINE) if match: result = match.group(1) else: result = None try: if os.path.exists(result): with open(result) as namesFH: namesList = namesFH.read().strip().split("\n") self.altNames = [x.strip() for x in namesList] except TypeError: print("Erreur self.altNames") if self.gpu: self.free_network = darknet.lib.api_free_network # Create an image we reuse for each detect self.darknet_image = darknet.make_image(\ darknet.network_width(self.netMain), darknet.network_height(self.netMain), 3) def get_instruments(self): """Récupère les infos de instruments.txt dans self.instruments.""" file_name = self.images_directory + "/instruments.txt" data = self.mt.read_file(file_name) if data: lines = data.splitlines() for line in lines: line_list = line.split(" ") self.instruments.append(line_list) else: print("Pas de fichier txt donc pas d'instruments !") print(" Morceau suivant ....\n\n") self.instruments = None self.loop = 0 def set_players(self): """Crée les players pour chaque canal Les drums ne sont pas sur le channel 9, complique et sert à rien la font i est sur le canal i for i in range(len(self.instruments)): self.instruments = [[0, 12, 5], [0, 0, 1]] [bank, bank_number = instrument, font] """ if self.instruments: i = 0 for instrument in self.instruments: channel = int(instrument[2]) bank = int(instrument[0]) bank_number = int(instrument[1]) self.players[channel] = OneInstrumentPlayer( self.fonts, channel, bank, bank_number) i += 1 print("Nombre de player:", len(self.players)) def create_trackbar(self): """ thresh min 0 max 1 hier_thresh min 0 max 1 nms min 0 max 1 """ self.reglage_img = np.zeros((100, 600, 3), np.uint8) # #self.reglage_img = put_text(self.reglage_img, # #self.filename, # #(10, 50), # #size=0.8, # #thickness=2) cv2.createTrackbar('threshold_', 'Reglage', 0, 100, self.onChange_thresh) cv2.createTrackbar('hier_thresh', 'Reglage', 0, 100, self.onChange_hier_thresh) cv2.createTrackbar('nms_____', 'Reglage', 0, 100, self.onChange_nms) def set_init_tackbar_position(self): """setTrackbarPos(trackbarname, winname, pos) -> None""" cv2.setTrackbarPos('threshold_', 'Reglage', self.thresh) cv2.setTrackbarPos('hier_thresh', 'Reglage', self.hier_thresh) cv2.setTrackbarPos('nms_____', 'Reglage', self.nms) def onChange_thresh(self, thresh): """min=1 max=100 step=1 default=0.5""" if thresh == 0: thresh = 5 if thresh == 100: thresh = 95 self.thresh = int(thresh) self.save_change('play_letters', 'thresh', self.thresh) def onChange_hier_thresh(self, hier_thresh): """min=1 max=100 step=1 default=0.5""" if hier_thresh == 0: hier_thresh = 5 if hier_thresh == 100: hier_thresh = 95 self.hier_thresh = int(hier_thresh) self.save_change('play_letters', 'hier_thresh', self.hier_thresh) def onChange_nms(self, nms): """min=1 max=100 step=1 default=0.5""" if nms == 0: nms = 5 if nms == 100: nms = 95 self.nms = int(nms) self.save_change('play_letters', 'nms', self.nms) def save_change(self, section, key, value): lp.save_config(section, key, value) def get_sorted_shot_list(self): images = self.mt.get_all_files_list(self.images_directory, ".jpg") shot_list = [0] * len(images) # Récup du numéro le plus petit, les numéros ensuite se suivent mini = 10000000 for image in images: nbr = int(image.split("/")[-1].split("_")[-1][:-4]) if nbr < mini: mini = nbr # Tri des images n = 0 for image in images: # Si de 500 à 1500 # ../play_letters/s_j_to_i_1243.jpg devient s_j_to_i_1243.jpg nbr = int(image.split("/")[-1].split("_")[-1][:-4]) # 1243 shot_list[nbr - mini] = image return shot_list def get_all_shot(self): """Charge en mémoire toutes les images du dossiers à lire par l'IA""" print("\n\nChargement de toutes les images en RAM. Patience ...\n\n") all_shot = [] for shot_file in self.shot_list: img = cv2.imread(shot_file) all_shot.append(img) return all_shot def notes_cleaning(self, notes): # Suppression des doublons clean_notes = [] for note in notes: if note not in clean_notes: clean_notes.append(note) # Validation des notes new_notes = [] for font, note, vol in notes: # self.instruments = [[0, 12, 5], [0, 0, 1]] all_fonts = [] for inst in self.instruments: all_fonts.append(int(inst[2])) if font not in all_fonts: font = None # note 1 à 127 if note < 1 or note > 127: note = None # ## Volume 0 à 127: # #if vol > 127: vol = 127 # #if vol < 0: vol = 0 # Le volume est forcé à 127 vol = 127 if font is not None: if note: new_notes.append([font, note, vol]) return new_notes def play_notes(self, notes): """new_notes = [(police, note, volume), ...] = [(5, 124, 127), ... ] la police n'est pas le player self.players[i].thread_dict[key] = 0 """ new_notes = self.notes_cleaning(notes) # Notes en en_cours ****************************************** en_cours = [] # key=note, val=thread en cours 0 ou 1 for k, v in self.players.items(): for key, val in self.players[k].thread_dict.items(): if val != 0: en_cours.append((k, key)) # #print("en_cours:", en_cours) # Fin des notes qui ne sont plus en en_cours ***************** # notes = [(player, note, volume), ...] # en_cours = [(player, note), ... ] for ec in en_cours: player, note = ec ssss = [player, note, 127] # list et non tuple !! if ssss not in new_notes: self.players[player].thread_dict[note] = 0 # #print("Fin de:", player, note) # Lancement des nouvelles notes ****************************** for player, note, vol in new_notes: if (player, note) not in en_cours: # #print("nouvelle", player, note) self.players[player].thread_play_note(note, 127) # vol) def save_all_notes(self): """ /bla...bla/play_letters_shot_jpg_3/bob_sheriff to /bla...bla/play_letters_shot_jpg_3/bob_sheriff_data.json """ if not self.weights: json_name = self.images_directory + "_" + str(self.essai) + ".json" else: # Bidouille non générale a = len("/media/serge/BACKUP/play_letters_shot/pl_shot_14_jpg/") name = self.images_directory[a:] + "_" # les fichiers sont dans 1 sous dossier indice indice = str(self.get_weights_file_indice()) doss = "/media/serge/BACKUP/play_letters_shot/pl_shot_14_jpg/test/" json_name = doss + indice + "/" + name + str(self.essai) + ".json" with open(json_name, 'w') as f_out: json.dump(self.all_notes, f_out) f_out.close() print('Enregistrement de:', json_name) def put_titre(self, image): """Insère le titre si i""" if self.titre: filename = self.filename filename = filename.replace("f_", "") filename = filename.replace("_", " ") filename = filename.replace("-", " ") image = put_text(image, filename, (10, 50), size=0.5, thickness=1) return image def apply_k(self, k, i): # Space pour morceau suivant et attente if k == 32: self.loop = 0 # Affichage du titre si "i" if k == ord('i'): # 105: if not self.titre: self.titre = 1 else: self.titre = 0 # Echap pour finir le script python if k == 27: os._exit(0) # Gestion de la fin du morceaux if i == len(self.shot_list): self.loop = 0 def detect(self): """FPS = 40 sur GTX1060""" i = 0 fps = 0 t_init = time.time() tempo = 1 t_tempo = time.time() # Si pas d'image, on passe la boucle if not self.all_shot: self.loop = 0 while self.loop: black_image = self.black_image.copy() # Récup d'une image img = self.all_shot[i] # ## Capture des positions des sliders # #self.thresh = cv2.getTrackbarPos('threshold_','Reglage') # #self.hier_thresh = cv2.getTrackbarPos('hier_thresh','Reglage') # #self.nms = cv2.getTrackbarPos('nms','Reglage') # #img_resized = cv2.resize(img, # #(darknet.network_width(self.netMain), # #darknet.network_height(self.netMain)), # #interpolation=cv2.INTER_LINEAR) darknet.copy_image_from_bytes(self.darknet_image, img.tobytes()) detections_l = darknet.detect_image(self.netMain, self.metaMain, self.darknet_image, self.thresh / 100, self.hier_thresh / 100, self.nms / 100) # Application des détections dans l'image image, letters = cvDrawBoxes(detections_l, img) notes = letters_to_notes(letters) self.play_notes(notes) # Ajout des notes pour enregistrement à la fin if self.save: self.all_notes.append(notes) # Insertion du titre image = self.put_titre(image) if not self.fullscreen: img = cv2.resize(image, (600, 600), interpolation=cv2.INTER_LINEAR) else: # gray[y1:y2, x1:x2] 162:578 # 1440/900 = 1.6 # #a = (self.screen[0]/self.screen[1] -1) / 2 # #x1 = int(a*416) # #x2 = x1 + 416 # #y1 = 0 # #y2 = 416 # #black_image[y1:y2, x1:x2] = image img = image # black_image img = put_text(img, str(self.fps), (10, 100), size=0.5, thickness=1) # Affichage cv2.imshow('Letters', img) # image) # Affichage des trackbars cv2.imshow('Reglage', self.reglage_img) # Comptage i += 1 # prochaine image fps += 1 ta = time.time() # Pour fps = 40 soit ta - t_tempo = 0.025 # 0.035 pour fps = 40, 0.052 pour fps = 30 tempo = int(1000 * (0.052 - (ta - t_tempo))) if tempo < 1: tempo = 1 t_tempo = ta if ta > t_init + 1: self.fps = fps # #print("FPS =", round(fps, 1)) t_init = time.time() fps = 0 k = cv2.waitKey(tempo) self.apply_k(k, i) cv2.destroyAllWindows() # Libération de la mémoire GPU if self.gpu: self.free_network(self.netMain) # Enregistrement des notes if self.save: self.save_all_notes() # Fin des fluidsynth for k, v in self.players.items(): self.players[k].stop_audio() time.sleep(0.3)
class BlurAndConvert: def __init__(self): self.mt = MyTools() self.blur_min = CONF["play_letters_shot"]["blur_min"] self.blur_max = CONF["play_letters_shot"]["blur_max"] self.size = CONF["play_letters_shot"]["shot_size"] # Dossiers self.shot = CONF["play_letters_shot"]["pl_shot"] print("Dossier play_letters:", self.shot) self.shot_jpg = self.shot + "_jpg" print("Dossier play_letters jpg:", self.shot_jpg) self.create_shot_jpg_dir() # Liste des sous-dossiers avec le dossier play_letters_shot self.sub_directories_list = [x[0] for x in os.walk(self.shot)] print("Liste des sous-répertoires:", self.sub_directories_list) self.create_sub_directories() # Copie des txt self.copy_all_txt() # Images png self.all_png_files = self.mt.get_all_files_list(self.shot, '.png') print("Nombre de fichiers à convertir:", len(self.all_png_files)) if len(self.all_png_files) == 0: print("\n\nPas d'images à convertir") print("Créer les images avant !") os._exit(0) # Exécution du script flou puis save self.save_to_jpg() def copy_all_txt(self): """ /bla...bla/play_letters_shot/bob_sherif/instruments.txt to /bla...bla/play_letters_shot_jpg_6/bob_sherif/instruments.txt """ # Tous les txt txts = self.mt.get_all_files_list(self.shot, '.txt') for txt in txts: dst = txt.replace(self.shot, self.shot_jpg) # Copie du fichier txt des png dans les jpg copyfile(txt, dst) def create_shot_jpg_dir(self): print("Dossier pl_shot_jpg:", self.shot_jpg) # Si le dossier n'existe pas, je le crée self.mt.create_directory(self.shot_jpg) def create_sub_directories(self): """Création des sous dossiers.""" for sd in self.sub_directories_list: if sd != self.shot: print("Sous répertoire en png:", sd) # Soustraction du chemin de shot_dir shot_dir = Path(self.shot) a = str(sd).replace(str(shot_dir), "") # Ajout du chemin de jpg_dir b = Path(str(self.shot_jpg) + a) print("Sous répertoire en jpg:", b) self.mt.create_directory(b) def apply_blur(self, img): blur = random.randint(self.blur_min, self.blur_max) if blur != 0: img = cv2.blur(img, (blur, blur)) return img def save_to_jpg(self): n = 0 for png in self.all_png_files: if n % 100 == 0 and n != 0: a = len(self.all_png_files) print("Nombre de fichiers convertis:", n, "sur", a) n += 1 # print(png) # Lecture de png img = cv2.imread(png) # Retaillage avec size de letters.ini img = cv2.resize(img, (self.size, self.size), interpolation=cv2.INTER_AREA) # Flou img = self.apply_blur(img) # On travaille avec Path png_path = Path(png) jpg_path = self.get_jpg_name(png_path) # PosixPath # Ecriture de l'image jpg, cv2 prend seulement path en str cv2.imwrite(str(jpg_path), img, [int(cv2.IMWRITE_JPEG_QUALITY), 100]) # On prend son temps sleep(0.01) print("Nombre de fichiers convertis:", n) def get_jpg_name(self, png_path): """ png = str png = str(self.shot) + /25/shot_4126.png = str jpg = str(self.shot_jpg) + /25/shot_4126.jpg = str """ # Soustraction du chemin de shot_dir a = str(png_path).replace(str(self.shot), "") # Ajout du chemin de jpg_dir b = Path(str(self.shot_jpg) + a) # Changement de l'extension jpg_path = b.with_suffix(".jpg") return jpg_path
class TtftoPng: def __init__(self, size): self.size = size self.tools = MyTools() # 10 polices possible seulement self.colors = COLORS self.color_num = 0 # Create pngs directory self.tools.create_directory("./pngs") # Dict des dossiers avec ttf self.ttf_list = self.get_ttfs() # Création des sous dossiers dans ./pngs self.create_sub_directories() def convert_ttfs(self): """Convertit tous les ttfs""" for rep in self.ttf_list: # récup du ttf ttf = self.tools.get_all_files_list(rep, 'ttf') print("Conversion de:", rep) self.convert_ttf(rep, ttf) self.color_num += 1 def convert_ttf(self, rep, ttf): """Convertit un ttf""" for l in LETTRES: l = l.upper() self.convert_letter(l, rep, ttf) l = l.lower() self.convert_letter(l, rep, ttf) # #for c in CHIFFRES: # #self.convert_letter(c, rep, ttf) def convert_letter(self, letter, rep, ttf): """Convertit une lettre Conversion de: ./ttfs/southern/Southern.ttf lettre: A dans: ./pngs/southern/ command convert -background none -fill black -font ./ttfs/southern/Southern.ttf -pointsize 300 -write ./pngs/southern/ label:"A" A.png """ #print("Conversion de {}".format(letter)) filename = "./pngs" + rep[6:] + "/" + letter + ".png" if len(ttf) > 0: font = "./" + ttf[0] # remplacement espace dans le nom, # mais dossier ne doit pas avoir d'espace font = font.replace(' ', '\\ ') color = self.colors[self.color_num] # #print( "Conversion de: ", font, # #" lettre: ", letter, # #" dans: ", filename, # #"color", color) command = 'convert -background none -fill {4} -font {3} \ -pointsize {1} label:"{0}" {2}'.format( letter, self.size, filename, font, color) #print("command", command) subprocess.call(command, shell=True) def create_sub_directories(self): """"Création des sous dossiers dans ./pngs""" for d in self.ttf_list: parts = d.split("/") self.tools.create_directory("./pngs/" + parts[-1]) def get_ttfs(self): # Tous les fichiers ttf ttfs = self.tools.get_all_sub_directories("./ttfs") ttf_list = [] for subdir in ttfs: if subdir != "./ttfs": dd = self.tools.get_all_sub_directories(subdir) for d in dd: if "MACOSX" not in d: if subdir not in ttf_list: ttf_list.append(subdir) return ttf_list