diff --git a/InterfaceCEREMA/AperoDeDenis-3.14-1.x86_64.rpm b/InterfaceCEREMA/AperoDeDenis-3.14-1.x86_64.rpm new file mode 100644 index 0000000..943e5f0 Binary files /dev/null and b/InterfaceCEREMA/AperoDeDenis-3.14-1.x86_64.rpm differ diff --git a/InterfaceCEREMA/AperoDeDenis-5.0-win32.msi b/InterfaceCEREMA/AperoDeDenis-5.0-win32.msi new file mode 100644 index 0000000..5c8a673 Binary files /dev/null and b/InterfaceCEREMA/AperoDeDenis-5.0-win32.msi differ diff --git a/InterfaceCEREMA/AperoDeDenis-5.32-amd64.msi b/InterfaceCEREMA/AperoDeDenis-5.32-amd64.msi new file mode 100644 index 0000000..8858b61 Binary files /dev/null and b/InterfaceCEREMA/AperoDeDenis-5.32-amd64.msi differ diff --git a/InterfaceCEREMA/AperoDeDenis.py b/InterfaceCEREMA/AperoDeDenis.py index dd5b7e7..631582e 100644 --- a/InterfaceCEREMA/AperoDeDenis.py +++ b/InterfaceCEREMA/AperoDeDenis.py @@ -2,10 +2,148 @@ # -*- coding: utf-8 -*- # PEP 0008 -- Style Guide for Python Code -#ajout le 7/10 : second item de qualité des photos - -import tkinter # gestion des fenêtre, des boutons ,des menus +# Version python 3 ou plus +# est-il possible de relancer Malt en conservant le niveau de zoom déjà atteint ??? pas sur, sauf en passant par Micmac + +# Version 2.35 : +# le 26 avril 2016 +# - affichage des heures avec les secondes +# - Controle que le nom du répertoire bin de micmac ne comporte pas d'espace. +#v 2.41 +# correction d'un bogue sur la suppression des points gps +# autorise 30 points gps +# 2.42 +# suppression bogue suppression de points gps multiples +# gcpbascule après tapas ET toujours avant malt +# 2.43 +# les conséquences du choix de nouvelles photos sont modifiées de trois façons : +# - si des emplacements de points GPS doivent être supprimés alors il y a demande à l'utilisateur +# - le nettoyage du chantier est moins brutal : les fichiers exp (exports) et ply sont conservés. +# - le chantier est enregistré avant de rendre la main (si l'utilsiateur ne validait pas un enregistrement ultérieur le chantier devenait inaccessible) +# ajout de import tkinter.messagebox pour le message d'avertissement si AperoDeDenis est dèjà lancé sous windows +# 2.44 +# Accepte les virgules comme séparateur décimal pour les points gps : remplacement des virgules saisies dans les coordonnées gps par des points +# 2.45 +# accepte la virgule pour la distance de la calibration métrique (remplace virguule par point) +# nouveau bouton : lance la calibration gps +# +# ajout de tawny après Malt, avec saisie libre des options (mosaiquage du résultat de malt/ortho) +# 2.50 +# Active/désactive le tacky message de lancement +# 2.6 +# saisie de l'incertitude sur la position des points GPS +# 2.61 +# correction d'un bogue de compatibilité ascendante (changement de structure de la liste des points gps. Le 14/09/2016 + +# a faire : corriger le mode d'obtention de ALL ou Line dans le calcul des indices de qualité +# toutes les focales : la commande explore les sous-répertoires comportant la chaine JPG !!! +# v 3.00 : bilingue (début novembre 2016) +# V 3.10 : sélection des meilleures photos +# v 3.11 : sélection des meilleurs images pour créer un nouveau chantier +# v 3.12 : correction bogue affichage gps +# v 3.13 : recherche exiftool et convert sous binaire-aux\windows ffmpeg absent sous bin; +# possibilité de saisir une unité avec la distance +# controle des photos supprimé si lanceMicMac après Tapas. +# v 3.14 : correction d'une régression de la v 3.13 lors de la restauration des paramètres (dûe à l'ajout de self.ffmpeg dans la sauvegarde). +# v 3.20 : les photos autour de la maitresse pour Malt ne sont plus "autour" mais choisies parmi les meilleures en correspondances +# Ajout d'un choix pour Malt : AperoDeDenis, l'interface recherche les maitresses et les photos correspondantes +# ajout filtre pour afficher l'erreur max sur gcpbascule (erreur positionnement des points GPS. +# controle affiné des points gps : on indique ceux qui ne sont placés sur une seule photo et on vérifie la présence de 3 points sur 2 photos +# après plantage durant malt ou fusion : on renomme les JPG et les PLY lors du rédémarrage (reste pb semblable pour calibration intrinsèque) +# suppression d'un point GPS sur une photo (avant : suppression de tous les points) +# Affichage dans l'état du chantier des points GPS positionnés sur une seule photo +# Non mise dans le xml des points gps positionnés une seule fois. +# Si le controle des points GPS est négatif alors les fichiers xml ne sont pas créés +# 3.30 +# 1) créer une mosaique après tapas sur toutes les photos : "Tarama" ".*.JPG" "Arbitrary" +# 2) la mosaïque est un tif : sour le répertoire TA : TA_LeChantier.tif +# 3) saisir un masque sur la mosaïque créée : par l'outil de saisie de masque, la masque doit s'appeler : +# Les masques sont pris en compte par défaut ou si l’option DirTA = "TA" et UseTA=1 de Malt sont actives. (UseTA = 1 par défaut) +# Par défaut l’ajout est _Masq, qui peut être modifiée avec l’option MasqIm de Malt. ( "_Masq" après le nom) +# un fichier xml accompagne le masque (créé par MicMac ?) +# voir description : http://jmfriedt.free.fr/lm_sfm.pdf +# 4) Lancer Malt option Ortho : "C:/MicMac6706/bin\mm3d.exe" "Malt" "Ortho" ".*.JPG" "Arbitrary" "NbVI=2" "ZoomF=4" DirTA=TA +# 5) Lancer Tawny pour créer une mosaïque sur le résultat de malt : "mm3d" "Tawny" "Ortho-MEC-Malt/" : +# ce qui donne la mosaique Orthophotomosaic.tif sous le répertoire "Ortho-MEC-Malt/" +# 6) lancer Nuage2Ply pour obtenir le ply sous le répertoire Mec-Malt : NuageImProf_STD-MALT_Etape_7.ply +# C:\Python340\MesScripts\AperoDeDenis\vaches noires\micmac_17>mm3d Nuage2Ply Mec-Malt/NuageImProf_STD-MALT_Etape_7.xml Attr=Ortho-MEC-Malt/Orthophotomosaic.tif +# 7) vérifier si une nouvelle version est disponible +# 8) faire un masque "inverse" ou multiple ok +# 9) ouvrir les mosaiques par menu +# menu expert : exécuter une ligne de commande +# correction : self.e au lieu de e dans MyDialog +# version 3.31 +# copier les points gps d'une chantier dans un autre (en corrigeant ce qu'il faut, menu expert) +# version 3.32 : 2 corrections mineures (lignes 3854 supprimée et 3953 orthographe) +# Version 3.33 : correction comptage des points GPS et des points GPS avec les mêmes coordonnées ( définition de listePointsActifs revue) +# Version 3.34 : janvier 2018 +# correction de : e remplacé par self.e dans MyDialog (fixe le problème du renommage des chantiers) +# ajout de self.pasDeFocales = False après la mise à jour des exifs. (fixe le problème du message erroné concerné les focales manquantes) +# modification de l'icone de la fenêtre = l'icone du cerema remplace le graindsel. +# possibilité de choisir le ménage : suppression totale ou conservation des résultats seuls +# Affichage du gain de place en MO après le ménage +# affichage de la taille du dossier en MO dans l'affichage de l'état du chantier +# test de la présence de sous répertoire dans afficheetat : +# si etatChantier>2 et pas de sous-répertoire alors etatChantier remis à 2 et +# message "chantier nettoyé" affiché +# la version 3.34 est rebaptisée 5.0 (suppression de l'item "indice surfacique") +# Version 5.1 : 4 décembre 2018 : ajout du widget pour éliminer les photos ayant servis à la calibration de l'appareil photo +# ajout d'un item dans le menu expert : copier les coordonnées des points gps à partir d'un fichier texte +# modification des onglets Malt et C3DC, réunis dans un même onglet "Densification" +# renommage de l'onglet "calibration" en "mise à l'échelle" +# Version 5.2 janvier 2019 : +# correction bug sur l'affichage des photos pour calibration après Tapas +# ajout des paramètres pour Campari dans la fenêtre des options/points GPS +# lancement automatique de campari après GCP_bascul s'il y a les bons paramètres. +# ajout dans le menu expert de la consultation du log mm3d +# mise à jour de dico camera pour "tous" les appareils photos du lot de données +# fix bug sur mise à jour de l'exif mal pris en compte, suppression des variables pasDeFocales et uneseulefocale. +# ajout de l'item " ajout d'un chantier à partir d'un répertoire" dans le menu fichier +# version 5.21 janvier 2019 +# python 3.5 nécessaire pour renommer un chantier (commonpath) +# ajout possibilité de passer une commande "python" dans le menu expert +# Modification de l'option "Autocal" de Tapas : Figee (au lieu de Autocal) : permet de 'figer' la calibration initiale +# version 5.22 11 février 2019 +# fix 2 issues : +# - suppression du l'annonce d'une nouvelle version sur internet (incorrecte) +# - suppression d'un bug concernant les tags de l'exif suite au renommage d'un chantier, bug de la version 5.1 +# version 5.30 21 février 2019 : +# - dans les items "qualité des photos" ajout des photos "isolées", en disjontion de toutes les autres. +# Ces photos font "planter" le traitement tapas +# - Ajout d'un fonction vérifiant le nombre de scènes disjointes en terme de points homologues. +# lorsqu'il y a plusieurs scènes l'orientation est impossible : arrêt de micmac aprés tapioca. +# - Lorsque le message MAXLINELENGTH est émis par Tapioca il est affiché et expliqué dans la trace synthétique +# - Ajout de cette fonction dans l'item "outils/qualité des photos du dernier traitement" +# - prise en compte de l'issue concernant la fonction filedialog sous Mac-Os lors des recherche de programmes (exiftool...) +# - suppression des lignes de codes inutilisées concernant les indices surfaciques +# - Ajout d'un item dans paramètrage : recherche d'une nouvelle version GitHub +# - la recherche systématique d'une nouvelle version est réactivée (désactivée en version 5.22 +# 5.31 : 25/2 +# - Les échelles par défaut de Tapioca sont calculées suivant les photos : 60% de la dimension maxi des photos (qui semble être un optimum) +# - l'instruction commonpath nécessitant la version 3.5 de python est mise en "try", la version 3.5 de python n'est plus obigatoire +# - fix sur la qualité des photos si pas de points homologues, idem après Tapioca +# - modif du filtre qualité des photos : affichage écran de la trace +# - suppresssion des items de menu outils\qualité des photos line et qualité des photos ALL, +# maintient de la qualité des photos sur le dernier traitement +# - Ajout d'un controle d'unicité de la scène aprés le premier passage, rapide, de Tapioca MultiScale : +# évite de se lancer dans une recherche approfondie de points homologues si l'échec est prévu +# - Ajout de 1 item au menu outils : retirer des photos au chantier +# - modification de la fonction "Expert/plusieurs appareils" : +# la modification du tag model de l'exif est faite à partir du préfixe du nom de fichier, sur 3 caractères +# la modification a lieu après accord de l'utilisateur, sans autre condition +# la modification est faite une seule fois, non cumulative +# - fonction "encadre" : la valeur par défaut du paramètre nouveauDepart passe de 'oui' à 'non' +# les appels à la fonction encadre sont modifiés en conséquence +# 5.32 : +# - l'item de menu "rechercher la présence d'une nouvelle version sur GitHub" est désormais placé dans le menu Outils. +# cet item propose de visualiser la page web de téléchargement ou le readme.txt sur GitHub. +# - correction d'un bug : la modification des tag "model" des exif met à jour la variable self.lesTagsExifs +# - accélération importante du traitement de la modification des tag "model" +# - ajout d'une verrue dans lanceCommande pour essayer de traiter la cas d'une ligne de commande dont la longueur serait supérieure à 8191 sous Windows + +from tkinter import * # gestion des fenêtre, des boutons ,des menus import tkinter.filedialog # boite de dialogue "standards" pour demande fichier, répertoire +import tkinter.messagebox # pour le message avertissant que AperoDeDenis est déjà lancé import tkinter.ttk as ttk # amélioration de certains widgets de tkinter : le comportement est géré indépendamment de l'apparence : c'est mieux ! mais différent ! import pickle # pour la persistence import os.path # pour les noms de fichier @@ -14,19 +152,189 @@ import time import sys # info système import subprocess # appel des procédures MicMac +import signal import traceback # uniquement pour pv : affiche les propriétés des variables (qui sert pour débug) from PIL import Image # pour travailler sur les images, définir le masque, placer les points GPS : PIL from PIL import ImageTk from PIL import ImageDraw import base64 import tempfile +import inspect +import zipfile +import zlib +import ctypes +import gettext +import urllib.request +import webbrowser +import threading +from textwrap import wrap + +################################## Classe : Choix de la langue en cas d'absence dans les paramètres ###########################" + + +def foreach_window(hwnd, lParam): + if IsWindowVisible(hwnd): + length = GetWindowTextLength(hwnd) + buff = ctypes.create_unicode_buffer(length + 1) + GetWindowText(hwnd, buff, length + 1) + titles.append(buff.value) + return True + +def heure(): # time.struct_time(tm_year=2015, tm_mon=4, tm_mday=7, tm_hour=22, tm_min=56, tm_sec=23, tm_wday=1, tm_yday=97, tm_isdst=1) + return ("le %(jour)s/%(mois)s/%(annee)s à %(heure)s:%(minutes)s:%(secondes)s") % {"jour" : str(time.localtime()[2]), "mois" : str(time.localtime()[1]), "annee" : str(time.localtime()[0]), "heure" : str(time.localtime()[3]), "minutes" : str(time.localtime()[4]), "secondes": str(time.localtime()[5])} + +def fin(codeRetour=0): + os._exit(codeRetour) + +class InitialiserLangue(tkinter.Frame): + def __init__(self, frame, **kwargs): + self.frame = tkinter.Frame + self.frame.__init__(self, frame, **kwargs) + frame.geometry("400x200") + photo = tkinter.PhotoImage(data=iconeTexte) + frame.tk.call('wm', 'iconphoto', frame._w, photo) + self.pack(fill=tkinter.BOTH) + frame.title("") + global langue + langue = "NA" + + self.message = tkinter.Label(self, text="Choisissez une langue\nSelect your language") + self.message.pack() + + self.bouton_francais = tkinter.Button(self, text = "Français/French", command = self.langueFrancaise) + + self.bouton_anglais = tkinter.Button(self, text = "Anglais/English", command = self.langueAnglaise) + self.bouton_francais.pack(side = tkinter.LEFT) + self.bouton_anglais.pack(side = tkinter.RIGHT) + + frame.protocol("WM_DELETE_WINDOW", self.arret) + + def arret(self): + frame.destroy() + print("Fermeture inatendue de la fenêtre / Unexpected closure of the window") + sys.exit() + + + def langueFrancaise(self): + global langue + langue = "fr" + frame.destroy() + + + def langueAnglaise(self): + global langue + langue = "en" + frame.destroy() + + +################################# Outils de traduction ###################################################### +def chargerLangue(): + try: + sauvegarde2 = open(os.path.join(repertoire_data, "ParamMicmac.sav"),mode='rb') + r2=pickle.load(sauvegarde2) + sauvegarde2.close() + langue = r2[9] + return(langue) + + except Exception as e: + return "null" + + +################################## INITIALISATION DU PROGRAMME ########################################################### + +# Variables globales + +numeroVersion = "5.32" +version = " V "+numeroVersion # conserver si possible ce format, utile pour controler +continuer = True # si False on arrête la boucle de lancement de l'interface +messageDepart = str() # Message au lancement de l'interface +compteur = 0 # Compte le nombre de relance de l'interface +iconeTexte = "R0lGODlhIAAgAIcAMfr8+EqrpcfLEe16CJnE1Lnb3Hm7whaXjuzdu+VLEp64HuiRL9TYVfPImeqoU4e1NAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACwAAAAAIAAgAAcI/gABCBxIEACCgwgENliYsKDDhwMVKHjwQOCAiwMgaiwoUaLABRgbboSIYKLEhCAvNhipkUFHBQwAOMC4gOVDBAI6CoiJAOMAkTYFMhCQUwHRjzSDDhxK1CjRmA18OlDKlKjVozKlssR5VQCAqzEBpLy4YGXBgwyqWk2oNmFPnwMWOGjQsOvVhAUCdHU7NoFfvwnt7hSYN4CBvQCi/l0cGGxDAgEiB3jQte/iBGzTiixgQHLkAlxnwh3A2CFnz5EJCB1L0wFQAAViE+iM2nABpD7LPixwoHdvw5INGJhNgPUAs7AJKFfN27dv28tnP6DZsMDs4cphO39+GwBx5TNrcCbHHl1ggOeeVXtfbmABXvLf1Q887bk7+9uc2RPoDhFyfdjkWXefTYVFZoBA7AUwYFAFKgggZAcMZwB/QflnGIKdRbifUgT9x9lv8nHonWTMnXdAABRyWOCBCJiIoogdSiaQczASJJxw5slY444DBQQAOw==" +versionInternet = str() # version internet disponible sur GitHub, "" au départ + +# recherche du répertoire d'installation de "aperodedenis" (différent suivant les systèmes et les versions de système) + +repertoire_script=os.path.realpath(os.path.abspath(os.path.split(inspect.getfile( inspect.currentframe() ))[0])) +if not os.path.isdir(repertoire_script): + repertoire_script = os.path.dirname(os.path.abspath(__file__)) +if not os.path.isdir(repertoire_script): + repertoire_script = os.path.dirname(sys.argv[0]) +if not os.path.isdir(repertoire_script): + repertoire_script = os.getcwd() +if not os.path.isdir(repertoire_script): + repertoire_script = os.getcwd() + +if os.name=="nt": + + # lancement unique d'aperodedenis sous WINDOWS : (pas trouvé d'équivalent sous Linux/Ubuntu) + # liste des fenetres sous windows, pour éviter de relancer l'appli si déjà lancée + EnumWindows = ctypes.windll.user32.EnumWindows + EnumWindowsProc = ctypes.WINFUNCTYPE(ctypes.c_bool, ctypes.POINTER(ctypes.c_int), ctypes.POINTER(ctypes.c_int)) + GetWindowText = ctypes.windll.user32.GetWindowTextW + GetWindowTextLength = ctypes.windll.user32.GetWindowTextLengthW + IsWindowVisible = ctypes.windll.user32.IsWindowVisible + titles = [] + EnumWindows(EnumWindowsProc(foreach_window), 0) # liste des fenetres ouvertes dans titles + + # apero déjà ouvert ? + liste = [e for e in titles if "AperoDeDenis V "in e] + if liste.__len__(): + texte = "AperoDeDenis est déjà lancé dans la fenêtre :\n\n"+liste[0]+"\n\n"+\ + "La version actuelle d'AperoDeDenis n'autorise qu'une seule instance du programme.\n"+\ + "Valider pour quitter." + tkinter.messagebox.showwarning("AperoDeDenis : Avertissement",texte) + fin() + # Répertoire de travail + + repertoire_data = os.path.join(os.getenv('APPDATA'),'AperoDeDenis') + try: os.mkdir(repertoire_data) + except: pass + if not os.path.isdir(repertoire_data): + repertoire_data = repertoire_script + langue = chargerLangue() + if (langue != "en" and langue != "fr"): + frame = tkinter.Tk() + initialiserLangue = InitialiserLangue(frame) + initialiserLangue.mainloop() + + +else: # sous Linux + + if not os.path.isdir(repertoire_script): + repertoire_script = os.getenv('HOME') + repertoire_data = repertoire_script + try: os.mkdir(repertoire_data) + except: pass + if not os.path.isdir(repertoire_data): + repertoire_data = repertoire_script + langue = chargerLangue() + if(langue != "en" and langue != "fr"): + frame = tkinter.Tk() + initialiserLangue = InitialiserLangue(frame) + initialiserLangue.mainloop() +repertoire_langue = os.path.join( repertoire_script, 'locale') +try: + traduction = gettext.translation('AperoDeDenis', localedir = repertoire_langue, languages=[langue]) + traduction.install() +except: + def _(a=str(),b=str()): + return a+b + + +# Message indiquant le lancement de l'outil dans le shell + +print(heure()+_(" lancement d'aperodedenis")+version+".") + + +############################ FIN DE L'INITIALISATION ######################################################### + ########################### Classe pour tracer les masques class TracePolygone(): - def __init__(self, fenetre, image, masque,labelBouton='Tracer le masque'): # fenetre : root de l'appli ; image : fichier image sur lequel tracer le polygone ; masque = nom du fichier à créer + def __init__(self, fenetre, image, masque,labelBouton=_('Tracer le masque')): # fenetre : root de l'appli ; image : fichier image sur lequel tracer le polygone ; masque = nom du fichier à créer self.root = tkinter.Toplevel() #fenêtre spécifique à la saisie du masque - self.root.title("Saisie sur la photo : "+image) # titre + self.root.title(_("Saisie sur la photo : ")+image) # titre fenetreIcone(self.root) self.root.geometry( "900x900" ) # Taille self.dimMaxiCanvas = 600 # dimension max du canvas accueillant l'image @@ -36,8 +344,8 @@ def __init__(self, fenetre, image, masque,labelBouton='Tracer le masque'): # fe self.listePointsJPG = list() # liste des points du polygone self.polygone = False # deviendra vrai lorsque le polygone sera effectif self.file = image # nom du fichier partagé, devient attribut de la classe - self.nomMasque = masque # nom du fichier masque partagé (en principe : os.path.splitext(self.file)[0]+"_mask.tif") - + self.nomMasque = masque # nom du fichier masque partagé (en principe : os.path.splitext(self.file)[0]+"_Mask.tif") + self.inverse = False #pour inverser le masque : intervertit l'intérieur et l'extérieur # initialisations de l'affichage de l'image, dimensions du cadre, positionnement : self.imageFichier = Image.open(self.file) # ouverture de la photo @@ -75,18 +383,20 @@ def __init__(self, fenetre, image, masque,labelBouton='Tracer le masque'): # fe self.root.bind("a",self.delete) self.frame2 = ttk.Frame(self.root, borderwidth = 2,relief = 'sunken') # cadre pour la photo et les boutons - self.boutonQuitter = ttk.Button(self.frame2, text="Valider",command = self.quitter) - self.boutonAbandon = ttk.Button(self.frame2, text="Abandon",command = self.abandon) + self.boutonInverser = ttk.Button(self.frame2, text=_("Inverser"),command = self.inverser) + self.boutonQuitter = ttk.Button(self.frame2, text=_("Valider"),command = self.quitter) + self.boutonAbandon = ttk.Button(self.frame2, text=_("Abandon"),command = self.abandon) self.boutonTracer = ttk.Button(self.frame2, text=labelBouton,command = self.tracerMasqueBis) self.boutonAide = ttk.Label (self.frame2, - text= "\nmolette de la souris = zoom,\n"+\ - "utilisable avant ET pendant le tracé\n"+\ - "glisser-déposer actif avant le tracé\n\n"+\ - "Tracer :\n"+\ - "Clic gauche : ajouter un point;\n clic droit : fermer le polygone,\n"+\ - "Touche Del pour supprimer un point ou le polygone,\n") + text= "\n" + _("molette de la souris = zoom,") + "\n"+\ + _("utilisable avant ET pendant le tracé") + "\n"+\ + _("glisser-déposer actif avant le tracé=") + "\n\n"+\ + _("Tracer :") + "\n"+\ + _("Clic gauche : ajouter un point;\n double clic gauche : fermer le polygone,") +"\n"+\ + _("Touche Del pour supprimer un point ou le polygone,") + "\n") self.boutonAide.pack(side='left',pady=2,padx=2) self.boutonTracer.pack(side='left',pady=2,padx=8) + self.boutonInverser.pack(side='left',pady=2,padx=8) self.boutonQuitter.pack(side='left',pady=2,padx=8) self.boutonAbandon.pack(side='left',pady=2,padx=8) self.frame2.pack() @@ -96,7 +406,9 @@ def __init__(self, fenetre, image, masque,labelBouton='Tracer le masque'): # fe self.root.grab_set() fenetre.wait_window(self.root) - def quitter(self): # libère les ressources images pour ne pas les "bloquer" + def quitter(self): + # libère les ressources images pour ne pas les "bloquer" + try: self.imageFichier.close() except: pass try: self.imageMasque.close() @@ -158,7 +470,7 @@ def b1Double(self,event): # pour clore la poly if event.widget!=self.canvas: return # si le clic n'est pas sur l'image (canvas=frame=image) on ne fait rien if self.frame.cget("cursor").string=="plus": # le cursor "plus" indique l'ajout d'un point : on clot if self.listePointsJPG.__len__()<=1: #polygone avec trop peu de point - self.infoBulle(event,"Il faut au moins 2 points dans le polygone.") + self.infoBulle(event,_("Il faut au moins 2 points dans le polygone.")) return self.tracerMasqueBis() # on désactive le bouton de tracé self.afficherPolygone() @@ -188,7 +500,7 @@ def moletteLinux5(self,event): # l'utilisateur Linu def redrawZoom(self, event): # l'utilisateur zoom avant avec la molette de la souris : mémo du zoom précédent if self.scale>self.maxScale: # si l'échelle passe à plusieurs pixels écran pour un pixel image on arrête - self.infoBulle(event,texte="Zoom maximum atteint") # l'utilisateur est informé + self.infoBulle(event,texte=_("Zoom maximum atteint")) # l'utilisateur est informé return self.listeSauveImages.append((self.xNW,self.yNW,self.xSE,self.ySE,self.img,self.scale)) # sauvegarde pour retour arrière (redrawDeZoom) self.positionNouveauZoom(event.x,event.y) # calcule les positions du centre, du coin nw pour le nouveau zoom @@ -230,7 +542,7 @@ def retailleEtAffiche(self): def afficheImage(self): # Remplace l'image actuelle du canvas par l'image self.img, # positionnée dans le canvas suivant le calcul de "positionNouveauZoom" - try: self.canvas.delete(self.imgTk_id) #si jamais il n'y a pas encore d'image + try: self.canvas.delete(self.imgTk_id) # si jamais il n'y a pas encore d'image except: pass self.imgTk = ImageTk.PhotoImage(self.img) self.imgTk_id = self.canvas.create_image(0,0,image = self.imgTk,anchor="nw") @@ -241,11 +553,11 @@ def tracerMasqueBis(self): # appui sur un bouto self.frame.config(cursor="arrow") # on remet le cursor "normal" return self.listePointsJPG=list() # nouvelles données - self.polygone = False # pas de polygone fini + self.polygone = False # pas de polygone fini self.menagePol() self.fermerMasque() # efface le masque affiché en cours self.frame.config(cursor="plus") # curseur en mode ajout - self.boutonTracer.state(["pressed","!focus",'selected']) # etat séléctionné du bouton + self.boutonTracer.state(["pressed","!focus",'selected'])# etat séléctionné du bouton def retirerPointPolyligne(self): try: self.listePointsJPG.pop() @@ -274,18 +586,31 @@ def infoBulle(self,event,texte=" "): # affiche un i = ImageDraw.Draw(self.imageFichier) l,h = i.textsize(texte,font=None) try: self.bulle.destroy() - except: pass + except Exception as e: print(_("Erreur suppression d'info bulle : "),str(e)) self.bulle = tkinter.Toplevel() # nouvelle fenêtre pour l'info bulle self.bulle.overrideredirect(1) # sans le bordel tout autour self.bulle.geometry("%dx%d%+d%+d" % (l+10,h+6,event.x_root+15,event.y_root)) # position du coin nw de la fenêtre par rapport au curseur ttk.Label(self.bulle,text = texte,background="#ffffaa",relief = 'solid').pack() # texte, la taille de la fenêtre s'adapte au texte, style infobulle - #self.bulle.mainloop() # boucle d'attente d'événement sur la fenêtre (pas de pack possible) + #self.bulle.mainloop() # boucle d'attente d'événement sur la fenêtre (pas de pack possible) + def inverser(self): + self.inverse = not self.inverse + self.sauverMasque() + self.ouvrirMasque() + def sauverMasque(self): # création d'une image 200x200 avec un fond de couleur noire - img = Image.new("1",self.imageFichier.size) # 1 bit par pixel (noir et blanc (la couleur par défaut est le noir (http://pillow.readthedocs.org/en/latest/reference/Image.html) - dessin = ImageDraw.Draw(img) # création d'un objet Draw - dessin.polygon(self.listePointsJPG,fill="white",outline="green") - img.save(self.nomMasque,"TIFF") + if self.inverse: + img = Image.new("1",self.imageFichier.size,color=255) # 1 bit par pixel (noir et blanc (la couleur par défaut est le noir (http://pillow.readthedocs.org/en/latest/reference/Image.html) + dessin = ImageDraw.Draw(img) # création d'un objet Draw + dessin.draw + dessin.polygon(self.listePointsJPG,fill="black",outline="green") + img.save(self.nomMasque,"TIFF") + else: + img = Image.new("1",self.imageFichier.size,color=0) # 1 bit par pixel (noir et blanc (la couleur par défaut est le noir (http://pillow.readthedocs.org/en/latest/reference/Image.html) + dessin = ImageDraw.Draw(img) # création d'un objet Draw + dessin.draw + dessin.polygon(self.listePointsJPG,fill="white",outline="green") + img.save(self.nomMasque,"TIFF") def ouvrirMasque(self): @@ -323,8 +648,8 @@ def __init__(self,fenetre,image,points,dejaPlaces): self.file = image # nom de la photo avec chemin (au moins relatif) self.root = tkinter.Toplevel() - self.root.title( "Calibration GPS "+image) - self.root.title("Position des points sur la photo : "+image) # titre + self.root.title( _("Calibration GPS ")+image) + self.root.title(_("Position des points sur la photo : ")+image) # titre fenetreIcone(self.root) self.root.geometry( "900x900" ) self.dimMaxiCanvas = 600 # dimension max du canvas accueillant l'image @@ -341,8 +666,9 @@ def __init__(self,fenetre,image,points,dejaPlaces): self.retourSiAbandon = dejaPlaces self.boutonActif = ttk.Button() self.tempo = 0 + self.points = points # pour la suppression d'un point - # initialisations de l'affichage de l'image, dimesions du cadre, positionnement : + # initialisations de l'affichage de l'image, dimensions du cadre, positionnement : self.imageFichier = Image.open(self.file) self.largeurImageFichier, self.hauteurImageFichier = self.imageFichier.size if self.hauteurImageFichier>self.largeurImageFichier: # plus haut que large : on calcule l'échelle sur la hauteur @@ -370,22 +696,24 @@ def __init__(self,fenetre,image,points,dejaPlaces): # boutons de controle : self.frame3 = ttk.Frame(self.root,borderwidth = 2,relief = "sunken") - self.boutonQuitter = ttk.Button(self.frame3, text="Valider",command = self.quitter) - self.boutonSupprimerTousLesPoints = ttk.Button(self.frame3, text="Supprimer tous les points",command = self.supprimerTousLesPoints) - self.boutonAbandon = ttk.Button(self.frame3, text="Abandon",command = self.abandon) + self.boutonQuitter = ttk.Button(self.frame3, text=_("Valider"),command = self.quitter) + #self.boutonSupprimerTousLesPoints = ttk.Button(self.frame3, text=_("Supprimer tous les points"),command = self.supprimerTousLesPoints) + self.boutonSupprimerUnPoint = ttk.Button(self.frame3, text=_("Supprimer un ou plusieurs points"),command = self.supprimerUnPoint) + self.boutonAbandon = ttk.Button(self.frame3, text=_("Abandon"),command = self.abandon) self.boutonQuitter.pack(side='left',pady=2,ipady=2) - self.boutonSupprimerTousLesPoints.pack(side='left',pady=2,ipady=2,padx=5) + #self.boutonSupprimerTousLesPoints.pack(side='left',pady=2,ipady=2,padx=5) + self.boutonSupprimerUnPoint.pack(side='left',pady=2,ipady=2,padx=5) self.boutonAbandon.pack(side='left',pady=2,ipady=2,padx=5) self.frame3.pack(pady=10) self.frame4 = ttk.Frame(self.root,borderwidth = 2,relief = "sunken") - self.boutonchangerCouleurTexte = ttk.Button(self.frame4, text="Changer la couleur des libellés",command = self.changerCouleurTexte) + self.boutonchangerCouleurTexte = ttk.Button(self.frame4, text=_("Changer la couleur des libellés"),command = self.changerCouleurTexte) self.boutonchangerCouleurTexte.pack(pady=2,ipady=2,padx=5) self.frame4.pack(pady=10) # message d'inforamtion self.frame5 = ttk.Frame(self.root,borderwidth = 2) - ttk.Label(self.frame5,text="Utiliser la molette pour zoomer/dezoomer pendant la saisie.").pack() + ttk.Label(self.frame5,text=_("Utiliser la molette pour zoomer/dezoomer pendant la saisie.")).pack() self.frame5.pack() # évènements @@ -402,10 +730,18 @@ def __init__(self,fenetre,image,points,dejaPlaces): fenetre.wait_window(self.root) def placerBoutons(self,listePoints): # Place les boutons correspondants aux points de listePoints + textePoint = _("Placer le point ") # on raccourcit les textes si il y bcp de points (30 max)) + padding = 5 # version 2.41 + if listePoints.__len__()>5: + textePoint = _("Point ") + padding = 3 + if listePoints.__len__()>10: + textePoint = "" + padding = 1 for e in listePoints: # un bouton pour chaque référence de la liste des boutons; - b = ttk.Button(self.frame2, text="Placer le point "+e[0],cursor="plus",command = lambda i = (e[0],e[1]) :self.activerBouton(i)) + b = ttk.Button(self.frame2, text=textePoint+e[0],cursor="plus",width=0,command = lambda i = (e[0],e[1]) :self.activerBouton(i)) self.dicoBoutons.update({e[0]:b}) # mémo dans un dico du nom du point / références du bouton - b.pack(side="left",padx=5) + b.pack(side="left",padx=padding) def bouton1(self,event): # l'utilisateur appuie sur le bouton 1 de la souris @@ -452,7 +788,7 @@ def moletteLinux5(self,event): # l'utilisateur Linu def redrawZoom(self, event): # l'utilisateur zoom avant avec la molette de la souris : mémo du zoom précédent if self.scale>self.maxScale: # si l'échelle passe à plusieurs pixels écran pour un pixel image on arrête - self.infoBulle(event,texte="Zoom maximum atteint") # l'utilisateur est informé + self.infoBulle(event,texte=_("Zoom maximum atteint")) # l'utilisateur est informé return self.listeSauveImages.append((self.xNW,self.yNW,self.xSE,self.ySE,self.img,self.scale)) # sauvegarde pour retour arrière (redrawDeZoom) self.positionNouveauZoom(event.x,event.y) # calcule les positions du centre, du coin nw pour le nouveau zoom @@ -509,7 +845,7 @@ def afficheUnPoint(self,xJPG,yJPG,bouton): def activerBouton(self,boutonChoisi): # appui sur un bouton "ajouter un point" self.boutonActif.state(["!active","!focus","!pressed",'!selected']) # RAZ état de l'ancien bouton - if self.boutonActif==self.dicoBoutons[boutonChoisi[0]]: # réappuie sur le bouton actif : on le désactive et on quitte + if self.boutonActif==self.dicoBoutons[boutonChoisi[0]]: # réappuie sur le bouton actif : on le désactive et on quitte self.frame.config(cursor="arrow") self.boutonActif = ttk.Button() return # dans ce cas, c'est fini @@ -554,54 +890,67 @@ def abandon(self): self.dicoPointsJPG = self.retourSiAbandon self.quitter() - def supprimerTousLesPoints(self): - aSupprimer = dict(self.dicoPointsJPG) - for cle in aSupprimer: + def supprimerTousLesPoints(self): # suppression de la localisation de tous les points GPS présents sur l'image self.file + aSupprimer = dict(self.dicoPointsJPG) # self.dicoPointsJPG[(self.boutonChoisi,self.file,self.numBoutonChoisi)] = (self.xJPG,self.yJPG) + for cle in aSupprimer: # if cle[1]==self.file: del self.dicoPointsJPG[cle] self.afficheImage() - + + def supprimerUnPoint(self): + tousLesPoints = dict(self.dicoPointsJPG) + aSupprimer = choisirDansUneListe(fenetre,[e for e,f,g in tousLesPoints if self.file==f],"Supprimer un ou plusieurs points").selectionFinale + for cle in tousLesPoints: + if cle[1]==self.file and cle[0] in aSupprimer: + del self.dicoPointsJPG[cle] + self.afficheImage() + ################# Classe Principale : la fenêtre maître de l'application, le menu, l'IHM class Interface(ttk.Frame): ################################## INITIALISATIONS - MENU - VALEURS PAR DEFAUT - EXIT ########################################################### - + + def __init__(self, fenetre, **kwargs): # initialise les "constantes" self.initialiseConstantes() - #affiche le logo durant 5 secondes - try: - global compteur - if compteur==1: - self.logo1 = ttk.Frame(fenetre) # cadre dans la fenetre ; affiche la photo sélectionnée - self.canvasLogo = tkinter.Canvas(self.logo1,width = 560, height = 200) # Canvas pour revevoir l'image - self.canvasLogo.pack(fill='both',expand = 1) - self.logo1.pack() - self.imageLogo = Image.open(self.logoCerema) - self.img = self.imageLogo.resize((560,200)) - self.imgTk = ImageTk.PhotoImage(self.img) - self.imgTk_id = self.canvasLogo.create_image(0,0,image = self.imgTk,anchor="nw") # affichage effectif de la photo dans canvasPhoto - fenetreIcone(fenetre) - for i in range(len(self.titreFenetre+" : Une interface graphique pour MicMac...")+8): - fenetre.title((self.titreFenetre+" : Une interface graphique pour MicMac...")[0:i]) - fenetre.update() - time.sleep(0.1) - self.logo1.destroy() - except Exception as e: - print(e) - # initialise les variables "chantier" - self.initialiseValeursParDefaut() # valeurs par défaut pour un nouveau chantier (utile si pas encore de chantier) # pour les paramètres du chantier sous le répertoire chantier, aprés lancement Micmac + self.initialiseValeursParDefaut() # valeurs par défaut pour un nouveau chantier (utile si pas encore de chantier) # pour les paramètres du chantier sous le répertoire chantier, après lancement Micmac - # On restaure la session précédente + # On restaure les paramètres et la session précédente self.restaureParamEnCours() # restaure les paramètres locaux par défaut + #affiche le logo durant 5 secondes, sauf demande expresse + if self.tacky: + try: + global compteur + if compteur==1: + self.canvasLogo1 = tkinter.Canvas(self.logo1,width = 560, height = 200) # Canvas pour revevoir l'image + self.canvasLogo1.pack(fill='both',expand = 1) + self.logo1.pack() + self.imageLogo = Image.open(self.logoCerema) + self.img = self.imageLogo.resize((560,200)) + self.imgTk = ImageTk.PhotoImage(self.img) + self.imgTk_id = self.canvasLogo1.create_image(0,0,image = self.imgTk,anchor="nw") # affichage effectif de la photo dans canvasPhoto + fenetreIcone(fenetre) + + try: + for i in range(len(self.titreFenetre+_(" : une interface graphique pour MicMac..."))+8): + fenetre.title((self.titreFenetre+_(" : une interface graphique pour MicMac..."))[0:i]) + fenetre.update() + time.sleep(0.1) + except: + print(_("Fermeture inatendue de la fenêtre.")) + + except Exception as e: + print(_("Erreur initialisation de la fenêtre principale : ")),str(e) + # Fenêtre principale : fenetre ttk.Frame.__init__(self, fenetre, **kwargs) @@ -611,7 +960,7 @@ def __init__(self, fenetre, **kwargs): self.style.theme_use('clam') fenetreIcone(fenetre) fenetre.title(self.titreFenetre) # Nom de la fenêtre - fenetre.geometry("600x600+100+200") + fenetre.geometry("800x700+100+200") # fenentre.geometry("%dx%d%+d%+d" % (L,H,X,Y)) # construction des item du menu @@ -620,126 +969,208 @@ def __init__(self, fenetre, **kwargs): # Fichier menuFichier = tkinter.Menu(mainMenu,tearoff = 0) ## menu fils : menuFichier, par défaut tearOff = 1, détachable - menuFichier.add_command(label="Nouveau chantier", command=self.nouveauChantier) - menuFichier.add_command(label="Ouvrir un chantier", command=self.ouvreChantier) + menuFichier.add_command(label=_("Nouveau chantier"), command=self.nouveauChantier) + menuFichier.add_command(label=_("Ouvrir un chantier"), command=self.ouvreChantier) menuFichier.add_separator() - menuFichier.add_command(label="Enregistrer le chantier en cours", command=self.enregistreChantier) - menuFichier.add_command(label="Renommer le chantier en cours", command=self.renommeChantier) + menuFichier.add_command(label=_("Enregistrer le chantier en cours"), command=self.enregistreChantierAvecMessage) + menuFichier.add_command(label=_("Renommer ou déplacer le chantier en cours"), command=self.renommeChantier) menuFichier.add_separator() - menuFichier.add_command(label="Du ménage !", command=self.supprimeRepertoires) + menuFichier.add_command(label=_("Exporter le chantier en cours"), command=self.exporteChantier) + menuFichier.add_command(label=_("Importer un chantier"), command=self.importeChantier) menuFichier.add_separator() - menuFichier.add_command(label="Quitter", command=self.quitter) + menuFichier.add_command(label=_("Ajouter un chantier à partir d'un répertoire"), command=self.ajoutRepertoireCommechantier) + menuFichier.add_separator() + menuFichier.add_command(label=_("Du ménage !"), command=self.supprimeRepertoires) + menuFichier.add_separator() + menuFichier.add_command(label=_("Quitter"), command=self.quitter) # Edition menuEdition = tkinter.Menu(mainMenu,tearoff = 0) ## menu fils : menuFichier, par défaut tearOff = 1, détachable - menuEdition.add_command(label="Afficher l'état du chantier", command=self.afficheEtat) + menuEdition.add_command(label=_("Afficher l'état du chantier"), command=self.afficheEtat) menuEdition.add_separator() - menuEdition.add_command(label="Visualiser toutes les photos sélectionnées", command=self.afficherToutesLesPhotos) - menuEdition.add_command(label="Visualiser les points GPS", command=self.afficherLesPointsGPS) - menuEdition.add_command(label="Visualiser le masque 2D et l'image maitre", command=self.afficherMasqueEtMaitre) - menuEdition.add_command(label="Visualiser le masque 3D", command=self.afficheMasqueC3DC) - menuEdition.add_command(label="Visualiser la ligne horizontale/verticale", command=self.afficherLigneHV) - menuEdition.add_command(label="Visualiser la zone plane", command=self.afficherZonePlane) - menuEdition.add_command(label="Visualiser la distance", command=self.afficherDistance) + menuEdition.add_command(label=_("Visualiser toutes les photos sélectionnées"), command=self.afficherToutesLesPhotos) + menuEdition.add_command(label=_("Visualiser les photos pour la calibration intrinsèque"), command=self.afficherCalibIntrinseque) + menuEdition.add_command(label=_("Visualiser les maîtresses et les masques"), command=self.afficherLesMaitresses) + menuEdition.add_command(label=_("Visualiser le masque sur mosaique Tarama"), command=self.afficherMasqueTarama) + menuEdition.add_command(label=_("Visualiser le masque 3D"), command=self.afficheMasqueC3DC) + menuEdition.add_command(label=_("Visualiser les points GPS"), command=self.afficherLesPointsGPS) + menuEdition.add_separator() + menuEdition.add_command(label=_("Visualiser la ligne horizontale/verticale"), command=self.afficherLigneHV) + menuEdition.add_command(label=_("Visualiser la zone plane"), command=self.afficherZonePlane) + menuEdition.add_command(label=_("Visualiser la distance"), command=self.afficherDistance) + menuEdition.add_separator() + menuEdition.add_command(label=_("Afficher la trace complète du chantier"), command=self.lectureTraceMicMac) + menuEdition.add_command(label=_("Afficher la trace synthétique du chantier"), command=self.lectureTraceSynthetiqueMicMac) menuEdition.add_separator() - menuEdition.add_command(label="Afficher la trace complete du chantier", command=self.lectureTraceMicMac) - menuEdition.add_command(label="Afficher la trace synthétique du chantier", command=self.lectureTraceSynthetiqueMicMac) + menuEdition.add_command(label=_("Afficher la mosaïque Tarama"), command=self.afficheMosaiqueTarama) + menuEdition.add_command(label=_("Afficher l'ortho mosaïque Tawny"), command=self.afficheMosaiqueTawny) menuEdition.add_separator() - menuEdition.add_command(label="Afficher l'image 3D aprés Tapas", command=self.afficheApericloud) - menuEdition.add_command(label="Afficher l'image 3D aprés Malt ou C3DC", command=self.affiche3DNuage) + menuEdition.add_command(label=_("Afficher l'image 3D non densifiée"), command=self.afficheApericloud) + menuEdition.add_command(label=_("Afficher l'image 3D densifiée"), command=self.affiche3DNuage) + menuEdition.add_separator() + menuEdition.add_command(label=_("Lister-Visualiser les images 3D"), command=self.lister3DPly) + menuEdition.add_command(label=_("Fusionner des images 3D"), command=self.choisirPuisFusionnerPly) # menuMaintenance.add_command(label="Vérifier les dépendances",command=self.verifierDependances) # MicMac menuMicMac = tkinter.Menu(mainMenu,tearoff = 0) ## menu fils : menuFichier, par défaut tearOff = 1, détachable - menuMicMac.add_command(label="Choisir des photos", command=self.lesPhotos) - menuMicMac.add_command(label="Options", command=self.optionsOnglet) + menuMicMac.add_command(label=_("Choisir des photos"), command=self.lesPhotos) + menuMicMac.add_command(label=_("Options"), command=self.optionsOnglet) menuMicMac.add_separator() - menuMicMac.add_command(label="Lancer MicMac", command=self.lanceMicMac) ## Ajout d'une option au menu fils menuFile + menuMicMac.add_command(label=_("Lancer MicMac"), command=self.lanceMicMac) ## Ajout d'une option au menu fils menuFile + + # GoPro + + menuGoPro = tkinter.Menu(mainMenu,tearoff = 0) ## menu fils : menuFichier, par défaut tearOff = 1, détachable + menuGoPro.add_command(label=_("Options (GoPro par défaut)"), command=self.optionsGoPro) + menuGoPro.add_separator() + menuGoPro.add_command(label=_("Nouveau chantier : choisir une vidéo GoPro, ou autre"), command=self.laVideo) + menuGoPro.add_command(label=_("Sélection des meilleures images"), command=self.selectionGoPro) ## Sélection des "meilleures images" avec le taux passé en paramètre # Outils menuOutils = tkinter.Menu(mainMenu,tearoff = 0) ## menu fils : menuFichier, par défaut tearOff = 1, détachable - menuOutils.add_command(label="Nom et focale de l'appareil photo", command=self.OutilAppareilPhoto) - menuOutils.add_command(label="Toutes les focales des photos", command=self.toutesLesFocales) - menuOutils.add_command(label="Mettre à jour DicoCamera.xml", command=self.miseAJourDicoCamera) - menuOutils.add_separator() - menuOutils.add_command(label="Qualité des photos 'line'", command=self.OutilQualitePhotosLine) - menuOutils.add_command(label="Qualité des photos 'All' ", command=self.OutilQualitePhotosAll) - - # Paramètrage - - menuParametres = tkinter.Menu(mainMenu,tearoff = 0) - menuParametres.add_command(label="Afficher les paramètres", command=self.afficheParam) ## Ajout d'une option au menu fils menuFile - menuParametres.add_separator() - menuParametres.add_command(label="Associer le répertoire bin de MicMac'", command=self.repMicmac) ## Ajout d'une option au menu fils menuFile - menuParametres.add_command(label="Associer 'exiftool'", command=self.repExiftool) ## Exiftool : sous MicMac\bin-aux si Windows, mais sinon ??? - menuParametres.add_command(label="Associer 'Meshlab' ou 'CloudCompare'", command=self.repMeslab) ## Meslab - + menuOutils.add_command(label=_("Nom et focale de l'appareil photo, dimension des photos"), command=self.outilAppareilPhoto) + menuOutils.add_command(label=_("Toutes les focales et les noms des appareils photos"), command=self.toutesLesFocales) + menuOutils.add_command(label=_("Mettre à jour DicoCamera.xml"), command=self.miseAJourDicoCamera) + menuOutils.add_separator() + menuOutils.add_command(label=_("Qualité des photos du dernier traitement"), command=self.nombrePointsHomologues) + menuOutils.add_command(label=_("Sélectionner les N meilleures photos"), command=self.outilMeilleuresPhotos) + menuOutils.add_command(label=_("Retirer des photos"), command=self.retirerPhotos) + menuOutils.add_separator() + menuOutils.add_command(label=_("Modifier l'exif des photos"), command=self.majExif) + menuOutils.add_separator() + menuOutils.add_command(label=_("Modifier les options par défaut"), command=self.majOptionsParDefaut) + menuOutils.add_separator() + menuOutils.add_command(label=_("Vérifie la présence d'une nouvelle version sur GitHub"),command=self.verifVersion) ## Meslab + + # mode Expert + + menuExpert = tkinter.Menu(mainMenu,tearoff = 0) ## menu fils : menuFichier, par défaut tearOff = 1, détachable + menuExpert.add_command(label=_("Exécuter une ligne de commande système"), command=self.lignesExpert) + menuExpert.add_command(label=_("Exécuter une commande python"), command=self.lignesPython) + menuExpert.add_separator() + menuExpert.add_command(label=_("Ajouter les points GPS à partir d'un fichier"), command=self.ajoutPointsGPSDepuisFichier) + menuExpert.add_command(label=_("Ajouter les points GPS d'un autre chantier"), command=self.ajoutPointsGPSAutreChantier) + menuExpert.add_separator() + menuExpert.add_command(label=_("Définir plusieurs appareils photos"), command=self.plusieursAppareils) + menuExpert.add_command(label=_("Liste des appareils photos"), command=self.listeAppareils) + menuExpert.add_separator() + menuExpert.add_command(label=_("Consulter le fichier mm3d-LogFile.txt"), command=self.logMm3d) + + # Paramétrage + + def updateParam(): + if self.tacky: + menuParametres.entryconfig(10, label=_("Désactiver le 'tacky' message de lancement")) + else: + menuParametres.entryconfig(10, label=_("Activer le 'tacky' message de lancement")) + + menuParametres = tkinter.Menu(mainMenu,tearoff = 0,postcommand=updateParam) + menuParametres.add_command(label=_("Afficher les paramètres"), command=self.afficheParam) ## Ajout d'une option au menu fils menuFile + menuParametres.add_separator() + menuParametres.add_command(label=_("Associer le répertoire bin de MicMac"), command=self.repMicmac) ## Ajout d'une option au menu fils menuFile + menuParametres.add_command(label=_("Associer 'exiftool'"), command=self.repExiftool) ## Exiftool : sous MicMac\binaire-aux si Windows, mais sinon ??? + menuParametres.add_command(label=_("Associer 'convert' d'ImageMagick"), command=self.repConvert) ## convert : sous MicMac\binaire-aux si Windows, mais sinon ??? + menuParametres.add_command(label=_("Associer 'ffmpeg (décompacte les vidéos)"), command=self.repFfmpeg) ## ffmpeg : sous MicMac\binaire-aux si Windows, mais sinon ??? + menuParametres.add_command(label=_("Associer 'Meshlab' ou 'CloudCompare'"), command=self.repMeslab) ## Meslab + menuParametres.add_separator() + menuParametres.add_command(label=_("Changer la langue"), command = self.modifierLangue) + menuParametres.add_separator() + menuParametres.add_command(label=_("Désactive/Active le tacky message de lancement..."),command=self.modifierTacky) ## Meslab + menuParametres.add_separator() + # Aide menuAide = tkinter.Menu(mainMenu,tearoff = 0) ## menu fils : menuFichier, par défaut tearOff = 1, détachable - menuAide.add_command(label="Pour commencer...", command=self.commencer) - menuAide.add_command(label="Aide", command=self.aide) - menuAide.add_command(label="Quelques conseils", command=self.conseils) - menuAide.add_command(label="A Propos", command=self.aPropos) + menuAide.add_command(label=_("Pour commencer..."), command=self.commencer) + menuAide.add_command(label=_("Aide sur les menus"), command=self.aide) + menuAide.add_command(label=_("Quelques conseils"), command=self.conseils) + menuAide.add_command(label=_("Historique"), command=self.historiqueDesVersions) + menuAide.add_command(label=_("A Propos"), command=self.aPropos) # ajout des items dans le menu principal : - mainMenu.add_cascade(label = "Fichier",menu=menuFichier) - mainMenu.add_cascade(label = "Edition",menu=menuEdition) + mainMenu.add_cascade(label = _("Fichier"),menu=menuFichier) + mainMenu.add_cascade(label = _("Edition"),menu=menuEdition) mainMenu.add_cascade(label = "MicMac",menu=menuMicMac) - mainMenu.add_cascade(label = "Outils",menu=menuOutils) - mainMenu.add_cascade(label = "Paramètrage",menu=menuParametres) - mainMenu.add_cascade(label = "Aide",menu=menuAide) + mainMenu.add_cascade(label = _("Vidéo"),menu=menuGoPro) + mainMenu.add_cascade(label = _("Outils"),menu=menuOutils) + mainMenu.add_cascade(label = _("Expert"),menu=menuExpert) + mainMenu.add_cascade(label = _("Paramétrage"),menu=menuParametres) + mainMenu.add_cascade(label = _("Aide"),menu=menuAide) # affichage du menu principal dans la fenêtre fenetre.config(menu = mainMenu) - + # Fonction a éxécuter lors de la sortie du programme fenetre.protocol("WM_DELETE_WINDOW", self.quitter) # zone de test éventuel : - - - ####################### initialiseValeursParDefaut du défaut : On choisit de nouvelles photos : on oublie ce qui précéde, sauf les paramètres généraux de aperodedenis (param micmac) - + + #initialise les valeurs par défaut au lancement de l'outil + def initialiseConstantes(self): - # initialisation variables globales et propre au contexte local : + # Pour suivre les nouvelles versions + + self.versionInternetAncienne = str() # Dernière version lue sur GitHub (ne sert plus) + self.messageVersion = bool(True) # l'utilisateur peut désactiver l'affichage du message d'avertissement (False) + + # initialisation variables globales et propre au contexte local : - self.repertoireScript = os.path.dirname(sys.argv[0]) # là sont enrgistrés les paramètres généraux et le dossie ren cours + self.repertoireScript = repertoire_script # là où est le script et les logos cerema et IGN + self.repertoireData = repertoire_data # là ou l'on peut écrire des données self.systeme = os.name # nt ou posix - self.version = " V 1.4" self.nomApplication = os.path.splitext(os.path.basename(sys.argv[0]))[0] # Nom du script - self.titreFenetre = self.nomApplication+self.version # nom du programme titre de la fenêtre + self.titreFenetre = self.nomApplication+version # nom du programme titre de la fenêtre (version = varaioble globale) self.tousLesChantiers = list() # liste de tous les réchantiers créés + self.exptxt = "0" # 0 pour exptxt format binaire, 1 format texte (pts homologues) + self.indiceTravail = 0 # lors de l'installation, valeur initial de l'indice des répertoires de travail # Les 3 chemins utiles : mecmac\bin, meshlab et exiftool : + self.micMac = _('Pas de répertoire désigné pour MicMac\\bin') # oar défaut il n'y a pas de répertoire micMac, sauf si restauration ligne suivante + self.meshlab = _('Pas de fichier désigné pour ouvrir les .PLY') + self.exiftool = _("Pas de chemin pour ExifTool") + self.mm3d = _("Pas de fichier pour mm3d") # lanceur des commandes micmac + self.ffmpeg = _("Pas de fichier pour ffmpeg") # outil d'extraction des images à partir de video + self.mercurialMicMac = _("Pas de version MicMac") + self.mercurialMicMacChantier = "" + self.convertMagick = _("Pas de version Image Magick") # pour convertir les formats + self.noRep = [self.micMac, self.meshlab, self.exiftool, self.mm3d, self.convertMagick,self.ffmpeg] # pour des question de traduction si message et pas si répertoire !! - self.micMac = 'Pas de répertoire désigné pour MicMac\\bin' # oar défaut il n'y a pas de répertoire micMac, sauf si restauration ligne suivante - self.meshlab = 'Pas de fichier désigné pour ouvrir les .PLY' - self.exiftool = "Pas de chemin pour ExifTool" - self.mm3d = "Pas de fichier pour mm3d" + # le controle des photos + self.dimensionsDesPhotos = list() # [(x,Image.open(x).size) for x in self.photosSansChemin] + self.dimensionsOK = bool() # set([y for (x,y) in self.dimensionsDesPhotos]).__len__()==1 # vrai si une seule taille + self.nbFocales = int() # nb de focales parmi les photos + + # les caractéristiques de l'appareil photo : + + self.fabricant = str() + self.nomCamera = str() + self.focale = str() + self.focale35MM = str() + # Les noms des fichiers xml self.masque3DSansChemin = "AperiCloud_selectionInfo.xml" # nom du fichier XML du masque 3D, fabriqué par self.masque3DBisSansChemin = "AperiCloud_polyg3d.xml" # nom du second fichier XML pour le masque 3D self.dicoAppuis = "Dico-Appuis.xml" # nom du fichier XML des points d'appui (nom, X,Y,Z,incertitude) pour Bascule - self.mesureAppuis = "Mesure-Appuis.xml" # nom du XML positionnant les points d'appuis dans les photos + self.mesureAppuis = "Mesure-Appuis.xml" # nom du XML positionnant les points d'appuis GPS dans les photos self.miseAEchelle = "MiseAEchelle.xml" # pour l'axe des x, le plan self.dicoCameraUserRelatif = "include/XML User/DicoCamera.xml" # relatif au répertoire MicMac self.dicoCameraGlobalRelatif = "include/XML_MicMac/DicoCamera.xml" # relatif au répertoire MicMac # Constante sous nt et posix : - self.nomTapioca = "Tapioca" + self.nomTapioca = "Tapioca" self.nomTapas = "Tapas" self.nomMalt = "Malt" self.nomApericloud = "AperiCloud" @@ -769,13 +1200,22 @@ def initialiseConstantes(self): self.resul100=ttk.Frame(fenetre,height=50,relief='sunken') self.texte101=ttk.Label(self.resul100, text="",justify='center',style="C.TButton") self.texte101.pack(ipadx=5,ipady=5) + + # la fenetre pour afficher les textes (traces et aides) + + self.resul200 = ttk.Frame(fenetre,height=100,relief='sunken') # fenêtre texte pour afficher le bilan + self.scrollbar = ttk.Scrollbar(self.resul200) + self.scrollbar.pack(side='right',fill='y',expand=1) + self.scrollbar.config(command=self.yviewTexte) + self.texte201 = tkinter.Text(self.resul200,width=200,height=100,yscrollcommand = self.scrollbar.set,wrap='word') + self.texte201.pack() # Les variables, Widgets et options de la boite à onglet : # Pour tapioca - self.echelle1 = tkinter.StringVar() # nécessaire pour définir la variable obtenue le widget - self.echelle2 = tkinter.StringVar() + self.echelle1 = tkinter.StringVar() # nécessaire pour définir la variable obtenue le widget : pour All + self.echelle2 = tkinter.StringVar() # self.echelle3 = tkinter.StringVar() self.echelle4 = tkinter.StringVar() self.delta = tkinter.StringVar() @@ -783,61 +1223,83 @@ def initialiseConstantes(self): self.modeTapioca = tkinter.StringVar() self.modeMalt = tkinter.StringVar() - # Pour tapas : - self.modeCheckedTapas = tkinter.StringVar() # nécessaire pour définir la variable obtenue par radiobutton - self.arretApresTapas = tkinter.IntVar() + # Pour tapas : - #pour la calibration + self.modeCheckedTapas = tkinter.StringVar() # nécessaire pour définir la variable obtenue par radiobutton + self.arretApresTapas = tkinter.IntVar() # + self.lancerTarama = tkinter.IntVar() # booléen : Tarama crée une mosaique des images, utilisable pour faire un masque sur Malt/ortho + self.calibSeule = tkinter.BooleanVar() + self.repCalibSeule = "PhotosCalibrationIntrinseque" # nom du répertoire pour cantonner les photos servant uniquement à la calibration + + # pour la calibration self.distance = tkinter.StringVar() - # L'onglet : + # pour Campari : pour l'onglet des points GPS : + + self.incertitudeCibleGPS = tkinter.StringVar() + self.incertitudePixelImage = tkinter.StringVar() + self.incertitudeCibleGPS.set("0.05") + self.incertitudePixelImage.set("1") + + # Pour Malt - self.modeMalt = tkinter.StringVar() + self.zoomF = tkinter.StringVar() # niveau de zoom final pour malt : 8,4,2,1 1 le plus dense + self.photosUtilesAutourDuMaitre = tkinter.IntVar() # pour le mode geomimage seul : nombre de photos avant/après autour de la maitresse + self.tawny = tkinter.BooleanVar() # pour le mode Orthophoto seul : lancer ou non tawny + self.tawnyParam = tkinter.StringVar() # paramètres manuel de tawny + + # pour C3DC + + self.choixDensification = tkinter.StringVar() # + self.modeC3DC = tkinter.StringVar() + + # L'onglet : self.onglets = ttk.Notebook(fenetre) # create Notebook in "master" : boite à onglet, supprimé par menageEcran() comme les frames # tapioca : 400 self.item400=ttk.Frame(self.onglets,borderwidth=5,height=50,relief='sunken',padding="0.3cm") - + self.item410=ttk.Label(self.item400, text=_("Tapioca recherche les points homologues entre photos : indiquer l'échelle ou les échelles utilisées")) self.item401 = ttk.Radiobutton(self.item400, text="All", variable=self.modeTapioca, value='All', command=self.optionsTapioca) self.item402 = ttk.Radiobutton(self.item400, text="MulScale", variable=self.modeTapioca, value='MulScale',command=self.optionsTapioca) self.item403 = ttk.Radiobutton(self.item400, text="Line", variable=self.modeTapioca, value='Line', command=self.optionsTapioca) self.item404 = ttk.Radiobutton(self.item400, text="File", variable=self.modeTapioca, value='File') + self.item410.pack(anchor='w') self.item401.pack(anchor='w') self.item402.pack(anchor='w') self.item403.pack(anchor='w') self.item404.pack(anchor='w') self.item404.state(['disabled']) # dans cette version de l'outil - # tapioca Echelle 1 + # tapioca Echelle 1 All self.item480 = ttk.Frame(self.item400,height=50,relief='sunken',padding="0.3cm") - self.item481 = ttk.Label(self.item480, text="Echelle image (-1 pour l'image entière) :") + self.item481 = ttk.Label(self.item480, text=_("Echelle image (-1 pour l'image entière) :")) self.item482 = ttk.Entry(self.item480,textvariable=self.echelle1) self.item481.pack() self.item482.pack() - # tapioca Echelle2 (MultiScale) + # tapioca Echelle2 et 3 (MultiScale) self.item460=ttk.Frame(self.item400,height=50,relief='sunken',padding="0.3cm") - self.item461=ttk.Label(self.item460, text="Echelle image réduite : ") + self.item461=ttk.Label(self.item460, text=_("Echelle image réduite : ")) self.item462=ttk.Entry(self.item460,textvariable=self.echelle2) self.item461.pack() self.item462.pack() - self.item463=ttk.Label(self.item460, text="Seconde Echelle (-1 pour l'image entière) :") + self.item463=ttk.Label(self.item460, text=_("Seconde Echelle (-1 pour l'image entière) :")) self.item464=ttk.Entry(self.item460,textvariable=self.echelle3) self.item463.pack() self.item464.pack() - # tapioca Delta + # tapioca Delta Echelle4 self.item470=ttk.Frame(self.item400,height=50,relief='sunken',padding="0.3cm") - self.item471=ttk.Label(self.item470, text="Echelle image (-1 pour l'image entière) :") + self.item471=ttk.Label(self.item470, text=_("Echelle image (-1 pour l'image entière) :")) self.item472=ttk.Entry(self.item470,textvariable=self.echelle4) - self.item473=ttk.Label(self.item470, text="Delta (nombre d'images se recouvrant, avant et après) : ") + self.item473=ttk.Label(self.item470, text=_("Delta (nombre d'images se recouvrant, avant et après) : ")) self.item474=ttk.Entry(self.item470,textvariable=self.delta) self.item471.pack() self.item472.pack() @@ -848,25 +1310,56 @@ def initialiseConstantes(self): # Tapas : 500 self.item500=ttk.Frame(self.onglets,height=150,relief='sunken',padding="0.3cm") - modesTapas=[('RadialExtended','RadialExtended','active'),('RadialStd','RadialStd','active'),('RadialBasic','RadialBasic','active'), - ('Fraser','Fraser','disabled'),('FraserBasic','FraserBasic','disabled'),('FishEyeEqui','FishEyeEqui','disabled'), - ('HemiEqui','HemiEqui','disabled'),('AutoCal','AutoCal','disabled'),('Figee','Figee','disabled')] # déconnexion texte affichée, valeur retournée + self.item505=ttk.Label(self.item500, text=_("Tapas positionne les appareils photos sur le nuage de points homologues. Préciser le type d'appareil.")) + self.item506=ttk.Label(self.item500, text=_("Quelques photos avec une grande profondeur d'image aident à calibrer l'optique des appareils photos.")) + self.item505.pack() + self.item506.pack() + modesTapas=[('RadialExtended (REFLEX)','RadialExtended','active'), + ('RadialStd (Compact)','RadialStd','active'), + ('RadialBasic (SmartPhone)','RadialBasic','active'), + ('FishEyeBasic (GOPRO)','FishEyeBasic','active'), + ('FishEyeEqui','FishEyeEqui','active'), # déconnexion texte affichée, valeur retournée + ('Fraser','Fraser','active'), + ('FraserBasic','FraserBasic','active'),] +## ('HemiEqui','HemiEqui','disabled'), +## ('AutoCal','AutoCal','disabled'), +## ('Figee','Figee','disabled') for t,m,s in modesTapas: b=ttk.Radiobutton(self.item500, text=t, variable=self.modeCheckedTapas, value=m) b.pack(anchor='w') b.state([s]) - self.modeCheckedTapas.set('RadialExtended') # valeur par défaut nécessaire pour définir la variable obtenue par radiobutton - self.item510 = ttk.Frame(self.item500,height=50,relief='sunken',padding="0.3cm") # pour le check button, fera un encadrement - self.item511 = ttk.Checkbutton(self.item510, variable=self.arretApresTapas, text="Arrêter le traitement après TAPAS") - self.item511.pack() - self.item510.pack() - - - # Calibration : 950 + self.item520 = ttk.Frame(self.item500,height=50,relief='sunken',padding="0.3cm") # pour la calibration, fera un encadrement + + # photosPourCalibrationIntrinseque + + self.item525 = ttk.Button(self.item520,text=_("Choisir quelques photos pour la calibration intrinsèques"),command=self.imagesCalibrationIntrinseques) + self.item526 = ttk.Label(self.item520, text="") + self.item527 = ttk.Checkbutton(self.item520, variable=self.calibSeule, + text=_(" N'utiliser ces photos que pour la calibration")) # inutile ? + self.item528 = ttk.Label(self.item520, text=_("Toutes ces photos doivent avoir la même focale.")) + self.item510 = ttk.Frame(self.item500,height=50,relief='sunken',padding="0.3cm") # pour le check button, fera un encadrement + self.item530 = ttk.Checkbutton(self.item510, variable=self.lancerTarama, text=_("lancer Tarama après TAPAS : mosaique pouvant définir un masque pour Malt/ortho)")) + self.item530.pack(ipady=5) + self.item540 = ttk.Frame(self.item500,height=50,relief='sunken',padding="0.3cm") # pour le check button, fera un encadrement + self.item550 = ttk.Checkbutton(self.item540, variable=self.arretApresTapas, text=_("Arrêter le traitement après TAPAS")) + self.item550.pack(ipady=5) + + self.item505.pack() + self.item506.pack() + self.item525.pack() + self.item526.pack() + self.item527.pack() # je ne comprends plus l'intérêt de cet item : la suite s'accomode très bien de 2 focales différentes... mais si : camille utilise des photos d'un autre site + self.item528.pack() + + # Mise à l'échelle : 950 self.item950 = ttk.Frame( self.onglets, height=5, relief='sunken') + self.item955=ttk.Label(self.item950, text=_("Définition d'un référentiel et d'une métrique sur le nuage de points homologues.")) + self.item956=ttk.Label(self.item950, text=_("Une ligne, un plan et la distance entre 2 points sont nécessaires.")) + self.item955.pack() + self.item956.pack() # Cadre définition des axes : @@ -876,17 +1369,17 @@ def initialiseConstantes(self): padding="0.3cm") self.item961 = ttk.Label(self.item960, - text='Choisir entre :') + text=_('Choisir entre :')) self.item962 = ttk.Button(self.item960, - text='Ligne horizontale', + text=_('Ligne horizontale'), command= self.ligneHorizontale) self.item963 = ttk.Label(self.item960, - text='ou') + text=_('ou')) self.item964 = ttk.Button(self.item960, - text='Ligne verticale', + text=_('Ligne verticale'), command= self.ligneVerticale) self.item961.pack(ipadx=5,padx=5,ipady=2) @@ -899,7 +1392,7 @@ def initialiseConstantes(self): # conjonction de coordination : self.item965 = ttk.Frame( self.item950) - self.item966 = ttk.Label(self.item965,text='ET :') + self.item966 = ttk.Label(self.item965,text=_('ET :')) self.item966.pack() self.item965.pack() @@ -911,17 +1404,17 @@ def initialiseConstantes(self): padding="0.3cm") self.item971 = ttk.Label(self.item970, - text='Choisir entre :') + text=_('Choisir entre :')) self.item972 = ttk.Button(self.item970, - text='Zone plane horizontale', + text=_('Zone plane horizontale'), command= self.planHorizontal) self.item973 = ttk.Label(self.item970, - text='ou') + text=_('ou')) self.item974 = ttk.Button(self.item970, - text='Zone plane verticale', + text=_('Zone plane verticale'), command= self.planVertical) self.item971.pack(ipadx=5,padx=5,ipady=2) @@ -933,7 +1426,7 @@ def initialiseConstantes(self): # conjonction de coordination : self.item975 = ttk.Frame(self.item950) - self.item976 = ttk.Label(self.item975,text='ET :') + self.item976 = ttk.Label(self.item975,text=_('ET :')) self.item976.pack() self.item975.pack() @@ -944,12 +1437,12 @@ def initialiseConstantes(self): relief='sunken', padding="0.3cm") self.item981 = ttk.Label(self.item980, - text='Distance entre les 2 points :') + text=_('Distance entre les 2 points :')) self.item982 = ttk.Entry(self.item980,textvariable=self.distance) # distance self.item983 = ttk.Button(self.item980, - text='Placer 2 points identiques sur 2 photos', + text=_('Placer 2 points identiques sur 2 photos'), command= self.placer2Points) self.item981.pack() @@ -959,71 +1452,162 @@ def initialiseConstantes(self): self.item990 = ttk.Frame( self.item950, relief='sunken') - self.item991 = ttk.Label(self.item990,text='\nPour annuler la calibration mettre la distance = 0') + self.item991 = ttk.Label(self.item990,text='\n' + _('Pour annuler la calibration mettre la distance = 0')) self.item991.pack() + + # Item de la densification : 600, recevra item700 (Malt) ou Item800 (C3DC) + + self.item600 = ttk.Frame(self.onglets,height=5,relief='sunken',padding="0.15cm") + self.item605 = ttk.Frame(self.item600,height=50,relief='sunken',padding="0.15cm") # pour le check button, fera un encadrement + self.item606 = ttk.Radiobutton(self.item605, text=_("Utiliser C3DC"), variable=self.choixDensification, value='C3DC', command=self.optionsDensification) + self.item607 = ttk.Radiobutton(self.item605, text=_("Utiliser MALT"), variable=self.choixDensification, value='Malt', command=self.optionsDensification) + self.item605.pack(pady=3) + self.item606.pack(side='left') + self.item607.pack(side='left') + - # Malt + # Onglet Malt : item700 + + self.item700 = ttk.Frame(self.item600,height=5,relief='sunken',padding="0.15cm") + self.item709 = ttk.Label(self.item700, text= _("Option de Malt :" )) + self.item709.pack(anchor='w') + + self.modesMalt = [(_('UrbanMNE pour photos urbaines'),'UrbanMNE'), + (_("GeomImage pour photos du sol ou d'objets"),'GeomImage'), + (_('Ortho pour orthophotos de terrain naturel [f(x,y)=z)]'),'Ortho'), + (_('AperoDeDenis choisit pour vous les options de GeomImage'),'AperoDeDenis') + ] + + self.TawnyListeparam = ( + "* [Name=DEq] INT :: {Degree of equalization (Def=1)}\n"+ + "* [Name=DEqXY] Pt2di :: {Degree of equalization, if diff in X and Y}\n"+ + "* more : see MicMac documentation" + ) - self.item700 = ttk.Frame(self.onglets,height=5,relief='sunken',padding="0.3cm") - - self.modesMalt=[('Ortho pour orthophotos','Ortho'),('UrbanMNE pour photos urbaine','UrbanMNE'),('GeomImage pour photos du sol','GeomImage')] for t,m in self.modesMalt: - b=ttk.Radiobutton(self.item700, text=t, variable=self.modeMalt, value=m) + b = ttk.Radiobutton(self.item700, text=t, variable=self.modeMalt, value=m, command=self.optionsMalt) b.pack(anchor='w') if self.modesMalt==m: b.state(['selected']) self.modeMalt.set(m) # positionne la valeur initiale sélectionnée - self.item710=ttk.Frame(self.item700,height=50,relief='sunken',padding="0.2cm") # pour le check button, fera un encadrement - self.item701=ttk.Label(self.item710,text="image maitresse = ") - self.item702=ttk.Button(self.item710,text="Choisir l'image maîtresse",command=self.imageMaitresse) - self.item703=ttk.Label(self.item710,text="masque = ") - self.item704=ttk.Button(self.item710,text='Tracer le masque',command=self.traceMasque) - self.item705=ttk.Label(self.item700,text="Attention : le masque 3D de C3DC a la priorité sur Malt") - self.item701.pack() - self.item702.pack(ipady=2,pady=10) - self.item703.pack() - self.item704.pack(ipady=2,pady=10) - self.item705.pack() - self.item710.pack(pady=15) - + + # Boites item710 et 730 dans item700 pour l'option GeomImage - # C3DC + self.item710 = ttk.Frame(self.item700,height=50,relief='sunken',padding="0.15cm") # pour le check button, fera un encadrement + self.item701 = ttk.Label(self.item710) # nom ou nombre d'images maitresses + self.item702 = ttk.Button(self.item710,text=_("Choisir les maîtresses"),command=self.imageMaitresse) + self.item703 = ttk.Label(self.item710) # nom ou nombre de masques + self.item704 = ttk.Button(self.item710,text=_('Tracer les masques'),command=self.tracerLesMasques) + self.item705 = ttk.Label(self.item710,text=_("Attention : Le masque 3D de C3DC a la priorité sur Malt") + "\n" + _("Pour supprimer un masque : supprimer la maitresse")) + self.item730 = ttk.Frame(self.item700,relief='sunken',padding="0.15cm") # fera un encadrement pour nb photos à retenir + self.item732 = ttk.Label(self.item730,text=_("Nombre de photos à retenir autour de l'image maitresse (-1 = toutes) :")) + self.item733 = ttk.Entry(self.item730,width=5,textvariable=self.photosUtilesAutourDuMaitre) + + + # Boite item720 pour le niveau de zoom final - self.item800 = ttk.Frame(self.onglets,height=5,relief='sunken',padding="0.3cm") - - self.item801 = ttk.Button(self.item800,text='Tracer le masque 3D sur le nuage AperiCloud',command=self.affiche3DApericloud) - self.item801.pack(ipady=2,pady=10) - self.item802 = ttk.Label(self.item800, text= "Tapas doit avoir créé un nuage de points.\n\n"+\ - "Dans l'outil : \n"+\ - "Définir le masque : F9 \n"+\ - "Ajouter un point : clic gauche\n"+\ - "Fermer le polygone : clic droit\n"+\ - "Sélectionner : touche espace\n"+\ - "Sauver le masque : Ctrl S.\n"+ - "Quitter : Ctrl Q.\n\n"+ - "Supprimer le masque : Ctrl Q (sans saisie préalable).\n\n"+ - "Attention : C3DC a la priorité sur le masque 2D de Malt") - self.item802.pack(ipady=2,pady=10) + self.item720 = ttk.Frame(self.item700,relief='sunken',padding="0.15cm") # fera un encadrement pour le zoom + self.item722 = ttk.Label(self.item720,text=_("Zoom final : 8, 4, 2 ou 1 (8=le plus rapide, 1=le plus précis)")) + self.item723 = ttk.Entry(self.item720,width=5,textvariable=self.zoomF) - - #Ajout des onglets dans la boite à onglet : + + # Boite item740 pour Tawny dans item700 pour l'option Ortho + + self.item740 = ttk.Frame(self.item700,relief='sunken',padding="0.2cm") # fera un encadrement + self.item741 = ttk.Checkbutton(self.item740, variable=self.tawny, text=_("Lancer tawny après MALT")) + self.item742 = ttk.Label(self.item740,text=_("Tawny génère une ortho mosaïque qui sera drapée sur le nuage densifié.")+"\n"+ + _("Saisir si besoin les paramètres facultatifs, exemple :") + + "\nDEq=2 DegRapXY=[4,1]") + self.item743 = ttk.Entry(self.item740,width=45,textvariable=self.tawnyParam) + self.item744 = ttk.Label(self.item740,text=_("Liste des paramètres facultatifs nommés :") + "\n"+self.TawnyListeparam) + + # Bouton pour tracer un masque sur la mosaique créée par tarama - self.onglets.add(self.item400,text="Tapioca") # add onglet to Notebook - self.onglets.add(self.item500,text="Tapas") # add onglet to Notebook - self.onglets.add(self.item950,text="Calibration") # add onglet to Notebook - self.onglets.add(self.item700,text="Malt") - self.onglets.add(self.item800,text="C3DC") + self.item745 = ttk.Button(self.item700,text=_('Tracer un masque sur la mosaïque Tarama'),command=self.tracerUnMasqueSurMosaiqueTarama) + + + # Boite item750 dans item700 pour l'option AperoDeDenis + + self.item750 = ttk.Frame(self.item700,height=50,relief='sunken',padding="0.2cm") # pour le check button, fera un encadrement + self.item751 = ttk.Label(self.item750,text=_("La saisie des masques n'est active qu'après Tapas.")) # nom ou nombre d'images maitresses + self.item752 = ttk.Label(self.item750,text=_("Pas de masque.")) # nom ou nombre de masque + self.item753 = ttk.Button(self.item750,text=_('Tracer les masques'),command=self.tracerLesMasquesApero) + self.item754 = ttk.Label(self.item750,text= _("Pour supprimer un masque : supprimer la maitresse dans l'option GeomImage")+"\n" + + _("Consulter la documentation.")) + + + self.item701.pack() + self.item702.pack() + self.item703.pack() + self.item704.pack(ipady=2,pady=3) + self.item705.pack() + self.item722.pack(side='left') + self.item723.pack(side='left') + self.item720.pack(pady=3) + self.item732.pack(side='left') + self.item733.pack(side='left') + self.item741.pack() + self.item742.pack() + self.item743.pack() + self.item744.pack() + self.item751.pack() + self.item752.pack() + self.item753.pack(ipady=2,pady=3) + self.item754.pack() + + + # Boite item800 pour l'onglet C3DC + + self.item800 = ttk.Frame(self.item600,height=5,relief='sunken',padding="0.3cm") + self.item808 = ttk.Label(self.item800, text= _("Option de C3DC :" )) + self.item811 = ttk.Radiobutton(self.item800, text=_("Forest - avec drapage, rapide"), variable=self.modeC3DC, value='Forest') + self.item812 = ttk.Radiobutton(self.item800, text=_("Statue - avec drapage"), variable=self.modeC3DC, value='Statue') + self.item813 = ttk.Radiobutton(self.item800, text=_("QuickMac - rapide, sans drapage"), variable=self.modeC3DC, value='QuickMac') + self.item814 = ttk.Radiobutton(self.item800, text=_("MicMac - sans drapage"), variable=self.modeC3DC, value='MicMac') + self.item815 = ttk.Radiobutton(self.item800, text=_("BigMac - précis, sans drapage"), variable=self.modeC3DC, value='BigMac') + self.item808.pack(anchor='w') + self.item811.pack(anchor='w') + self.item812.pack(anchor='w') + self.item813.pack(anchor='w') + self.item814.pack(anchor='w') + self.item815.pack(anchor='w') + self.item801 = ttk.Button(self.item800,text=_('Tracer un masque 3D'),command=self.affiche3DApericloud) + self.item801.pack(ipady=2,pady=3) + self.item802 = ttk.Button(self.item800,text=_('Supprimer le masque 3D'),command=self.supprimeMasque3D) + + self.item803 = ttk.Label(self.item800, text= \ + _("Dans la boîte de dialogue pour tracer le masque : " ) +"\n"+\ + _("Définir le masque : F9 ") + "\n"+\ + _("Ajouter un point : clic gauche") + "\n"+\ + _("Fermer le polygone : clic droit") + "\n"+\ + _("Sélectionner : touche espace") +"\n"+\ + _("Sauver le masque : Ctrl S.") + "\n"+ + _("Quitter : Ctrl Q.") + "\n\n"+ + _("Agrandir les points : Maj +") + "\n\n"+\ + _("Saisie simultanée de plusieurs masques disjoints possible")) + self.item803.pack(ipady=2,pady=3) + self.item802.pack(ipady=2,pady=3) + self.item804 = ttk.Label(self.item800, text= "") # état du masque (créé, supprimé, absent, absence de nuage non dense) + self.item804.pack(ipady=2,pady=3) + + + # Ajout des onglets dans la boite à onglet : + + self.onglets.add(self.item400,text="Points homologues") # add onglet to Notebook + self.onglets.add(self.item500,text="Orientation") # add onglet to Notebook + self.onglets.add(self.item950,text="Mise à l'échelle") # add onglet to Notebook + self.onglets.add(self.item600,text="Densification") # boutons généraux à la boite à onglet : self.item450 = ttk.Frame(fenetre) # frame pour bouton de validation, permet un ménage facile self.item451 = ttk.Button(self.item450, - text=' Valider les options', + text=_(' Valider les options'), command=self.finOptionsOK) # bouton permettant de tout valider self.item452 = ttk.Button(self.item450, - text=' Annuler', + text=_(' Annuler'), command=self.finOptionsKO) # bouton permettant de tout annuler # les 2 boutons globaux : @@ -1032,32 +1616,183 @@ def initialiseConstantes(self): self.item452.pack(side='left') # La boite de dialogue pour demander les dimensions du capteur de l'appareil photo - + self.item1000 = ttk.Frame(fenetre) self.item1001 = ttk.Label(self.item1000) self.item1002 = ttk.Label(self.item1000, - text= "Indiquer les dimensions du capteur, en mm.\n"+\ - "par exemple :\n\n 5.7 7.6 \n\n"+\ - "Le site :\n \http://www.dpreview.com/products\n"+\ - "fournit les dimensions de tous les appareils photos.") + text= _("Indiquer les dimensions du capteur, en mm.") + "\n"+\ + _("par exemple :") + "\n\n 5.7 7.6 \n\n"+\ + _("Le site :") + "\n \http://www.dpreview.com/products\n"+\ + _("fournit les dimensions de tous les appareils photos.")) self.item1003 = ttk.Entry(self.item1000) self.item1004 = ttk.Button(self.item1000, - text=' Valider', + text=_(' Valider'), command=self.dimensionCapteurOK) # bouton permettant de tout valider self.item1005 = ttk.Button(self.item1000, - text=' Annuler', + text=_(' Annuler'), command=self.dimensionCapteurKO) # bouton permettant de tout annuler self.item1001.pack(pady=15) self.item1002.pack(pady=15) self.item1003.pack(pady=15) self.item1004.pack(pady=15) self.item1005.pack(pady=15) + + + # La boite de dialogue pour demander les options pour la video (GoPro par défaut) + + self.goProMaker = tkinter.StringVar() + self.goProFocale35 = tkinter.StringVar() + self.goProFocale = tkinter.StringVar() + self.goProNomCamera = tkinter.StringVar() + self.goProNbParSec = tkinter.StringVar() # taux de conservation des photos pour DIV + self.goProEchelle = tkinter.StringVar() # pour tapioca + self.goProDelta = tkinter.StringVar() + + # GoPRO : les options à saisir pour le traitement GoPro : valeurs par défaut (non modifiées lors de la création d'un nouveau chantier) + + self.goProMaker.set("GoPro") + self.goProFocale35.set("16.53") # Hero3 + self.goProFocale.set("2.98") #2.98 4.52 + self.goProNomCamera.set("GoPro Hero3 HD3") + self.goProNbParSec.set("3") # taux de conservation des photos pour DIV + self.goProEchelle.set("1000") # pour tapioca + self.goProDelta.set("10") + self.extensionChoisie = ".JPG" + + + self.item2000 = ttk.Frame(fenetre) + self.item2010 = ttk.Label(self.item2000, + text=_("Marque de l'appareil : ")) + self.item2011 = ttk.Entry(self.item2000, + textvariable=self.goProMaker) + self.item2001 = ttk.Label(self.item2000, + text=_("Nom de la camera : ")) + self.item2002 = ttk.Entry(self.item2000, + textvariable=self.goProNomCamera) + self.item2003 = ttk.Label(self.item2000, + text= _("Focale en mm:")) + self.item2004 = ttk.Entry(self.item2000, + textvariable=self.goProFocale) + self.item2005 = ttk.Label(self.item2000, + text= _("Focale équivalente 35mm :")) + self.item2006 = ttk.Entry(self.item2000, + textvariable=self.goProFocale35) + self.item2007 = ttk.Label(self.item2000, + text= "--------------\n" + _("Nombre d'images à conserver par seconde :"), + justify='center') + self.item2008 = ttk.Entry(self.item2000, + textvariable=self.goProNbParSec) + + self.item2020 = ttk.Button(self.item2000, + text=_(' Valider'), + command=self.optionsGoProOK) # bouton permettant de tout valider + self.item2021 = ttk.Button(self.item2000, + text=_(' Annuler'), + command=self.optionsGoProKO) # bouton permettant de tout annuler + self.item2010.pack(pady=5) + self.item2011.pack(pady=1) + self.item2001.pack(pady=5) + self.item2002.pack(pady=1) + self.item2003.pack(pady=5) + self.item2004.pack(pady=1) + self.item2005.pack(pady=5) + self.item2006.pack(pady=1) + self.item2007.pack(pady=5) + self.item2008.pack(pady=1) + self.item2020.pack(pady=5) + self.item2021.pack(pady=5) + + self.goProMaker.set("GoPro") + self.goProFocale35.set("16.53") # Hero3 + self.goProFocale.set("2.98") #2.98 4.52 + self.goProNomCamera.set("GoPro Hero3 HD3") + self.goProNbParSec.set("3") # taux de conservation des photos pour DIV + self.goProEchelle.set("1000") # pour tapioca + self.goProDelta.set("10") + + # La fenetre des options pour l'exif : + + self.exifMaker = tkinter.StringVar() + self.exifFocale35 = tkinter.StringVar() + self.exifFocale = tkinter.StringVar() + self.exifNomCamera = tkinter.StringVar() + + self.exifMaker.set("") + self.exifFocale35.set("") + self.exifFocale.set("") + self.exifNomCamera.set("") + + self.item3000 = ttk.Frame(fenetre) + self.item3010 = ttk.Label(self.item3000, + text=_("Modification des Exif") + "\n\n" + _("Marque de l'appareil : ")) + self.item3011 = ttk.Entry(self.item3000, + textvariable=self.exifMaker) + self.item3001 = ttk.Label(self.item3000, + text=_("Modèle de l'appareil: ")) + self.item3002 = ttk.Entry(self.item3000, + textvariable=self.exifNomCamera) + self.item3003 = ttk.Label(self.item3000, + text= _("Focale en mm:")) + self.item3004 = ttk.Entry(self.item3000, + textvariable=self.exifFocale) + self.item3005 = ttk.Label(self.item3000, + text= _("Focale équivalente 35mm :")) + self.item3006 = ttk.Entry(self.item3000, + textvariable=self.exifFocale35) + + self.item3020 = ttk.Button(self.item3000, + text=_('Valider et mettre à jour'), + command=self.exifOK) # bouton permettant de tout valider + self.item3021 = ttk.Button(self.item3000, + text=_(' Annuler'), + command=self.exifKO) # bouton permettant de tout annuler + + self.item3010.pack(pady=5) + self.item3011.pack(pady=1) + self.item3001.pack(pady=5) + self.item3002.pack(pady=1) + self.item3003.pack(pady=5) + self.item3004.pack(pady=1) + self.item3005.pack(pady=5) + self.item3006.pack(pady=1) + self.item3020.pack(pady=5) + self.item3021.pack(pady=5) + + # La boite de dialogue pour demander le nombre de photos a retenir parmi les meilleures + + self.item9000 = ttk.Frame(fenetre) + self.item9001 = ttk.Label(self.item9000) + self.item9002 = ttk.Label(self.item9000, + text= _("Indiquer le nombre de photos à retenir.") + "\n"+ + _("Un nouveau chantier sera créé avec les photos ayant, par paire, le plus de points homologues")+ "\n"+ + _("Ce choix est différent du nombre moyen de points homologues par photo.")) + self.item9003 = ttk.Entry(self.item9000) + self.item9004 = ttk.Button(self.item9000, + text=_(' Valider'), + command=self.nbMeilleuresOK) # bouton permettant de tout valider + self.item9005 = ttk.Button(self.item9000, + text=_(' Annuler'), + command=self.nbMeilleuresKO) # bouton permettant de tout annuler + self.item9001.pack(pady=15) + self.item9002.pack(pady=15) + self.item9003.pack(pady=15) + self.item9004.pack(pady=15) + self.item9005.pack(pady=15) + + # les logo, l'apropos + + self.logo1 = ttk.Frame(fenetre) # cadre dans la fenetre de départ : CEREMA ! + self.logo = ttk.Frame(self.resul100) # logo cerema dans l'apropos + self.canvasLogo = tkinter.Canvas(self.logo,width = 225, height = 80) # Canvas pour revevoir l'image + self.logoIgn = ttk.Frame(self.resul100) # logo IGN dans l'apropos + self.canvasLogoIGN = tkinter.Canvas(self.logoIgn,width = 149, height = 162)# Canvas pour revevoir l'image + self.labelIgn = ttk.Label(self.logo,text=_("MicMac est une réalisation de\n Marc Pierrot-Deseilligny, IGN")) # Les fichiers XML : - # fichier XML de description du masque + # fichier XML de description du masque - self.masqueXML = ( '\n'+ + self.masqueXMLOriginal = ( '\n'+ "\n"+ "MonImage_Masq.tif\n"+ "largeur hauteur\n"+ @@ -1326,9 +2061,9 @@ def initialiseConstantes(self): # Fichier de persistance des paramètres self.paramChantierSav = 'ParamChantier.sav' - self.fichierParamMicmac = os.path.join(self.repertoireScript,'ParamMicmac.sav') # sauvegarde des paramètres globaux d'AperodeDenis - self.fichierParamChantierEnCours= os.path.join(self.repertoireScript,self.paramChantierSav) # pour les paramètres du chantier en cours - + self.fichierParamMicmac = os.path.join(self.repertoireData,'ParamMicmac.sav') # sauvegarde des paramètres globaux d'AperodeDenis + self.fichierParamChantierEnCours= os.path.join(self.repertoireData,self.paramChantierSav) # pour les paramètres du chantier en cours + self.fichierSauvOptions = os.path.join(self.repertoireData,'OptionsMicmac.sav') # pour la sauvegarde d'options personnalisées # Divers @@ -1336,90 +2071,131 @@ def initialiseConstantes(self): self.logoIGN = os.path.join(self.repertoireScript,'logoIGN.jpg') self.messageNouveauDepart = str() # utilisé lorsque l'on relance la fenêtre self.nbEncadre = 0 # utilisé pour relancer la fenetre - + self.suffixeExport = "_export" # ne pas modifierr : rendra incompatible la nouvelle version + + self.messageSauvegardeOptions = (_("Quelles options par défaut utiliser pour les nouveaux chantiers ?") + "\n"+ + _("Les options par défaut concernent :") + "\n"+ + _("Points homologues : All, MulScale, line ,les échelles et delta") + "\n"+ + _("Orientation : RadialExtended,RadialStandard, Radialbasic, arrêt après Tapas") + "\n"+ + _("Points GPS : options de CAMPARI") + "\n"+ + _("Densification Malt : mode, zoom final, nombre de photos autour de la maîtresse") + "\n"+ + _("Densification Malt Ortho : Tawny et ses options en saisie libre") + "\n"+ + _("Densification C3DC : mode (Statue ou QuickMac)") + "\n\n") + self.tacky = True # Suite au message de Luc Girod sur le forum le 21 juin 17h + self.chantierNettoye = False # par défaut : le chantier n'est pas nettoyé ! + + # il faudrait mettre ici les textes de l'Aide, des conseils, de l'historique, de l'apropos + + ####################### initialiseValeursParDefaut du défaut : nouveau chantier, On choisira de nouvelles photos : on oublie ce qui précéde, sauf les paramètres généraux de aperodedenis (param micmac) + def initialiseValeursParDefaut(self): - - # Numéro du chantier : pour indicer le numéro du répertoire de travail : un nouveau est créé à chaque éxécution - - try: self.indiceTravail += 1 # on incrémente s'il existe - except: self.indiceTravail = 1 # sinon met à 1 sinon - # le chantier : variable self.etatDuChantier + # Etat du chantier : variable self.etatDuChantier # 0 : en cours de construction, pas encore de photos # 1 : photos saisies, répertoire origine fixé, non modifiable # 2 : chantier enregistré - # 3 : micmac lancé, pendant l'exécution de Tapioca et tapas - # 4 : arrêt aprés tapas et durant malt en cours d'exécution - # 5 : malt terminé - # 6 : rendu modifiable aprés une première exécution + # 3 : micmac lancé, pendant l'exécution de Tapioca et tapas, reste si plantage + # 4 : arrêt après tapas et durant malt en cours d'exécution + # 5 : densification terminée OK + # 6 : rendu modifiable après une première exécution + # 7 : densification effectuée mais pas de nuage dense généré # - 1 : en cours de suppression self.etatDuChantier = 0 + # Type de chantier : c'est une liste de string (on pourrait aussi mettre un dictionnaire), avec : + # [0] = s'il s'agit de 'photos' ou d'une 'vidéo' + # [1] = s'il s'agit d'un chantier 'initial' ou 'renommé' + # [2] = 'original' ou "importé" + + self.typeDuChantier = ['photos','initial','original'] + # La sauvegarde : self.etatSauvegarde # "" : lorsque le chantier est sauvegardé sous son répertoire de travail, l'exécution de micMac sauve le chantier # "*" : lors de sa création avant sauvegarde et lorsque le chantier a été modifié par l'utilisateur. self.etatSauvegarde = "" # Indicateur du caractère sauvegardé ("") ou à sauvegarder ("*") du chantier. utile pour affichage title fenetre - - # les photos : - + # Faut-il avertir l'utilisateur qu'il y a une nouvelle version disponible sur GitHub - self.repertoireDesPhotos = 'Pas de répertoire pour les photos' + self.avertirNouvelleVersion = False + + # les photos : + + self.repertoireDesPhotos = _('Pas de répertoire pour les photos') self.photosAvecChemin = list() # liste des noms des fichiers photos avec chemin complet self.photosSansChemin = list() # nom des photos sans le chemin - self.photosPropresAvecChemin = list() # les photos propres = photos à copier : on remplace les photos "sales" par les "propres" (nettoyées) self.lesExtensions = str() # l'utilisateur pourrait sélectionner des photos avec des extensions différentes - self.repTravail = self.repertoireScript # répertoire ou seront copiés les photos et ou se fera le traitement,Pour avoir un répertoire valide au début + self.repTravail = self.repertoireData # répertoire ou seront copiés les photos et ou se fera le traitement,Pour avoir un répertoire valide au début self.chantier = str() # nom du chantier (répertoire sosu le répertoire des photos) self.extensionChoisie = str() # extensions des photos (actuellement JPG obligatoire) - - # Malt : Mode, Maitre et Masque : - - self.modeMalt.set('GeomImage') - self.masque = str() # nom du fichier image représentant le masque sur l'image maitresse - self.masqueSansChemin = str() # image masque : en TIF, choisi par l'utilisateur - self.maitreSansChemin = str() # image maitresse - self.maitreCommentaire = str() # indique si l'image maitresse est choisie automatiquement - self.maitre = str() - self.fichierMasqueXML = str() # nom du fichier XML décrivant le masque - self.nomMaitreSansExtension = str() - self.monImage_MaitrePlan = str() # Nom de l'image maitresse du plan repere (sans extension) - self.monImage_PlanTif = str() # nom du masque correspondant - self.planProvisoireHorizontal = "planHorizontal.tif" - self.planProvisoireVertical = "planVertical.tif" - - # mieux que Mic Mac qui prend par défaut le masque de l'image maitre avec le nom prédéfini masq - - + self.lesTagsExif = dict() # pour mémoriser les valeurs des tags de l'exif, long à récolter + # Tapioca - self.modeTapioca.set('MulScale') - self.echelle1.set('500') - self.echelle2.set('500') - self.echelle3.set('1500') - self.echelle4.set('1500') - self.delta.set(1) + self.modeTapioca.set('MulScale')# Mode (All, MulScale, Line) + self.echelle1.set('1200') # echelle pour "All" + self.echelle2.set('300') # echelle base pour MulScale (si 2 photos n'ont qu'un seul point homologues a cette échelle la paire est ignorées dans l'étape suivante + self.echelle3.set('1200') # echelle haute pour MulScale + self.echelle4.set('1200') # echelle pour Line + self.delta.set('3') # delta en + et en = pour Line + self.nePasLancerTapas = False # si tapioca mulscale est interrompu aprés la première échelle : devient True # TAPAS - self.modeCheckedTapas.set('RadialExtended') - self.arretApresTapas.set(1) # 1 : on arrête le traitement après Tapas, 0 on poursuit - + self.modeCheckedTapas.set('RadialBasic') # mode par défaut depuis la v 2.23 du 14 mars 2016 + self.arretApresTapas.set(0) # 1 : on arrête le traitement après Tapas, 0 on poursuit + self.lancerTarama.set(0) # 0 : on ne lance pas Tarama (mosaique des photos après Tapas) + self.photosPourCalibrationIntrinseque = list() # quelques images pour calibrer Tapas + self.calibSeule.set(True) # par défaut : uniquement pour la calibration + self.mosaiqueTaramaTIF = str() + self.mosaiqueTaramaJPG = str() + self.masqueTarama = str() + # Malt + # mieux que Mic Mac qui prend par défaut le masque de l'image maitre avec le nom prédéfini masq - self.modeMalt.set('GeomImage') - - # Calibration + self.modeMalt.set('GeomImage') # par défaut + self.photosUtilesAutourDuMaitre.set(5) # 5 autour de l'image maîtresse (les meilleures seront choisies en terme de points homologues) + self.tawny.set(0) # pas de lancement par défaut de Tawny après Malt Ortho + self.tawnyParam.set("") # paramètres pour tawny + self.zoomF.set('4') # doit être "1","2","4" ou "8" (1 le plus détaillé, 8 le plus rapide) + self.etapeNuage = "5" # par défaut (très mystérieux!) + self.modele3DEnCours = "modele3D.ply" # Nom du self.modele3DEnCours courant + self.dicoInfoBullesAAfficher = None # pour passer l'info à afficherLesInfosBullesDuDico (dans choisirUnePhoto) + self.listeDesMaitresses = list() + self.listeDesMasques = list() + self.choixDensification.set("C3DC") # la densification par défaut : C3DC + self.zoomI = "" # le niveau de zoom initial en reprise de Malt + self.listeDesMaitressesApero = list() # les maitresses pour l'option AperoDeDenis (recalculées en fonction du répertoire Homol) + self.reinitialiseMaitreEtMasque() # initialise toutes les variables lièes à l'image maitresse et au masque + + #Tawny - self.listePointsGPS = list() # 6-tuples (nom du point, x, y et z gps, booléen actif, identifiant) + self.orthoMosaiqueTawny = "OrthoMosaique.tif" + + # C3DC + + self.modeC3DC.set("Forest") # valeur possible : Statue, Ground, QuickMac, Forest... + self.choixDensification.set("C3DC") # valeur possible : C3DC ou MALT + + # Calibration par points GPS + + self.listePointsGPS = list() # 6-tuples (nom du point, x, y et z gps, booléen actif ou supprimé, identifiant) self.idPointGPS = 0 # identifiant des points, incrémenté de 1 a chaque insertion self.dicoPointsGPSEnPlace = dict() # dictionnaire des points GPS placés dans les photos (créé par la classe CalibrationGPS) - self.dicoLigneHorizontale = dict() # les deux points de la ligne horizontale (sur 2 photos) - self.dicoLigneVerticale = dict() # les 2 points décrivant une ligne horizontale + self.dicoLigneHorizontale = dict() # les deux points de la ligne horizontale + self.dicoLigneVerticale = dict() # les 2 points décrivant une ligne self.dicoCalibre = dict() # les 2 points décrivant un segment de longueur donnée + self.dicoPointsAAfficher = None # pour passer l'info à afficherTousLesPointsDuDico (dans choisirUnePhoto) + self.listeWidgetGPS = str() # liste des widgets pour la saisie + + # et mise à l'échelle + + self.planProvisoireHorizontal = "planHorizontal.tif" + self.planProvisoireVertical = "planVertical.tif" + self.distance.set("") # pour la trace : @@ -1427,393 +2203,686 @@ def initialiseValeursParDefaut(self): self.ligneFiltre = str() self.TraceMicMacComplete = str() self.TraceMicMacSynthese = str() - self.fichierParamChantier = "" #fichier paramètre sous le répertoire du chantier + self.fichierParamChantier = "" #fichier paramètre sous le répertoire du chantier + # divers - self.messageSiPasDeFichier = 1 # pour affichage de message dans choisirphoto, difficile a passer en paramètre - if self.systeme=="posix": # dépend de l'os, mais valeur par défaut nécessaire + self.messageSiPasDeFichier = 1 # pour affichage de message dans choisirphoto, difficile a passer en paramètre + if self.systeme=="posix": # dépend de l'os, mais valeur par défaut nécessaire self.shell = False if self.systeme=="nt": self.shell = True + self.homolActuel = str() # nom du répertoire qui a été renommé en "Homol" + self.fermetureOngletsEnCours = False # pour éviter de boucler sur la fermeture de la boite à onglet + self.fermetureOptionsGoProEnCours= False + self.fermetureModifExif = False + + # si les options par défaut sont personnalisées on les restaure : - ################# Le Menu FICHIER : Ouvre un nouveau chantier avec les valeurs par défaut, ouvre un chantier existant, enregistrer, renommer, supprimer + self.restaureOptions() - def nouveauChantier(self): # on conserve : micMac,meshlab,tousLesRepertoiresDeTravail - texte="" + ################# Le Menu FICHIER : Ouvre un nouveau chantier avec les valeurs par défaut, ouvre un chantier existant, enregistrer, renommer, supprimer + + # Enregistre le chantier précédent, prépare un chantier vide avec le répertoire de travail par défaut + + def nouveauChantier(self): # conserve : micMac,meshlab,tousLesRepertoiresDeTravail + self.menageEcran() + texte="" # réinitialise les paramètres du chantier (initialiseValeursParDefaut) if self.etatDuChantier == 1 : - if self.deuxBoutons("Enregistrer le chantier ?", - "Chantier non encore enregistré. Voulez-vous l'enregistrer ?", - "Enregistrer", - "Ne pas enregistrer.") == 0: + if self.troisBoutons(_("Enregistrer le chantier ?"), + _("Chantier non encore enregistré. Voulez-vous l'enregistrer ?"), + _("Enregistrer"), + _("Ne pas enregistrer.")) == 0: self.enregistreChantier() - texte="Chantier précédent enregistré : "+self.chantier+"\n" + texte=_("Chantier précédent enregistré : %s") % (self.chantier)+ "\n" if self.etatDuChantier >= 2 and self.etatSauvegarde =="*": - if self.deuxBoutons("Enregistrer le chantier "+self.chantier+" ?", - "Chantier modifé depuis la dernière sauvegarde. Voulez-vous l'enregistrer ?", - "Enregistrer", - "Ne pas enregistrer.") == 0: + if self.troisBoutons(_("Enregistrer le chantier %s ?") % (self.chantier), + _("Chantier modifié depuis la dernière sauvegarde. Voulez-vous l'enregistrer ?"), + _("Enregistrer"), + _("Ne pas enregistrer.")) == 0: self.copierParamVersChantier() - texte = "Chantier précédent enregistré : "+self.chantier+"\n" + texte = _("Chantier précédent enregistré : %s") % (self.chantier)+ "\n" self.initialiseValeursParDefaut() os.chdir(self.repTravail) # lors de la création d'un chantier il s'agir du répertoire de l'appli self.afficheEtat(texte) - - + def ouvreChantier(self): + self.menageEcran() texte="" - if self.etatDuChantier == 1 : - if self.deuxBoutons("Enregistrer le chantier ?", - "Chantier non encore enregistré. Voulez-vous l'enregistrer ?", - "Enregistrer", - "Ne pas enregistrer.") == 0: + if self.etatDuChantier == 1 and self.etatSauvegarde =="*": + if self.troisBoutons(_("Enregistrer le chantier ?"), + _("Chantier non encore enregistré. Voulez-vous l'enregistrer ?"), + _("Enregistrer"), + _("Ne pas enregistrer.")) == 0: self.enregistreChantier() - texte="Chantier précédent enregistré : "+self.chantier+"\n" + texte=_("Chantier précédent enregistré : %s") % (self.chantier) + "\n" if self.etatDuChantier >= 2 and self.etatSauvegarde =="*": - if self.deuxBoutons("Enregistrer le chantier "+self.chantier+" ?", - "Chantier modifé depuis la dernière sauvegarde. Voulez-vous l'enregistrer ?", - "Enregistrer", - "Ne pas enregistrer.") == 0: + if self.troisBoutons(_("Enregistrer le chantier %s ?") % (self.chantier), + _("Chantier modifié depuis la dernière sauvegarde. Voulez-vous l'enregistrer ?"), + _("Enregistrer"), + _("Ne pas enregistrer.")) == 0: self.copierParamVersChantier() - texte="Chantier précédent enregistré : "+self.chantier+"\n" - - bilan = self.choisirUnRepertoire("Choisir un chantier.") # boite de dialogue de sélection du chantier à ouvrir, renvoi : self.selectionRepertoireAvecChemin + texte=_("Chantier précédent enregistré : %s") % (self.chantier) + "\n" + bilan = self.choisirUnChantier(_("Choisir un chantier.")) # boite de dialogue de sélection du chantier à ouvrir, renvoi : self.selectionRepertoireAvecChemin if bilan!=None: - self.afficheEtat("Aucun chantier choisi.\n"+bilan+"\n") + self.afficheEtat(_("Aucun chantier choisi.") + "\n" + bilan + "\n") return - self.fichierParamChantier = self.selectionRepertoireAvecChemin+os.sep+self.paramChantierSav + self.fichierParamChantier = os.path.join(self.selectionRepertoireAvecChemin,self.paramChantierSav) if os.path.exists(self.fichierParamChantier): - self.restaureParamChantier(self.fichierParamChantier) - self.etatSauvegarde = "" + self.restaureParamChantier(self.fichierParamChantier) self.sauveParam() # pour assurer la cohérence entre le chantier en cours et le chantier ouvert (écrase le chantier en cours) self.afficheEtat(texte) else: - self.encadre ('Chantier choisi "'+self.selectionRepertoireAvecChemin+'" corrompu. Abandon.') + self.encadre (_('Chantier choisi %s corrompu. Abandon.') % (self.selectionRepertoireAvecChemin)) + def enregistreChantierAvecMessage(self): + if(self.enregistreChantier()): + self.afficheEtat(_("Chantier enregistré")+"\n") def enregistreChantier(self): # Correspond simplement à la copie du fichier paramètre sous le répertoire de travail et à l''apparition du nom + self.menageEcran() if self.etatDuChantier == 0: # pas de photo : pas d'enregistrement - self.encadre("Indiquer les photos à traiter avant d'enregistrer le chantier.") - return + self.encadre(_("Indiquer les photos à traiter avant d'enregistrer le chantier.")) + return False if self.etatDuChantier == 1: # des photos, pas encore enregistré : on mote l'enregistrement : etat = 2 self.etatDuChantier = 2 self.copierParamVersChantier() # on enregistre, ou on réenregistre + return True def renommeChantier(self): + self.menageEcran() if self.etatDuChantier==0: - self.encadre("Le chantier est en cours de définition.\nIl n'a pas encore de nom, il ne peut être renommé.\n\nCommencer par choisir les photos") - return - texte = "Nouveau nom pour le chantier "+self.chantier+" :\n" - bas = "Un chemin, absolu ou relatif, est un nom valide\n\nAucun fichier de l'arborecence du chantier ne soit être ouvert." - if self.etatSauvegarde=="*": - bas = bas+"\nLe chantier, actuellement modifié, sera enregistré." - new = MyDialog(fenetre,texte,basDePage=bas) - if new.saisie!="": - nouveauRepertoire = os.path.join(self.repertoireDesPhotos,new.saisie) - if os.path.splitdrive(nouveauRepertoire)[0].upper()!=os.path.splitdrive(self.repTravail)[0].upper(): - self.encadre("Le nom \n\n"+new.saisie+"\n\nimplique un changement de disque.\nCette version ne permet pas cette opération.") - return - if os.path.exists(nouveauRepertoire): - self.encadre("Le nom \n"+new.saisie+"\npour le chantier est déjà utilisé.\nChoississez un autre nom.") - return - self.fermerVisuPhoto() # fermer tous les fichiers potentiellement ouvert. - os.chdir(self.repertoireScript) # quitter le répertoire courant - try: - self.meshlabExe1.kill() - time.sleep(0.1) - except: pass # fermer meshlab si possible - try: - self.meshlabExe2.kill() - time.sleep(0.1) - except: pass - try: - time.sleep(0.1) - os.rename (self.repTravail,nouveauRepertoire) # RENOMMER + self.encadre(_("Le chantier est en cours de définition.") + "\n" + + _("Il n'a pas encore de nom, il ne peut être renommé.") + "\n\n" + + _("Commencer par choisir les photos")) + return + texte = _("Nouveau nom ou nouveau chemin pour le chantier %s :") % (self.chantier) + "\n" + bas = (_("Donner le nouveau nom du chantier") + "\n"+ + _("Un chemin absolu sur la même unité disque ou relatif au répertoire pére est valide") + "\n"+ + _("Aucun fichier de l'arborescence du chantier ne doit être ouvert.")+ "\n\n"+ + _("Chemin actuel : ") + "\n"+ + self.repTravail) + repertoirePere = os.path.dirname(self.repTravail) + new = MyDialog(fenetre,texte,basDePage=bas).saisie + if new=="": return + nouveauRepertoire = os.path.normcase(os.path.normpath(os.path.join(repertoirePere,new))) # sinon on renomme sous ou sur le répertoire des photos + if nouveauRepertoire==self.repTravail : + self.encadre(_("Nouveau nom = ancien nom ; Abandon")) + return # destination == origine : retour + nouveauChantier = os.path.basename(nouveauRepertoire) + if nouveauChantier.upper() in [os.path.basename(e).upper() for e in self.tousLesChantiers] and self.chantier.upper()!=nouveauChantier.upper(): + self.encadre(_("Le nom du nouveau chantier %s est déjà un chantier. Abandon.") % (nouveauChantier)) + return + if os.path.splitdrive(nouveauRepertoire)[0].upper()!=os.path.splitdrive(self.repTravail)[0].upper(): + self.encadre(_("Le nouveau répertoire ") + "\n\n" + + nouveauRepertoire + "\n\n" + + _("implique un changement de disque.") + "\n" + + _("Utiliser l'Export-Import.")) + return + if os.path.exists(nouveauRepertoire): + self.encadre(_("Le répertoire") + "\n" + nouveauRepertoire + "\n" + + _("pour le chantier est déjà utilisé.") + "\n" + + _("Choisissez un autre nom.")) + return + try: + if os.path.commonpath([self.repTravail,nouveauRepertoire]) == self.repTravail: # Attention : commande nouvelle en version python 3.5 + self.encadre(_("Le répertoire") + "\n" + nouveauRepertoire + "\n" + + _("désigne un sous-répertoire du chantier en cours.") + "\n" + + _("Choisissez un autre nom.")) + return + except: pass + self.fermerVisuPhoto() # fermer tous les fichiers potentiellement ouvert. + os.chdir(self.repertoireData) # quitter le répertoire courant + try: self.meshlabExe1.kill() + except: pass # fermer meshlab si possible + try: self.meshlabExe2.kill() + except: pass + try: + time.sleep(0.1) + os.renames (self.repTravail,nouveauRepertoire) # RENOMMER + except Exception as e: + self.encadre(_("Le renommage du chantier ne peut se faire actuellement,") + "\n" + _("soit le nom fourni est incorrect,") + "\n"+ + _("soit un fichier du chantier est ouvert par une autre application.") + "\n"+ + _("soit l'explorateur explore l'arborescence.") + "\n" + _("erreur : ") + "\n\n"+str(e)) + return + # Chantier renommé correctement + ancienChantier = self.chantier + self.chantier = nouveauChantier + try: self.tousLesChantiers.remove(self.repTravail) # retirer l'ancien nom de la liste des répertoires de travail + except: pass + self.repTravail = nouveauRepertoire # positionner le nouveau nom + self.redefinirLesChemins() # mettre à jour le nom de tous les chemins realtifs + ajout(self.tousLesChantiers,self.repTravail) # ajouter le nouveau nom parmi les noms de chantiers + # Type de chantier : self.typeDuChantier : c'est une liste de string (on pourrait aussi mettre un dictionnaire), avec : + # [0] = s'il s'agit de 'photos' ou d'une 'vidéo' + # [1] = s'il s'agit d'un chantier 'initial' ou 'renommé' + # [2] = 'original' ou "importé" + self.typeDuChantier[1] = 'renommé' + + self.encadreEtTrace("\n---------\n"+ heure() + "\n" + _("Chantier :") + "\n" + ancienChantier + "\n" + _("renommé en :") + "\n" + self.chantier + "\n" + _("Répertoire : ") + self.repTravail + "\n") + + def redefinirLesChemins(self): # Mettre self.repTravail dans les chemins des images, des maitres et masques et dans les dictionnaires, sauver + # si le chantier n'est plus sous le répertoire des photos alors le répertoire des photos devient le chantier lui même + self.photosAvecChemin = [os.path.join(self.repTravail,os.path.basename(afficheChemin(e))) for e in self.photosAvecChemin] + self.listeDesMaitresses = [os.path.join(self.repTravail,os.path.basename(afficheChemin(e))) for e in self.listeDesMaitresses] + self.listeDesMasques = [os.path.join(self.repTravail,os.path.basename(afficheChemin(e))) for e in self.listeDesMasques] + self.lesTagsExif = dict() + + # le répertoire où se trouvent les photos pour la calibration change après Tapas : + + if self.photosPourCalibrationIntrinseque: + if self.repCalibSeule in os.path.dirname(self.photosPourCalibrationIntrinseque[0]): + self.photosPourCalibrationIntrinseque = [os.path.join(self.repTravail,self.repCalibSeule,os.path.basename(afficheChemin(e))) + for e in self.photosPourCalibrationIntrinseque] + else: + self.photosPourCalibrationIntrinseque = [os.path.join(self.repTravail,os.path.basename(afficheChemin(e))) + for e in self.photosPourCalibrationIntrinseque] + + + if self.fichierMasqueXML!=str(): + self.fichierMasqueXML = os.path.join(self.repTravail,os.path.basename(afficheChemin(self.fichierMasqueXML))) + if self.monImage_MaitrePlan!=str(): + self.monImage_MaitrePlan = os.path.join(self.repTravail,os.path.basename(afficheChemin(self.monImage_MaitrePlan))) + self.monImage_PlanTif = os.path.join(self.repTravail,os.path.basename(afficheChemin(self.monImage_PlanTif))) + + + # dicoPointsGPSEnPlace key = nom point, photo, identifiant, value = x,y + dico=dict() + for e in self.dicoPointsGPSEnPlace.keys(): + f = (e[0],os.path.join(self.repTravail,os.path.basename(afficheChemin(e[1]))),e[2]) + dico[f]=self.dicoPointsGPSEnPlace[e] + self.dicoPointsGPSEnPlace = dict(dico) + + # axe horizontal, dans le dico : self.dicoLigneHorizontale. key = nom point, photo, identifiant ;Retrouver nom de la photo, coordonnées des points + # items = liste de tuple (key,values) soit tuple = (point,photo, id),(x1,y1) + + dico=dict() + for e in self.dicoLigneHorizontale.keys(): + f = (e[0],os.path.join(self.repTravail,os.path.basename(afficheChemin(e[1]))),e[2]) + dico[f]=self.dicoLigneHorizontale[e] + self.dicoLigneHorizontale = dict(dico) + dico=dict() + for e in self.dicoLigneVerticale.keys(): + f = (e[0],os.path.join(self.repTravail,os.path.basename(afficheChemin(e[1]))),e[2]) + dico[f]=self.dicoLigneVerticale[e] + self.dicoLigneVerticale = dict(dico) + dico=dict() + + for e in self.dicoCalibre.keys(): + f = (e[0],os.path.join(self.repTravail,os.path.basename(afficheChemin(e[1]))),e[2]) + dico[f]=self.dicoCalibre[e] + self.dicoCalibre = dict(dico) + + # nouveau répertoire des photos : + + self.repertoireDesPhotos = afficheChemin(self.repertoireDesPhotos) + + if not os.path.isdir(self.repertoireDesPhotos): + self.repertoireDesPhotos = self.repTravail + + self.definirFichiersTrace() # positionne sous le répertoire de travail + self.copierParamVersChantier() # sauve param puis copie vers chantier en cours + + def exporteChantier(self): + self.menageEcran() + if self.etatDuChantier == 0: + self.encadre(_("Pas de chantier en cours")) + return + self.encadre(_("Patience : chantier en cours d'archivage...") + "\n") + self.copierParamVersChantier() # enregistre et sauve le chantier + self.encadre(_("Archive ") + "\n" + self.chantier + ".exp" + "\n" + + _("créée sous ") + "\n" + self.repTravail + "\n\n" + + _("Taille =") + str(int(zipdir(self.repTravail)/1024)) + "Ko") + + def importeChantier(self): + self.menageEcran() + try: + self.encadre(_("Choisir le nom de l'archive à importer.")) + archive = tkinter.filedialog.askopenfilename( initialdir=self.repTravail, + filetypes=[(_("Export"),"*.exp"),(_("Tous"),"*")], + multiple=False, + title = _("Chantier à importer")) + if archive==str(): + self.encadre(_("Importation abandonnée.")) + return + if not zipfile.is_zipfile(archive): + self.encadre(archive+_(" n'est pas un fichier d'export valide") + "\n"+ + _("ou alors, sous ubuntu,il lui manque le droit d'exécution.")) + return + + self.encadre(_("Choisir le répertoire dans lequel recopier le chantier.")) + destination = tkinter.filedialog.askdirectory(title='Désigner le répertoire où importer le chantier ', + initialdir=self.repTravail) + if not os.path.isdir(destination): + self.encadre(destination+_(" n'est pas un répertoire valide.")) + return + os.chdir(destination) # relativise les chemins + self.encadre(_("Recopie en cours dans") + "\n" + destination + "\n" + _("Patience !")) + + zipf = zipfile.ZipFile(archive, 'r') # ouverture du zip + # récupération du nom du futur chantier : c'est la racine commune de tous les fichiers dans la sauvegarde + nouveauChantier = os.path.normpath(os.path.commonprefix(zipf.namelist())[:-1]) + ancienChantier = nouveauChantier.split(self.suffixeExport)[0] # ancien chantier = nouveau - suffixe + if os.path.isdir(nouveauChantier): + zipf.close() + self.encadre(_("Le répertoire destination") + "\n" + + os.path.join(destination, nouveauChantier) + "\n" + + _("existe déjà. Abandon")) + return + zipf.extractall(path=destination) + zipf.close() + oldChantier = nouveauChantier + i = 0 + while (os.path.basename(nouveauChantier) in [os.path.basename(e) for e in self.tousLesChantiers]) or os.path.isdir(os.path.join(destination,nouveauChantier)) and i<20: + nouveauChantier = nouveauChantier+"x" + i += 1 + try: os.renames (oldChantier,nouveauChantier) # on a trouvé un nom nouveau de chantier ET de répertoire (plante si old=nouveau) except Exception as e: - self.encadre("Le renommage du chantier ne peut se faire actuellement,\nsoit le nom fourni est incorrect,\n"+ - "soit un fichier du chantier est ouvert par une autre application.\n"+ - "soit l'explorateur explore l'arborescence.\nerreur : \n\n"+str(e)) + print(_("Erreur copie lors d'un import : "),str(e)) + self.encadre(_("L'importation a échouée. Erreur : ")+str(e)) return - self.tousLesChantiers.remove(self.repTravail) # retirer de la liste des répertoires de travail - ajout(self.tousLesChantiers,nouveauRepertoire) # ajouter le nouveau - ancienChantier = self.chantier - self.repTravail = nouveauRepertoire # maj des paramètres + + nouveauChemin = os.path.normcase(os.path.normpath(os.path.join(destination,nouveauChantier))) + + # on copie si possible l'archive sous le nouveau répertoire de travail + try: shutil.copy(archive,nouveauChemin) + except Exception as e: + print(_("Erreur copie lors d'un import : "),str(e)) + self.encadre(_("L'importation a échouée. Erreur : ")+str(e)) + return + # le répertoire des photos devient le répertoire de travail - #redéfinir les chemins des images maitre et masques + # on ajoute le chantier dans les paramètres généraux - if self.maitre!=str(): - self.maitre = os.path.join(self.repTravail,self.maitreSansChemin) - if self.masque!=str(): - self.masque = os.path.join(self.repTravail,self.masqueSansChemin) - if self.fichierMasqueXML!=str(): - self.fichierMasqueXML = os.path.join(self.repTravail,os.path.basename(self.fichierMasqueXML)) - if self.monImage_MaitrePlan!=str(): - self.monImage_MaitrePlan = os.path.join(self.repTravail,os.path.basename(self.monImage_MaitrePlan)) - self.monImage_PlanTif = os.path.join(self.repTravail,os.path.basename(self.monImage_PlanTif)) - - self.photosPropresAvecChemin = [os.path.join(self.repTravail,os.path.basename(e)) for e in self.photosPropresAvecChemin] + ajout(self.tousLesChantiers,nouveauChemin) # ajouter le nouveau + self.sauveParamMicMac() - # dicoPointsGPSEnPlace key = nom point, photo, identifiant, value = x,y - print("avant : ",self.dicoPointsGPSEnPlace) - dico=dict() - for e in self.dicoPointsGPSEnPlace.keys(): - f = (e[0],os.path.join(self.repTravail,os.path.basename(e[1])),e[2]) - dico[f]=self.dicoPointsGPSEnPlace[e] - self.dicoPointsGPSEnPlace = dict(dico) - print("aprés : ",self.dicoPointsGPSEnPlace) - - # axe horizontal, dans le dico : self.dicoLigneHorizontale. key = nom point, photo, identifiant ;Retrouver nom de la photo, coordonnées des points - # items = liste de tuple (key,values) soit tuple = (point,photo, id),(x1,y1) - - print("avant : ",self.dicoLigneHorizontale) - dico=dict() - for e in self.dicoLigneHorizontale.keys(): - f = (e[0],os.path.join(self.repTravail,os.path.basename(e[1])),e[2]) - dico[f]=self.dicoLigneHorizontale[e] - self.dicoLigneHorizontale = dict(dico) - print("aprés : dicoLigneHorizontale",self.dicoLigneHorizontale) - - print("avant : ",self.dicoLigneVerticale) - dico=dict() - for e in self.dicoLigneVerticale.keys(): - f = (e[0],os.path.join(self.repTravail,os.path.basename(e[1])),e[2]) - dico[f]=self.dicoLigneVerticale[e] - self.dicoLigneVerticale = dict(dico) - print("aprés dicoLigneVerticale: ",self.dicoLigneVerticale) - - print("avant : ",self.dicoCalibre) - dico=dict() - for e in self.dicoCalibre.keys(): - f = (e[0],os.path.join(self.repTravail,os.path.basename(e[1])),e[2]) - dico[f]=self.dicoCalibre[e] - self.dicoCalibre = dict(dico) - print("aprés dicoCalibre: ",self.dicoCalibre) + # on met à jour les paramètres locaux : remplacer les répertoires ancien par le nouveau, sauvegarder + fichierParam = os.path.join(nouveauChemin,self.paramChantierSav) + + if os.path.isfile(fichierParam): + self.restaureParamChantier(fichierParam) # la restauration positionne self.reptravail et self.chantier sur l'ancien répertoire de travail + else: + self.encadre(fichierParam+_(" absent")) + return + self.repTravail = nouveauChemin + self.chantier = nouveauChantier + self.definirFichiersTrace() # la restauration a défini des chemins suivant l'ancien reptravail : il faut corriger + # Type de chantier : c'est une liste de string (on pourrait aussi mettre un dictionnaire), avec : + # [0] = s'il s'agit de 'photos' ou d'une 'vidéo' + # [1] = s'il s'agit d'un chantier 'initial' ou 'renommé' + # [2] = 'original' ou "importé" + self.typeDuChantier[2] = 'importé' + self.redefinirLesChemins() # mise à jour des chemins et sauvegarde des paramètres. - self.chantier = new.saisie - self.definirFichiersTrace() #positionne sous le répertoire de travail - self.copierParamVersChantier() # sauve param puis copie on enregistre, ou on réenregistre - self.afficheEtat("Chantier :\n"+ancienChantier+"\nrenommé en :\n"+self.chantier+"\n") + # on affiche l'état du chantier : + self.encadreEtTrace("\n\n -------------- \n"+ + heure()+ + "\n" + _("Chantier importé :") + "\n" + self.chantier + "\n\n" + _("Répertoire :") + "\n" +self.repTravail+ "\n\n" + _("Vous pouvez le renommer si besoin.")+ + "\n -------------- ") + try: + self.ajoutLigne("\n" + _("Version de MicMac avant l'import : %s") % (self.mercurialMicMacChantier) +"\n") + self.ajoutLigne("\n" + _("Version de MicMac : %s") % (self.mercurialMicMac) +"\n") + self.ecritureTraceMicMac() + except Exception as e: + print(_("erreur affichage version lors de l'import d'un chantier : ")+str(e)) + except Exception as e: + self.encadre(_("Anomalie lors de l'importation : ")+str(e)) + return + + def ajoutRepertoireCommechantier(self): # ajoute un répertoire dans le liste des chantiers : le répertoire doit contenir le fichier paramChantier.sav + self.menageEcran() + nouveauRepChantier = tkinter.filedialog.askdirectory(title='Désigner le répertoire contenant un chantier ', + initialdir=self.repTravail) + if os.path.isdir(nouveauRepChantier): # c'est bien un répertoire + param = os.path.join(nouveauRepChantier,self.paramChantierSav) + if os.path.isfile(param): # il existe un fichier paramètre + if nouveauRepChantier in self.tousLesChantiers: + self.encadre(_("Le répertoire du nouveau chantier \n %s \n est déjà un chantier.\n Abandon.") % (nouveauRepChantier)) + return + self.encadre(_("Répertoire correct. Patience...")) + # on ajoute le chantier dans les paramètres généraux + ajout(self.tousLesChantiers,nouveauRepChantier) # on ajoute le chantier dans les paramètres généraux + self.restaureParamChantier(param) + self.repTravail = nouveauRepChantier + self.chantier = os.path.basename(self.repTravail) + self.typeDuChantier[2] = 'ajouté' + self.sauveParam() # pour assurer la cohérence entre le chantier en cours et le chantier ouvert (écrase le chantier en cours) + self.redefinirLesChemins() # pour convertir les chemins dans les paramètres + ajout(self.tousLesChantiers,nouveauRepChantier) # on ajoute le chantier dans les paramètres généraux + self.afficheEtat() + else: + self.encadre(_("Le répertoire ne contient pas le fichier :\n")+ + self.paramChantierSav+_("Ce n'est pas un chantier.\nAbandon."), + nouveauDepart="non") + + def copierParamVersChantier(self): # copie du fichier paramètre sous le répertoire du chantier, pour rejouer et trace try: - self.etatSauvegarde = "" # Pour indiquer que le chantier sauvegardé sous le répertoire du chantier + self.etatSauvegarde = "" self.sauveParam() - if self.repTravail!=os.path.dirname(self.fichierParamChantierEnCours): # pour éviter de copier un fichier sur lui même - shutil.copy(self.fichierParamChantierEnCours,self.repTravail) + try: shutil.copy(self.fichierParamChantierEnCours,self.repTravail) # pour éviter de copier un fichier sur lui même + except Exception as e: print(_("erreur copie fichier param chantier : %(param)s vers %(rep)s erreur=") % {"param" : self.fichierParamChantierEnCours, "rep" : self.repTravail} ,str(e)) fenetre.title(self.etatSauvegarde+self.titreFenetre) except Exception as e: - self.ajoutLigne("Erreur lors de la copy du fichier paramètre chantier \n"+self.fichierParamChantierEnCours+"\n vers \n"+self.repTravail+"\n erreur : \n"+e) + self.ajoutLigne(_("Erreur lors de la copie du fichier paramètre chantier") + "\n" + self.fichierParamChantierEnCours + "\n" + _("vers") + "\n" + self.repTravail + "\n" + _("erreur :") + "\n" +str(e)) ################################## LE MENU EDITION : afficher l'état, les photos, lire une trace, afficher les nuages de points ############################ def afficheEtat(self,entete="",finale=""): + if self.pasDeMm3d():return self.sauveParam() + self.avertissementNouvelleVersion() nbPly = 0 photosSansCheminDebutFin = list(self.photosSansChemin) + texte = str() if len(self.photosSansChemin)>5: photosSansCheminDebutFin =photosSansCheminDebutFin[:2]+list('..',)+photosSansCheminDebutFin[-2:] - try: # rappel des valeurs par défauts (try car erreur si le format de la sauvegarde a changé cela plante) : - texte = entete+'\nRépertoire des photos : \n'+afficheChemin(self.repertoireDesPhotos) + try: + # affiche les options du chantier (try car erreur si le format de la sauvegarde a changé cela plante) : + # Type de chantier : c'est une liste de string (on pourrait aussi mettre un dictionnaire), avec : + # [0] = s'il s'agit de 'photos' ou d'une 'vidéo' + # [1] = s'il s'agit d'un chantier 'initial' ou 'renommé' + # [2] = 'original' ou "importé" + if self.typeDuChantier[0]=='photos': + texte = entete + _('Répertoire des photos :') + "\n" + afficheChemin(self.repertoireDesPhotos) + if self.typeDuChantier[0]=='vidéo': + texte = entete + "\n" + _("Répertoire de la vidéo :") + "\n" + afficheChemin(self.repertoireDesPhotos) if len(self.photosSansChemin)==0: - texte = texte+'\n\n'+'Aucune photo sélectionnée.\n' - if len(self.photosSansChemin)>=1: # Il ne peut en principe pas y avoir une seule photo sélectionnée - texte = texte+'\n\n'+str(len(self.photosSansChemin))+' photos sélectionnées : \n' +\ - '\n'.join(photosSansCheminDebutFin)+finale + texte = texte+'\n\n'+_('Aucune photo sélectionnée.') + '\n' + if len(self.photosSansChemin)>=1: # Il ne peut en principe pas y avoir une seule photo sélectionnée + if self.calibSeule.get(): + m = _(' photos sélectionnées') + '\n' + _('(sans calibration si tapas executé) : ') + '\n' + else: + m = _(' photos sélectionnées : ') + '\n' + texte = texte+'\n\n'+str(len(self.photosSansChemin))+m+'\n'.join(photosSansCheminDebutFin)+finale if self.nombreDExtensionDifferentes(self.photosSansChemin)>1: # il y a plus d'un format de photo ! - texte = texte+'\n\nATTENTION : plusieurs extensions différentes dans les photos choisies !\n Le traitement ne se fera que sur un type de fichier.' + texte = texte+'\n\n' + _('ATTENTION : plusieurs extensions différentes dans les photos choisies !') + '\n' + _('Le traitement ne se fera que sur un type de fichier.') # Options pour Tapioca : if self.modeTapioca.get()!='': - texte = texte+'\n\nTapioca :\nMode : '+self.modeTapioca.get()+'\n' + texte = texte+'\n\n' + 'Recherche des points homologues :' + '\n' + _('Mode : ')+self.modeTapioca.get()+'\n' if self.modeTapioca.get()=="All": - texte = texte+'Echelle 1 : '+self.echelle1.get()+'\n' + texte = texte+_('Echelle 1 : ')+self.echelle1.get()+'\n' if self.modeTapioca.get()=="MulScale": - texte = texte+'Echelle 1 : '+self.echelle2.get()+'\n' - texte = texte+'Echelle 2 : '+self.echelle3.get()+'\n' + texte = texte+_('Echelle 1 : ')+self.echelle2.get()+'\n' + texte = texte+_('Echelle 2 : ')+self.echelle3.get()+'\n' if self.modeTapioca.get()=="Line": - texte = texte+'Echelle : '+self.echelle4.get()+'\n' - texte = texte+'Delta : '+self.delta.get()+'\n' + texte = texte+_('Echelle : ')+self.echelle4.get()+'\n' + texte = texte+_('Delta : ')+self.delta.get()+'\n' # Options pour Tapas : if self.modeCheckedTapas.get()!='': - texte = texte+'\nTapas :\nMode : '+self.modeCheckedTapas.get()+'\n' + texte = texte+'\n' + 'Orientation des appareils photos :\n' + _('Mode : ')+self.modeCheckedTapas.get()+'\n' + if self.photosPourCalibrationIntrinseque.__len__()>0: + texte = texte+_("Nombre de photos pour calibration intrinsèque : ")+str(self.photosPourCalibrationIntrinseque.__len__())+"\n" + if self.calibSeule.get(): + texte = texte+_('Ces photos servent uniquement à la calibration.') + '\n' + if self.lancerTarama.get()==1: + texte = texte+_('Tarama demandé après Tapas') + '\n' if self.arretApresTapas.get()==1: - texte = texte+'Arrêt demandé après Tapas\n' - - # Calibration + texte = texte+_('Arrêt demandé après Tapas') + '\n' + + # Mise à l'échelle if self.controleCalibration(): - texte = texte+'\nCalibration présente\n'+self.etatCalibration + texte = texte+'\n' + _("Mise à l'échelle présente") + '\n'+self.etatCalibration else: if self.distance.get()=='0': - texte = texte+'\nCalibration annulée : distance=0\n' + texte = texte+'\n' + _("Mise à l'échelle invalide : distance=0") + '\n' elif self.etatCalibration!=str(): # calibration incomplète - texte = texte+"\nCalibration incomplète :\n"+self.etatCalibration+"\n" + texte = texte+"\n" + _("Mise à l'échelle incomplète :") + "\n"+self.etatCalibration+"\n" # Points GPS + if self.listePointsGPS: + if self.controlePointsGPS(): + texte += "\n"+_("Points GPS : Saisie complète, les points seront pris en compte") + "\n" + else: + texte += "\n"+_("Points GPS : Saisie incomplète, les points ne seront pas pris en compte") + "\n" + + # C3DC est-il installé ? + + if not self.mm3dOK: # La version de MicMac n'autorise pas les masques 3D : info + texte = texte + "\n" + _("La version installée de Micmac n'autorise pas les masques en 3D") + "\n" + + # C3DC est choisi : - if self.controlePointsGPS(): - texte = texte+self.etatPointsGPS - - # Masque 3D pour D3DC ou alors Malt et image maitresse et masque : - malt = True # a priori on éxécute malt - if self.mm3dOK: # La version de MicMac autorise les masques 3D + if self.choixDensification.get()=="C3DC": if self.existeMasque3D(): - texte = texte+'\nC3DC : Masque 3D\n' - malt = False # on éxécutera C3DC - else: - texte = texte + "\nLa version installée de Micmac n'autorise pas les masques en 3D\n" - - if malt: - if self.maitreSansChemin!='': - texte = texte+'\nMalt :\nMode : '+self.modeMalt.get()+'\nImage maitresse : '+self.maitreSansChemin - else: - texte = texte+'\nMalt :\nMode : '+self.modeMalt.get()+"\nPas d'image maitresse." - if self.masqueSansChemin!='': - texte = texte+'\nMasque : '+self.masqueSansChemin+'\n' + texte = texte+'\n' + _('Densification : C3DC avec masque 3D') + '\n' else: - texte = texte+"\nPas de masque.\n" + texte = texte+'\n' + _('Densification : C3DC sans Masque') + '\n' + # Malt est choisi : + + if self.choixDensification.get()=="Malt": + texte = texte+'\n' + 'Densification : Malt\n' + _('Mode : ')+self.modeMalt.get() + if self.modeMalt.get()=="GeomImage": + if self.listeDesMaitresses.__len__()==0: + texte = texte+"\n" + _("Pas d'image maîtresse\n") + if self.listeDesMaitresses.__len__()==1: + texte = texte+'\n' + _('Image maîtresse : ')+os.path.basename(self.listeDesMaitresses[0]) + if self.listeDesMaitresses.__len__()>1: + texte = texte+'\n'+str(self.listeDesMaitresses.__len__())+_(' images maîtresses') + if self.listeDesMasques.__len__()==1: + texte = texte+'\n' + _('1 masque') + '\n' + if self.listeDesMasques.__len__()==0 and self.listeDesMaitresses.__len__()>0: + texte = texte+"\n" + _("Pas de masque.") + "\n" + if self.listeDesMasques.__len__()>1: + texte = texte+"\n"+str(self.listeDesMasques.__len__())+_(" masques") + "\n" + if self.listeDesMaitresses.__len__()>0 and self.photosUtilesAutourDuMaitre.get()>0: + texte = texte+_("%s photos utiles autour de la maîtresse") %(str(self.photosUtilesAutourDuMaitre.get()))+"\n" + + if self.modeMalt.get()=="Ortho": + if self.tawny.get(): + texte = texte+"\n" + _("Tawny lancé après Malt")+"\n" + + if self.modeMalt.get()=="AperoDeDenis": + if self.listeDesMaitressesApero.__len__()==1: + texte = texte+'\n' + _('Image maîtresse : ')+os.path.basename(self.listeDesMaitressesApero[0]) + if self.listeDesMaitressesApero.__len__()>1: + texte = texte+'\n' + str(self.listeDesMaitressesApero.__len__())+_(' images maîtresses') + + texte = texte + _("arrêt au zoom : ")+self.zoomF.get()+"\n" + # état du chantier : if self.etatDuChantier == 0: # pas encore de chantier - texte = texte+"\nChantier en cours de définition.\n" - if self.etatDuChantier >= 1: # le chantier est créé : il y a des photos choisies (2 enregistré, - # 3 en cours d'exécution, - # 4 arrêt tapas, 5 terminé, 6 modifiable mais n'existe plus) - texte = texte+"\nChantier : "+self.chantier+".\n" - else: - texte = texte+"\nChantier en attente d'enregistrement.\n" - if self.etatDuChantier in (2,6) and self.etatSauvegarde=="": - texte = texte+"\nChantier enregistré.\n" - if self.etatDuChantier==2: - texte = texte+"Chantier modifiable.\n" - if self.etatDuChantier == 3: - texte = texte+"\nChantier interrompu.\nRelancer micmac.\n" - if self.etatDuChantier == 4: - texte = texte+"Arrêté aprés Tapas.\n" - if self.etatDuChantier == 5: - texte = texte+"Chantier terminé.\n" - if self.etatDuChantier == 6: - texte = texte+"\nChantier exécuté puis débloqué.\n" + texte = texte+"\n" + _("Chantier en cours de définition.") + "\n" + + + # un chantier avec des traitements effectués et pas de sous-répertoire : il a été nettoyé ! + + if self.etatDuChantier >= 3 and len([f for f in os.listdir(self.repTravail) if os.path.isdir(os.path.join(self.repTravail, f))])==0: + self.chantierNettoye = True + self.etatDuChantier = 2 + self.sauveParam() + + # chantier nettoyé mais relancé depuis donc etatDuChantier >= 3 : + + if self.chantierNettoye and self.etatDuChantier>=3: + self.chantierNettoye = False # le chantier a été relancé, n'est plus nettoyé + + # Message si chantier nettoyé non relancé : + + if self.chantierNettoye: + texte = texte+"\n" + _("Chantier nettoyé.") + "\n" + + # Affichage de l'état du chantier : + if self.etatDuChantier >= 1: # le chantier est créé : il y a des photos choisies (2 enregistré, + # 3 en cours d'exécution, + # 4 arrêt après tapas, 5 terminé après malt ou c3dc, 6 modifiable mais n'existe plus) + texte = texte+"\n" + _("Chantier : ")+self.chantier+".\n" + # Type de chantier : c'est une liste de string (on pourrait aussi mettre un dictionnaire), avec : + # [0] = s'il s'agit de 'photos' ou d'une 'vidéo' + # [1] = s'il s'agit d'un chantier 'initial' ou 'renommé' + # [2] = 'original' ou "importé" + if self.typeDuChantier[1]=="renommé" or self.typeDuChantier[2]=="importé" or self.typeDuChantier[2]=="ajouté": + texte = texte + _("Chemin du chantier :") + "\n"+afficheChemin(os.path.dirname(self.repTravail))+"\n\n" + else: + texte = texte+"\n" + _("Chantier en attente d'enregistrement.") + "\n" + if self.etatDuChantier in (2,3,4,5,6) and self.etatSauvegarde=="": + texte = texte+"\n" + _("Chantier enregistré.") + "\n" + if self.etatDuChantier == "2": + texte = texte+_("Options du chantier modifiables.") + "\n" + if self.etatDuChantier == 3: + texte = texte+"\n" + _("Chantier interrompu suite à erreur.") + "\n" + _("Relancer micmac.") + "\n" + if self.etatDuChantier == 4: + texte = texte+_("Options de Malt/C3DC modifiables.") + "\n" + if self.etatDuChantier == 5: + texte = texte+_("Chantier terminé.")+ "\n" + if self.etatDuChantier == 6: + texte = texte+"\n" + _("Chantier exécuté puis débloqué.") + "\n" + if self.etatDuChantier == 7: + texte = texte+"\n" + _("La densification a echoué : pas de nuage dense généré.") + "\n" + # Résultat des traitements : - - + if os.path.exists('AperiCloud.ply'): - texte = texte+"Nuage de point non densifié généré après Tapas.\n" + texte = texte+_("Nuage de point non densifié généré après Tapas.") + "\n" nbPly=1 - if os.path.exists('modele3D.ply'): - texte = texte+"Nuage de point densifié généré après Malt ou C3DC.\n" + + if os.path.exists(self.modele3DEnCours): + texte = texte+_("Nuage de point densifié généré.")+".\n" nbPly+=1 - if self.etatDuChantier in (4,5,6) and nbPly==0: - texte = texte+"Aucun nuage de point généré.\n" + if self.etatDuChantier in (4,5,6,7) and nbPly==0: + texte = texte+_("Aucun nuage de point généré.") + "\n" + + texte += "\n Taille du chantier : "+str(sizeDirectoryMO(self.repTravail))+" MO" # Affichage : os.chdir(self.repTravail) - self.encadre(texte,nouveauDepart='oui') + self.encadre(texte) except Exception as e: - texte = "Les caractéristiques du chantier précédent \n"+self.chantier+"\n n'ont pas pu être lues correctement.\n"+\ - "Le fichier des paramètres est probablement incorrect.\n"+\ - "Un nouveau chantier a été ouvert afin de débloquer la situation.\n"+\ - "Désolé pour l'incident.\n\n"+\ - "Erreur : "+str(e) +"\n"+texte - self.initialiseValeursParDefaut() - os.chdir(self.repTravail) - self.encadre(texte,nouveauDepart='oui') - - + texte = _("Les caractéristiques du chantier précédent") + "\n" + self.chantier + "\n" + _("n'ont pas pu être lues correctement." ) + "\n"+\ + _("Le fichier des paramètres est probablement incorrect ou vous avez changé la version de l'interface.") + "\n"+\ + _("Certaines fonctions seront peut_être défaillantes.") + "\n"+\ + _("Désolé pour l'incident.") + "\n\n"+\ + _("Erreur : ")+str(e) +"\n"+texte + self.encadre(texte) + +############### Existance des maitres 2D 3D : vrai, faux + def existeMasque3D(self): - if self.repTravail==self.repertoireScript: + if self.repTravail==self.repertoireData: return False - self.masque3D = os.path.join(self.repTravail,self.masque3DSansChemin) + self.masque3D = os.path.join(self.repTravail,self.masque3DSansChemin) if os.path.exists(self.masque3D): return True else: return False - def existeMasque2D(self): - if self.repTravail==self.repertoireScript: - return False - if os.path.exists(self.masque) and os.path.exists(self.maitre) and self.modeMalt.get()=="GeomImage": - return True - if str(self.modeMalt.get())=="GeomImage": # pas besoin de masque ! - return False - return True + def existeMaitre2D(self): + if self.repTravail==self.repertoireData: # pas enregistré + return False + if str(self.modeMalt.get())!="GeomImage": # pas besoin d'image maîtresse ! + return True + if self.listeDesMaitresses.__len__()>0: # GeoImage et maitresses : OK + return True + else: # le mode est geomimage et il n'y a pas d'image maitre + return False + +############### Affichages des photos choisies, points, masques, distance... def afficherToutesLesPhotos(self): - self.choisirUnePhoto(self.photosAvecChemin, - titre='Toutes les photos', + if self.photosPourCalibrationIntrinseque.__len__()==0: + titre = _('Toutes les photos') + message = _('Toutes les photos') + else: + titre = _('Toutes les photos utiles') + message = _('Toutes les photos') + '\n' + _('sans les %s photos pour calibration intrinseque') % (str( self.photosPourCalibrationIntrinseque.__len__())) + + self.choisirUnePhoto(self.photosSansChemin, + titre=titre, mode='single', - message="Toutes les photos", - messageBouton="Fermer") + message=message, + messageBouton=_("Fermer")) def afficherLesPointsGPS(self): photosAvecPointsGPS = [ e[1] for e in self.dicoPointsGPSEnPlace.keys() ] # dicoPointsGPSEnPlace key = nom point, photo, identifiant, value = x,y if photosAvecPointsGPS.__len__()==0: - self.encadre("Aucun point GPS saisi.") + self.encadre(_("Aucun point GPS saisi.")) return self.choisirUnePhoto(photosAvecPointsGPS, - titre='Affichage des photos avec points GPS', + titre=_('Affichage des photos avec points GPS'), mode='single', - message="seules les photos avec points sont montrées.", - messageBouton="Fermer", + message=_("seules les photos avec points sont montrées."), + messageBouton=_("Fermer"), dicoPoints=self.dicoPointsGPSEnPlace) - def afficherMasqueEtMaitre(self): - if os.path.isfile(self.masque) and os.path.isfile(self.maitre)>0: - masqueEtMaitre = [self.masque,self.maitre] - self.choisirUnePhoto(masqueEtMaitre, - titre="Visualiser l'image maitresse et le masque 2D", + def afficherLesMaitresses(self): + + self.maltApero() # pour abonder la liste des maitressesApero (un peu lourd) + if self.listeDesMaitresses.__len__()+self.listeDesMaitressesApero.__len__()>0: + self.choisirUnePhoto(self.listeDesMaitresses+self.listeDesMasques+self.listeDesMaitressesApero, + titre=_('Liste des images maîtresses et des masques ')+"\n"+_("communs à GeomImage et AperoDedenis"), mode='single', - message="Répertoire : \n"+os.path.dirname(self.maitre), - messageBouton="Fermer") + message=_("Images maîtresses et masques"), + messageBouton=_("Fermer") + ) else: - self.encadre("Pas de masque 2D défini pour ce chantier") + self.encadre(_("Pas de maîtresses définies pour ce chantier")) + + def afficherMasqueTarama(self): + + if os.path.exists(self.masqueTarama): + self.choisirUnePhoto([self.mosaiqueTaramaJPG,self.masqueTarama], + titre=_('Mosaique Tarama et masque ')+"\n"+_("Option Ortho de Malt"), + mode='single', + message=_("Image maîtresse et masque"), + messageBouton=_("Fermer") + ) + def afficheMasqueC3DC(self): if self.existeMasque3D()==False: - self.encadre("Pas de masque 3D pour ce chantier.") + self.encadre(_("Pas de masque 3D pour ce chantier.")) return os.chdir(self.repTravail) self.topMasque3D = tkinter.Toplevel(relief='sunken') fenetreIcone(self.topMasque3D) self.item900 = ttk.Frame(self.topMasque3D,height=5,relief='sunken',padding="0.3cm") - self.item901 = ttk.Button(self.item900,text='Visaliser le masque 3D',command=self.affiche3DApericloud) + self.item901 = ttk.Button(self.item900,text=_('Visaliser le masque 3D'),command=self.affiche3DApericloud) self.item901.pack(ipady=2,pady=10) - self.item903 = ttk.Button(self.item900,text='Fermer',command=lambda : self.topMasque3D.destroy()) + self.item903 = ttk.Button(self.item900,text=_('Fermer'),command=lambda : self.topMasque3D.destroy()) self.item903.pack(ipady=2,pady=10) - self.item902 = ttk.Label(self.item900, text= "Affichage du masque 3D :\n\n"+\ - "Les points blancs du nuage sont dans le masque\n"+\ - "Ce masque C3DC a la priorité sur le masque 2D de Malt\n\n"+ - "ATTENTION : FERMER la fenêtre 3D pour continuer") - self.item902.pack(ipady=2,pady=10) - - + self.item902 = ttk.Label(self.item900, text=_("Affichage du masque 3D :") + "\n\n"+ + _("Les points blancs du nuage sont dans le masque") + "\n"+ + _("Ce masque C3DC a la priorité sur le masque 2D de Malt") + "\n\n"+ + _("ATTENTION : pour continuer FERMER la fenêtre 3D")+ "\n"+ + _("puis cliquer si besoin sur le bouton FERMER ci-dessus.")) + self.item902.pack(ipady=2,pady=10) self.item900.pack() fenetre.wait_window(self.topMasque3D) def afficherZonePlane(self): if len(self.monImage_MaitrePlan)>0: - masqueEtMaitre = [self.monImage_PlanTif,self.monImage_MaitrePlan] - if self.monImage_PlanTif==self.planProvisoireHorizontal: - plan = "horizontale" - else: - plan = "verticale" - self.choisirUnePhoto(masqueEtMaitre, - titre="Visualiser l'image maitresse et le plan horizontal ou vertical", + if os.path.exists(self.monImage_PlanTif) and os.path.exists(self.monImage_MaitrePlan): + masqueEtMaitre = [self.monImage_PlanTif,self.monImage_MaitrePlan] + if self.monImage_PlanTif==self.planProvisoireHorizontal: + plan = _("horizontale") + else: + plan = _("verticale") + self.choisirUnePhoto(masqueEtMaitre, + titre=_("Visualiser l'image maîtresse et le plan horizontal ou vertical"), mode='single', - message="Zone plane "+plan, - messageBouton="Fermer") + message=_("Zone plane ")+plan, + messageBouton=_("Fermer")) + else: + self.monImage_PlanTif = self.monImage_MaitrePlan = str() + self.encadre("Pas de plan horizontal ou vertical défini pour ce chantier") else: - self.encadre("Pas de plan horizontal ou vertical défini pour ce chantier") + self.encadre(_("Pas de plan horizontal ou vertical défini pour ce chantier")) def afficherLigneHV(self): photosAvecLigneH = [ e[1] for e in self.dicoLigneHorizontale.keys() ] @@ -1823,35 +2892,84 @@ def afficherLigneHV(self): sens = str() for e in self.dicoLigneHorizontale: dicoAvecLigne[e] = self.dicoLigneHorizontale[e] - sens = "HORIZONTALE" + sens = _("HORIZONTALE") for e in self.dicoLigneVerticale: dicoAvecLigne[e] = self.dicoLigneVerticale[e] - sens = "VERTICALE" + sens = _("VERTICALE") if photosAvecLigne.__len__(): self.choisirUnePhoto(photosAvecLigne, - titre='Affichage des photos avec ligne horizontale ou verticale', + titre=_('Affichage des photos avec ligne horizontale ou verticale'), mode='single', - message="ligne "+sens, - messageBouton="Fermer", + message=_("ligne ")+sens, + messageBouton=_("Fermer"), dicoPoints=dicoAvecLigne) else: - self.encadre("Pas de ligne horizontale ou verticale définie pour ce chantier") + self.encadre(_("Pas de ligne horizontale ou verticale définie pour ce chantier")) def afficherDistance(self): - if self.distance.get()==str(): - self.encadre("Pas de distance définie pour ce chantier.") - else: - photosAvecDistance = list(set([ e[1] for e in self.dicoCalibre.keys() ])) - self.choisirUnePhoto(photosAvecDistance, - titre="Visualiser les photos avec distance", - mode='single', - message="Valeur de la distance : "+self.distance.get(), - messageBouton="Fermer", - dicoPoints=self.dicoCalibre) + try: + float(self.distance.get().split(" ")[0]) #pour permettre la saisie d'une unité + except: + self.encadre(_("Pas de distance correcte définie pour ce chantier.")) + return + + photosAvecDistance = list(set([ e[1] for e in self.dicoCalibre.keys() ])) + self.choisirUnePhoto(photosAvecDistance, + titre=_("Visualiser les photos avec distance"), + mode='single', + message=_("Valeur de la distance : ")+self.distance.get(), + messageBouton=_("Fermer"), + dicoPoints=self.dicoCalibre) - def lectureTraceMicMac(self,complete=True): + def afficherCalibIntrinseque(self): + if self.photosPourCalibrationIntrinseque.__len__()==0: + self.encadre(_("Pas de photos pour la calibration intrinsèque par Tapas.")) + return + self.choisirUnePhoto(self.photosPourCalibrationIntrinseque, + titre=_('Les photos pour calibration intrinsèque (Tapas)'), + mode='single', + message=_("Calibration intrinsèque"), + messageBouton=_("Fermer")) + + def afficheMosaiqueTarama(self): + + if not os.path.exists(self.mosaiqueTaramaTIF): + self.encadre(_("Pas de mosaique. Choisir l'option Tarama de tapas.")) + return - if self.pasDePhoto():return + if not os.path.exists(self.mosaiqueTaramaJPG): + self.conversionJPG(liste=[self.mosaiqueTaramaTIF]) + if not os.path.exists(self.mosaiqueTaramaJPG): + self.encadre(_("Echec de la conversion mosaique en JPG.")) + return + + self.choisirUnePhoto([self.mosaiqueTaramaJPG], + titre=_('Mosaique créée par Tarama'), + mode='single', + message="", + messageBouton=_("Fermer")) + + def afficheMosaiqueTawny(self): + orthoMosaiqueTIF = os.path.join(self.repTravail,"Ortho-MEC-Malt",self.orthoMosaiqueTawny) # chemin complet + if not os.path.exists(orthoMosaiqueTIF): + self.encadre(_("Pas d' ortho mosaique par Tawny. Choisir l'option Tawny de Malt.")) + return + orthoMosaiqueJPG = os.path.splitext(orthoMosaiqueTIF)[0]+".JPG" + if not os.path.exists(orthoMosaiqueJPG): + self.conversionJPG(liste=[orthoMosaiqueTIF]) + if not os.path.exists(orthoMosaiqueJPG): + self.encadre(_("Echec de la conversion de la mosaïque TIF en JPG.")) + return + + self.choisirUnePhoto([orthoMosaiqueJPG], + titre=_('Ortho mosaique créée par Tawny'), + mode='single', + message="", + messageBouton=_("Fermer")) + +############### Affichages des traces + + def lectureTraceMicMac(self,complete=True): if complete: fichier = self.TraceMicMacComplete @@ -1860,271 +2978,576 @@ def lectureTraceMicMac(self,complete=True): os.chdir(self.repTravail) if os.path.exists(fichier): self.cadreVide() - trace=open(fichier,"r") - contenu=trace.read() + trace=open(fichier,"r",encoding="utf-8") + try: + contenu=trace.read() + except: # pour compatibilité ascendante + trace.close + trace=open(fichier,"r",encoding="latin-1") + contenu=trace.read() trace.close self.ajoutLigne(contenu) self.texte201.see("1.1") else: - texte = "Pas de trace de la trace !" + texte = _("Pas de trace de la trace !") self.encadre(texte) def lectureTraceSynthetiqueMicMac(self): self.lectureTraceMicMac(complete=False) +############### Affichages des nuages de points + def afficheApericloud(self): retour = self.lanceApericloudMeshlab() if retour == -1: - self.encadre("Pas de nuage de points aprés Tapas.") + self.encadre(_("Pas de nuage de points non densifié.")) if retour == -2: - self.encadre("Programme pour ouvrir les .PLY non trouvéé.") + self.encadre(_("Programme pour ouvrir les .PLY non trouvéé.")) def affiche3DNuage(self): - retour = self.lanceMeshlab() + retour = self.ouvreModele3D() if retour == -1 : - self.encadre("Pas de nuage de points aprés Malt ou C3DC.") + self.encadre(_("Pas de nuage de points densifié.")) if retour == -2 : - self.encadre("Programme pour ouvrir les .PLY non trouvé.") + self.encadre(_("Programme pour ouvrir les .PLY non trouvé.")) ################################## Le menu PARAMETRAGE : répertoires MicMAc et Meshlab ########################################################### def afficheParam(self): - texte =('\nRépertoire bin de MicMac : \n\n'+afficheChemin(self.micMac)+ - '\n\n------------------------------\n'+ - '\n\nOutil exiftool : \n\n'+afficheChemin(self.exiftool)+ - '\n\n------------------------------\n'+ - '\n\nOutil pour afficher les .ply : \n\n'+afficheChemin(self.meshlab)+ - '\n\n------------------------------\n') + texte =('\n' + _("Répertoire bin de MicMac : ")+'\n\n'+afficheChemin(self.micMac)+ + '\n------------------------------\n'+ + '\n' + _("Version MicMac :")+'\n\n' + str(self.mercurialMicMac)+ + '\n------------------------------\n'+ + '\n' + _("Outil exiftool :") + '\n\n' + afficheChemin(self.exiftool)+ + '\n------------------------------\n'+ + '\n' + _("Outil convert d\'ImageMagick :") + ' \n\n' + afficheChemin(self.convertMagick)+ + '\n------------------------------\n'+ + '\n' + _("Outil pour afficher les .ply :") + '\n\n' + afficheChemin(self.meshlab)+ + '\n------------------------------\n'+ + '\n' + _("Outil pour décompacter les vidéos (ffmpeg):") + "\n\n" + afficheChemin(self.ffmpeg)+ + '\n------------------------------\n'+ + '\n' + _("Répertoire d'AperoDeDenis :") + "\n\n" + afficheChemin(self.repertoireScript)+ + '\n------------------------------\n'+ + '\n' + _("Répertoire des paramètres :") + "\n\n" + afficheChemin(self.repertoireData)+ + '\n------------------------------\n') self.encadre(texte) def repMicmac(self): - if self.micMac=="": - texte="Pas de chemin pour le répertoire MICMAC\\bin." - else: - texte="Répertoire bin sous MICMAC : "+afficheChemin(self.micMac) - self.encadre(texte,nouveauDepart='non') # pour éviter le redémarrage de la fenêtre - # Choisir le répertoire de MicMac + + self.menageEcran() + + #affichage de la valeur actuelle du répertoire de micmpac : + + texte=_("Répertoire bin sous MICMAC : ")+afficheChemin(self.micMac) + self.encadre(texte) # pour éviter le redémarrage de la fenêtre existe = False - exiftoolOK = False - source=tkinter.filedialog.askdirectory(title='Désigner le répertoire bin sous Micmac ',initialdir=self.micMac) + exiftoolOK = False + convertOK = False + ffmpegOK = False + + # Choisir le répertoire de MicMac + + source=tkinter.filedialog.askdirectory(title=_('Désigner le répertoire bin sous Micmac '),initialdir=self.micMac) if len(source)==0: - texte="Abandon, pas de changement.\nRépertoire bin de Micmac : \n\n"+afficheChemin(self.micMac) + texte=_("Abandon, pas de changement.") + "\n" + _("Répertoire bin de Micmac :") + "\n\n"+afficheChemin(self.micMac) self.encadre(texte) return + + if " " in source: + texte = _("Le chemin du répertoire bin de micmac ne doit pas comporter le caractère 'espace'.") + "\n" + texte = _("Renommer le répertoire de MicMac.") + "\n" + texte += _("Abandon, pas de changement.") + "\n" + _("Répertoire bin de Micmac :") + "\n\n"+afficheChemin(self.micMac) + self.encadre(texte) + return + + # mm3d sous Windows : + if self.systeme=="nt": - self.mm3d = os.path.join(source,"mm3d.exe") - if os.path.exists(self.mm3d): + mm3d = os.path.join(source,"mm3d.exe") + + if os.path.exists(mm3d): self.micMac = source + self.mm3d = mm3d existe = True + else: + self.encadre(_("Le répertoire %s ne contient pas le fichier mm3d.exe. Abandon") % (source)) + return + + # chemin pour lire les exifs + if self.pasDeExiftool(): + exiftool = os.path.join(source+"aire-aux","exiftool.exe") # recherche de l'existence de exiftool sous binaire-aux + if os.path.exists(exiftool): + self.exiftool = exiftool + exiftoolOK = True + else: + exiftool = os.path.join(source+"aire-aux\\windows","exiftool.exe") # le répertoire change dans les dernières versions de micmac + if os.path.exists(exiftool): + self.exiftool = exiftool + exiftoolOK = True + else: exiftoolOK = True + + # chemin pour convertir les formats de photos + if self.pasDeConvertMagick(): + convertMagick = os.path.join(source+"aire-aux","convert.exe") + if os.path.exists(convertMagick): + self.convertMagick = convertMagick + convertOK = True + else: + convertMagick = os.path.join(source+"aire-aux\\windows","convert.exe") + if os.path.exists(convertMagick): + self.convertMagick = convertMagick + convertOK = True + else: convertOK = True - exiftool = os.path.join(source+"aire-aux","exiftool.exe") # recherche de l'existence de exiftool sous binaire-aux - if os.path.exists(exiftool): - self.exiftool = exiftool - exiftoolOK = True - + # Chemin de ffmpeg pour décompacter les vidéo : si existe + if self.pasDeFfmpeg(): + ffmpeg = os.path.join(source,"ffmpeg.exe") # vrai dans certaines anciennes versions de micmac + if os.path.exists(ffmpeg): + self.ffmpeg = ffmpeg + ffmpgegOK = True + + + # mm3D sous linux, mas os : + if self.systeme=="posix": - self.mm3d = os.path.join(source,"mm3d") - if os.path.exists(self.mm3d): + mm3d = os.path.join(source,"mm3d") + if os.path.exists(mm3d): self.micMac = source + self.mm3d = mm3d existe = True - - '''exiftool = os.path.join(self.micMac+"aire-aux","exiftool") # la recherche d'exitool sous ubuntu ne peut se faire comme cela : on demande à l'utilisateur - if os.path.exists(exiftool): - self.exiftool = exiftool''' + else: + self.encadre(_("Le répertoire %s ne contient pas le fichier mm3d. Abandon") % (source)) + return + + # DicoCamera : self.CameraXML = os.path.join(os.path.dirname(self.micMac),self.dicoCameraGlobalRelatif) + + # Vérification que mm3D fonctionne : + executable = verifierSiExecutable(self.mm3d) if executable: # nouveau répertoire correct self.micMac = source - texte="Nouveau répertoire de Micmac : \n\n"+afficheChemin(self.micMac) + texte=_("Nouveau répertoire de Micmac :") + "\n\n"+afficheChemin(self.micMac) self.sauveParam() else: if existe: - texte = "Le programme mm3d est présent mais ne peut s'exécuter.\n Vérifier si la version est compatible avec le système. :\n" + texte = _("Le programme mm3d est présent mais ne peut s'exécuter.") + "\n" + _("Vérifier si la version est compatible avec le système. :") + "\n" else: - texte = "Le programme mm3d est absent du répertoire choisi :\n"+source+"\n Répertoire bin sous MicMac incorrect. \nAbandon." + texte = _("Le programme mm3d est absent du répertoire choisi :") + "\n"+source+"\n" + _("Répertoire bin sous MicMac incorrect.") +"\n" + _("Abandon.") - if exiftoolOK: - texte = texte + "\n\nChemin de exiftool :\n\n"+self.exiftool + # chemin pour exiftool si sous micmac\bin : - self.mm3dOK = verifMm3d(self.mm3d) # Booléen indiquant si la version de MicMac permet la saisie de masque 3D + if exiftoolOK: + texte = texte + "\n\n" + _("Chemin de exiftool :") + "\n\n"+self.exiftool + if convertOK: + texte = texte + "\n\n" + _("Chemin de convert d'image Magick :") + "\n\n" +self.convertMagick + if ffmpegOK: + texte = texte + "\n\n" + _("Chemin de ffmpeg :") + "\n\n" +self.ffmpeg + + self.mm3dOK = verifMm3d(self.mm3d) # Booléen indiquant si la version de MicMac permet la saisie de masque 3D + self.mercurialMicMac = mercurialMm3d(self.mm3d) + if self.mercurialMicMac==False: + self.mercurialMicMac = _("Pas de version identifiée de MicMac") + self.ajoutLigne("\n" + _("Nouvelle version de MicMac : ")+str(self.mercurialMicMac)+"\n") + self.ecritureTraceMicMac() self.encadre(texte) def repExiftool(self): + self.menageEcran() if self.exiftool=="": - texte="Pas de chemin pour le programme exiftool" + texte=_("Pas de chemin pour le programme exiftool") else: - texte="Programme exiftool :\n"+afficheChemin(self.exiftool) - self.encadre(texte,nouveauDepart='non') + texte=_("Programme exiftool :") + "\n"+afficheChemin(self.exiftool) + self.encadre(texte) # Choisir le répertoire de Meshlab ou CLoudCompare : + _filetypes = [] if sys.platform == 'darwin' else [("exiftool","exiftool*"),(_("Tous"),"*")] source=tkinter.filedialog.askopenfilename(initialdir=os.path.dirname(self.exiftool), - filetypes=[('exiftool','exiftool.*;*.app'),('tous','.*')],multiple=False, - title = "Recherche exiftool") + filetypes=_filetypes, + multiple=False, + title = _("Recherche exiftool")) if len(source)==0: - texte="Abandon, pas de changement.\nFichier exiftool inchangé :\n\n"+afficheChemin(self.exiftool) + texte=_("Abandon, pas de changement.") + "\n" + _("Fichier exiftool inchangé :") + "\n\n"+afficheChemin(self.exiftool) self.encadre(texte) return self.exiftool=''.join(source) self.sauveParam() - texte="\nProgramme exiftool :\n\n"+afficheChemin(self.exiftool) + texte="\n" + _("Programme exiftool :") + "\n\n" +afficheChemin(self.exiftool) self.encadre(texte) + def repConvert(self): + self.menageEcran() + if self.convertMagick=="": + texte=_("Pas de chemin pour le programme convert d'ImageMagick") + else: + texte=_("Programme convert :") + "\n"+afficheChemin(self.convertMagick) + self.encadre(texte) + + # Choisir le répertoire de convert : + _filetypes = [] if sys.platform == 'darwin' else [("convert",("convert*","avconv*")),(_("Tous"),"*")] + source=tkinter.filedialog.askopenfilename(initialdir=os.path.dirname(self.exiftool), + filetypes=_filetypes, + multiple=False, + title = _("Recherche convert")) + if len(source)==0: + texte=_("Abandon, pas de changement.") + "\n" + _("Fichier convert inchangé :") + "\n\n"+afficheChemin(self.convertMagick) + self.encadre(texte) + return + self.convertMagick=''.join(source) + self.sauveParam() + texte="\n" + _("Programme convert :") + "\n\n"+afficheChemin(self.convertMagick) + self.encadre(texte) + def repMeslab(self): + self.menageEcran() if self.meshlab=="": - texte="Pas de chemin pour le programme ouvrant les .PLY" + texte=_("Pas de chemin pour le programme ouvrant les .PLY") else: - texte="Programme ouvrant les .PLY :\n"+afficheChemin(self.meshlab) - self.encadre(texte,nouveauDepart='non') - # Choisir le répertoire de Meshlab ou CLoudCompare : + texte=_("Programme ouvrant les .PLY :") + "\n"+afficheChemin(self.meshlab) + self.encadre(texte) + # Choisir le répertoire de Meshlab ou CLoudCompare + _filetypes = [] if sys.platform == 'darwin' else [(_("meshlab ou CloudCompare"),("meshlab*","Cloud*")),(_("Tous"),"*")] source=tkinter.filedialog.askopenfilename(initialdir=os.path.dirname(self.meshlab), - filetypes=[('meshlab ou cloud compare','meshlab.*;*.app;cloud*;*'),('tous','.*')],multiple=False, - title = "Recherche fichier Meshlab sous VCG, ou CloudCompare") + filetypes=_filetypes, + multiple=False, + title = _("Recherche fichier Meshlab sous VCG, ou CloudCompare")) + if len(source)==0: + texte=_("Abandon, pas de changement.") + "\n" + _("Fichier Meshlab ou cloud compare :") + "\n\n"+afficheChemin(self.meshlab) + self.encadre(texte) + return + self.meshlab = source + self.sauveParam() + texte="\n" + _("Programme ouvrant les .PLY :") + "\n\n"+afficheChemin(self.meshlab) + self.encadre(texte) + + def repFfmpeg(self): + self.menageEcran() + if self.ffmpeg=="": + texte=_("Pas de chemin pour le programme Ffmpeg") + else: + texte=_("Programme ffmpeg :") + "\n"+afficheChemin(self.ffmpeg) + self.encadre(texte) + + # Choisir le répertoire de ffmpeg: + _filetypes = [] if sys.platform == 'darwin' else [("ffmpeg","ffmpeg*"),(_("Tous"),"*")] + source=tkinter.filedialog.askopenfilename(initialdir=os.path.dirname(self.ffmpeg), + filetypes=_filetypes, + multiple=False, + title = _("Recherche ffmpeg")) if len(source)==0: - texte="Abandon, pas de changement.\nFichier Meshlab ou cloud compare :\n\n"+afficheChemin(self.meshlab) + texte=_("Abandon, pas de changement.") + "\n" + _("Fichier ffmpeg inchangé :") + "\n\n"+afficheChemin(self.ffmpeg) self.encadre(texte) return - self.meshlab=''.join(source) + self.ffmpeg=''.join(source) self.sauveParam() - texte="\nProgramme ouvrant les .PLY :\n\n"+afficheChemin(self.meshlab) + texte="\n" + _("Programme ffmpeg :") + "\n\n"+afficheChemin(self.ffmpeg) self.encadre(texte) + def modifierTacky(self): + self.tacky = not self.tacky + if self.tacky: + self.encadre(_("Tacky message au lancement activé")) + else: + self.encadre(_("Tacky message au lancement désactivé")) + + def modifierLangue(self): + self.menageEcran() + self.encadre(_("Sélectionnez la langue à utiliser. L'application sera redémarrée.")) + frame = tkinter.Frame(fenetre) + frameListe = tkinter.Frame(frame) + frameBoutton = tkinter.Frame(frame) + self.choixLangue = tkinter.Listbox(frameListe) + frame.pack() + frameListe.pack(side = tkinter.TOP) + frameBoutton.pack(side = tkinter.BOTTOM) + valider = tkinter.Button(frameBoutton, text = _("Appliquer"), command = self.selectionLangue) + self.choixLangue.pack(side = tkinter.LEFT, fill = tkinter.Y) + valider.pack() + self.choixLangue.insert(1, _("Français")) + self.choixLangue.insert(2, _("Anglais")) + + def selectionLangue(self): + nouvelleLangue = self.choixLangue.get(self.choixLangue.curselection()) + global langue + if(nouvelleLangue == _("Français")): + langue = 'fr' + else: + langue = 'en' + try: + traduction = gettext.translation('AperoDeDenis', localedir = repertoire_langue, languages=[langue]) + traduction.install() + except: + message = "Version bilingue non installée. Revoir la procédure d'installation.\nChoisir KO pour quitter l'application" + if self.troisBoutons(titre="traduction absente",question=message,b1='OK',b2='KO',b3=None,b4=None)==1: + self.quitter() + try: fenetre.destroy() + except: pass + ################################## LE MENU MICMAC : Choisir les photos, les options, le traitement ########################################################## def lesPhotos(self): # Choisir des images dans un répertoire - self.fermerVisuPhoto() # s'il y a une visualisation en cours des photos ou du masque on la ferme + if not os.path.isdir(self.micMac): + self.encadre(_("Avant de choisir les photos associer le répertoire bin de micmac (Menu Paramétrage\\associer le répertoire bin de MicMac).")) + return + + if not os.path.isfile(self.exiftool): + self.encadre(_("Avant de choisir les photos associer le chemin du programme exiftool (Menu trage\\Associer exiftool).")) + return + self.fermerVisuPhoto() # s'il y a une visualisation en cours des photos ou du masque on la ferme + self.menageEcran() + reinitialationAFaire = False if self.etatDuChantier>2: # 1 = avec photo ; 2 = enregistré, plus = traitement effectué - if self.deuxBoutons("Réinialiser le chantier.", - "Les résultats en cours seront effacés.\n Pour conserver le chantier créer un nouveau chantier.?", - "Abandon", - "Réinitialiser") == 0: + reinitialationAFaire = True + if self.troisBoutons(_("Nouvelles photos pour le meme chantier"), + _("Choisir de nouvelles photos réinitialisera le chantier." ) + "\n"+ + _("Les traces et l'arborescence des calculs seront effacées.") + "\n"+ + _("Les options compatibles avec les nouvelles photos seront conservées.") + "\n", + _("Abandon"), + _("Réinitialiser le chantier")) == 0: + self.encadre(_("Abandon, le chantier n'est pas modifié.")) return - - - photos=tkinter.filedialog.askopenfilename(title='Choisir des JPEG', - initialdir=self.repertoireDesPhotos, - filetypes=[('Photos JPG',('*.JPG')),('tous','*.*')], + + + repIni = "" # répertoire initial de la boite de dialogue + self.lesTagsExif = dict() # réinitialise la mémo des exifs + if os.path.isdir(self.repertoireDesPhotos): + repIni = self.repertoireDesPhotos + photos=tkinter.filedialog.askopenfilename(title=_('Choisir des photos'), + initialdir=repIni, + filetypes=[(_("Photos"),("*.JPG","*.jpg","*.BMP","*.bmp","*.TIF","*.tif")),(_("Tous"),"*")], multiple=True) if len(photos)==0: - self.encadre("Abandon, aucune sélection,\n le répertoire et les photos restent inchangés.\n") + self.encadre(_("Abandon, aucune sélection de fichier image,") + "\n" + _("le répertoire et les photos restent inchangés.") + "\n") return if self.nombreDExtensionDifferentes(photos)==0: - self.encadre("Aucune extension acceptable pour des images. Abandon.") + self.encadre(_("Aucune extension acceptable pour des images. Abandon.")) return if self.nombreDExtensionDifferentes(photos)>1: - self.encadre("Plusieurs extensions différentes :\n"+",".join(self.lesExtensions)+".\n Impossible dans cette version. Abandon.") + self.encadre(_("Plusieurs extensions différentes :") + "\n"+ + ",".join(self.lesExtensions)+".\n" + + _("Impossible dans cette version. Abandon.")) return - if self.lesExtensions[0] not in ".JPG.JPEG": - self.encadre("La version actuelle ne traite que les photos au format JPG, or le format des photos est "+self.lesExtensions[0]+". Désolé." ) - return + if self.lesExtensions[0].upper() not in ".JPG.JPEG": + + if self.troisBoutons(_("Info : format des photos"),_("La version actuelle ne traite que les photos au format JPG,") + "\n\n" + _("or le format des photos est : ")+self.lesExtensions[0]+ + ".\n\n" + _("les photos vont être converties au format JPG."), + b1=_('Convertir en JPG'), + b2=_('Abandonner'))==1: + return + if verifierSiExecutable(self.convertMagick)==False: + self.encadre(_("Désigner l'outil de conversation 'convert' d'ImageMagick") + "\n" + _("(Menu Paramétrage)")) + return + if self.pasDeConvertMagick():return + + self.conversionJPG(photos) + photos = [os.path.splitext(e)[0]+".JPG" for e in photos] + + if self.nombreDExtensionDifferentes(photos)==0: + self.encadre(_("Aucune extension acceptable pour des images. Abandon.")) + return + + + # si des points GPS placés sur d'anciennes photos : vont-ils être supprimés ? + + NbPointsSupprimes = int() + if self.dicoPointsGPSEnPlace.__len__()>0: + photosAvecPointsGPS = set([os.path.basename(e[1]) for e in self.dicoPointsGPSEnPlace.keys()]) + photosChoisies = [os.path.basename(e) for e in photos] + for e in photosAvecPointsGPS: + if e not in photosChoisies: + NbPointsSupprimes+=1 # le compte n'y est pas (si positif) + if NbPointsSupprimes>0: + if self.troisBoutons(_("ATTENTION !"),_("ATTENTION : des points GPS ont été précedemment placés sur des photos non choisies pour ce chantier.") + "\n"+ + _("Les emplacements de ces points vont être supprimés si vous validez cette sélection de photos."), + b1=_('Valider la sélection de photos'), + b2=_('Abandonner'))==1: + return + + + # Nouvelle sélection valide self.extensionChoisie = self.lesExtensions[0] # l'extension est OK - - self.encadre("Copie des photos en cours... Patience",nouveauDepart='non') # pour éviter le redémarage + + self.encadre(_("Copie des photos en cours... Patience")) # pour éviter le redémarage + + # crée le repertoire de travail, copie les photos avec l'extension choisie et renvoit le nombre de fichiers photos "aceptables", + # met à 1 l'état du chantier crée self.photosAvecChemin et self.photosSansChemin + # ATTENTION : Supprime l'arborescence et certains résultats. - retourExtraire=self.extrairePhotoEtCopier(photos) # crée le repertoire de travail, copie les photos et renvoit le nombre de fichiers photos "aceptables" + retourExtraire = self.extrairePhotoEtCopier(photos) if retourExtraire.__class__()=='': # si le retour est un texte alors erreur, probablement création du répertoire impossible - self.encadre (retourExtraire) + self.encadre (_("Impossible de créer le répertoire de travail.") + "\n" + + _("Vérifier les droits en écriture sous le répertoire des photos") + + "\n"+str(retourExtraire)) return if retourExtraire==0: # extraction et positionne self.repertoireDesPhotos, et les listes de photos avec et sanschemin (photosAvecChemin et photosSansChemin) - self.encadre ("Aucun JPG sélectionné,\nle répertoire et les photos restent inchangés.\n") + self.encadre (_("Aucun JPG, PNG, BMP, TIF, ou GIF sélectionné,") + "\n" + + _("le répertoire et les photos restent inchangés.") + "\n") return - # conséquences du choix de nouvelles photos : on supprime tous le répertoire de travail ancien - # - même si la photo maitre n'est pas choisie on supprime le maitre et le masque + self.etatSauvegarde="*" # chantier modifié + + # Controle des photos : + + message = str() + self.lesTagsExif = dict() # supprime les ancienne mémorisation des tags des exifs + self.controlePhotos() # Compte le nombre de focales et les dimensions des photos + if self.nbFocales==0: + message+=_('Les focales sont absentes des exif.') + "\n" + _('Mettez à jour les exifs avant de lancer MicMac.') + '\n'+\ + _("Utiliser le menu Outils/Modifier l'exif des photos.") + "\n\n" + if self.nbFocales>1: + message += _("Attention : Les focales des photos ou ne sont pas toutes identiques.") + "\n\n" + if self.dimensionsOK==False: + message += _("Attention : les dimensions des photos ne sont pas toutes identiques.") + "\n"+\ + "\n" + _("Le traitement par MicMac ne sera peut-être pas possible.") + "\n\n" + + # conséquences du choix de nouvelles photos sur un ancien chantier : on supprime tous le répertoire de travail ancien + # on conserve les options # - s'il y a une visualisation en cours des photos ou du masque on la ferme + + self.reinitialiseMaitreEtMasqueDisparus() # fait un grand ménage + self.photosPourCalibrationIntrinseque = [e for e in self.photosPourCalibrationIntrinseque if e in photos] - self.masque = str() # nom du fichier image représentant le masque sur l'image maitresse - self.masqueSansChemin = str() # image masque : en TIF, choisi par l'utilisateur - self.maitreSansChemin = str() # image maitresse - self.maitreCommentaire = str() # indique si l'image maitresse est choisie automatiquement - self.maitre = str() - self.fichierMasqueXML = str() # nom du fichier XML décrivant le masque - self.nomMaitreSansExtension = str() + if reinitialationAFaire: + # trace dans la trace + message += (_("De nouvelles photos ont été sélectionnés sur un chantier pré-existant.") + "\n"+ + _("Les anciennes options compatibles avec les nouvelles photos ont été conservées.") + "\n") + + self.ajoutLigne(message) + self.ecritureTraceMicMac() + + + # Adaption des options au lot de photos choisi : + # l'échelle de Tapioca est dimensionnée par défaut à 60% de la dimension maxi des photos : + echelle = int(round(max(self.dimensionsDesPhotos[0][1])*6/10,-2)) + self.echelle1.set(echelle) + self.echelle3.set(echelle) + self.echelle4.set(echelle) + + # sauvegarde = recréation du fichier param.sav qui a été supprimé + + self.enregistreChantier() + + # affiche etat avec message : + + self.afficheEtat(message) - self.etatSauvegarde="*" # chantier modifié - self.afficheEtat() - # extraire les photos dans le résultat de l'opendialogfilename (celui-ci dépend de l'OS et du nombre 0,1 ou plus de fichier choisis) : # puis création du chantier (si impossible : erreur ! ################################## COPIER LES FICHIERS DANS LE REPERTOIRE DE TRAVAIL ########################################################### + ################################## ATTENTION : FAIT UN GRAND MENAGE : supprime toute l'arborescence de travail et des fichiers dans le chantier dont param.sav ############### - def extrairePhotoEtCopier(self,photos): # création repertoire du chantier, copie les photos OK, chdir. retour : nombre de photos - # photosPropresAvecChemin photosAvecChemin photosSansChemin - liste=[x for x in photos if x[-3:].upper() in 'JPGJPEG'] # on restreint aux deux formats d'images identifiés correct / JPG + def extrairePhotoEtCopier(self,photos): # création repertoire du chantier, copie les photos OK, chdir. retour : nombre de photos ou message d'erreur + # photosAvecChemin photosSansChemin + #attention : self.extensionChoisie doit être positionné - if len(liste)==0: - return 0 - liste.sort() - oldRepertoireDesphotos = self.repertoireDesPhotos - self.repertoireDesPhotos=os.path.dirname(liste[0]) # si positif alors on affecte le repertoire (string) - self.photosAvecChemin= list(liste) # les photos avec les chemins initiaux - - # création du répertoire du chantier si nouveau chantier - - if self.etatDuChantier==0 or oldRepertoireDesphotos!=self.repertoireDesPhotos: # nouveau répertoire si pas de photos ou changement de répertoire # si pas encore de nom pour le chantier on lui en donne un ! - retour = self.creationNouveauRepertoireTravail() - if isinstance(retour, str): - return retour #y a un pb + liste=[x for x in photos if x[-3:].upper() in 'JPGJPEGPNGRAWBMPTIFTIFFGIF'] # on restreint aux seul format d'images accepté : JPG, PNG, BMP, TIF, RAW, GIF + if len(liste)==0: return 0 + + # Quel répertoire pour le chantier ? + retour = self.quelChantier(liste[0]) + + if retour!=None: + return retour # y a un pb - # copie des photos sous le répertoire de travail : (attention, il peut y en avoir d'autres, qui seront supprimées au lancement de Micmac, mais pas de la qualité) - - listeCopie=list() # liste des fichiers copiés, vide + # copie des photos sous le répertoire de travail : (attention, il peut y en avoir d'autres, + # qui seront supprimées au lancement de Micmac, mais pas de la qualité) + liste.sort() + self.photosAvecChemin = list(liste) # les photos avec les chemins initiaux, triées alphabétique + listeCopie=list() # liste des fichiers copiés, vide try: - for e in self.photosAvecChemin: # self.photosPropresAvecChemin est la liste des photos nettoyées à copier - if self.extensionChoisie.upper() in e.upper(): # ON NE COPIE QUE L'EXTENSION CHOISIE, en majuscule - dest=os.path.join(self.repTravail,os.path.basename(e).upper().replace(" ","_")) #sans blanc : mm3d plante ! - if not os.path.exists(dest): # on ne copie que si le fichier n'est pas déjà présent - shutil.copy(e,dest) # copie du fichier sous le répertoire de travail - ajout(listeCopie,dest) # liste des fichiers à traiter - except Exception as err: - texte= 'erreur lors de la copie du fichier\n'+e+'\n dans le répertoire \n'+self.repTravail+"\nlibellé de l'erreur : \n"+str(err)+\ - "\nCauses possibles : manque d'espace disque ou droits insuffisants." + self.extensionChoisie = self.extensionChoisie.upper() + for f in self.photosAvecChemin: # self.photosAvecChemin est la liste des photos nettoyées à copier + self.encadrePlus("...") + if self.extensionChoisie in f.upper(): # ON NE COPIE QUE L'EXTENSION CHOISIE, en majuscule + dest=os.path.join(self.repTravail,os.path.basename(f).upper().replace(" ","_")) # en majuscule et sans blanc : mm3d plante ! + if os.path.exists(dest): # si déjà présent + supprimeFichier(dest) + shutil.copy(f,dest) # copie du fichier sous le répertoire de travail + ajout(listeCopie,dest) # liste des fichiers à traiter + except Exception as e: + texte= _("erreur lors de la copie du fichier") + "\n" + f + "\n" + _("dans le répertoire ") + "\n" + self.repTravail + "\n" + _("libellé de l\'erreur :") + "\n" + str(e) + "\n" + _("Causes possibles : manque d\'espace disque ou droits insuffisants.") return texte - - self.photosPropresAvecChemin = list(listeCopie) # listes des photos copiées - self.photosSansChemin=list([os.path.basename(x) for x in listeCopie]) # liste des noms de photos copiès, sans le chemin. [tuple] - - supprimeArborescenceSauf(self.repTravail,self.photosSansChemin) # suppression de tous sous le répertoire actuel : sauf photos sélectionnées, (résultats, traces, arbres) - + self.photosAvecChemin = list(listeCopie) # on oublie les photos initiales + self.photosSansChemin = list([os.path.basename(x) for x in listeCopie]) # liste des noms de photos copiès, sans le chemin. + # on conserve les options déjà saisies, mais pas les résultats de traitement qui n'ont plus de sens + # suppression de tous sous le répertoire actuel : sauf photos sélectionnées et paramètres saisis + aConserver = list(self.photosSansChemin) + aConserver += [e for e in os.listdir(self.repTravail) if os.path.splitext(e)[1]==".xml"] # garde les xml (paramètres) + aConserver += [e for e in os.listdir(self.repTravail) if os.path.splitext(e)[1]==".exp"] # garde les exports + aConserver += [e for e in os.listdir(self.repTravail) if os.path.splitext(e)[1]==".ply"] # garde les ply + aConserver += [e for e in os.listdir(self.repTravail) if os.path.splitext(e)[1]==".txt"] # garde les traces + aConserver.append(self.monImage_PlanTif) + aConserver += self.listeDesMasques + supprimeArborescenceSauf(self.repTravail,aConserver) os.chdir(self.repTravail) - self.etatDuChantier = 1 # les photos sont choisies, le répertoire de travail est créé - - # définit les fichiers trace vides, débuter la trace - - self.definirFichiersTrace() # positionne sous le répertoire de travail + self.etatDuChantier = 1 # les photos sont choisies, le répertoire de travail est créé + # Type de chantier : c'est une liste de string (on pourrait aussi mettre un dictionnaire), avec : + # [0] = s'il s'agit de 'photos' ou d'une 'vidéo' + # [1] = s'il s'agit d'un chantier 'initial' ou 'renommé' + # [2] = 'original' ou "importé" ou "ajouté" + # définit les fichiers trace vides, débuter la trace à vide (tout nouveau choix de photos efface la trace précédente + self.typeDuChantier = ['photos','initial','original'] + self.definirFichiersTrace() # affecte leur noms auc fichiers trace, existant ou pas, sous le répertoire de travail + self.initialisationFichiersTrace() # Efface les anciens et initialisation de nouveaux fichiers trace + return len(listeCopie) # on retourne le nombre de photos + + ################# controler les photos dans leur ensemble : même focale, mêmes dimensions, présence d'un exif avec focale : + + def controlePhotos(self): #[liste = self.photosSansChemin] Vérification globale des focales et des dimensions. en retour nbFocales et dimensionsOk + # les dimensions : + self.dimensionsDesPhotos = [(x,Image.open(x).size) for x in self.photosSansChemin] # si OK : x = self.dimensionsDesPhotos[0][0] et y=self.densionsDesPhotos[0][1] + self.dimensionsOK = set([y for (x,y) in self.dimensionsDesPhotos]).__len__()==1 # vrai si une seule taille + + # le nombre de focales : + touteLesFocales = [(x,self.tagExif(tag="FocalLength",photo=x)) for x in self.photosSansChemin] + lesFocales = set([y for (x,y) in touteLesFocales if y!='']) # les focales parmi les couples (photo, focale) + self.nbFocales = lesFocales.__len__() + + ################# définir le répertoire de travail, le créer : + + def quelChantier(self,unePhoto): # on a une photo ou une vidéo : quel répertoire de travail et quel chantier ? - open(self.TraceMicMacSynthese,'w').close() # création d'un fichier de trace, vide - open(self.TraceMicMacComplete,'w').close() # création d'un fichier de trace, vide + self.chantier = os.path.basename(self.repTravail) # par défaut on suppose que le répertoire existe déjà : on ne change rien - self.ajoutLigne(heure()+ "\n\nChoix des photos :\n"+"\n".join(self.photosAvecChemin)+"\n") - self.ajoutLigne(heure()+ "\n\nrépertoire du chantier :\n"+self.repTravail+"\n\n") - self.ecritureTraceMicMac() + # Le répertoire de unePhoto est-il le répertoire des photos : si oui on ne change pas le répertoire de travail, sinon nouveau $repTravail et nouveau chantier - return len(listeCopie) # on retourne le nombre de fichi + oldRepertoireDesphotos = self.repertoireDesPhotos + + self.repertoireDesPhotos = os.path.normcase(os.path.dirname(unePhoto)) # si positif alors on affecte le repertoire (string) + + # création du répertoire du chantier si nouveau chantier + # état du chantier : 1 = créé, fixé ; si 0 : alors il faut créer un nouveau chantier + if self.etatDuChantier==0 or oldRepertoireDesphotos!=self.repertoireDesPhotos: # nouveau répertoire si pas de photos ou changement de répertoire # si pas encore de nom pour le chantier on lui en donne un ! + return self.creationNouveauRepertoireTravail() # si pas de changement de répertoire des photos alors pas de création def creationNouveauRepertoireTravail(self): - self.indiceTravail+=1 - self.repTravail=os.path.join(self.repertoireDesPhotos,'MicMac_'+str(self.indiceTravail)) + # Numéro du chantier : pour indicer le numéro du répertoire de travail : un nouveau est créé à chaque éxécution + + try: self.indiceTravail += 1 # on incrémente s'il existe + except: self.indiceTravail = 1 # sinon met à 1 sinon + + self.repTravail = os.path.normcase(os.path.normpath(os.path.join(self.repertoireDesPhotos,'MicMac_'+str(self.indiceTravail)))) while os.path.exists(self.repTravail): # détermine le nom du répertoire de travail (chantier) self.indiceTravail+=1 # numéro particulier au répertoire de travail créé - self.repTravail=os.path.join(self.repertoireDesPhotos,'MicMac_'+str(self.indiceTravail))# répertoire différent à chaque éxécution (N° séquentiel) + self.repTravail = os.path.normcase(os.path.normpath(os.path.join(self.repertoireDesPhotos,'MicMac_'+str(self.indiceTravail)))) # répertoire différent à chaque éxécution (N° séquentiel) try: os.mkdir(self.repTravail) # création répertoire du chantier - except Exception as e : return "Impossible de créer le répertoire de travail : erreur = \n"+str(e) + except Exception as e : return _("Impossible de créer le répertoire de travail : erreur = ") + "\n"+str(e) ajout(self.tousLesChantiers,self.repTravail) # on ajoute le répertoire créé dans la liste des répertoires self.chantier = os.path.basename(self.repTravail) # nom du chantier, puis état du chantier : 1 = créé, fixé @@ -2135,17 +3558,49 @@ def creationNouveauRepertoireTravail(self): def optionsOnglet(self): - # l'état du chantier permet-il de choisir des options : - - if self.etatDuChantier==3: - self.encadre("Le chantier est interrompu suite à incident. \n\n"+ - "Si besoin créer un nouveau chantier ou débloquer le chantier en lancant micmac.") - return + # l'état du chantier permet-il de choisir des options : + + if self.etatDuChantier==3: # En principe ne doit pas arriver : plantage en cours d'un traitement précédent + retour = self.troisBoutons( titre=_("Le chantier %s a été interrompu en cours d'exécution.") % (self.chantier), + question=_("Le chantier est interrompu.") + "\n" + _("Vous pouvez le débloquer,")+ + _( "ce qui permettra de modifier les options et de le relancer.") + "\n", + b1=_('Débloquer le chantier'),b2=_('Abandon')) + if abs(retour)==1: # 1 ou -1 : abandon ou fermeture de la fenêtre par la croix + return + if retour==0: + self.nettoyerChantier() # le chantier est noté comme de nouveau modifiable + self.sauveParam() + self.afficheEtat(_("Chantier %s de nouveau modifiable, paramètrable et exécutable.") % (self.chantier)) + + + # Chantier arrété après tapas : l'utilisateur a pu modifier les options et veut continuer ou reprendre au début suivant les résultats + # poursuite du traitement ou arrêt suivant demande utilisateur + + + # Chantier terminé, l'utilisateur peur décider de le débloquer en conservant les résultats de tapas ou supprimer tous les résultats + + if self.etatDuChantier==5: # Chantier terminé + retour = self.troisBoutons( titre=_('Le chantier %(x)s est terminé.') % {"x" : self.chantier}, + question=_("Le chantier est terminé après ")+self.choixDensification.get()+".\n"+ + _("Vous pouvez :") + "\n"+ + _(" - Modifier les options de Tapioca et Tapas") + "\n"+ + _(" - Conserver les traitements de Tapioca/Tapas pour relancer la densification") + "\n"+ + _(" - Ne rien faire.") + "\n", + b1=_('Modifier les options de Tapioca et Tapas'), + b2=_('Modifier les options de la densification'), + b3=_('Ne rien faire'),) + if retour==-1: # -1 : fermeture fenêtre, abandon + self.afficheEtat() + return + if retour==2: # 0 : ne rien faire (b3)) + self.afficheEtat() + return + if retour==0: # 1 : on nettoie, on passe à l'état 2 (b1)) + self.nettoyerChantier() + + if retour==1: # modifier les options de malt C3DC et points GPS (b2)) + self.etatDuChantier = 4 - if self.etatDuChantier==5: - self.encadre("Le chantier est terminé. Modification des options inutile.\n\n."+ - "Si besoin créer un nouveau chantier ou débloquer le chantier en lancant micmac.") - return # L'état du chantier permet de choisir des options : @@ -2154,71 +3609,88 @@ def optionsOnglet(self): self.sauveParamChantier() self.menageEcran() - if self.etatDuChantier in (0,1,2,6): # sinon self.etatDuChantier vaut 4 et on va direct à Malt ou C3DC + if self.etatDuChantier in (0,1,2,6,7): # sinon self.etatDuChantier vaut 4 et on va direct à Malt ou C3DC self.onglets.add(self.item400) # tapioca self.onglets.add(self.item500) # tapas self.onglets.add(self.item950) # Calibration self.optionsTapioca() # les frames à afficher ne sont pas "fixes" - self.item510.pack() # la frame fixe de tapas - self.item710.pack(pady=15) # Malt + self.item520.pack(pady=10) # la frame fixe de tapas pour calibration + self.item510.pack(pady=10) # la frame fixe de tapas pour arrêt ou poursuite + self.item540.pack(pady=10) # la frame fixe de tapas pour arrêt ou poursuite + self.item526.config(text=_("Nombre de photos choisies : ")+str(self.photosPourCalibrationIntrinseque.__len__())) + self.item720.pack(pady=10) # Malt + self.optionsMalt() # La frame Image Maitre à afficher n'est pas "fixe" self.item960.pack(padx=5,pady=10,ipady=2,ipadx=15) # Calibration de 960 à 980 self.item965.pack() # calibration suite self.item970.pack(padx=5,pady=10,ipady=2,ipadx=15) # calibration suite self.item975.pack() # calibration suite self.item980.pack(padx=5,pady=10,ipady=2,ipadx=15) # calibration suite - self.item990.pack() # calibration suite + self.item990.pack() # calibration suite selection = self.item400 # onglet sélectionné par défaut else: self.onglets.hide(self.item400) # tapioca self.onglets.hide(self.item500) # tapas self.onglets.hide(self.item950) # Calibration - self.item710.pack(pady=15) # Malt : toujours présent - selection = self.item700 - - if self.mm3dOK: # ne pas proposer C3DC si MicMac ne l'accepte pas + self.item720.pack(pady=10) # Malt + self.optionsMalt() # La frame Image Maitre à afficher n'est pas "fixe" + selection = self.item600 - os.chdir(self.repTravail) - supprimeFichier(self.masque3DSansChemin) # suppression des anciens masques 3D - supprimeFichier(self.masque3DBisSansChemin) - else: - try: self.onglets.hide(self.item800) - except: pass + # Onglet Densification : + + self.optionsDensification() # onglet Densification variable suivant Malt ou C3DC + + if not self.mm3dOK: # ne pas proposer C3DC si MicMac ne l'accepte pas + self.item804.configure(text= _("La version de Micmac installée ne propose pas le module C3DC. Choisir MALT."),foreground='red',style="C.TButton") + else: # Si l'onglet existe on met à jour les messages : + os.chdir(self.repTravail) + if os.path.exists("AperiCloud.ply")==False: + self.item804.configure(text= _("Pas de nuage Apericloud : pour construire un masque") + "\n" + _("lancer Tapioca/tapas."),foreground='red',style="C.TButton") + self.item801.configure(state = "disable") + else: + self.item801.configure(state = "normal") + if self.existeMasque3D(): + self.item804.configure(text = _("Masque 3D créé"),foreground='red') + else: + self.item804.configure(text = _("Pas de masque 3D"),foreground='black') + + # met à jour les infos sur les maîtresses et les masques + + self.miseAJourItem701_703() + self.masqueProvisoire = str() # utile pour tracemasque + # dernier onglet (qui se régénére, forcément le dernier) self.optionsReperes() # points GPS, en nombre variable # points de repères calés dans la scène self.onglets.pack(fill='none', padx=2, pady=0) # on active la boite à onglet self.item450.pack() # et les 2 boutons en bas - self.onglets.select(selection) # onglet sélectionné par défaut - + self.onglets.select(selection) # onglet sélectionné par défaut + fenetre.wait_window(self.onglets) # boucle d'attente : la fenêtre pricncipale attend la fin de l'onglet def finOptionsOK(self): # l'utilisateur a valider l'ensemble des options + self.onglets.pack_forget() # on ferme la boite à onglets texte = str() - # Pour Tapioca : toutes les variables sont sauvées - # Pour tapas : - - self.maitreSansChemin = os.path.basename(self.maitre) # photoMaitre sans chemin avec extension, en minuscule - - self.ecrireMasqueXML() # création du fichier xml associé à l'image maitresse - - try: del self.masqueRetour # suppression de l'objet "saisie du masque" s'il existe - except : pass # on enregistre les options de calibration et de GPS self.finCalibrationGPSOK() # mise à jour des options de calibration self.finRepereOK() # mise à jour des options de repérage (axe Ox, plan horizontal, distance - # Sauvegarde des nouvelles info : + # Controle puis Sauvegarde des nouvelles info : + + retour = self.controleOptions() - self.sauveParam() self.etatSauvegarde="*" # chantier modifié ="*" #Pour indiquer que le chantier a été modifié, sans être sauvegardé sous le répertoire du chantier - - if self.controleOptions()!=True: # Controle de cohérence de la saisie (valeur entière...) - texte=("Saisie d'une option incomplète ou incorrecte.\nCorriger.\n"+str(self.controleOptions())) + self.sauveParam() + + if retour!=True: + texte = "\n" + _("Option incorrecte :") + "\n"+str(retour) + self.encadreEtTrace(texte) + return + self.afficheEtat(texte) def finCalibrationGPSOK(self): # crée le fichier xml qui va bien avec les données saisies @@ -2226,19 +3698,20 @@ def finCalibrationGPSOK(self): # crée le fichi supprimeFichier(self.mesureAppuis) self.actualiseListePointsGPS() # met a jour proprement la liste des 6-tuples (nom,x,y,z,actif,identifiantgps) if self.dicoPointsGPSEnPlace.__len__()==0: # dicoPointsGPSEnPlace key = nom point, photo, identifiant, value = x,y - return - if self.controlePoints(): - self.encadre("Points GPS non conformes. Vérifiez.",nouveauDepart='non') - return + return False + if self.controlePointsGPS()==False: # retour False si problème ! + self.encadre(_("Points GPS non conformes. Nom est absent ou en double. Vérifiez.")) + return False + os.chdir(self.repTravail) - with open(self.dicoAppuis, 'w', encoding='utf-8') as infile: #écriture de la description de chaque point GPS + with open(self.dicoAppuis, 'w', encoding='utf-8') as infile: # écriture de la description de chaque point GPS infile.write(self.dicoAppuisDebut) - self.actualiseListePointsGPS() - for Nom,X,Y,Z,num,ident in self.listePointsGPS: # listePointsGPS : 6-tuples (nom du point, x, y et z gps, booléen actif, identifiant) - point=self.dicoAppuis1Point.replace("Nom",Nom) + for Nom,X,Y,Z,num,ident,incertitude in self.listePointsGPS: # listePointsGPS : 7-tuples (nom du point, x, y et z gps, booléen actif ou supprimé, identifiant) + point=self.dicoAppuis1Point.replace(_("Nom"),Nom) point=point.replace("X",X) point=point.replace("Y",Y) - point=point.replace("Z",Z) + point=point.replace("Z",Z) + point=point.replace("10 10 10",incertitude) infile.write(point) infile.write(self.dicoAppuisFin) @@ -2253,66 +3726,127 @@ def finCalibrationGPSOK(self): # crée le fichi if key!="": infile.write(self.mesureAppuisFinPhoto) key = cle[1] - photo = self.mesureAppuisDebutPhoto.replace("NomPhoto",os.path.basename(cle[1])) + photo = self.mesureAppuisDebutPhoto.replace(_("NomPhoto"),os.path.basename(cle[1])) infile.write(photo) - point = self.mesureAppuis1Point.replace("NomPoint",cle[0]) + point = self.mesureAppuis1Point.replace(_("NomPoint"),cle[0]) point = point.replace("X",self.dicoPointsGPSEnPlace[cle][0].__str__()) point = point.replace("Y",self.dicoPointsGPSEnPlace[cle][1].__str__()) - infile.write(point) + if cle[0] not in self.pointsPlacesUneFois: # on n'écrit pas le point s'il n'est présent que sur une seule photo + infile.write(point) else: - point = self.mesureAppuis1Point.replace("NomPoint",cle[0]) + point = self.mesureAppuis1Point.replace(_("NomPoint"),cle[0]) point = point.replace("X",self.dicoPointsGPSEnPlace[cle][0].__str__()) point = point.replace("Y",self.dicoPointsGPSEnPlace[cle][1].__str__()) - infile.write(point) + if cle[0] not in self.pointsPlacesUneFois: # on n'écrit pas le point s'il n'est présent que sur une seule photo + infile.write(point) infile.write(self.mesureAppuisFinPhoto) infile.write(self.mesureAppuisFin) - - def controlePointsGPS(self): # controle pour affiche etat : informer de la situation : si vrai alors self.etatPointsGPS sera affiché - #si pas de chantier, pas de problème mais retour False : pas de calibration + return True + + def controlePointsGPS(self): # controle pour affiche etat et afficher tous les points : informer de la situation : + # le message self.etatPointsGPS sera affiché dans l'état du chantier + # finCalibrationGPSOK doit avoir été éxécuté avant self.etatPointsGPS = str() - if self.repTravail==self.repertoireScript: + retour = True + + if self.repTravail==self.repertoireData: # si pas de chantier, pas de problème mais retour False : pas de calibration return False - listePointsActifs = [ (e[0],e[5]) for e in self.listePointsGPS if e[4] and e[0]!="" ] # listePointsGPS : 6-tuples (nom du point, x, y et z gps, booléen actif, identifiant) - - if len(listePointsActifs)>0: - self.etatPointsGPS = ("\n"+str(len(self.dicoPointsGPSEnPlace))+" points GPS placés\n"+ # dicoPointsGPSEnPlace key = nom point, photo, identifiant, value = x,y - "pour "+str(len(listePointsActifs))+" points GPS définis\n") - return True - if os.path.exists(os.path.join(self.repTravail,self.mesureAppuis))==False: - self.etatPointsGPS+="Saisie incomplète : les points ne seront pas pris en compte\n" + # listePointsGPS : liste de (nom du point, x, y et z gps, booléen actif ou supprimé, identifiant, incertitude) + listePointsActifs = [f[0] for f in self.listePointsGPS if f[4] and f[0]!=""] + + # ICI : on pourrait controler que les x,y,z et incertitudes sont bien des valeurs numériques + if len(listePointsActifs)==0: + self.etatPointsGPS += _("Pas de points GPS.") + "\n" return False - def controleCalibration(self): # controle de saisie globale du repère, arrêt à la première erreur, True si pas d'erreur, sinon message - #si pas de chantier, pas de problème mais retour False : pas de calibration - self.etatCalibration = str() - if self.repTravail==self.repertoireScript: - return False - # fichier xml présent : + if listePointsActifs: + # dicoPointsGPSEnPlace key = nom point, photo, identifiant, value = x,y + self.etatPointsGPS = ("\n" + _("%s points GPS placés") % (str(len(self.dicoPointsGPSEnPlace))) + "\n" + + _("pour %s points GPS définis") % (str(len(listePointsActifs)))) + "\n" + if len(listePointsActifs)<3: + self.etatPointsGPS += _("Attention : il faut au moins 3 points pour qu'ils soient pris en compte.") + "\n" + retour = False + + # sur le modèle pythonique l'élément le plus représenté dans une liste l : x=sorted(set(l),key=l.count)[-1] + # ou pour avoir toute l'info [(valeur,nombre),...] : [(e,a.count(e)) for e in a] + # dicoPointsGPSEnPlace key = nom point, photo, identifiant, value = x,y + # ce bout de code est dupliqué dans controlePointsGPS et actualiseListePointsGPS + + listePointsPlaces=[e[0] for e in self.dicoPointsGPSEnPlace] + pointsPlaces = [(e,listePointsPlaces.count(e)) for e in listePointsPlaces] + self.pointsPlacesUneFois = [f[0] for f,g in set([(e,pointsPlaces.count(e)) for e in pointsPlaces]) if g==1] + self.pointsPlacesUneFois.sort() + + # Nombre de points placés 2 fois ou plus : + self.pointsPlacesDeuxFoisOuPlus = [f[0] for f,g in set([(e,pointsPlaces.count(e)) for e in pointsPlaces]) if g>1] + + ############################################ + + if self.pointsPlacesDeuxFoisOuPlus.__len__()<3: + self.etatPointsGPS += _("Il n'y a pas 3 points placés sur 2 photos : les points GPS seront ignorés.")+"\n" + retour = False + if self.pointsPlacesUneFois.__len__()>1: + self.etatPointsGPS += _("Anomalie : les points suivants ne sont placés que sur une seule photo : ")+"\n"+\ + " ".join(self.pointsPlacesUneFois)+"\n" + if self.pointsPlacesUneFois.__len__()==1: + self.etatPointsGPS += _("Anomalie : le point suivant n'est placé que sur une seule photo : ")+"\n"+\ + " ".join(self.pointsPlacesUneFois)+"\n" + + # vérification : y-a-t-il 2 points avec les mêmes coordonnées géographiques ? + + xyz = [(f[1],f[2],f[3]) for f in self.listePointsGPS if f[4] and f[0]!=""] + if xyz.__len__()!=set(xyz).__len__(): + self.etatPointsGPS+=_("Attention : plusieurs points GPS ont les mêmes coordonnées.") + "\n" + + if retour==False: + self.etatPointsGPS+=_("Saisie incomplète : les points GPS ne seront pas pris en compte") + "\n" + + return retour + + def controleCalibration(self): # controle de saisie globale du repère axe, plan métrique, arrêt à la première erreur, True si pas d'erreur, sinon message + #si pas de chantier, pas de problème mais retour False : pas de calibration + self.etatCalibration = str() + if self.repTravail==self.repertoireData: + return False + # fichier xml présent : if os.path.exists(os.path.join(self.repTravail,self.miseAEchelle))==False: return False #ligne : if len(self.dicoLigneHorizontale)+len(self.dicoLigneVerticale)!=2: - self.etatCalibration = self.etatCalibration+"La ligne horizontale ou verticale ne comporte pas 2 points\n" - # Plan : - if os.path.exists(self.monImage_PlanTif)==False: - self.etatCalibration = self.etatCalibration+"Pas de plan horizontal ou vertical\n" + self.etatCalibration = self.etatCalibration+_("La ligne horizontale ou verticale ne comporte pas 2 points") + "\n" + # Plan : + if os.path.exists(self.monImage_MaitrePlan)==False or self.monImage_MaitrePlan==str(): + self.etatCalibration = self.etatCalibration+_("Pas de maitre plan horizontal ou vertical") + "\n" + self.monImage_PlanTif = str() # réinit le plan sans maitre + else: + if os.path.exists(self.monImage_PlanTif)==False: + self.etatCalibration = self.etatCalibration+_("Pas de plan horizontal ou vertical") + "\n" # Distance - try: - d = float(self.distance.get()) + try : + d=float(self.distance.get().split(" ")[0]) # pour permettre la saisie d'une unité if d<0: - self.etatCalibration = self.etatCalibration+"Distance "+self.distance.get()+" invalide.\n" + self.etatCalibration = _("%(x)s Distance %(y)s invalide.") % {"x": self.etatCalibration, "y": self.distance.get()} + "\n" if d==0: - self.etatCalibration = "Calibration annulée.\n" + self.etatCalibration = _("Calibration annulée.") + "\n" except: - self.etatCalibration = self.etatCalibration+"Pas de distance.\n" + self.etatCalibration = _("%s Pas de distance.") % (self.etatCalibration) + "\n" return False - # métrique : - liste = list(self.dicoCalibre.items()) - if liste.__len__()!=4: - self.etatCalibration = self.etatCalibration+"La distance n'est pas mesurée par 2 points repérés sur 2 photos.\n" - + # métrique : + if self.dicoCalibre.__len__()>0: + liste = list(self.dicoCalibre.items()) + if liste.__len__()!=4: + self.etatCalibration += _("La distance n'est pas mesurée par 2 points repérés sur 2 photos.") + "\n" + photosAvecDistance = list(set([os.path.basename(e[1]) for e in self.dicoCalibre.keys() ])) + if not os.path.exists(photosAvecDistance[0]): + self.etatCalibration += _("La photo avec distance %s est absente.") % (photoavecDistance[0]) + "\n" + if photosAvecDistance.__len__()>1: + if not os.path.exists(photosAvecDistance[1]): + self.etatCalibration += _("La photo avec distance %s est absente.") % (photosAvecDistance[1]) + "\n" + if self.dicoCalibre.__len__()==0: + self.etatCalibration += _("Pas de distance pour la calibration.") + "\n" + if self.etatCalibration==str(): return True # calibration OK, tout va bien else: return False @@ -2322,9 +3856,13 @@ def finRepereOK(self): # ne mettre à jour que pour les var existe = False # par défaut : pas de xml, true si il existe une des variables "reperes" xml = self.miseAEchelleXml + # remplace la virgule possible dans self.distance par un point : + + self.distance.set(self.distance.get().replace(",",".")) # on remplace la virgule éventuelle par un point + # Pattern des fichiers à traiter : - xml = xml.replace("Fichiers",str(' .*'+self.extensionChoisie)) + xml = xml.replace(_("Fichiers"),str(' .*'+self.extensionChoisie)) # axe horizontal, dans le dico : self.dicoLigneHorizontale. key = nom point, photo, identifiant ;Retrouver nom de la photo, coordonnées des points # items = liste de tuple (key,values) soit tuple = (point,photo, id),(x1,y1) @@ -2344,8 +3882,8 @@ def finRepereOK(self): # ne mettre à jour que pour les var xml = xml.replace("photoHorizon",os.path.basename(liste[0][0][1])) xml = xml.replace("X1H",liste[0][1][0].__str__()) - xml = xml.replace("X2H",liste[0][1][1].__str__()) - xml = xml.replace("Y1H",liste[1][1][0].__str__()) + xml = xml.replace("Y1H",liste[0][1][1].__str__()) + xml = xml.replace("X2H",liste[1][1][0].__str__()) xml = xml.replace("Y2H",liste[1][1][1].__str__()) # calibre pour les mesures @@ -2372,7 +3910,7 @@ def finRepereOK(self): # ne mettre à jour que pour les var xml = xml.replace("X2P2",liste[3][1][0].__str__()) xml = xml.replace("Y2P2",liste[3][1][1].__str__()) - xml = xml.replace("distance",self.distance.get()) + xml = xml.replace("distance",self.distance.get().split(" ")[0]) # pour permettre la saisie d'une unité # le plan horizontal ou vertical (OK même si absent) @@ -2385,7 +3923,7 @@ def finRepereOK(self): # ne mettre à jour que pour les var self.monImage_PlanTif = self.planProvisoireVertical existe=True - xml = xml.replace("monImage_MaitrePlan",os.path.basename(self.monImage_MaitrePlan)) # Nom de l'image maitresse du plan repere (sans extension) + xml = xml.replace("monImage_MaitrePlan",os.path.basename(self.monImage_MaitrePlan)) # Nom de l'image maîtresse du plan repere (sans extension) xml = xml.replace("monImage_Plan",os.path.basename(self.monImage_PlanTif)) # nom du masque correspondant if existe: @@ -2401,90 +3939,169 @@ def controleOptions(self): # controle que les valeurs numériqu # et que echelle1 < echelle2 # et enfin que echelle 1 et 2 sont au max = taille la plus grande de l'image # ce controle peut-être appelé avant de lancer micMac - texte=str() - echelle1 = int(self.echelle1.get()) - echelle2 = int(self.echelle2.get()) - echelle3 = int(self.echelle3.get()) - echelle4 = int(self.echelle4.get()) - delta = int(self.delta.get()) - if self.modeTapioca.get()=='MulScale': - try: - if 0<=echelle1<50: - texte="\nEchelle 1 trop petite : \n"+self.echelle1.get()+"\nMinimum = 50" - return texte - except: - texte = texte+"\nEchelle non numérique poutr Tapioca : \n"+self.echelle1.get()+"\n" - return texte - try: + # Retour : true si Ok, message d'erreur sinon (string) pas d'avertissement sans conséquence. + texte = str() # message informatif (pas toujours !) + erreur = str() # message erreur - if echelle2!=-1: - if echelle3maxi: - texte = "\nechelle1 = "+self.echelle1.get()+"\n plus grand que la dimension maxi de la photo : \n"+str(maxi)+".\n\nInutile et ralenti le traitement. Modifier." - return texte - if self.modeTapioca.get()=='MulScale': - if int(self.echelle2.get())>maxi: - texte = "\nechelle2 = "+self.echelle2.get()+"\n plus grand que la dimension maxi de la photo : \n"+str(maxi)+".\n\nInutile et ralenti le traitement. Modifier." - return texte + try: + if echelle2<50 and echelle2!=-1 and self.modeTapioca.get()=="MulScale": + texte += "\n" + _("L'échelle 1 pour le mode MulScale de Tapioca est trop petite : ") + "\n" + self.echelle2.get() + "\n" + _("Minimum = 50, maximum conseillé : 300") + "\n" + except: + pass + + # Controle echelle 3 pour le mode MulScale de tapioca (seconde échelle du MulScale) - return True + try: + if self.modeTapioca.get()=="MulScale": + echelle3 = int(self.echelle3.get()) + except: + echelle3 = 1200 + self.echelle3.set(str(echelle3)) + erreur += "\n" + _("L'échelle 2 pour le mode MulScale de Tapioca est invalide, une valeur par défaut, %s, est affectée.") % (self.echelle3.get()) + "\n" + + try: + if echelle3<50 and echelle3!=-1 and self.modeTapioca.get()=="MulScale": + texte += "\n" + _("L'échelle 2 pour le mode MulScale de Tapioca est trop petite :") + "\n" + self.echelle3.get() + "\n" + _("Minimum = 50") + "\n" + except: + pass + + # controle cohérence echelle2 et echelle3 + + try: + if echelle3<=echelle2 and echelle3!=-1 and self.modeTapioca.get()=="MulScale": + texte += "\n" + _("L'échelle 2 de MulScale pour tapioca") + "\n" + self.echelle3.get() + "\n" + _("plus petite que l'échelle 1 :") + "\n" + self.echelle2.get() + "\n" + except: + pass + + # Controle échelle pour le mode line + + try: + if self.modeTapioca.get()=="Line": + echelle4 = int(self.echelle4.get()) + except: + echelle4 = 1200 + self.echelle4.set(str(echelle4)) + erreur += "\n" + _("L'échelle pour le mode Line de tapioca est invalide, une valeur par défaut, %s, est affectée.") % (self.echelle4.get()) + "\n" + + try: + if echelle4<50 and echelle4!=-1 and self.modeTapioca.get()=="Line": + texte += "\n" + _("Echelle pour le mode Line de tapioca trop petite : ") + "\n" + self.echelle4.get() + "\n" % (self.echelle4.get()) + except: + pass + + # Controle delta pour le mode line + + try: + if self.modeTapioca.get()=="Line": + delta = int(self.delta.get()) + except: + delta = 4 + self.delta.set(str(delta)) + erreur += "\n" + _("La valeur de delta pour le mode Line de Tapioca est invalide,") + "\n" + _("une valeur par défaut, %s, est affectée.") % self.delta.get() + "\n" + + try: + if delta<1 and self.modeTapioca.get()=="Line": + texte += "\n" + _("Delta trop petit :") + "\n" + self.delta.get() + "\n" + _("Minimum = 1") + "\n" + except: + pass + + #vérification du zoom final : + + if self.zoomF.get() not in ("1","2","4","8"): + erreur += "\n" + _("Le zoom final pour MALT n'est pas 1,2,4 ou 8 : %s") % (self.zoomF.get()) + "\n" + + # zoom OK, les valeurs 8,4,2,1 correspondent au nuage étape 5, 6, 7, 8 + + if self.zoomF.get()=="8":self.etapeNuage = "5" + if self.zoomF.get()=="4":self.etapeNuage = "6" + if self.zoomF.get()=="2":self.etapeNuage = "7" + if self.zoomF.get()=="1":self.etapeNuage = "8" + + # vérification nombre d'images utiles autour du maître pour Malt en mode GeomImage - def finOptionsKO(self): + try: + self.photosUtilesAutourDuMaitre.set(int(self.photosUtilesAutourDuMaitre.get())) # met un entier (sinon galère !) + if self.photosUtilesAutourDuMaitre.get()<1 and self.photosUtilesAutourDuMaitre.get()!=-1: + texte += "\n" + _("Malt mode Geomimage :") + "\n" + _("Le nombre de photos utiles autour de l'image maîtresse est trop petit : %s") % (str(self.photosUtilesAutourDuMaitre.get())) + "\n" + except Exception as e: + texte += "\n" + _("Malt mode Geomimage :") + "\n" + _("Le nombre de photos utiles autour de l'image centrale n'est pas numérique : ") + "\n" + _("Il est mis à 5.") + "\n" + self.photosUtilesAutourDuMaitre.set(5) + + + # vérif taille image (s'il y a des images !): + + if len(self.photosAvecChemin)>0: + if os.path.exists(self.photosAvecChemin[0])==False: + texte += _("La photo %s n'existe plus.") % (self.photosAvecChemin[0]) + return texte+erreur + photo1 = Image.open(self.photosAvecChemin[0]) + largeur,hauteur = photo1.size + del photo1 + inutile = _("Inutile et ralenti le traitement. Modifier.") + maxi = max(largeur,hauteur) + if self.modeTapioca.get()=='All': + if int(self.echelle1.get())>maxi: + texte += "\n" + _("L'échelle pour le mode All de tapioca = ") + self.echelle1.get() + "\n" + _(", est plus grande que la dimension maxi de la photo : ") + "\n" + str(maxi) + "." + "\n\n" + inutile + + if self.modeTapioca.get()=='MulScale': + if int(self.echelle2.get())>maxi: + texte += "\n" + _("L'échelle 2 pour le mode MulScale de tapioca= ") + self.echelle2.get() + "\n" + _("est plus grande que la dimension maxi de la photo :") + "\n" + str(maxi) + "." + "\n\n" + inutile + + if self.modeTapioca.get()=='Line': + if int(self.echelle4.get())>maxi: + texte += "\n" + _("L'échelle pour le mode Line de tapioca = ") + self.echelle2.get() + "\n" + _("est plus grande que la dimension maxi de la photo :") + "\n" + str(maxi) + "." + "\n\n" + inutile + + # retour True ou String + + if texte+erreur==str(): + return True + else: + return texte+erreur + + def finOptionsKO(self): + + self.onglets.pack_forget() # on ferme la boite à onglets self.restaureParamChantier(self.fichierParamChantierEnCours) - self.afficheEtat('Pas de changement.') + self.afficheEtat() #""""""""""""""""""""""" Options de TAPIOCA def optionsTapioca(self): # utilisé dans la syntaxe : Tapioca Line Files Size delta ArgOpt= (ce qui exclut implicitement la syntaxe multiscale) - self.item460.pack_forget() self.item470.pack_forget() self.item480.pack_forget() @@ -2497,104 +4114,344 @@ def optionsTapioca(self): # utilisé dans la syntaxe : Tapio if self.modeTapioca.get()=='Line': self.item470.pack(pady=15) + + def optionsDensification(self): + self.item700.pack_forget() + self.item800.pack_forget() + + if self.choixDensification.get()=='C3DC': + self.item801.pack(ipady=2,pady=3) # bouton pour créer un masque + self.item802.pack(ipady=2,pady=3) # bouton pour supprimer le masque + self.item803.pack(ipady=2,pady=3) # Aide pour le widget IGN création de masque 3D + self.item804.pack(ipady=2,pady=3) # info sur la présence du masque + self.item800.pack(pady=15) # regroupe les widgets 801 à 804 + if os.path.exists("AperiCloud.ply")==False: + self.item801.pack_forget() + self.item802.pack_forget() + self.item803.pack_forget() + if not(self.existeMasque3D()): + self.item802.pack_forget() + + if self.choixDensification.get()=='Malt': + self.item700.pack(pady=15) + + + #"""""""""""""""""""""""" Options de Malt + + def imagesCalibrationIntrinseques(self): + if self.photosAvecChemin.__len__()==0: + self.infoBulle(_("Choisir d'abord les photos du chantier.")) + return + bulles = dict([(e,"") for e in self.photosPourCalibrationIntrinseque]) + self.choisirUnePhoto(self.photosAvecChemin, + _("Pour calibrer l'appareil photo"), + _("Quelques photos, convergentes, d'angles écartés") + "\n" + _("en jaune la calibration actuelle"), + boutonDeux=_("Supprimer"), + bulles=bulles) + if self.fermerVisu: # sortie par second bouton + self.item526.config(text=_("Pas de photos de calibration intrinseque.")) + self.photosPourCalibrationIntrinseque = list() + return + if self.selectionPhotosAvecChemin.__len__()==0: #sortie par fermeture fenêtre + self.item526.config(text=_("Choix inchangé.") + "\n") + return + self.photosPourCalibrationIntrinseque = self.selectionPhotosAvecChemin + self.item526.config(text=_("Nombre de photos choisies : ")+str(self.photosPourCalibrationIntrinseque.__len__())) + + #"""""""""""""""""""""""" Options de Malt + + def optionsMalt(self): + self.item710.pack_forget() + self.item730.pack_forget() + self.item740.pack_forget() + self.item745.pack_forget() + self.item750.pack_forget() + if self.modeMalt.get()=='GeomImage': + self.item710.pack(pady=10) + self.item730.pack(pady=10) + if self.modeMalt.get()=='Ortho': + self.item745.pack(pady=5) + self.item740.pack(pady=5) + if self.modeMalt.get()=='AperoDeDenis': + self.item750.pack(pady=5) + self.maltApero() # met à jour la liste des maitresses Apero : self.listeDesMaitressesApero et la liste des tuples + self.miseAJourItem701_703() + + def imageMaitresse(self): # bouton "choisir les maitresses" de l'option GeomImage + if self.photosAvecChemin.__len__()==0: + self.infoBulle("Choisir d'abord les photos du chantier.") + return + + # préparation des infos bulles + + bulles = dict() + + for f in self.listeDesMaitresses: + for e in self.listeDesMasques: + if os.path.splitext(f)[0]+"_masque.tif"==e: + bulles[f]=_("Image maitresse avec masque") + if f not in bulles: + bulles[f]="" # image maitresse sans masque + + # suppression des fichiers masques pour malt ;; ces fichiers sont créés au lancement de Malt + # par contre on garde les dessins des masques (_masque.tif) qui ne seront utiles qui si le nom est dans la liste des masques + + for e in self.photosAvecChemin: + supprimeFichier(os.path.splitext(e)[0]+"_Masq.xml") + supprimeFichier(os.path.splitext(e)[0]+"_Masq.tif") + + # choix des nouvelles maîtresses : + + self.choisirUnePhoto(self.photosAvecChemin, + _("Choisir les maîtresses"), + _("Choisir une ou plusieurs image(s) maîtresse(s)") + "\n" + _("en jaune : les maitresses actuelles") + "\n" + _("Une info bulle informe de la présence d'un masque"), + boutonDeux=_("Supprimer les images maîtresses"), # self.fermerVisu=True + mode="extended", + bulles=bulles) + + # suppression de toutes les maitresses + if self.fermerVisu: # sortie par bouton deux = fermeture de fenêtre + self.fermerVisu=True + self.reinitialiseMaitreEtMasque() + return + + #abandon de la saisie + if self.selectionPhotosAvecChemin.__len__()==0: #sortie par fermeture fenêtre ou sans choix + self.item701.config(text=_("Abandon. Choix inchangé.") + "\n") + return + + # nouvelle liste des maitresses : mettre à jour la nouvelle liste des masques + self.listeDesMaitresses = self.selectionPhotosAvecChemin + # mise à jour de la liste des masques : suppression des masques qui ne sont plus dans la liste des maitresses + new = list() + for e in self.listeDesMaitresses: + if ' '.join(self.listeDesMasques).count(os.path.splitext(e)[0]): # la maitresse est dans la liste des masques + nouveauMasque = os.path.splitext(e)[0]+"_masque.tif" + if nouveauMasque in self.listeDesMasques: + new.append(nouveauMasque) + + self.listeDesMasques = list(new) # nouvelle liste des masques + self.miseAJourItem701_703() + + def miseAJourItem701_703(self): # et 745 Onglet Malt, Cadres geomImage et Ortho et AperodeDenis + try: + if self.listeDesMaitresses.__len__()==0: + self.item701.config(text=_("Image maitresse obligatoire pour GeomImage.")) + if self.listeDesMaitressesApero.__len__()==0: + self.item751.config(text=_("Exécuter Tapioca/Tapas pour saisir des masques avec cette option.")) + self.item753.config(state=DISABLED) + else: + self.item753.config(state=NORMAL) + + if self.listeDesMaitresses.__len__()==1: + self.item701.config(text=_("image maîtresse = ")+os.path.basename(self.listeDesMaitresses[0])) + + if self.listeDesMaitressesApero.__len__()==1: + self.item751.config(text=_("image maîtresse = ")+os.path.basename(self.listeDesMaitressesApero[0])) + + + if self.listeDesMaitresses.__len__()>1: + self.item701.config(text=str(self.listeDesMaitresses.__len__())+_(" images maîtresses")) + + if self.listeDesMaitressesApero.__len__()>1: + self.item751.config(text=str(self.listeDesMaitressesApero.__len__())+_(" images maîtresses")) + if self.listeDesMasques.__len__()==0: + self.item703.config(text="\n" + _("Pas de masque.")) + self.item752.config(text="\n" + _("Pas de masque.")) + + if self.listeDesMasques.__len__()==1: + self.item703.config(text="\n" + _("un seul masque : ")+os.path.basename(self.listeDesMasques[0])) + self.item752.config(text="\n" + _("un seul masque : ")+os.path.basename(self.listeDesMasques[0])) + + if self.listeDesMasques.__len__()>1: + self.item703.config(text="\n"+str(self.listeDesMasques.__len__())+_(" masques")) + self.item752.config(text="\n"+str(self.listeDesMasques.__len__())+_(" masques")) + + if not os.path.exists(self.mosaiqueTaramaTIF): + self.item745.config(text="\n" + _("Pas de mosaique Tarama : pas de masque.")) + self.item745.config(state=DISABLED) + elif os.path.exists(self.masqueTarama): + self.item745.config(text=_("Tracer un nouveau masque sur la mosaique Tarama")) + self.item745.config(state=NORMAL) + else: + self.item745.config(text=_("Tracer un masque sur la mosaique Tarama")) + self.item745.config(state=NORMAL) + except Exception as e: + print(_("erreur dans miseAJour701_703 : "),str(e)) + + def tracerLesMasques(self): # Bouton de l'option GeomImage + if self.photosAvecChemin.__len__()==0: + self.infoBulle(_("Choisir d'abord les photos du chantier.")) + return + self.fermerVisuPhoto() + + if self.listeDesMaitresses.__len__()==0: + self.item703.config(text=_("Il faut au moins une image maîtresse pour définir un masque."), + background="#ffffaa") + return + bulles=dict() + for e in self.listeDesMasques: + for f in self.listeDesMaitresses: + if os.path.splitext(f)[0]+"_masque.tif"==e: + bulles[f]=_("Un masque existe déjà") + self.choisirUnePhoto(self.listeDesMaitresses, + _("Choisir l'image pour le masque"), + _("Choisir une image maîtresse pour le masque\nen jaune = un masque existe"), + mode="single", + bulles=bulles) + + if self.selectionPhotosAvecChemin.__len__()==0: + return + maitre = self.selectionPhotosAvecChemin[0] + masqueEnAttente = os.path.splitext(maitre)[0]+"_masque.tif" + + # l'utilisateur trace le masque - def imageMaitresse(self): - self.choisirUnePhoto(self.photosPropresAvecChemin, - "Choisir l'image maitresse", - "Choisir l'image maitresse pour Malt", - boutonDeux="Supprimer l'image maitresse", - mode="single") - if self.fermerVisu: #sortie par second bouton - self.item701.config(text="Pas d'image maîtresse.") - self.item703.config(text="Pas de masque.") - self.maitre = str() - self.maitreSansChemin = str() - self.masque = "" - self.masqueSansChemin = "" + self.masqueRetour = TracePolygone(fenetre,maitre,masqueEnAttente) # L'utilisateur peut tracer le masque sur l'image maitre + if self.masqueRetour.polygone == True: + ajout(self.listeDesMasques,masqueEnAttente) + self.miseAJourItem701_703() + + def tracerLesMasquesApero(self): # bouton pour l'option de malt aperodedenis + if self.photosAvecChemin.__len__()==0: + self.infoBulle(_("Choisir d'abord les photos du chantier.")) return - if self.selectionPhotosAvecChemin.__len__()==0: #sortie par fermeture fenêtre - self.item701.config(text="Abandon. Choix inchangé :\n"+self.maitreSansChemin) - return - self.item703.config(text="pas de masque") # réinitialise le masque - self.masque = "" - self.masqueSansChemin = "" - self.maitreProvisoire = str(self.selectionPhotosAvecChemin[0]) # puis l'image maitresse - self.maitreSansCheminProvisoire=os.path.basename(str(self.selectionPhotosAvecChemin[0])) # photoMaitre sans chemin avec extension, en minuscule - try: shutil.copy(self.maitreProvisoire,self.repTravail) - except: pass - self.maitre = os.path.join(self.repTravail,self.maitreSansCheminProvisoire) - self.item701.config(text="image maitresse = "+self.maitreSansCheminProvisoire) + if os.path.exists(os.path.join(self.repTravail,"Homol"))==False: + self.infoBulle(_("Exécuter d'abord Tapioca/Tapas.")) + return + self.fermerVisuPhoto() + if self.listeDesMaitressesApero.__len__()==0: + self.item751.config(text=_("Pas d'image maîtresse. Bizarre."), + background="#ffffaa") + return + + bulles=dict() + for e in self.listeDesMasques: + for f in self.listeDesMaitressesApero: + if os.path.splitext(f)[0]+"_masque.tif"==e: + bulles[f]=_("Un masque existe déjà") + self.choisirUnePhoto(self.listeDesMaitressesApero, + _("Choisir l'image pour le masque"), + _("Choisir une image maîtresse pour le masque\nen jaune = un masque existe"), + mode="single", + bulles=bulles) + + if self.selectionPhotosAvecChemin.__len__()==0: + return + maitre = self.selectionPhotosAvecChemin[0] + masqueEnAttente = os.path.splitext(maitre)[0]+"_masque.tif" + + # l'utilisateur trace le masque + + self.masqueRetour = TracePolygone(fenetre,maitre,masqueEnAttente) # L'utilisateur peut tracer le masque sur l'image maitre + if self.masqueRetour.polygone == True: + ajout(self.listeDesMasques,masqueEnAttente) + self.miseAJourItem701_703() - def traceMasque(self): + + def traceMasque(self): # Choisir le masque Bouton de l'option GeomImage ou AperoDeDenis self.fermerVisuPhoto() + if self.listeDesMaitresses.__len__()==0: + self.item703.config(text=_("Il faut au moins une image maîtresse pour définir un masque."), + background="#ffffaa") + return + + if self.listeDesMaitresses.__len__()==1: + self.maitre = self.listeDesMaitresses[0] + + # comme il y a plusieurs maîtres possibles il faut choisir ! + else: + self.choisirUnePhoto(self.listeDesMaitresses, + _("Choisir l'image pour le masque"), + _("Choisir une image maîtresse pour le masque"), + mode="single") + if self.selectionPhotosAvecChemin.__len__()==0: + return + else: + self.maitre = self.selectionPhotosAvecChemin[0] + + # un peu brutal si la visu n'est pas celle de la photo maitre, évite les incohérences - if os.path.exists(self.maitre): #l'image maître doit exister + if os.path.exists(self.maitre): # l'image maître doit exister self.masqueProvisoire = os.path.splitext(self.maitre)[0]+"_Masq_provisoire.tif" # Nom du fichier masque, à partir du fichier maître, imposé par micmac - self.masqueSansCheminProvisoire = os.path.basename(self.masqueProvisoire) # sans le chemin + supprimeMasque(self.repTravail,"_Masq.tif") # suppression des anciens masques + supprimeFichier(self.fichierMasqueXML) + self.masquesansChemin = str() self.masqueRetour = TracePolygone(fenetre,self.maitre,self.masqueProvisoire) # L'utilisateur peut tracer le masque sur l'image maitre - if self.masqueRetour.polygone == True: # si retour OK (masqueRetour est un élément de la classe tracePolygone) - self.item703.config(text="masque = "+self.masqueSansCheminProvisoire) # affichage du nom du masque - else: + if self.masqueRetour.polygone == False: # si retour OK (masqueRetour est un élément de la classe tracePolygone) self.masqueProvisoire = str() # pas de masque : détricotage - self.masqueSansCheminProvisoire = str() + self.item703.config(text=_("pas de masque")) else: - self.item703.config(text="Il faut une image maîtresse pour définir un masque.", + self.item703.config(text=_("Il faut une image maîtresse pour définir un masque."), background="#ffffaa") - def ecrireMasqueXML(self): - try: - if self.masqueProvisoire==str(): - return - except: return - self.masque = os.path.splitext(self.maitre)[0]+"_Masq.tif" # nom définitif du masque - self.masqueSansChemin = os.path.basename(self.masque) - if os.path.exists(self.masque): - try: - os.remove(self.masque) - except: - self.encadre ("Impossible de remplacer le fichier masque :\n"+self.masque+"\nVérifier s'il n'est pas ouvert.\n Masque inchangé.", - nouveauDepart='non') - return - os.rename(self.masqueProvisoire,self.masque) # on renomme le fichier (et on écrase l'ancien !) - self.masqueProvisoire = str() # plus de masque provisoire: détricotage - self.masqueSansCheminProvisoire = str() - - self.masqueXML=self.masqueXML.replace("MonImage_Masq.tif",self.masqueSansChemin) #écriture dans le fichier xml - self.masqueXML=self.masqueXML.replace("largeur",str(self.masqueRetour.largeurImageFichier)) - self.masqueXML=self.masqueXML.replace("hauteur",str(self.masqueRetour.hauteurImageFichier)) - self.fichierMasqueXML=self.masque.replace(".tif",".xml") + def MasqueXML(self): # préparation du masque pour malt GeomImage. self.maitreSansChemin est nécessaire + + # le masque est constitué d'un fichier .tif ET d'un fichier .xml (masqueSansChemin est le tif + # la racine des noms est le nom de l'image maître, suivi de _Masq. puis de tif ou xml + + masque = os.path.splitext(self.maitreSansChemin)[0]+"_masque.tif" + + # On vérifie l'existencce du "masque" : + if os.path.exists(masque)==False: + supprimeFichier(self.fichierMasqueXML) # suppression ancien xml + return + # copie du fichier masque tif sous le nom requis par Malt = nom du maitre+"_Masq.tif" + masqueTIF = os.path.splitext(self.maitreSansChemin)[0]+"_Masq.tif" + supprimeFichier(masqueTIF) + shutil.copy(masque,masqueTIF) + + #écriture xml + self.masqueXML = self.masqueXMLOriginal # version initiale du fichier XML + self.masqueXML=self.masqueXML.replace("MonImage_Masq.tif",masqueTIF) # écriture dans le fichier xml + self.masqueXML=self.masqueXML.replace("largeur",str(self.dimensionsDesPhotos[0][1][0])) # x = self.dimensionsDesPhotos[0][0] + self.masqueXML=self.masqueXML.replace("hauteur",str(self.dimensionsDesPhotos[0][1][1])) # y=self.densionsDesPhotos[0][1] + self.fichierMasqueXML=masqueTIF.replace(".tif",".xml") # nom du fichier xml + with open(self.fichierMasqueXML, 'w', encoding='utf-8') as infile: infile.write(self.masqueXML) + def tracerUnMasqueSurMosaiqueTarama(self): + + if not os.path.exists(self.mosaiqueTaramaTIF): # en principe existe si on arrive ici + return + + if not os.path.exists(self.mosaiqueTaramaJPG): + self.conversionJPG(liste=[self.mosaiqueTaramaTIF]) + if not os.path.exists(self.mosaiqueTaramaJPG): + return + # l'utilisateur trace le masque + + self.masqueRetour = TracePolygone(fenetre,self.mosaiqueTaramaJPG,self.masqueTarama) # L'utilisateur peut tracer le masque sur l'image maitre + if self.masqueRetour.polygone == True: + self.miseAJourItem701_703() + pass + #""""""""""""""""""""""" Options masque 3D pour C3DC def affiche3DApericloud(self): # lance SAisieMasqQT, sans le fermer.... attente de la fermeture (subprocess.call) - os.chdir(self.repTravail) - if os.path.exists("AperiCloud.ply")==False: - try: - self.item803 = ttk.Label(self.item800, - text= "pas de fichier AperiCloud.ply pour construire le masque :\nlancer Micmac pour en constituer un.", - style="C.TButton") - self.item803.pack(ipady=2,pady=10) - except: pass - return - else: - try: self.item803.destroy() - except: pass masque3D = [self.mm3d,"SaisieMasqQT","AperiCloud.ply"] # " SaisieAppuisInitQT AperiCloud.ply" - self.apericloudExe=subprocess.call(masque3D,shell=self.shell) # Lancement du programme et attente du retour - try: #marche pas si on est en visu + self.apericloudExe = subprocess.call(masque3D,shell=self.shell) # Lancement du programme et attente du retour + + try: # marche pas si on est en visu if self.existeMasque3D(): - self.item803 = ttk.Label(self.item800, text= "masque 3D créé") - self.item803.pack(ipady=2,pady=10) + self.item804.configure(text= _("Masque 3D créé"),foreground='red') + self.item802.pack() # bouton "supprimer" else: - self.item803 = ttk.Label(self.item800, text= "Abandon : pas de masque créé.",foreground='red') - self.item803.pack(ipady=2,pady=10) + self.item804.configure(text= _("Abandon : pas de masque créé."),foreground='red') + self.item802.forget() # bouton "supprimer" except: pass + + + def supprimeMasque3D(self): + supprimeFichier(self.masque3DSansChemin) # suppression définitive des fichiers pour le masque 3D + supprimeFichier(self.masque3DBisSansChemin) + self.item804.configure(text= _("Masque 3D supprimé."),foreground='red') + self.item802.forget() + #""""""""""""""""""""""" Options de CalibrationGPS : faire correspondre des points (x,y,z) numérotés de 1 à N, avec des pixels des images. @@ -2607,104 +4464,137 @@ def optionsReperes(self): # en entrée : self.listePointsGPS qui comp self.item650 = ttk.Frame( self.onglets, # création du cadre d'accueil de l'onglet height=5, - relief='sunken') + relief='sunken') # message en haut de fenêtre - self.item670 = ttk.Frame(self.item650,height=10,relief='sunken') - self.item671=ttk.Label(self.item670,text="Chaque point doit être placé sur au moins 2 photos",justify='left') - self.item671.pack(pady=10,padx=10,ipady=2,ipadx=2) - self.item670.pack(side='top') - - - if self.listePointsGPS.__len__()==0: # ajout d'une ligne de saisie blanche si aucun point : - self.listePointsGPS.append(["","","","",True,self.idPointGPS]) # listePointsGPS : 6-tuples (nom du point, x, y et z gps, booléen actif, identifiant) - self.idPointGPS += 1 + self.item670 = ttk.Frame(self.item650,relief='sunken') + texte = _("3 points doivent être placés sur au moins 2 photos") + "\n" + texte+= _("Les points GPS sont prioritaires sur la mise à l'échelle.\n") + self.item671=ttk.Label(self.item670,text=texte,justify='left') + self.item671.pack(pady=1,padx=5,ipady=1,ipadx=1,fill="y") + self.item670.pack(side='top',pady=5,padx=5) + + # demande info globale pour Campari : erreur orientation cible gps et pixel image + + self.item672 = ttk.Frame(self.item650,height=10,relief='sunken') + self.item673 = ttk.Label(self.item672,text=_('CAMPARI : incertitude cible GPS :')) + self.item674 = ttk.Entry(self.item672,textvariable=self.incertitudeCibleGPS) # incertitude globale cible GPS + self.item675 = ttk.Label(self.item672,text=_('incertitude pixel image :')) + self.item676 = ttk.Entry(self.item672,textvariable=self.incertitudePixelImage) # incertitude globale cible GPS + self.item673.pack(side="left",pady=5,padx=5,ipady=1,ipadx=1) + self.item674.pack(side="left") + self.item675.pack(side="left") + self.item676.pack(side="left") + self.item672.pack(side='top',pady=5,padx=5,ipady=1,ipadx=1) + # affichage des entêtes de colonne self.item660 = ttk.Frame(self.item650,height=5,relief='sunken') - self.item661 = ttk.Label(self.item660,text='point').pack(side='left',pady=10,padx=60,fill="both") - self.item662 = ttk.Label(self.item660,text='X').pack(side='left',pady=10,padx=40) - self.item663 = ttk.Label(self.item660,text='Y').pack(side='left',pady=10,padx=70) - self.item664 = ttk.Label(self.item660,text='Z').pack(side='left',pady=10,padx=70) + self.item661 = ttk.Label(self.item660,text='point').pack(side='left',pady=10,padx=40,fill="both") + self.item662 = ttk.Label(self.item660,text='X').pack(side='left',pady=10,padx=60) + self.item663 = ttk.Label(self.item660,text='Y').pack(side='left',pady=10,padx=60) + self.item664 = ttk.Label(self.item660,text='Z').pack(side='left',pady=10,padx=60) + self.item665 = ttk.Label(self.item660,text=_('Incertitude sur X,Y,Z')).pack(side='left',pady=10,padx=30) self.item660.pack(side="top") # préparation des boutons en bas de liste - self.item653=ttk.Button(self.item650,text='Ajouter un point',command=self.ajoutPointCalibrationGPS) - self.item654=ttk.Button(self.item650,text='Supprimer des points',command=self.supprPointsGPS) - self.item655=ttk.Button(self.item650,text='Placer les points',command=self.placerPointsGPS) - + self.item653=ttk.Button(self.item650,text=_('Ajouter un point'),command=self.ajoutPointCalibrationGPS) + self.item654=ttk.Button(self.item650,text=_('Supprimer des points'),command=self.supprPointsGPS) + self.item655=ttk.Button(self.item650,text=_('Placer les points'),command=self.placerPointsGPS) + self.item656=ttk.Button(self.item650,text=_('Appliquer au ') + '\n' + _('nuage non densifié'),command=self.appliquerPointsGPS) + self.item653.pack_forget() #on oublie les boutons du bas s'ils étaient affichés self.item654.pack_forget() self.item655.pack_forget() - - + self.item656.pack_forget() + # Affichage de la liste des points actuellement saisis: - + self.item680 = ttk.Frame(self.item650,height=10,relief='sunken') self.listeWidgetGPS = list() # liste des widgets affichés, qui sera abondée au fur et à mesure par copie de self.listePointsGPS - for n,x,y,z,actif,ident in self.listePointsGPS: # affichage de tous les widgets nom,x,y,z,actif ou supprimé (booléen), identifiant - if actif: # listePointsGPS : liste de tuples (nom du point, x gps, y gps, z gps, booléen actif, identifiant) - self.affichePointCalibrationGPS(n,x,y,z,ident) # ajoute une ligne d'affichage - self.item653.pack(side='left',padx=20) # affichage des boutons en bas d'onglet + self.listePointsGPS.sort(key=lambda e: e[0]) # tri par ordre alpha du nom + + for n,x,y,z,actif,ident,incertitude in self.listePointsGPS: # affichage de tous les widgets nom,x,y,z,actif ou supprimé (booléen), identifiant + if actif: # listePointsGPS : liste de tuples (nom du point, x gps, y gps, z gps, booléen actif ou supprimé, identifiant) + self.affichePointCalibrationGPS(n,x,y,z,ident,incertitude) # ajoute une ligne d'affichage + + self.item680.pack() + self.item653.pack(side='left',padx=20) # affichage des boutons en bas d'onglet self.item654.pack(side='left',padx=20) self.item655.pack(side='left',padx=20) - - self.onglets.add(self.item650, text="GPS") # affichage onglet - self.onglets.select(self.item650) # active l'onglet + self.item656.pack(side='left',padx=20) + + # placer l'onglet vant l'onglet "Densification" + + placeDensification = self.onglets.index("end")-1 # Densification est le dernier onglet + self.onglets.add(self.item650, text="Points GPS") + self.onglets.insert(self.item650, placeDensification) # affichage onglet Points GPS en avant dernière position - def affichePointCalibrationGPS(self,n,x,y,z,ident): + def affichePointCalibrationGPS(self,n,x,y,z,ident,incertitude): # affiche un point + + f = ttk.Frame(self.item680,height=5,relief='sunken') # cadre d'accueil de la ligne - f = ttk.Frame(self.item650,height=5,relief='sunken') # cadre d'accueil de la ligne self.listeWidgetGPS.append( (f, # cadre : [0] ttk.Entry(f), # zones de saisie de [1] à [4] ttk.Entry(f), ttk.Entry(f), ttk.Entry(f), - ident) - ) - + ident, + ttk.Entry(f) + ) + ) + self.listeWidgetGPS[-1][0].pack(side='top') + if self.onglets.tab(self.onglets.select(), "text")=="Points GPS" and not self.listeWidgetGPS[-1][0].winfo_viewable(): + self.item650.configure(height=int(self.item650.cget('height'))+2) + self.listeWidgetGPS[-1][1].pack(side='left',padx=5) self.listeWidgetGPS[-1][1].focus() self.listeWidgetGPS[-1][2].pack(side='left') self.listeWidgetGPS[-1][3].pack(side='left') self.listeWidgetGPS[-1][4].pack(side='left') + self.listeWidgetGPS[-1][6].pack(side='left') self.listeWidgetGPS[-1][1].insert(0,n) # affichage de la valeur dans le widget self.listeWidgetGPS[-1][2].insert(0,x) self.listeWidgetGPS[-1][3].insert(0,y) self.listeWidgetGPS[-1][4].insert(0,z) - + self.listeWidgetGPS[-1][6].insert(0,incertitude) def ajoutPointCalibrationGPS(self): + if self.onglets.tab(self.onglets.select(), "text")=="GPS" and not self.item452.winfo_viewable(): # controle la visibilité des boutons " valider les options" et "annuler" + self.infoBulle(_("Agrandissez la fenêtre avant d'ajouter un point GPS !") + "\n" + _("(ou si impossible : supprimer un point)")) + return self.actualiseListePointsGPS() - if self.listePointsGPS.__len__()>5: - self.infoBulle("Soyez raisonnable : pas plus de 5 points GPS !") + if [ e[0] for e in self.listePointsGPS if e[4]].__len__()>=30: + self.infoBulle(_("Soyez raisonnable : pas plus de 30 points GPS !")) return - - self.listePointsGPS.append(["","","","",True,self.idPointGPS]) # listePointsGPS : 6-tuples (nom du point, x, y et z gps, booléen actif, identifiant) + nom = chr(65+self.listePointsGPS.__len__()) + self.listePointsGPS.append([nom,"","","",True,self.idPointGPS,"1 1 1"]) # listePointsGPS : 7-tuples (nom du point, x, y et z gps, booléen actif ou supprimé, identifiant,incertitude) self.idPointGPS += 1 # identifiant du point suivant self.optionsReperes() # affichage avec le nouveau point + self.onglets.select(self.item650) # active l'onglet (il a été supprimé puis recréé par optionsReperes) self.actualiseListePointsGPS() - def supprPointsGPS(self): + def supprPointsGPS(self): # Suppression des points GPS try: self.bulle.destroy() except: pass if self.listePointsGPS.__len__()==0: # pas de points : on sort - self.infoBulle("Aucun point à supprimer !") + self.infoBulle(_("Aucun point à supprimer !")) return - self.actualiseListePointsGPS() # listePointsGPS : 6-tuples (nom du point, x, y et z gps, booléen actif, identifiant) + self.actualiseListePointsGPS() # listePointsGPS : 7-tuples (nom du point, x, y et z gps, booléen actif ou supprimé, identifiant) listeIdentifiants = [ (e[0],e[5]) for e in self.listePointsGPS if e[4] ] # liste des noms,identifiants si point non supprimé self.messageSiPasDeFichier = 0 # pour affichage de message dans choisirphoto, difficile a passer en paramètre self.choisirUnePhoto([ f[0] for f in listeIdentifiants], - titre='Points à supprimer', + titre=_('Points à supprimer'), mode='extended', - message="Multiselection possible.", - boutonDeux="Annuler") + message=_("Multiselection possible."), + objets='points', + boutonDeux=_("Annuler")) self.messageSiPasDeFichier = 1 # en retour une liste : self.selectionPhotosAvecChemin @@ -2713,10 +4603,10 @@ def supprPointsGPS(self): return listeIdentifiantsASupprimer = [g[1] for g in listeIdentifiants if g[0] in self.selectionPhotosAvecChemin] - - for i in self.listePointsGPS: #on met le flag i[4] à zéro : pour conserver le lien avec les points placés ?? + listeIni = list(self.listePointsGPS) + for i in listeIni: # on met le flag i[4] à zéro : pour conserver le lien avec les points placés ?? if i[5] in listeIdentifiantsASupprimer: - self.listePointsGPS.remove(i) + self.listePointsGPS.remove(i) i[4] = False self.listePointsGPS.append(i) dico = dict(self.dicoPointsGPSEnPlace) # dicoPointsGPSEnPlace key = nom point, photo, identifiant, value = x,y @@ -2725,50 +4615,70 @@ def supprPointsGPS(self): del self.dicoPointsGPSEnPlace[keys] self.optionsReperes() - + self.onglets.select(self.item650) # active l'onglet (il a été supprimé puis recréé par optionsReperes) def actualiseListePointsGPS(self): # actualise les valeurs saisies pour les points GPS + # n'éxécuter que s'il y a eu saisie de points gps : self.listeWidgetGPS existe ! try: self.bulle.destroy() except: pass dico = dict(self.dicoPointsGPSEnPlace) # dicoPointsGPSEnPlace key = nom point, photo, identifiant, value = x,y - for a,nom,x,y,z,ident in self.listeWidgetGPS: - for i in self.listePointsGPS: # listePointsGPS : 6-tuples (nom du point, x, y et z gps, booléen actif, identifiant) + for a,nom,x,y,z,ident,incertitude in self.listeWidgetGPS: + for i in self.listePointsGPS: # listePointsGPS : 6-tuples (nom du point, x, y et z gps, booléen actif ou supprimé, identifiant) if i[5] == ident: self.listePointsGPS.remove(i) i[0] = nom.get() i[0] = i[0].replace(" ","_") # pour corriger une erreur : l'espace est interdit dans les tag d'item de canvas ! - i[1] = x.get() - i[2] = y.get() - i[3] = z.get() + i[1] = x.get().replace(",",".") # remplace la virgule éventuelle par un point + i[2] = y.get().replace(",",".") + i[3] = z.get().replace(",",".") + i[6] = incertitude.get().replace(",",".") self.listePointsGPS.append(i) for e,v in dico.items(): if e[2]==i[5] and i[0]!=e[0]: # l'identifiant du point placé = identifiant du point gps mais le nom du point est différent - #cela signifie que l'utilisateur à modifié le nom + # cela signifie que l'utilisateur à modifié le nom self.dicoPointsGPSEnPlace[(i[0],e[1],e[2])] = v # ajout d'une entrée quicorrige cette anomalie (on devrait utiliser l'identifiant...) try: - del self.dicoPointsGPSEnPlace[e] # suppression de l'ancienen entrée + del self.dicoPointsGPSEnPlace[e] # suppression de l'ancienne entrée except: pass - if e[2]==i[5] and i[4]==False: #si l'identifiant est identique et le point GPS supprimé alors on supprime le point placé + if e[2]==i[5] and i[4]==False: # si l'identifiant est identique et le point GPS supprimé alors on supprime le point placé try: del self.dicoPointsGPSEnPlace[e] - except: pass + except: pass + ############################# + # sur le modèle pythonique l'élément le plus représenté dans une liste l : x=sorted(set(l),key=l.count)[-1] + # ou pour avoir toute l'info [(valeur,nombre),...] : [(e,a.count(e)) for e in a] + # dicoPointsGPSEnPlace key = nom point, photo, identifiant, value = x,y + # ce bout de code est dupliqué dans controlePointsGPS et actualiseListePointsGPS + + listePointsPlaces=[e[0] for e in self.dicoPointsGPSEnPlace] + pointsPlaces = [(e,listePointsPlaces.count(e)) for e in listePointsPlaces] + self.pointsPlacesUneFois = [f[0] for f,g in set([(e,pointsPlaces.count(e)) for e in pointsPlaces]) if g==1] + self.pointsPlacesUneFois.sort() + + # Nombre de points placés 2 fois ou plus : + self.pointsPlacesDeuxFoisOuPlus = [f[0] for f,g in set([(e,pointsPlaces.count(e)) for e in pointsPlaces]) if g>1] + ############################# def placerPointsGPS(self): - + if self.photosAvecChemin.__len__()==0: + self.infoBulle(_("Choisir d'abord les photos du chantier.")) + return + self.actualiseListePointsGPS() - if self.controlePoints(): + if self.erreurPointsGPS(): return - liste = list ([(n,ident) for n,x,y,z,actif,ident in self.listePointsGPS if actif]) # listePointsGPS : 6-tuples (nom du point, x, y et z gps, booléen actif, identifiant) + + liste = list ([(n,ident) for n,x,y,z,actif,ident,incertitude in self.listePointsGPS if actif]) # listePointsGPS : 7-tuples (nom du point, x, y et z gps, booléen actif ou supprimé, identifiant, incertitude) self.messageSiPasDeFichier = 0 # pour affichage de message dans choisirphoto, difficile a passer en paramètre self.choisirUnePhoto( - self.photosPropresAvecChemin, - message="Choisir une photo pour placer les points GPS : ", + self.photosAvecChemin, + message=_("Choisir une photo pour placer les points GPS : "), mode='single', - dicoPoints=self.dicoPointsGPSEnPlace) # dicoPointsGPSEnPlace key = nom point, photo, identifiant, value = x,y + dicoPoints=self.dicoPointsGPSEnPlace) # dicoPointsGPSEnPlace key = (nom point, photo, identifiant), value = (x,y) self.messageSiPasDeFichier = 1 # en retour une liste : self.selectionPhotosAvecChemin @@ -2782,46 +4692,88 @@ def placerPointsGPS(self): liste, # liste des identifiants en "string" des points self.dicoPointsGPSEnPlace, # les points déjà placés key = nom point, photo, identifiant ) # value = x,y - try: self.dicoPointsGPSEnPlace = self.calibre.dicoPointsJPG # si pas de retour ! - except: pass + try: + self.dicoPointsGPSEnPlace = self.calibre.dicoPointsJPG # si pas de retour ! + except: + pass - def controlePoints(self): + def erreurPointsGPS(self): # regarde si la liste des points GPS comporte une erreur : nom absent ou en double, retourne True si erreur try: self.bulle.destroy() except: pass - texte = "" - ensemble=set(e[0] for e in self.listePointsGPS if e[4]) # listePointsGPS : 6-tuples (nom du point, x, y et z gps, booléen actif, identifiant) + texte = str() + ensemble=set(e[0] for e in self.listePointsGPS if e[4]) # listePointsGPS : 6-tuples (nom du point, x, y et z gps, booléen actif ou supprimé, identifiant, incertitude) liste=list(e[0] for e in self.listePointsGPS if e[4]) if ensemble.__len__()!=liste.__len__(): - texte = "Attention : Des points portent le même nom." + texte = _("Impossible : des points portent le même nom : modifier ou supprimer !") if "" in ensemble: - texte = "Attention : un point n'a pas de nom. "+texte - if texte!="": + texte = _("Attention : un point n'a pas de nom. ")+texte + if texte!=str(): + print(_("controle points : ")+texte) self.infoBulle(texte) return True return False + + + def appliquerPointsGPS(self): + + try: self.bulle.destroy() + except: pass + if not os.path.exists(os.path.join(self.repTravail,"AperiCloud.ply")): + self.infoBulle(_("Lancer d'abord tapioca/tapas") + "\n" + _("pour obtenir un nuage non densifié.")) + return + + if self.erreurPointsGPS(): # erreur : nom en double ou point sans nom, affiche une info bulle, retourne True si pb + return + + if self.controlePointsGPS()==False: # les points GPS sont assez nombreux et présents sur assez de photos, retourne False si Pb + self.infoBulle(_("Points GPS non conformes :") + "\n"+self.etatPointsGPS) + return + + if self.finCalibrationGPSOK()==False: # création des fichiers xml qui vont bien (dicoAppuis, mesureAppuis) return False si problème + self.infoBulle(_("Points GPS non conformes :") + "\n"+self.etatPointsGPS) + return + + self.infoBulle(_("Patienter :") + "\n" + _("le nuage est en cours de calibration")) + self.lanceBascule() # calibration suivant les points GPS + + # Apericloud crée le nuage 3D des points homologues puis visualisation : + + self.lanceApericloud() # création d'un nuage de points 3D + self.lanceApericloudMeshlab() # affiche le nuage 3D si il existe + try: self.bulle.destroy() + except: pass + +############################ Calibration par axe, plan et métrique def ligneHorizontale(self): - self.dicoLigneVerticale = dict() # on efface le dico horizontal (l'un ou l'autre) - liste = (("Origine Ox",1),("Extrémité Ox",2)) # liste de tuple nom du point et identifiant du widget - self.messageSiPasDeFichier = 0 # pour affichage de message dans choisirphoto, difficile a passer en paramètre + if self.photosAvecChemin.__len__()==0: + self.infoBulle(_("Choisir d'abord les photos du chantier.")) + return + liste = ((_("Origine Ox"),1),(_("Extrémité Ox"),2)) # liste de tuple nom du point et identifiant du widget + self.messageSiPasDeFichier = 0 # pour affichage de message dans choisirphoto, difficile a passer en paramètre + bulles={} + if self.dicoLigneHorizontale.__len__(): + bulles={list(self.dicoLigneHorizontale.items())[0][0][1]:""} self.choisirUnePhoto( - self.photosPropresAvecChemin, - message="Placer une ligne horizontale sur une seule photo : ", + self.photosAvecChemin, + message=_("Placer une ligne horizontale sur une seule photo : "), mode='single', - dicoPoints=self.dicoLigneHorizontale) + dicoPoints=self.dicoLigneHorizontale, + bulles=bulles) self.messageSiPasDeFichier = 1 # en retour une liste : self.selectionPhotosAvecChemin if self.selectionPhotosAvecChemin.__len__()==0: + print("pas de photos choisie") return - + self.dicoLigneVerticale = dict() # on efface le dico vertical (l'un ou l'autre) horizonVierge = dict() try: if self.selectionPhotosAvecChemin[0]==list(self.dicoLigneHorizontale.items())[0][0][1]: # si l'image choisie est la même on conserve le dico horizonVierge = self.dicoLigneHorizontale # sinon nouveau dico - except: pass + except Exception as e: print(str(e)) self.calibre = CalibrationGPS(fenetre, self.selectionPhotosAvecChemin, # image sur laquelle placer les points liste, # liste des identifiants en "string" des points @@ -2830,28 +4782,34 @@ def ligneHorizontale(self): #il doit y avoir 2 points placés, sinon erreur : try: if self.calibre.dicoPointsJPG.__len__()!=2: - self.infoBulle("il faut placer les 2 points.") + self.infoBulle(_("il faut placer les 2 points.")) return - except: pass - try: self.dicoLigneHorizontale = self.calibre.dicoPointsJPG # si pas de retour ! - except: pass + except Exception as e: print(str(e)) + try: self.dicoLigneHorizontale = self.calibre.dicoPointsJPG # si pas de retour on saute + except Exception as e: print(str(e)) def ligneVerticale(self): - self.dicoLigneHorizontale = dict() # on efface le dico horizontal (l'un ou l'autre) + if self.photosAvecChemin.__len__()==0: + self.infoBulle(_("Choisir d'abord les photos du chantier.")) + return self.messageSiPasDeFichier = 0 # pour affichage de message dans choisirphoto, difficile a passer en paramètre + bulles={} + if self.dicoLigneVerticale.__len__(): + bulles={list(self.dicoLigneVerticale.items())[0][0][1]:""} self.choisirUnePhoto( - self.photosPropresAvecChemin, - message="Placer une ligne verticale sur une seule photo : : ", + self.photosAvecChemin, + message=_("Placer une ligne verticale sur une seule photo : : "), mode='single', - dicoPoints=self.dicoLigneVerticale) + dicoPoints=self.dicoLigneVerticale, + bulles=bulles) self.messageSiPasDeFichier = 1 # en retour une liste : self.selectionPhotosAvecChemin if self.selectionPhotosAvecChemin.__len__()==0: return - - liste = (("Origine Oy",1),("Extrémité Oy",2)) # liste de tuple nom du point et identifiant du widget + self.dicoLigneHorizontale = dict() # on efface le dico horizontal (l'un ou l'autre) + liste = ((_("Origine Oy"),1),(_("Extrémité Oy"),2)) # liste de tuple nom du point et identifiant du widget horizonVierge = dict() try: if self.selectionPhotosAvecChemin[0]==list(self.dicoLigneVerticale.items())[0][0][1]: # si l'image choisie est la même on conserve le dico @@ -2865,21 +4823,26 @@ def ligneVerticale(self): # il doit y avoir 2 points placés, sinon erreur :) try: if self.calibre.dicoPointsJPG.__len__()!=2: - self.infoBulle("il faut placer les 2 points.") + self.infoBulle(_("il faut placer exactement 2 points.")) return except Exception as e: pass try: self.dicoLigneVerticale = self.calibre.dicoPointsJPG # si pas de retour ! except Exception as e: pass def planVertical(self): - - self.planProvisoireHorizontal = str() #un seul plan : le dernier - self.planProvisoireVertical = str() + if self.photosAvecChemin.__len__()==0: + self.infoBulle(_("Choisir d'abord les photos du chantier.")) + return self.messageSiPasDeFichier = 0 + if self.planProvisoireVertical=="planVertical.tif": + bulles = {self.monImage_MaitrePlan:_("Plan vertical")} + else: + bulles = {self.monImage_MaitrePlan:_("Plan horizontal")} self.choisirUnePhoto( - self.photosPropresAvecChemin, - message="Une photo pour placer le plan vertical : ", - mode='single') + self.photosAvecChemin, + message=_("Une photo pour placer le plan vertical : "), + mode='single', + bulles=bulles) self.messageSiPasDeFichier = 1 # en retour une liste : self.selectionPhotosAvecChemin @@ -2887,42 +4850,56 @@ def planVertical(self): if self.selectionPhotosAvecChemin.__len__()==0: return - self.planProvisoireVertical = "planVertical.tif" #os.path.splitext(self.selectionPhotosAvecChemin[0])+"_planvertical.tif" # Nom du fichier masque, à partir du fichier maître, imposé par micmac + self.planProvisoireHorizontal = str() #un seul plan : le dernier + self.planProvisoireVertical = str() + + self.planProvisoireVertical = "planVertical.tif" #os.path.splitext(self.selectionPhotosAvecChemin[0])+"_planvertical.tif" # Nom du fichier masque, à partir du fichier maître, imposé par micmac self.monImage_MaitrePlan = self.selectionPhotosAvecChemin[0] self.planV = TracePolygone(fenetre, self.monImage_MaitrePlan, self.planProvisoireVertical, - labelBouton="Délimiter un plan vertical") # L'utilisateur peut tracer le masque sur l'image maitre + labelBouton=_("Délimiter un plan vertical")) # L'utilisateur peut tracer le masque sur l'image maitre def planHorizontal(self): - - self.planProvisoireHorizontal = str() #un seul plan : le dernier - self.planProvisoireVertical = str() + if self.photosAvecChemin.__len__()==0: + self.infoBulle(_("Choisir d'abord les photos du chantier.")) + return self.messageSiPasDeFichier = 0 + if self.planProvisoireVertical=="planVertical.tif": + bulles = {self.monImage_MaitrePlan:_("Plan vertical")} + else: + bulles = {self.monImage_MaitrePlan:_("Plan horizontal")} self.choisirUnePhoto( - self.photosPropresAvecChemin, - message="Une photo pour placer le plan horizontal : ", - mode='single') + self.photosAvecChemin, + message=_("Une photo pour placer le plan horizontal : "), + mode='single', + bulles=bulles) self.messageSiPasDeFichier = 1 # en retour une liste : self.selectionPhotosAvecChemin if self.selectionPhotosAvecChemin.__len__()==0: - return - + return + + self.planProvisoireHorizontal = str() #un seul plan : le dernier + self.planProvisoireVertical = str() + self.planProvisoireHorizontal = "planHorizontal.tif" # os.path.splitext(self.selectionPhotosAvecChemin[0])+"_planhorizontal.tif" # Nom du fichier masque, à partir du fichier maître, imposé par micmac self.monImage_MaitrePlan = self.selectionPhotosAvecChemin[0] self.planH = TracePolygone(fenetre, self.monImage_MaitrePlan, self.planProvisoireHorizontal, - labelBouton="Délimiter un plan horizontal") # L'utilisateur peut tracer le masque sur l'image maitre + labelBouton=_("Délimiter un plan horizontal")) # L'utilisateur peut tracer le masque sur l'image maitre def placer2Points(self): + if self.photosAvecChemin.__len__()==0: + self.infoBulle(_("Choisir d'abord les photos du chantier.")) + return liste = (("Début",1),("Fin",2)) # liste de tuple nom du point et identifiant du widget self.messageSiPasDeFichier = 0 self.choisirUnePhoto( - self.photosPropresAvecChemin, - message="Choisir deux fois une photo pour placer les 2 points : ", + self.photosAvecChemin, + message=_("Choisir deux fois une photo pour placer les 2 points : "), mode='single', dicoPoints=self.dicoCalibre) self.messageSiPasDeFichier = 1 @@ -2938,87 +4915,260 @@ def placer2Points(self): ajout(photosAvecDistance,os.path.basename(self.selectionPhotosAvecChemin[0])) if photosAvecDistance.__len__()>2: - self.infoBulle("Il y a dèjà 2 images avec des points 'distance'. Supprimer les points sur une des 2 images.") + self.infoBulle(_("Il y a dèjà 2 images avec des points 'distance'. Supprimer les points sur une des 2 images.")) return self.calibre = CalibrationGPS(fenetre, self.selectionPhotosAvecChemin, # image sur laquelle placer les points liste, # liste des identifiants en "string" des points - self.dicoCalibre # les points déjà placés key = nom point, photo, identifiant - ) # value = x,y + self.dicoCalibre # les points déjà placés key = nom point, photo, identifiant + ) # value = x,y try: self.dicoCalibre = self.calibre.dicoPointsJPG # si pas de retour ! except: pass - ################################## LANCEMENT DE MICMAC ########################################################### + ################################## LANCEMENT DE MICMAC ########################################################### def lanceMicMac(self): # vérification du choix de photos, de présence de l'éxécutable, du choix de l'extension, de la copie effective dans le répertoire de travail + + if self.etatDuChantier==5: # Chantier terminé + self.encadre(_("Le chantier %(chant)s est terminé après %(densif)s") % {"chant" : self.chantier, "densif" : self.choixDensification} + ".\n\n"+ + _("Vous pouvez modifier les options puis relancer MicMac.")) + return + + # réinitialisation des variables "locales" définies dans le module + + self.zoomI = "" # pour Malt + # Vérification de l'état du chantier : - # si pas de photos choisies : retour : + # si pas de photo ou pas de répertoire micmac : retour : + + if self.pasDePhoto():return + if self.pasDeMm3d():return + if self.pasDeExiftool():return + + # controle que les options sont correctes (toutes, même si elles ne doivent pas servir) + + retour = self.controleOptions() + if retour!=True: + self.encadre(_("Options incorrectes : corriger") + "\n\n"+retour) + return - if self.etatDuChantier==0: # pas de photos choisies : avertissement à l'utilisateur - self.encadre("Choisir les photos à traiter avant d'exécuter Micmac.") + # pas assez de photos choisies : + + if self.photosAvecChemin.__len__()==2: + message = _("Avec 2 photos MicMac construira difficilement un nuage de point dense.") + "\n" + _("Utiliser l'échelle -1 dans Tapioca pour obtenir un nuage optimal.") + "\n" + retour = self.troisBoutons(titre=_('Avertissement : 2 photos seulement'), + question=message, + b1=_('Continuer'),b2=_('Abandon'),b3=None) # b1 renvoie 0, b2 renvoie 1 ; fermer fenetre = -1, + if retour != 0: + self.afficheEtat() + return + + # pas assez de photos si on retire les photos pour calibration (pour tapas): + if self.etatDuChantier<=2: + if self.calibSeule.get(): + nbPhotosPourTapas = self.photosAvecChemin.__len__() - self.photosPourCalibrationIntrinseque.__len__() + if nbPhotosPourTapas<2: + message = _("Nombre de photos insuffisant après retrait des photos pour la calibration : ")+str(nbPhotosPourTapas) + self.encadre(message,) + return + + # il faut au moins deux photos calibration par appareil photo : vérification + + if len(self.photosPourCalibrationIntrinseque)==1: #une seule photo pour la calibration : cela ne marche pas + message = _("Une seule photo pour la calibration intrinsèque de l'appareil photo. C'est insuffisant.\n")+\ + _("Modifier la liste des photos pour calibration.") + self.encadre(message) return + nbAppareils = self.nombreDeExifTagDifferents("Model") + # si un seul appareil : pas de message initial, message final si pas de résultat + + if nbAppareils>1: # plusieurs appareils potos, calibration nécessaire, liste des appareils dans self.lesTags + if self.photosPourCalibrationIntrinseque: + nb = dict() + message = str() + for appareil in self.lesTags: + nb[appareil] = 0 + for photo in self.photosPourCalibrationIntrinseque: + appareil = self.tagExif("Model",photo) + nb[appareil] += 1 + for a in nb: + if nb[a]==1: + message += _("Une seule photo pour la calibration de l'appareil ")+a+_(" c'est insuffisant.\n") + if nb[a]==0: + message += _("Aucune photo pour la calibration de l'appareil ")+a+_(" c'est insuffisant.\n") + if message: + message += _("\n\n Modifier la liste des photos pour calibration.") + message += _("\n\n Le menu 'expert/liste des appareils' fournit le nom de l'appareil pour chaque photo.") + self.encadre(message) + return + else: # Plusieurs appareils et Aucune photo pour calibration intrinsèque + if len(self.photosPourCalibrationIntrinseque)==0: + message = _("Aucune photo pour la calibration intrinsèque des ")+str(nbAppareils)+_(" appareils photos.")+\ + _("\nCela peut rendre difficile les traitements.")+\ + _("\n\nConseil : prendre 2 photos pour la calibration de chaque appareil.") + self.ajoutLigne(message) + retour = self.troisBoutons(titre=_('Avertissement'),question=message,b1=_('Continuer'),b2=_('Abandon'),b3=None) + if retour != 0: + self.afficheEtat() + return + # pas enregistré : on enregistre on poursuit - + if self.etatDuChantier==1: # Des photos mais fichier paramètre non encore enregistré, on enregistre et on poursuit self.enregistreChantier() # sauvegarde du fichier paramètre sous le répertoire du chantier : modif etatduchantier = 2 - # anormal : chantier planté lors de la dernière éxécution : on propose le déblocage mais on sort dans tous les cas + # on lance Tapioca ou on repart après erreur : Les photos sont-elles correctes ? + + self.encadre(_("Controle des photos en cours....\nPatienter jusqu'à la fin du controle.")) + self.controlePhotos() # positionne self.dimensionsOK self.nbFocales + self.menageEcran() + message = str() + if self.dimensionsOK==False: + message = "\n" + _("Les dimensions des photos ne sont pas toutes identiques.") + "\n"+\ + _("Le traitement par MicMac est incertain.") + "\n"+\ + "\n".join([ a+" : "+str(b[0])+" "+str(b[1]) for a, b in self.dimensionsDesPhotos]) + retour = self.troisBoutons(titre=_('Avertissement'),question=message,b1=_('Continuer'),b2=_('Abandon'),b3=None) + if retour != 0: + self.afficheEtat() + return + + if self.nbFocales==0: + retour = self.troisBoutons(titre=_('Absence de focales'), + question=_("Certaines photos n'ont pas de focales.") + "\n"+ + _("Le traitement echouera probablement.") + "\n"+ + _("Mettre à jour les exifs (menu Outils)"), + b1=_('Continuer'),b2=_('Abandon'),b3=None) # b1 renvoie 0, b2 renvoie 1 ; fermer fenetre = -1, + if retour != 0: + self.afficheEtat() + return + + + if self.nbFocales>1 and self.etatDuChantier<3 : + if self.calibSeule.get()==False: # plusieurs focales et pas de calibration + message = _("Les focales des photos ne sont pas toutes identiques.") + "\n"+\ + _("Le traitement par MicMac est préférable en utilisant une focale pour la calibration intrinsèque.") + retour = self.troisBoutons(titre=_('Avertissement'),question=message,b1=_('Continuer'),b2=_('Abandon'),b3=None) + if retour != 0: + self.afficheEtat() + return + + if self.photosSansChemin.__len__()<2: + message += _("Pas assez de photos pour le traitement : il en faut au moins 2.") + self.encadre(message) + return + + # anormal : chantier planté lors de la dernière éxécution de tapioca/Tapas : on propose le déblocage mais on sort dans tous les cas - if self.etatDuChantier==3: # En principe ne doit pas arriver : plantage en cours d'un traitement précédent - retour = self.deuxBoutons( titre="Le chantier "+self.chantier+" a été interrompu en cours d'exécution.", - question="Le chantier est interrompu.\nVous pouvez le débloquer, "+ - "ce qui permettra de modifier les options et de le relancer.\n", - b1='Débloquer le chantier',b2='Abandon') + if self.etatDuChantier==3: # En principe ne doit pas arriver : plantage en cours de tapas ou Tapioca + retour = self.troisBoutons( titre=_("Le chantier %s a été interrompu lors de Tapioca/Tapas.") % (self.chantier), + question=_("Le chantier est interrompu.") + "\n" + _("Vous pouvez le débloquer,")+ + _( "ce qui permettra de modifier les options et de le relancer.") + "\n", + b1=_('Débloquer le chantier'),b2=_('Abandon')) if abs(retour)==1: # 1 ou -1 : abandon ou fermeture de la fenêtre par la croix return if retour==0: self.nettoyerChantier() # le chantier est noté comme de nouveau modifiable self.sauveParam() - self.afficheEtat("Chantier "+self.chantier+" de nouveau modifiable, paramètrable et exécutable.") + self.afficheEtat(_("Chantier %s de nouveau modifiable, paramètrable et exécutable.") % (self.chantier)) + return + + # anormal : chantier planté lors de la dernière éxécution de Malt/c3dc : on propose le déblocage mais on sort dans tous les cas + + if self.etatDuChantier==7: # En principe ne doit pas arriver : plantage en cours de Malt/c3dc, + retour = self.troisBoutons( titre=_("Le chantier %s a été interrompu en cours densification.") % (self.chantier), + question=_("Le chantier est interrompu en cours de densification.") + "\n" + _("Vous pouvez le débloquer,")+ + _( "ce qui permettra de modifier les options et de le relancer la densification.") + "\n", + b1=_('Débloquer le chantier'),b2=_('Abandon')) + if abs(retour)==1: # 1 ou -1 : abandon ou fermeture de la fenêtre par la croix + return + if retour==0: + self.nettoyerChantierDensification() # le chantier est noté comme de nouveau modifiable + self.sauveParam() + self.afficheEtat(_("Chantier %s de nouveau modifiable, paramètrable et exécutable.") % (self.chantier)) return + # Chantier arrété après tapas : l'utilisateur a pu modifier les options et veut continuer ou reprendre au début suivant les résultats # poursuite du traitement ou arrêt suivant demande utilisateur if self.etatDuChantier==4: # Chantier arrêté après Tapas - retour = self.deuxBoutons( titre='Continuer le chantier '+self.chantier+' après tapas ?', - question = "Le chantier est arrêté après tapas.\nPoursuivre le traitement ou annuler le traitement précédent?\n"+ - "Pour ne rien faire cliquer sur le bouton 'fermer' de la fenêtre", - b1='Poursuivre',b2='Débloquer le chantier - garder les résultats') + + retour = self.troisBoutons( titre=_('Continuer le chantier %s après tapas ?') % (self.chantier), + question = _("Le chantier est arrêté après tapas. Vous pouvez :") + "\n"+ + _(" - lancer la densification") + "\n"+ + _(" - débloquer le chantier pour modifier les paramètres de Tapioca/tapas") + "\n"+ + _(" - ne rien faire") + "\n", + b1=_('Lancer la densification '), + b2=_('Débloquer le chantier - garder les résultats'), + b3=_('Abandon')) if retour == -1: # fermeture de la fenêtre + self.afficheEtat(entete=_("abandon de Malt")) return - - if retour == 0: # Lancer malt ou C3DC - self.menageEcran() # ménage écran - self.cadreVide() # fenêtre texte pour affichage des résultats. - self.ajoutLigne(heure()+" Reprise du chantier "+self.chantier+" arrêté aprés TAPAS - La trace depuis l'origine sera disponible dans le menu édition.") + self.cadreVide() # début de la trace : fenêtre texte pour affichage des résultats. + if retour == 0: # b1 : Lancer la densification + self.ajoutLigne(heure()+_(" Reprise du chantier %s arrêté après TAPAS - La trace depuis l'origine sera disponible dans le menu édition.") % (self.chantier)) self.suiteMicmac() # on poursuit par Malt ou C3DC return - if retour==1: # débloquer le chantier + if retour==1: # b2 : débloquer le chantier self.nettoyerChantier() - self.afficheEtat("Chantier "+self.chantier+" de nouveau modifiable, paramètrable et exécutable.") + self.afficheEtat(_("Chantier %s de nouveau modifiable, paramètrable et exécutable.") % (self.chantier)) return + if retour==2: # b3 : abandon + self.afficheEtat() + return + + # Chantier terminé, l'utilisateur peur décider de le débloquer en conservant les résultats de tapas ou supprimer tous les résultats - - if self.etatDuChantier==5: # Chantier terminé - retour = self.deuxBoutons( titre='Le chantier '+self.chantier+' est terminé.', - question="Le chantier est terminé.\nVous pouvez le nettoyer, "+ - "ce qui supprimera les calculs et permettra de le relancer.\n", - b1='Ne rien faire',b2='Nettoyer le chantier - garder les résultats') - if retour==-1: # -1 : fermeture fenêtre, abandon - return - if retour==0: # 0 : ne rien faire - return - if retour==1: # 1 : on nettoie, on passe à l'état 2 - self.nettoyerChantier() - self.afficheEtat("Chantier "+self.chantier+" de nouveau modifiable, paramètrable et exécutable.") - return + # est-il possible de relancer Malt en conservant le niveau de zoom déjà atteint ??? pas sur, sauf en passant par Micmac +## +## if self.etatDuChantier==5: # Chantier terminé +## if self.choixDensification.get()=="C3DC": +## self.encadre("Le chantier "+self.chantier+" est terminé après "+self.choixDensification.get()+".\n\n"+ +## "Vous pouvez modifier les options puis relancer MicMac.") +## return +## if self.zoomF.get()=="1": +## self.encadre("Le chantier "+self.chantier+" est terminé après "+self.choixDensification.get()+", avec un zoom final de 1.\n\n"+ +## "Vous pouvez modifier les options puis relancer MicMac.") +## return +## +## if self.zoomF.get()=="2": +## retour = self.troisBoutons( titre='Le chantier '+self.chantier+' est terminé.', +## question="Le chantier est terminé après Malt, avec un zoom final de 2.\n"+ +## "Vous pouvez :\n"+ +## " - Relancer MicMac pour obtenir un zoom final de 1\n"+ +## " - Modifier les options avant de relancer MicMac\n"+ +## " - Ne rien faire.\n", +## b1='Zoom final = 1', +## b2='Modifier les options', +## b3='Ne rien faire',) +## if retour==-1: # -1 : fermeture fenêtre, abandon +## self.afficheEtat() +## return +## +## if retour==0: # bouton b1, retour = 0 : on nettoie, on passe à l'état 2 +## self.zoomF.set("1") # zoom final = 1 +## self.zoomI = "4" # zoom Initial = 2 +## self.ajoutLigne(heure()+" Reprise du chantier "+self.chantier+" avec un zoom final = 1.\n") +## self.etatDuChantier=4 # état : arrêt après tapas +## self.suiteMicmac() +## return +## +## if retour==1: # retour=1, bouton b2 : modifier les options +## self.optionsOnglet() +## return +## +## if retour==2: # retour=2, bouton b3 : ne rien faire +## self.afficheEtat() +## return + + + # L'état du chantier est prêt pour l'exécution de Tapioca (2) ou débloqué (6) : sauvegarde des paramètres actuels puis traitement self.sauveParam() @@ -3028,47 +5178,72 @@ def lanceMicMac(self): # vérification du c retourAvantScene = self.avantScene() # Efface tout, Prépare le contexte, crée le répertoire de travail, copie les photos, ouvre les traces if retourAvantScene!=None: # Préparation de l'éxécution de MicMac - texte = "Pourquoi MicMac s'arrête : \n"+retourAvantScene + texte = _("Pourquoi MicMac s'arrête : ") + "\n"+retourAvantScene self.encadreEtTrace(texte) # si problème arrêt avec explication return - # Prêt : modification de l'état, lancement du premier module Tapioca (recherche des points homologues) + # Prêt : modification de l'état, lancement du premier module Tapioca (recherche des points homologues) arrêt si pas de points homologues self.etatDuChantier = 3 # trés provisoirement (en principe cette valeur est transitoire sauf si avantScène plante) self.lanceTapioca() + + # arrêt au milieu de Tapioca : + + if self.nePasLancerTapas: + self.nePasLancerTapas = False + return + + # tapioca a-t-il trouvé des points homologues ? + if not os.path.exists("Homol"): # le répertoire Homol contient les points homologues, si absent, pas de points en correspondancce - message = "Pourquoi MicMac s'arrête : \n"+"Aucun point en correspondance sur 2 images n'a été trouvé par Tapioca.\n\n"+\ - "Parmi les raisons de cet échec il peut y avoir :\n"+\ - "soit l'exif des photos ne comporte pas la focale ou plusieurs focales sont présentes \n+"+\ - "Soit l'appareil photo est inconnu de Micmac\n"+\ - "soit la qualité des photos est en cause.\n"+\ - "\nUtiliser les items du menu 'outils' pour vérifier ces points.\n\n" + message = _("Pourquoi MicMac s'arrête : ") + "\n"+_("Aucun point en correspondance sur 2 images n'a été trouvé par Tapioca.") + "\n\n"+\ + _("Parmi les raisons de cet échec il peut y avoir :") + "\n"+\ + _("soit les photos ne se recouvrent pas du tout") + "\n+" +\ + _("soit l'exif des photos ne comporte pas la focale ou plusieurs focales sont présentes") + "\n+" +\ + _("Soit l'appareil photo est inconnu de Micmac") + "\n"+\ + _("soit la qualité des photos est en cause.") + "\n\n"+\ + _("soit la trace compléte contient : 'Error: -- Input line too long, increase MAXLINELENGTH' .") + "\n\n"+\ + _("alors tenter, sans certitude, de modifier le fichier /binaire-aux/windows/startup/local.mk") + "\n\n"+\ + _("Utiliser les items du menu 'outils' pour vérifier ces points.") + "\n\n" self.ajoutLigne(message) self.messageNouveauDepart = message - self.nouveauDepart() # lance une fenêtre nouvelle sous windows (l'actuelle peyt-être polluée par le traitement + self.nouveauDepart() # lance une fenêtre nouvelle sous windows (l'actuelle peut-être polluée par le traitement) Ecrit la trace return - # points homologues trouvés, second module : Tapas positionne les prises de vue dans l'espace + # Tapioca a bien trouvé des points homologues : concernant-ils une seule scène ? + + if self.plusieursScenes(): + return + + # points homologues trouvés, corrects, second module : Tapas positionne les prises de vue dans l'espace - self.nbResiduTapas = 0 # booléen pour tester si taps fonctionne : si aucune orientation alors échec de tapioca self.lanceTapas() - - if self.nbResiduTapas == 0: # Tapioca n'a pu mettre en correspondance ce aucun point entre deux images : échec - message = "Pourquoi MicMac s'arrête : \n"+"Pas d'orientation trouvé par tapas.\nPrises de vues non positionnées.\n"+\ - "Verifier la qualité des photos (item du menu outil)\n\n" + + if os.path.isdir("Ori-Arbitrary")==False: # Tapioca n'a pu mettre en correspondance ce aucun point entre deux images : échec + message = _("Pourquoi MicMac s'arrête :") + "\n\n"+self.messageRetourTapas +"\n\n" + _("consulter la trace.") self.ajoutLigne(message) + self.ecritureTraceMicMac() # on écrit les fichiers trace + self.sauveParam() self.messageNouveauDepart = message - self.nouveauDepart() # lance une fenêtre nouvelle sous windows (l'actuelle peyt-être polluée par le traitement + self.nouveauDepart() # lance une fenêtre nouvelle sous windows (l'actuelle peut-être polluée par le traitement) Ecrit la trace return + # Si un fichier de calibration par axe plan et métrique est valide on lance apero, même s'il y a une calibration par points GPS (sera bon si GPS échoue) - # Si un fichier de calibration valide est présent on lance apero - - if self.controleCalibration(): # calibration OK + if self.controleCalibration(): # calibration OK = True self.lanceApero() - if self.etatCalibration!=str(): # calibration incomplète - self.ajoutLigne(heure()+"Calibration incomplète : "+self.etatCalibration) + if self.etatCalibration!=str(): # calibration incomplète s'il y a un message, motif dans etatCalibration + self.ajoutLigne(heure()+_("Calibration incomplète : ")+self.etatCalibration) + + + # calibrage de l'orientation suivant des points GPS, un axe ox, un plan déterminé par un masque + # si il existe un fichier XML de points d'appuis : self.mesureAppuis + + if os.path.exists(self.mesureAppuis): + + self.lanceBascule() # des points GPS : on calibre dessus, cela remplace la calibration précédente + # troisième module : Apericloud crée le nuage 3D des points homologues puis visualisation : @@ -3076,124 +5251,191 @@ def lanceMicMac(self): # vérification du c self.lanceApericloudMeshlab() # affiche le nuage 3D si il existe # Situation stable, changement d'état : 4 = Tapioca et Tapas exécutés, sauvegarde des paramètres - - self.etatDuChantier = 4 # état du chantier lors de l'arrêt aprés tapas - self.sauveParam() + + if os.path.exists('AperiCloud.ply'): + self.etatDuChantier = 4 # état du chantier lors de l'arrêt après tapas + self.copierParamVersChantier() # sauvegarde du fichier paramètre sous le répertoire du chantier self.ecritureTraceMicMac() # on écrit les fichiers trace + + # tarama ? + if self.lancerTarama.get(): # mosaïque ? + self.lanceTarama() # Faut-il poursuivre ? - + if self.arretApresTapas.get(): # L'utilisateur a demandé l'arrêt - ligne="\nArrêt après Tapas "+heure()+". Lancer MicMac pour reprendre le traitement. \n" - ligne=ligne+"\n\n************* Arrêt aprés Tapas sur demande utilisateur *******************\n\n" + ligne="\n" + _("Arrêt après Tapas ")+heure()+_(". Lancer MicMac pour reprendre le traitement.") + "\n" + ligne=ligne+"\n\-------------- " + _("Arrêt après Tapas sur demande utilisateur") + " --------------\n\n" self.ajoutLigne(ligne) - self.copierParamVersChantier() # sauvegarde du fichier paramètre sous le répertoire du chantier + self.nouveauDepart() # sauvegarde les paramètres, écrit la trace, relance "interface" si on est sous nt + return else: self.suiteMicmac() # PoursSuite : Malt ou C3DC, pouvant être appelé directement - self.nouveauDepart() # lance une fenêtre nouvelle sous windows (l'actuelle peyt-être polluée par le traitement - - def nettoyerChantier(self): # Le chantier est nettoyé : les résulats sous reptravail sont conservés, les arborescences de calcul effacés - self.etatDuChantier = 2 - self.enregistreChantier() - listeAConserver = os.listdir(self.repTravail) - supprimeArborescenceSauf(self.repTravail,listeAConserver) + # Controle si les points homologues définissent plusieurs scènes : si oui : relance un nouveau départ et message. + + def plusieursScenes(self,rep="Homol"): + nbGroupes = self.regroupementSuivantPointsHomologues(rep) + if ( ( nbGroupes>1 and not self.calibSeule.get() )or + ( nbGroupes>1 and self.calibSeule.get() and self.photosPourCalibrationIntrinseque.__len__()==0 ) or + ( nbGroupes>2 and self.calibSeule.get() ) + ) : + message = _("Pourquoi MicMac s'arrête : ") + "\n"+_("Les photos définissent plusieurs scènes disjointes") + "\n\n"+\ + _("MicMac ne peut travailler que sur une seule scène : toutes les photos doivent former une seule scéne.") + "\n"+\ + _("Les photos se répartissent en :") + str(nbGroupes)+_(" groupes distincts (consulter la trace) : ")+"\n" +\ + "\n".join([str(e)[:100] for e in self.lesGroupesDePhotos]) + self.ajoutLigne(message) + self.ajoutLigne("\n"+_("Les groupes de photos séparés : ")+"\n"+"\n".join([str(e) for e in self.lesGroupesDePhotos])) + self.messageNouveauDepart = message + self.nouveauDepart() # lance une fenêtre nouvelle sous windows (l'actuelle peut-être polluée par le traitement) Ecrit la trace + return True - def suiteMicmac(self): - + def suiteMicmac(self): # poursuite après tapas, avec ou sans arrêt après tapas, retour au menu - #on ne peut poursuivre que si il existe un fichier "apericloud.ply", et une image maitresse, 2D ou 3D. + # on ne peut poursuivre que si il existe un fichier "apericloud.ply", et une image maîtresse, 2D ou 3D. if os.path.exists("AperiCloud.ply")==False: - ligne = ("Tapas n'a pas généré de nuage de points.\n"+ - "Le traitement ne peut se poursuivre.\n"+ - "Vérifier la qualité des photos, modifier les paramètres et relancer tapioca-tapas") + ligne = (_("Tapas n'a pas généré de nuage de points.") + "\n"+ + _("Le traitement ne peut se poursuivre.") + "\n"+ + _("Consulter l'aide/quelques conseils.") + "\n"+ + _("Vérifier la qualité des photos, modifier les paramètres et relancer tapioca-tapas")) self.ajoutLigne(ligne) self.encadre(ligne) return - if not(self.existeMasque3D() or self.existeMasque2D()): - ligne = ("Pas de masque, 2D ou 3D, généré pour Malt.\n"+ - "Le traitement ne peut se poursuivre.\n"+ - "Changer le mode 'GeomImage' qui impose un masque\n"+ - "ou définir un masque 2D ou 3D (item option/Malt ou C3DC)\n") - self.ajoutLigne(ligne) + if self.choixDensification.get()=="Malt" and not self.existeMaitre2D(): + ligne = (_("Pas d'image maîtresse pour Malt option geoimage.") + "\n"+ + _("Le traitement ne peut se poursuivre.") + "\n"+ + _("Définir une image maîtresse") +"\n"+ + _("ou Changer le mode 'GeomImage' qui impose une image maîtresse") ) + self.ajoutLigne(ligne) self.encadre(ligne) return - - # calibrage de l'orientation suivant des points GPS, un axe ox, un plan déterminé par un masque + + # calibrage de l'orientation suivant des points GPS (possiblement modifiés après tapas) # si il existe un fichier XML de points d'appuis : self.mesureAppuis if os.path.exists(self.mesureAppuis): self.lanceBascule() - - # malt ou D3CD : suivant que le masque 3 D existe ou pas, avec préférence au masque 3D, - # la production sera "modele3D.ply" + + + # Si un modele3D existe déjà on le renomme pour le conserver (limité à 20 exemplaires !) + + if os.path.exists("modele3D.ply"): + for i in range(1,20): + new = "modele3D_V"+str(i)+".ply" + if not os.path.exists(new): + try: + os.replace(os.path.join(self.repTravail,"modele3D.ply"),os.path.join(self.repTravail,new)) + self.ajoutLigne("\n" + _("Le fichier modele3D.ply précédent est renommé en ")+new+".") + except Exception as e: + print(_("erreur renommage ancien modele_3d en "),new,str(e)) + self.ajoutLigne("\n" + _("Le fichier Modele3D.ply précédent n'a pu être renommé. Il sera remplacé.")) + break + + # malt ou D3CD + # la production sera self.modele3DEnCours - if self.existeMasque3D(): - self.sauveParam() - self.lanceC3DC() # C3DC crée directement le fichier modele3D.ply + if self.choixDensification.get()=="C3DC": + self.lanceC3DC() # C3DC crée directement le fichier self.modele3DEnCours else: self.suiteMicmacMalt() - if self.modeMalt.get()=="GeomImage": - self.lanceNuage2PlyGeom() - if self.modeMalt.get()=="UrbanMNE": - self.lanceNuage2PlyUrban() - if self.modeMalt.get()=="Ortho": - self.lanceNuage2PlyUrban() - # Final : affichage du modele3D.ply, sauvegarde, relance la fenêtre qui a pu être dégradé par le traitement externe + # Final : affichage du self.modele3DEnCours, sauvegarde, relance la fenêtre qui a pu être dégradé par le traitement externe - retour = self.lanceMeshlab() + retour = self.ouvreModele3D() texte = "" if retour == -1 : - texte = "Pas de nuage de points aprés Malt ou C3DC." + texte = _("Pas de nuage de points après Malt ou C3DC.") + self.etatDuChantier = 7 # 7 : chantier terminé sans génération de nuage dense + else: + self.etatDuChantier = 5 # 5 : chantier terminé OK if retour == -2 : - texte = "Programme pour ouvrir les .PLY non trouvé." - ligne = texte + "\n\n************* Fin du traitement MicMac "+heure()+" *******************\n\n" - self.etatDuChantier = 5 # 5 : chantier terminé + texte = _("Programme pour ouvrir les .PLY non trouvé.") + ligne = texte + "\n\n-------------- " + _("Fin du traitement MicMac ")+heure()+" --------------\n\n" self.ajoutLigne(ligne) - + + self.messageNouveauDepart = texte + self.nouveauDepart() # sauvegarde les paramètres, écrit la trace, relance "interface" si on est sous nt (nécessaire : suiteMicmac doit être autonome) + # Que faire après Tapioca et Tapas ? malt ou D3DC def suiteMicmacMalt(self): - if self.etatDuChantier==4: # en principe inutile : toujours vrai ! - if self.avantMalt()!=None: # copie l'image maitresse et le masque, sauve les paramètres - self.messageNouveauDepart = "Pourquoi MicMac est arrêté : \n"+self.avantMalt()+"\n Corriger." - self.ajoutLigne(self.messageNouveauDepart) - self.ecritureTraceMicMac() - return - self.lanceMalt() - else: - self.ajoutLigne("Tapas non effectué, lancer Micmac depuis le menu. Etat du chantier = ",self.etatDuChantier) - + if self.etatDuChantier!=4: # en principe inutile : il faut être juste après tapas (toujours vrai ici) ! + self.ajoutLigne(_("Tapas non effectué, lancer Micmac depuis le menu. Etat du chantier = "),self.etatDuChantier) + return -##############################################################################################################" - - def avantMalt(self): + # il faut une image maîtresse si le mode est geoimage + + if self.listeDesMaitresses.__len__()==0 and self.modeMalt.get()=="GeomImage": # self.photoMaitre : nom de la photo sans extension ni chemin, l'extension est dans self.extensionChoisie + message = ( _("Pourquoi MicMac est arrêté :")+ + "\n" + _("Pas d'image maîtresse.")+ + "\n" + _("Celle-ci est nécessaire pour l'option choisie geomImage de Malt.")+ + "\n" + _("Pour corriger modifier les options de Malt ou choississez un masque 3D avec C3DC.")+ + "\n" + _("Corriger.")) + self.ajoutLigne(message) + self.ecritureTraceMicMac() + self.afficheEtat(message) + return - # initialisation C3DC permet d'utiliser un masque e la photo maitresse pour MALT : il faut une image maitresse si le mode est geoimage + # si le mode est UrbanMne ou Ortho on lance simplement Malt - if self.maitreSansChemin=='' and self.modeMalt.get()=="GeomImage": # self.photoMaitre : nom de la photo sans extension ni chemin, l'extension est dans self.extensionChoisie - return "Pas d'image maîtresse.\nCelle-ci est nécessaire pour l'option choisie geomImage de Malt.\nPour corriger modifier les options de Malt ou choississez un masque 3D avec C3DC." - - # copie du fichier masque, s'il existe, pour accélérer MALT ( MicMac recherche un fichier de nom "fixé", suivant le nom de l'image maitresse - self.nomMaitreSansExtension = os.path.splitext(self.maitreSansChemin)[0] # utile pour nuage2ply - - if os.path.exists(self.masque): - try: shutil.copy(self.masque,self.repTravail) # on copie le masque - except: pass - try: shutil.copy(self.fichierMasqueXML,self.repTravail) # copie du fichier XML Associé au masque - except: pass - self.ajoutLigne("Fichier masque associé à l'image maitresse pour la procédure MALT : \n\n" - +self.masqueSansChemin+"\n\n") # PROBLEME SI L'EXTENSION CHOISIE pour les photos EST TIF - else: - self.ajoutLigne("\nPas de masque associé à l'image maîtresse.\n") - - self.sauveParam() - - + if self.modeMalt.get() in ("UrbanMNE","Ortho"): + self.lanceMalt() + self.lanceTawny() + self.tousLesNuages() + + # création de modele3D.ply (self.modele3DEnCours= dernier ply généré par tousLesNuages) + try: shutil.copy(self.modele3DEnCours,"modele3D.ply") + except Exception as e: self.ajoutLigne(_("Erreur copie modele3D.ply")) + self.modele3DEnCours = "modele3D.ply" # nécessaire pour l'affichage + return + + # si le mode est GeomImage il faut lancer Malt sur chaque Image Maitresse et préparer le résultat + + # Cas GeomImage : il faut traiter toutes les images maitresses : + + if self.modeMalt.get() in ("GeomImage"): + self.nuagesDenses = list() # liste des nuages denses de tous les masques pour fusion en fin de boucle + for e in self.listeDesMaitresses: + self.maitreSansChemin = os.path.basename(e) + self.MasqueXML() # préparation du masque et du maitre + self.lanceMalt() # création du nuage de points + self.tousLesNuages() # création des .ply à tous les niveaux, ajout du plus dense dans la liste + ajout(self.nuagesDenses,self.modele3DEnCours) # le dernier modele3dEncours est le plus dense + + # création de modele3D.ply + self.modele3DEnCours = "modele3D.ply" # nécessaire pour l'affichage + if self.nuagesDenses.__len__()==1: + try: shutil.copy(self.nuagesDenses[0],self.modele3DEnCours) + except Exception as e: print(_("erreur malt GeomImage copy de nuage en modele3D : "),str(e),_(" pour : "),self.nuagesDenses[0]) + else: + try: self.fusionnerPly(self.nuagesDenses,self.modele3DEnCours) + except Exception as e: print(_("erreur malt GeomImage fusion des nuages en modele3D : "),str(e),_(" pour : "),"\n".join(self.nuagesDenses[0])) + + # Cas AperoDeDenis : on construit la liste des images maitresses et des images associées + + if self.modeMalt.get() in ("AperoDeDenis"): + self.nuagesDenses = list() # liste des nuages denses de tous les masques pour fusion en fin de boucle + self.maltApero() # Construit la liste self.maitressesEtPhotoApero [(maitresse,photo),...] + for e,f in self.maitressesEtPhotoApero: + self.maitreSansChemin = e + self.photosApero = [f,e] # pour l'instant une seule photo + self.MasqueXML() # les masques sont saisis avec l'option GeomImage et le nom de l'image maitresse + self.lanceMalt() # création du nuage de points + self.tousLesNuages() # création des .ply à tous les niveaux, ajout du plus dense dans la liste + ajout(self.nuagesDenses,self.modele3DEnCours) # le dernier modele3dEncours est le plus dense + + # création de modele3D.ply + self.modele3DEnCours = "modele3D.ply" # nécessaire pour l'affichage + if self.nuagesDenses.__len__()==1: + try: shutil.copy(self.nuagesDenses[0],self.modele3DEnCours) + except Exception as e: print(_("erreur malt AperoDeDenis copy de nuage en modele3D : "),str(e),_(" pour : "),self.nuagesDenses[0]) + else: + try: self.fusionnerPly(self.nuagesDenses,self.modele3DEnCours) + except Exception as e: print(_("erreur malt AperoDeDenis fusion des nuages en modele3D : "),str(e),_(" pour : "),"\n".join(self.nuagesDenses[0])) + ################################## LES DIFFENTES PROCEDURES MICMAC ########################################################### # ------------------ PREAMBULE -------------------- @@ -3205,30 +5447,24 @@ def avantScene(self): # vérification nécessaires : if len(self.photosAvecChemin)==0: # photos sans chemin - texte='Aucune photo choisie. Abandon.' + texte=_('Aucune photo choisie. Abandon.') return texte if len(self.photosAvecChemin)==1: # photos sans chemin - texte='Une seule photo choisie. Abandon.' - return texte - - # si pas de chemin pour micmac on le demande : - - if not(os.path.exists(self.mm3d)): - texte='mm3d non trouvé : \n'+self.mm3d+'\nVeuillez indiquer le répertoire \\bin de MicMac (menu paramètres)' + texte=_('Une seule photo choisie. Abandon.') return texte - - if self.controleOptions()!=True: - return "\nOption incorrecte :\n"+str(self.controleOptions()) + retour = self.controleOptions() + if retour!=True: + return "\n" + _("Option incorrecte :") + "\n"+str(retour) - self.lignePourTrace = "****************************** TRACE DETAILLEE ****************************\n" # première ligne de la trace détaillée - self.ligneFiltre = "****************************** TRACE SYNTHETIQUE ****************************\n" # première ligne de la trace synthétique + self.lignePourTrace = ("-------------- " + _("TRACE DETAILLEE") + " **--------------\n") # première ligne de la trace détaillée + self.ligneFiltre = ("-------------- " + _("TRACE SYNTHETIQUE") + " --------------\n") # première ligne de la trace synthétique - texte='------------------------- DEBUT DU TRAITEMENT MICMAC ---- '+heure()+' ----------------------------------------\n\n\n' + texte = "-------------- " + _("DEBUT DU TRAITEMENT MICMAC à ")+ heure()+" -------------- \n\n" - photosPropres=list([os.path.basename(x) for x in self.photosPropresAvecChemin]) - texte = texte+'Photos choisies : \n\n'+'\n'.join(photosPropres)+'\n\n' - texte = texte+"Ces photos sont recopiées dans le répertoire du chantier : \n\n"+self.repTravail+'\n\n' + photosPropres=list([os.path.basename(x) for x in self.photosAvecChemin]) + texte = texte+_('Photos choisies :') + " \n\n"+'\n'.join(photosPropres)+'\n\n' + texte = texte+_("Ces photos sont recopiées dans le répertoire du chantier :") + "\n\n"+self.repTravail+'\n\n' self.ajoutLigne(texte) @@ -3238,7 +5474,7 @@ def avantScene(self): def lanceTapioca(self): - self.etape = 0 + self.etapeTapioca = 0 if self.modeTapioca.get()=="All": self.echelle1PourMessage = self.echelle1.get() tapioca = [self.mm3d, @@ -3246,7 +5482,7 @@ def lanceTapioca(self): self.modeTapioca.get(), '.*'+self.extensionChoisie, self.echelle1.get(), - "ExpTxt=0"] + "ExpTxt="+self.exptxt] if self.modeTapioca.get()=="MulScale": self.echelle1PourMessage = self.echelle2.get() @@ -3257,7 +5493,7 @@ def lanceTapioca(self): '.*'+self.extensionChoisie, self.echelle2.get(), self.echelle3.get(), - "ExpTxt=0"] + "ExpTxt="+self.exptxt] if self.modeTapioca.get()=="Line": self.echelle1PourMessage = self.echelle4.get() @@ -3267,13 +5503,14 @@ def lanceTapioca(self): '.*'+self.extensionChoisie, self.echelle4.get(), self.delta.get(), - "ExpTxt=0"] + "ExpTxt="+self.exptxt] self.lanceCommande(tapioca, - self.filtreTapioca) + filtre=self.filtreTapioca) def filtreTapioca(self,ligne): - + try: self.exe.terminate() + except Exception as e : print("erreur self.exe.terminate=",str(e)) if ligne[0]=="|": return ligne if 'points' in ligne and len(ligne)<=15: @@ -3282,40 +5519,140 @@ def filtreTapioca(self,ligne): return ligne if 'matches' in ligne: return ligne - if 'utopano' in ligne and self.etape==0: # début de la première étape sur la première échelle - self.etape+=1 - return heure()+"Recherche des points remarquables et des correspondances sur une image de taille "+self.echelle1PourMessage+" pixels.\n\n" - if 'utopano' in ligne and self.etape==1: # début de la seconde étape sur la seconde échelle - self.etape+=1 + if 'utopano' in ligne and self.etapeTapioca==0: # début de la première étape sur la première échelle + self.etapeTapioca += 1 + return heure()+" : " + _("Recherche des points remarquables et des correspondances sur une image de taille %s pixels.") % (self.echelle1PourMessage)+ "\n\n" + if 'utopano' in ligne and self.etapeTapioca==1: # début de la seconde étape sur la seconde échelle + self.etapeTapioca += 1 + if self.plusieursScenes("Homol_SRes"): + if self.systeme=="posix": + try: + os.killpg(os.getpgid(self.exe.pid), signal.SIGTERM) + self.nePasLancerTapas = True + except Exception as e: print("erreur killpg : ",str(e)) + if self.systeme=="nt": +# subprocess.Popen("TASKKILL /F /PID {pid} /T".format(pid=self.exe.pid)) # https://stackoverflow.com/questions/4789837/how-to-terminate-a-python-subprocess-launched-with-shell-true/4791612#4791612 + subprocess.Popen("TASKKILL /F /im mm3d.exe") # https://lecrabeinfo.net/tuer-processus-ligne-de-commande-cmd-windows.html + self.nePasLancerTapas = True + return heure()+"\n"+_("Plusieurs scènes : abandon après l'étape 1 de Tapioca")+"\n" if self.echelle2PourMessage=="-1": - return "\nRecherche des points remarquables et des correspondances sur l'image entière.\n\n" + return "\n" + heure()+" : " +_("Recherche des points remarquables et des correspondances sur l'image entière.") + "\n\n" if self.echelle2PourMessage!="": - return "\nRecherche des points remarquables et des correspondances sur une image de taille "+self.echelle2PourMessage+" pixels.\n\n" + return "\n" + heure()+" : " +_("Recherche des points remarquables et des correspondances sur une image de taille %s pixels.") % (self.echelle2PourMessage) + "\n\n" return ligne - - # ------------------ TAPAS ----------------------- + if 'MAXLINELENGTH' in ligne: + return "\n"+ligne+"\n"+_("Trop de photos pour Windows. Une idée : Utiliser Linux.") + # ------------------ TAPAS ----------------------- Avec ou sans calibrationj intrinsèque def lanceTapas(self): - tapas = [self.mm3d, - "Tapas", - self.modeCheckedTapas.get(), - '.*'+self.extensionChoisie, - 'Out=Arbitrary', - 'ExpTxt=0'] - self.lanceCommande(tapas, - self.filtreTapas, - "Calibration, pour trouver les réglages intrinsèques de l'appareil photo\nRecherche d'un point de convergence au centre de l'image.\n\n" ) + self.messageRetourTapas = str() + if self.photosPourCalibrationIntrinseque.__len__()>0: # s'il y a des photos pour calibration intrinsèque + self.photosCalibrationSansChemin = [os.path.basename(f) for f in self.photosPourCalibrationIntrinseque] + if self.photosCalibrationSansChemin.__len__()==1: + self.messageRetourTapas = _("Une seule photo pour un appareil pour la calibration intrinsèque : insuffisant.") + "\n" + self.ajoutLigne(self.messageRetourTapas) + return + + # limitation aux seules images pour la calibration par suppression de l'extension des photos ne servant pas à calibrer : + # mais rename peut planter si un fichier est ouvert par ailleurs + [os.rename(e,os.path.splitext(e)[0]) for e in self.photosSansChemin if e not in self.photosCalibrationSansChemin] + tapas = [self.mm3d, + "Tapas", + self.modeCheckedTapas.get(), + '.*'+self.extensionChoisie, + "ForCalib=1", + "SauvAutom=NONE", + "Out=Calib", + "ExpTxt="+self.exptxt] + self.lanceCommande(tapas, + filtre=self.filtreCalib, + info=_("Calibration intrinsèque, pour trouver les réglages de l'appareil photo sur quelques photos") + + "\n" + _("Recherche des paramètres optiques des appareils sur les photos :\n") + + "\n".join(self.photosCalibrationSansChemin)+ + "\n\n") + + # Remise en état initial des photos pour calibration (mais rename peut planter...) + + [os.rename(os.path.splitext(e)[0],e) for e in self.photosSansChemin if e not in self.photosCalibrationSansChemin] + + if os.path.isdir("Ori-Calib")==False: + self.messageRetourTapas = _("La calibration intrinsèque n'a pas permis de trouver une orientation.") + "\n" + self.ajoutLigne(self.messageRetourTapas) + self.ajoutLigne(_("Calibration intrinsèque effectuée mais pas d'orientation trouvée.")) + return + + if self.photosSansChemin.__len__()-self.photosCalibrationSansChemin.__len__()<2 and self.calibSeule.get(): + self.messageRetourTapas = _("Moins de 2 photos pour Tapas (sans les photos de calibration) : insuffisant.") + "\n" + self.ajoutLigne(self.messageRetourTapas) + return + + self.ajoutLigne(_("Calibration intrinsèque effectuée.")) + + ##################################################### + + # exclusion des images pour la calibration si elles ne servent plus après : + + if self.calibSeule.get(): + try : os.mkdir(self.repCalibSeule) + except: pass + [os.rename(e,os.path.join(self.repCalibSeule,e)) for e in self.photosCalibrationSansChemin] # déplacer photocalibration pour les traitements suivant + self.photosAvecChemin = [f for f in self.photosAvecChemin if os.path.basename(f) not in self.photosCalibrationSansChemin] + self.photosSansChemin = [os.path.basename(g) for g in self.photosAvecChemin] + self.photosPourCalibrationIntrinseque = [os.path.join(self.repTravail,self.repCalibSeule,e) for e in self.photosCalibrationSansChemin] + listePhotos = _('Photos retenues pour calibrer les appareils :') + " \n\n"+'\n'.join(self.photosSansChemin)+'\n\n' + self.ajoutLigne(listePhotos) + + # lancement de Tapas en autocalibration : FIgee (ou AutoCal mais la calibration initiale se perd peu à peu) + + tapas = [self.mm3d, + "Tapas", + "Figee", #fige la calibration fixée, sinon "AutoCal" la prend en compte mais la modifie + '.*'+self.extensionChoisie, + 'InCal=Calib', + 'Out=Arbitrary', + "SauvAutom=NONE", + "ExpTxt="+self.exptxt] + self.lanceCommande(tapas, + filtre=self.filtreTapas, + info=_("Recherche l'orientation des prises de vues") + "\n\n") + + # lance Tapas sans calibration préalable : + + else: + + tapas = [self.mm3d, + "Tapas", + self.modeCheckedTapas.get(), + '.*'+self.extensionChoisie, + 'Out=Arbitrary', + "SauvAutom=NONE", + "ExpTxt="+self.exptxt] + self.lanceCommande(tapas, + filtre=self.filtreTapas, + info=_("Calibration, pour trouver les réglages intrinsèques de l'appareil photo") + "\n" + _("Recherche l'orientation des prises de vue.") + "\n\n" ) + + if os.path.isdir("Ori-Arbitrary")==False: + self.messageRetourTapas = _("Tapas n'a pu trouver d'orientation pour les prises de vue.") + def filtreTapas(self,ligne): - if 'RESIDU LIAISON MOYENS' in ligne: - self.nbResiduTapas = 1 + if ('RESIDU LIAISON MOYENS' in ligne) or ('Residual' in ligne) : # Residual pour la version 5999 return ligne if ligne[0]=="|": return ligne return - # ------------------ APERO + def filtreCalib(self,ligne): + if ligne[0:3]=="---": + return ligne + return + + def verifiePresence2PhotosCalibParAppareil(self): + return + + + # ------------------ APERO : orientation par axe, plan et métrique, le nom de l'orientation est "echelle3" (attention : polysème) def lanceApero(self): @@ -3323,28 +5660,33 @@ def lanceApero(self): "Apero", os.path.basename(self.miseAEchelle)] self.lanceCommande(apero, - info="Fixe l'orientation (axe et plan) et met à l'échelle en fonction des options 'calibration'") + info=_("Fixe l'orientation (axe,plan et métrique) suivant les options de 'calibration'")) - # ------------------ APERICLOUD ----------------------- + # ------------------ APERICLOUD : ----------------------- + # l'orientation en entrée est soit : + # - Arbitrary (pas de calibration) + # - echelle3 (calibration par axe plan et métrique + # - bascul (calibration par points gps) def lanceApericloud(self): + apericloud=[self.mm3d, "AperiCloud", '.*'+self.extensionChoisie, self.orientation(), - "Out=AperiCloud.ply", - "ExpTxt=0"] + "Out=AperiCloud.ply", # c'est d'ailleurs la valeur par défaut pour AperiCloud + "ExpTxt="+self.exptxt] self.lanceCommande(apericloud, - self.filtreApericloud, - "Positionne les appareils photos autour du sujet.\n\Création d'un nuage de points grossier.") - + filtre=self.filtreApericloud, + info=_("Positionne les appareils photos autour du sujet.") + "\n" + _("Création d'un nuage de points grossier.")) + def filtreApericloud(self,ligne): if ligne[0]=="|": return ligne if "cMetaDataPhoto" in ligne: - print("ligne avec meta : ",ligne) - return "\n#### ATTENTION : Des Metadonnées nécessaires sont absentes des photos. Vérifier l'exif.\n\n" + print(_("ligne avec meta : "),ligne) + return "\n####" + _("ATTENTION : des metadonnées nécessaires sont absentes des photos. Vérifier l'exif.") + "\n\n" # ------------------ Meslab 1 : ouvre AperiCloud.ply avec l'outil choisi par l'utilisateur -------------------------- @@ -3355,215 +5697,441 @@ def lanceApericloudMeshlab(self): # ouvre le ply créé pa open_file('AperiCloud.ply') return self.lanceCommande([self.meshlab,'AperiCloud.ply'], - info="Ouverture du nuage de points après Apericloud", + info=_("Ouverture du nuage de points après Apericloud"), attendre=False) else: - texte="\nPas de fichier AperiCloud.ply généré.\n" + texte="\n" + _("Pas de fichier AperiCloud.ply généré.") + "\n" self.ajoutLigne(texte) - self.messageNouveauDepart = texte+"Consulter la trace.\n" + self.messageNouveauDepart = texte+_("Consulter l'aide (quelques conseils),\nConsulter la trace.") + "\n" return -1 + # ------------------ Tarama----------------------- crée TA_LeChantier.tif sous le répertoire TA + + def lanceTarama(self): + self.ajoutLigne("\n\n---------------------------\n" + _("Tarama : mosaïque des photos d'après les tie points") + "\n") + tarama = [ self.mm3d, + "Tarama", + '.*'+self.extensionChoisie, + "Arbitrary"] + self.lanceCommande(tarama) + + # ------------------ GCPBascule : utilise les points GPS----------------------- + + def lanceBascule(self): # une alternative est Campari - def lanceBascule(self): + self.ajoutLigne("\n\n---------------------------\n" + _("Prise en compte des points GPS : nécessite au minimum 3 points, chacun sur 2 photos") + "\n") + if len(self.dicoPointsGPSEnPlace)<6: + self.ajoutLigne("\n" + _("Le nombre minimum de points placés sur les photos n'est pas atteint. Abandon.") + "\n") + return GCPBascule = [ self.mm3d, "GCPBascule", '.*'+self.extensionChoisie, - self.orientation(), - "bascul", + "Arbitrary", # orientation obtenue après tapas, nuage non densifié + "bascul", # Orientation calibrée par les points GPS, utilisé par Malt ou C3DC os.path.basename(self.dicoAppuis), os.path.basename(self.mesureAppuis)] - self.lanceCommande(GCPBascule) + self.lanceCommande(GCPBascule, + filtre=self.filtreGCPBascule) + + # essai systématique de lancement de campari + self.lanceCampari() + + def filtreGCPBascule(self,ligne): + if "MAX" in ligne: # dans la version xxxx il y a ERRROR ! + return ligne + if "||" in ligne: + return ligne - + # ------------------ CAMPARI : correction après BASCULE (voir mail de Marc le ----------------------- + + def lanceCampari(self): # campari après bascule + try: + float(self.incertitudeCibleGPS.get()) + float(self.incertitudePixelImage.get()) + except Exception as e: + self.ajoutLigne("\n" + _("Campari non lancé : paramètres incorrects : ") + "\n"+ + "incertitude sur cible gps : "+self.incertitudeCibleGPS.get() + "\n"+ + "incertitude sur pixel image : "+self.incertitudePixelImage.get() + "\n"+ + str(e)) + return + if not os.path.exists(os.path.join(self.repTravail,"Ori-bascul")): # orientation obtenue après Tapas et GCPbascule (points GPS OK) + self.ajoutLigne("\n" + _("Campari non lancé : pas d'orientation 'bascul'") + "\n") + return + + self.ajoutLigne("\n\n---------------------------\n" + _("Campari : correction points GPS") + "\n") + # Campari "MyDir\IMG_.*.jpg" OriIn OriOut GCP=[GroundMeasures.xml,0.1,ImgMeasures.xml,0.5] + campari = [ self.mm3d, + "campari", + '.*'+self.extensionChoisie, + "bascul", # orientation obtenue après tapas, nuage non densifié + "campari", # Orientation calibrée par les points GPS, utilisé par Malt ou C3DC + "GCP=["+os.path.basename(self.dicoAppuis)+","+self.incertitudeCibleGPS.get()+","+os.path.basename(self.mesureAppuis)+","+self.incertitudePixelImage.get()+"]"] + self.lanceCommande(campari, + filtre=self.filtreCampari) + + def filtreCampari(self,ligne): + return # pas d'intérêt ? + # ------------------ MALT ----------------------- - def lanceMalt(self): - malt = [self.mm3d, - "Malt", - self.modeMalt.get(), - ".*"+self.extensionChoisie, - self.orientation(), - "Master="+self.maitreSansChemin] + def lanceMalt(self): # malt prend les points homologues dans le répertoire "Homol", + # et si geoImage : l'image maîtresse dans self.maitreSansChemin (str() si absent) + # et dans self.photosSansChemin les images autour de l'image maitressse + # si il y a un masque il faut les 2 fichiers maitre_Masq.xml et maitre_Masq.tif sans les indiquer dans la syntaxe + + self.ajoutLigne("\n\n---------------------------\n" + _("Préparation du lancement de Malt") + "\n") + aConserver = str() + if self.modeMalt.get()=="GeomImage": + # Les N meilleurs fichiers en correspondances avec la maitresse + aConserver = self.meilleuresPhotosAutourMaitresse(self.maitreSansChemin,self.photosUtilesAutourDuMaitre.get()) + # on renomme les autres + if aConserver: + [os.rename(e,os.path.splitext(e)[0]) for e in self.photosSansChemin if e not in aConserver] + self.ajoutLigne("\n\n"+_("Photos utiles pour malt GeomImage : ")+aConserver+"\n") + else: + self.ajoutLigne("\n\n"+_("Malt sur toutes les photos")) + malt = [self.mm3d, + "Malt", + self.modeMalt.get(), + ".*"+self.extensionChoisie, # les n meilleures photos en correspondance, les autres étant renommées + self.orientation(), + "NbVI=2", + "ZoomF="+self.zoomF.get(), + "Master="+self.maitreSansChemin] + elif self.modeMalt.get()=="AperoDeDenis": + # Les N fichiers en correspondances avec la maitresse sont dans la variable self.photosApero + [os.rename(e,os.path.splitext(e)[0]) for e in self.photosSansChemin if e not in self.photosApero] + self.ajoutLigne("\n\n"+_("Photos utiles pour malt AperoDeDenis : ")+str(self.photosApero)+"\n") + malt = [self.mm3d, + "Malt", + "GeomImage", + ".*"+self.extensionChoisie, # les n meilleures photos en correspondance, les autres étant renommées + self.orientation(), + "NbVI=2", + "ZoomF="+self.zoomF.get(), + "Master="+self.maitreSansChemin] + elif self.modeMalt.get()=="Ortho": + if os.path.exists(self.masqueTarama): + self.ajoutLigne("\n\n"+_("Mosaique et masque: ")+str(self.mosaiqueTaramaTIF)+"\n") + else: + self.ajoutLigne("\n\n"+_("Mosaique seule : ")+str(self.mosaiqueTaramaTIF)+"\n") + malt = [self.mm3d, + "Malt", + "Ortho", + ".*"+self.extensionChoisie, # les n meilleures photos en correspondance, les autres étant renommées + self.orientation(), + "NbVI=2", + "ZoomF="+self.zoomF.get(), + 'DirTA=TA'] + + else: + malt = [self.mm3d, + "Malt", + self.modeMalt.get(), + ".*"+self.extensionChoisie, + self.orientation(), + "NbVI=2", + "ZoomF="+self.zoomF.get()] # zoom 8,4,2,1 qui correspondent au nuage étape 5, 6, 7, 8 + self.lanceCommande(malt, - self.filtreMalt, - "ATTENTION : cette procédure est longue : patience !") - + filtre=self.filtreMalt, + info=_("ATTENTION : cette procédure est longue : patience !")) + + if aConserver or self.modeMalt.get()=="AperoDeDenis": # on renomme correctement les fichiers abandonnés pour le traitement de malt + [os.rename(os.path.splitext(e)[0],e) for e in self.photosSansChemin if (os.path.exists(os.path.splitext(e)[0]) and not (os.path.exists(e)))] + + def filtreMalt(self,ligne): if ligne[0]=="|": return ligne if 'BEGIN BLOC' in ligne: return ligne + + def reinitialiseMaitreEtMasque(self): # on conserve si la photo appartient au nouveau lot + self.masqueSansChemin = str() # image masque : en TIF, choisi par l'utilisateur + self.maitre = str() + self.maitreSansChemin = str() # image maîtresse + self.fichierMasqueXML = str() # nom du fichier XML décrivant le masque + self.maitreSansExtension = str() + self.monImage_MaitrePlan = str() # Nom de l'image maîtresse du plan repere (sans extension) + self.monImage_PlanTif = str() # nom du masque correspondant + self.listeDesMaitresses = list() # liste des images maitresses + self.listeDesMasques = list() # liste Des Masques associès aux maîtresses + self.listeDesMaitresses = list() + self.listeDesMasques = list() + self.miseAJourItem701_703() # met à jour les windgets de l'onglet Malt + + def reinitialiseMaitreEtMasqueDisparus(self): # on conserve les options si la photo appartient au nouveau lot (photos = liste avec chemins) + + self.masqueSansChemin = str() # image masque : en TIF, choisi par l'utilisateur + self.maitre = str() + self.maitreSansChemin = str() # image maîtresse + self.fichierMasqueXML = str() # nom du fichier XML décrivant le masque + self.maitreSansExtension = str() + + # les axes horizontal et vertical conservé si les photos sont présentes ainsi que les maitresses et les masques et le plan et la distance + photos = self.photosAvecChemin + + # Ligne horizontale ou verticale + # axe horizontal, dans le dico : self.dicoLigneHorizontale. key = nom point, photo, identifiant ;Retrouver nom de la photo, coordonnées des points + # items = liste de tuple (key,values) soit tuple = (point,photo, id),(x1,y1) + + if self.dicoLigneHorizontale.__len__()>0: + photosAvecLigneH = [e[1] for e in self.dicoLigneHorizontale.keys()][0] + + if photosAvecLigneH not in photos: + self.dicoLigneHorizontale = dict() + + if self.dicoLigneVerticale.__len__()>0: + photosAvecLigneV = [e[1] for e in self.dicoLigneVerticale.keys()][0] + if photosAvecLigneV not in photos: + self.dicoLigneVerticale = dict() + + # maitre plan et image + + if self.monImage_MaitrePlan not in photos: + self.monImage_MaitrePlan = str() # Nom de l'image maîtresse du plan repere (sans extension) + self.monImage_PlanTif = str() # nom du masque correspondant + + # Distance + # dicoCalibre key = nom point, photo, identifiant, value = x,y + + if self.dicoCalibre.__len__()>0: + photosAvecDistance = set([(e[1],e) for e in self.dicoCalibre.keys()]) # ensemble des clés et des noms de fichiers + for photo,key in photosAvecDistance: + if not os.path.exists(photo): + del self.dicoCalibre[key] + + + #Points GPS + # dicoPointsGPSEnPlace key = nom point, photo, identifiant, value = x,y + # Suppression des points GPS placés sur des photos non choisies dans le nouveau choix + # l'utilisateur a été prévenu + + if self.dicoPointsGPSEnPlace.__len__()>0: + photosAvecPointsGPS = set([e[1] for e in self.dicoPointsGPSEnPlace.keys()]) + for e in photosAvecPointsGPS: + if e not in photos: + copieDico = dict(self.dicoPointsGPSEnPlace) + for f in copieDico.keys(): + if f[1]==e: + del self.dicoPointsGPSEnPlace[f] + + + # masques et maitresses + + self.listeDesMaitresses = [e for e in self.listeDesMaitresses if e in photos] # liste des images maitresses + self.listeDesMasques = [e for e in self.listeDesMasques if e.replace('_masque.tif',self.extensionChoisie) in photos] # liste Des Masques associès aux maîtresses + + + # suppression du masque 3 d (qui dépend de apericloud.ply) + + supprimeFichier(self.masque3DSansChemin) + supprimeFichier(self.masque3DBisSansChemin) + + # reconstitution des xml + + self.finOptionsOK () # mise à jours des fichiers xml liès aux options + self.miseAJourItem701_703() # met à jour les windgets de l'onglet Malt + + # ------------------ Tawny : après Malt, si self.modeMalt.get() = Ortho et self.tawny.get() = Vrai ----------------------- + + def lanceTawny(self): + + if self.modeMalt.get() != "Ortho": + return + if not self.tawny.get(): + return + '''Tawny -help + ***************************** + * Help for Elise Arg main * + ***************************** + Unnamed args : + * string :: {Directory where are the datas} + Named args : + * [Name=DEq] INT :: {Degree of equalization (Def=1)} + * [Name=DEqXY] Pt2di :: {Degree of equalization, if diff in X and Y} + * [Name=AddCste] bool :: {Add unknown constant for equalization (Def=false)} + * [Name=DegRap] INT :: {Degree of rappel to initial values, Def = 0} + * [Name=DegRapXY] Pt2di :: {Degree of rappel to initial values, Def = 0} + * [Name=RGP] bool :: {Rappel glob on physically equalized, Def = true} + * [Name=DynG] REAL :: {Global Dynamic (to correct saturation problems)} + * [Name=ImPrio] string :: {Pattern of image with high prio, def=.*} + * [Name=SzV] INT :: {Sz of Window for equalization (Def=1, means 3x3)} + * [Name=CorThr] REAL :: {Threshold of correlation to validate''' + tawny = [self.mm3d, + "Tawny", + "Ortho-MEC-Malt/", + self.tawnyParam.get(), + "Out="+self.orthoMosaiqueTawny] + self.lanceCommande(tawny, + filtre=self.filtreTawny, + info=_("lance Tawny")) + + def filtreTawny(self,ligne): + if "Don't understand" in ligne: + return ligne + if "FATAL ERROR" in ligne: + return ligne+_(" : voir la trace complète.") + if "KBOX" in ligne: + return ligne # ------------------ C3DC : alternative à Malt avec un masque 3D ----------------------- def lanceC3DC(self): # Si on a un masque 3D on l'utilise et on ne cherche pas plus loin : - C3DC = [self.mm3d, - "C3DC", - "MicMac", - ".*"+self.extensionChoisie, - self.orientation(), - "Masq3D="+self.masque3DSansChemin, - "Out=modele3D.ply"] + if self.existeMasque3D(): + C3DC = [self.mm3d, + "C3DC", + self.modeC3DC.get(), + ".*"+self.extensionChoisie, + self.orientation(), + "Masq3D="+self.masque3DSansChemin, + "Out="+self.modele3DEnCours] + else: + C3DC = [self.mm3d, + "C3DC", + self.modeC3DC.get(), + ".*"+self.extensionChoisie, + self.orientation(), + "Out="+self.modele3DEnCours] + self.lanceCommande(C3DC, - self.filtreC3DC, - "ATTENTION : cette procédure est longue : patience !") + filtre=self.filtreC3DC, + info=_("ATTENTION : cette procédure est longue : patience !")) def filtreC3DC(self,ligne): if ligne[0]=="|": return ligne + if "long" in ligne: + return ligne if 'BEGIN BLOC' in ligne: return ligne + + # ------------------ NUAGE2PLY ----------------------- - # exemple après GeomImage : C:\MicMac64bits\bin\nuage2ply.exe MM-Malt-Img-P1000556\NuageImProf_STD-MALT_Etape_8.xml Attr=P1000556.JPG Out=modele3D.ply - def lanceNuage2PlyGeom(self): + + # exemple après GeomImage : C:\MicMac64bits\bin\nuage2ply.exe MM-Malt-Img-P1000556\NuageImProf_STD-MALT_Etape_8.xml Attr=P1000556.JPG Out=self.modele3DEnCours + # passe d'un nuage (fichier xml pour une maitresse si geomimage) à un ply, Attr = fichier de drapage. + def tousLesNuages(self): #le zoom est dans self.zoomF.get() et l'étape dans self.etapeNuage : ils sont corrélés comme suit + + # étapes = 1,2,3,4,5,6,7,8 zoom = 128,64,32,16,8,4,2,1 + # zoom : 1,2,4,8,16,32,64,128 étapes = 8,7,6,5,4,3,2,1 + + sauveEtapeNuage = self.etapeNuage + listeModeles = list() + for zoom in [[str(8-j),str(pow(2,j))] for j in range(8-int(self.etapeNuage),8)]: + self.maitreSansExtension = os.path.splitext(self.maitreSansChemin)[0] + + for zoom in [[str(j),str(pow(2,8-j))] for j in range(1,int(sauveEtapeNuage)+1)]: + self.modele3DEnCours = "modele3D_"+self.maitreSansExtension+"_Zoom_"+zoom[1]+".ply" + listeModeles.insert(0,self.modele3DEnCours) # liste triée des modèles, le plus précis en tête + self.etapeNuage = zoom[0] + self.zoomNuage = zoom[1] + self.lanceNuage2Ply() + + self.etapeNuage = sauveEtapeNuage + + # dernier modele ayant été créé : + for e in listeModeles: + if os.path.exists(e): + self.modele3DEnCours = e + return + + + def lanceNuage2Ply(self): # nuage2Ply avec un paramètre : self.etapeNuage, et crée le fichier ply : self.modele3DEnCours + if self.modeMalt.get() in ("GeomImage","AperoDeDenis"): + self.lanceNuage2PlyGeom() + if self.modeMalt.get() in ("UrbanMNE"): + self.lanceNuage2PlyUrban() + if self.modeMalt.get() in ("Ortho"): + self.lanceNuage2PlyOrtho() + + def lanceNuage2PlyGeom(self): + arg1 = 'MM-Malt-Img-'+self.maitreSansExtension+'/NuageImProf_STD-MALT_Etape_'+self.etapeNuage+'.xml' + if os.path.exists(arg1)==False: + return Nuage2Ply = [self.mm3d, "Nuage2Ply", - 'MM-Malt-Img-'+self.nomMaitreSansExtension+'/NuageImProf_STD-MALT_Etape_8.xml', + arg1, 'Attr='+self.maitreSansChemin, - 'Out=modele3D.ply'] + 'Out='+self.modele3DEnCours] self.lanceCommande(Nuage2Ply) - # exemple aprés UrbanMNE : mm3d Nuage2Ply "MEC-Malt/NuageImProf_STD-MALT_Etape_8.xml" Scale=8 Attr="MEC-Malt/Z_Num8_DeZoom1_STD-MALT.tif" Out="modele3D.ply" + # exemple après UrbanMNE : mm3d Nuage2Ply "MEC-Malt/NuageImProf_STD-MALT_Etape_8.xml" Scale=8 Attr="MEC-Malt/Z_Num8_DeZoom1_STD-MALT.tif" Out="self.modele3DEnCours" + # si tawny : ajouter l'attribut : def lanceNuage2PlyUrban(self): - Nuage2Ply = [self.mm3d, + if int(self.zoomNuage)>32: # le mode UrbanMNE ne génère apparemment des nuages que pour les zoom de 32 à 1, soit les étapes 3 à 8 + return + arg1 = "MEC-Malt/NuageImProf_STD-MALT_Etape_"+self.etapeNuage+".xml" + if os.path.exists(arg1)==False: + return + + Nuage2Ply = [self.mm3d, "Nuage2Ply", - "MEC-Malt/NuageImProf_STD-MALT_Etape_8.xml", - "Scale=8", - "Attr=MEC-Malt/Z_Num8_DeZoom1_STD-MALT.tif", - 'Out=modele3D.ply'] - self.lanceCommande(Nuage2Ply) - + arg1, + 'Out='+self.modele3DEnCours] + self.lanceCommande(Nuage2Ply) + + def lanceNuage2PlyOrtho(self): + + arg1 = "MEC-Malt/NuageImProf_STD-MALT_Etape_"+self.etapeNuage+".xml" + if os.path.exists(arg1)==False: + return + orthoMosaique = os.path.join(self.repTravail,"Ortho-MEC-Malt",self.orthoMosaiqueTawny) # Orthophotomosaic.tif sous le répertoire "Ortho-MEC-Malt/" + if os.path.exists(orthoMosaique): + Nuage2Ply = [self.mm3d, + "Nuage2Ply", + arg1, + "Attr="+orthoMosaique, # pour draper le ply (l'ortho est créée par Tawny) + 'Out='+self.modele3DEnCours] + else: + Nuage2Ply = [self.mm3d, + "Nuage2Ply", + arg1, + 'Out='+self.modele3DEnCours] + self.lanceCommande(Nuage2Ply) + # ------------------ Meslab 2 -------------------------- - def lanceMeshlab(self): - aOuvrir = os.path.join(self.repTravail,"modele3D.ply") + def ouvreModele3D(self): + + aOuvrir = os.path.join(self.repTravail,self.modele3DEnCours) if not os.path.exists(aOuvrir): - texte="Pas de fichier modele3D.ply généré.\n\nEchec du traitement MICMAC" + texte=_("Pas de fichier %s généré.") % (self.modele3DEnCours)+ "\n\n" + _("Echec du traitement MICMAC") self.ajoutLigne(texte) return -1 if not os.path.exists(self.meshlab): - open_file('AperiCloud.ply') + open_file(self.modele3DEnCours) return meshlab = [self.meshlab, aOuvrir] self.lanceCommande(meshlab, - info="Nuage de points modele3D.ply généré.", + info=_("Nuage de points %s généré.") % (self.modele3DEnCours), attendre=False) - ################################## UTILITAIRES MICMAC ########################################################### - - def OutilQualitePhotosLine(self): - - if self.pasDePhoto():return - - # on copie les photos dans un répertoire de test - - self.copieDansRepertoireDeTest() - - self.encadre("Détermine un indice de qualité des photos en mode 'line'\n\n"+ - "Le résultat sera inscrit dans le fichier trace synthétique\n\nPatience...",nouveauDepart='non') - - self.ajoutLigne(heure()+"Debut de la recherche sur la qualité des photos mode 'Line'.") - self.qualiteTrouvee = list() - qualite = [self.mm3d, - "Tapioca", - "Line", - ".*"+self.extensionChoisie, #'"'+str(self.repTravail+os.sep+".*"+self.extensionChoisie)+'"', - "1000", - "1"] - - - self.lanceCommande(qualite, - self.filtreQualite) - - # analyse des résultats : - os.chdir(self.repTravail) - self.analyseQualitePhotos() - - self.ajoutLigne("\n"+heure()+" : Fin de la recherche sur la qualité des photos mode 'Line'.") - self.ajoutLigne("\n\n ******") - ligneFiltre = self.ligneFiltre #l'écriture de la trace efface self.ligneFiltre et encadre doit être en fin de paragraphe - self.ecritureTraceMicMac() - self.encadre(ligneFiltre) - - def OutilQualitePhotosAll(self): - - if self.pasDePhoto():return - - # on copie les photos dans un répertoire de test - - self.copieDansRepertoireDeTest() + def nettoyerChantier(self): # Le chantier est nettoyé : les résulats sous reptravail sont conservés, les arborescences de calcul effacés + self.etatDuChantier = 2 + self.enregistreChantier() + # retour à l'état initial pour les photos de calibration + if self.calibSeule.get(): + [os.rename(e,os.path.basename(e)) for e in self.photosPourCalibrationIntrinseque] + self.photosPourCalibrationIntrinseque = [os.path.join(self.repTravail,os.path.basename(e)) for e in self.photosPourCalibrationIntrinseque] + self.photosAvecChemin = [os.path.join(self.repTravail,os.path.basename(e)) for e in self.photosAvecChemin] + self.photosSansChemin = [os.path.basename(g) for g in self.photosAvecChemin] + listeAConserver = os.listdir(self.repTravail) + supprimeArborescenceSauf(self.repTravail,listeAConserver) - self.encadre("Détermine un indice de qualité des photos en mode 'All' ou 'MulScale' \n\n"+ - "Le résultat sera inscrit dans le fichier trace synthétique\n\nPatience...",nouveauDepart='non') + def nettoyerChantierDensification(self): # Le chantier est remis aprés Tapas + self.etatDuChantier = 4 + self.enregistreChantier() - - self.ajoutLigne(heure()+"Debut de la recherche sur la qualité des photos, mode 'All' ou 'MulScale'.") - self.qualiteTrouvee = list() - - qualite = [self.mm3d, - "Tapioca", - "All", - ".*"+self.extensionChoisie, - "1000", - "ExpTxt=1"] - - self.lanceCommande(qualite, - self.filtreQualite) - - # analyse des résultats : - os.chdir(self.repTravail) # car copieDansRepertoireDeTest a changer le répertoire de travail - - self.analyseQualitePhotos() - - self.ajoutLigne("\n"+heure()+" : Fin de la recherche sur la qualité des photos, mode 'All' ou 'MulScale'.") - self.ajoutLigne("\n\n ******") - ligneFiltre = self.ligneFiltre #l'écriture de la trace efface self.ligneFiltre et encadre doit être en fin de paragraphe - self.ecritureTraceMicMac() - self.encadre(ligneFiltre) - - def filtreQualite(self,ligne): - - if 'matches' in ligne: - self.encadrePlus("***") - self.qualiteTrouvee.append(ligne) - return ligne - - def analyseQualitePhotos(self): - if self.pasDePhoto():return - #somme des scores de chaque photo : - homol = dict() - nb = dict() - moyenne = dict() - for p in self.photosSansChemin: - image = os.path.splitext(p)[0] - homol[image] = 0 - nb[image] = 0 - for e in self.qualiteTrouvee: - for p in self.photosSansChemin: - image = os.path.splitext(p)[0] - if image+".tif.dat" in e: # on a trouvé la photo dans la ligne - nombre = int(e.split()[-2]) #le nombre de points homologues est l'avant dernière info de la ligne - homol[image] = homol[image] + nombre - nb[image] = nb[image] + 1 - moyenne[image] = homol[image]/nb[image] - - listeHomol = list(moyenne.items()) - listeHomol.sort(key=lambda e: e[1],reverse=True) - self.effaceBufferTrace() - self.ajoutLigne("\n ******\n\nClassement des photos par nombre de points homologues :\n\n") - for e in listeHomol: - self.ajoutLigne("photo "+e[0]+" score = "+str(int(e[1]))+"\n") - - if len(listeHomol)==0: - self.ajoutLigne("Aucune photo n'a de point analogue avec une autre.\n") - + ################################## UTILITAIRES MICMAC ########################################################### def exploiterHomol(self): - self.ajoutLigne("\n ****** Qualité des photos suite au traitement : ") - repHomol = self.repTravail+os.path.sep+'Homol' + self.ajoutLigne("\n ****** " + _("Qualité des photos suite au traitement : ")) + repHomol = self.repTravail+os.path.sep+_('Homol') if os.path.exists(repHomol): lesRep = os.listdir(repHomol) for e in lesRep: @@ -3574,13 +6142,13 @@ def exploiterHomol(self): if os.path.exists(fi): with open(fi) as infile: lignes = infile.readlines() #lecture dicoCamera.xml - print (e,fic,lignes.__len__()) - self.ajoutLigne("\n ****** Fin d'examen de qualité des photos.") - def copieDansRepertoireDeTest(self): + self.ajoutLigne("\n ****** " + _("Fin d'examen de qualité des photos.")) + + def copieDansRepertoireDeTest(self,nom): - self.encadre("Copie des photos dans un répertoire de test.\n Patience...",nouveauDepart='non') - self.repTest = self.repTravail+os.path.sep+"test" + self.encadre(_("Copie des photos dans un répertoire de test.") + "\n" + _("Patience...")) + self.repTest = self.repTravail+os.path.sep+"test_"+nom if os.path.exists(self.repTest): supprimeArborescenceSauf(self.repTest,os.listdir(self.repTest)) else: @@ -3590,103 +6158,233 @@ def copieDansRepertoireDeTest(self): shutil.copy(e,self.repTest) os.chdir(self.repTest) + def retirerPhotos(self): + titre = _("Retirer des photos") + message = _("Choisir les photos a retirer du chantier") + self.choisirUnePhoto(self.photosAvecChemin, + titre=titre, + message=message, + messageBouton=_("Valider")) + if len(self.selectionPhotosAvecChemin)>0: + [supprimeFichier(photo) for photo in self.selectionPhotosAvecChemin] + self.photosAvecChemin = [e for e in self.photosAvecChemin if os.path.exists(e)] + self.photosSansChemin = [os.path.basename(x) for x in self.photosAvecChemin] + self.encadre(_("Nombre de photos retirées du chantier : %s Consulter la trace") % str(len(self.selectionPhotosAvecChemin))) + self.ajoutLigne("\n"+_("Les photos suivantes sont retirées du chantier par l'utilisateur : ")+"\n"+"\n".join(self.selectionPhotosAvecChemin)) + self.ecritureTraceMicMac() + + ###################### création d'un nouveau chantier avec les meilleurs photos - ###################### Appareil photo : affiche le nom de l'apapreil de la première photo, la focale, la taille du capteur dans dicocamera + def outilMeilleuresPhotos(self): + self.menageEcran() + repertoireHomol = os.path.join(self.repTravail,"Homol") # répertoire des homologues + if os.path.isdir(repertoireHomol)==False: + self.encadre("Lancer d'abord la recherche des points homologues.") + return + self.item9000.pack() + pass + + def nbMeilleuresOK(self): + nb=self.item9003.get() + liste = [os.path.join(self.repTravail,e) for e in self.lesMeilleuresPhotos(int(nb))] + if self.troisBoutons(titre=_("Nouveau chantier"),question=_("Créer un nouveau chantier avec les photos : ") + +"\n"+"\n"+"\n".join(liste)+" ?\n"+"\n"+_("Les paramètres de Tapioca/Malt seront optimisés."))==0: + self.nouveauChantier() + + # crée le repertoire de travail, copie les photos et renvoit le nombre de fichiers photos "acceptables", + # met à 1 l'état du chantier crée self.photosAvecChemin et self.photosSansChemin + # ATTENTION : Supprime l'arborescence et certains résultats. - def OutilAppareilPhoto(self): + self.nombreDExtensionDifferentes(liste) + self.extensionChoisie = self.lesExtensions[0] + retourExtraire = self.extrairePhotoEtCopier(liste) - if self.pasDePhoto():return - - if os.path.exists(self.exiftool)==False: - texte = "L'outil exiftool n'a pas été trouvé. Traitement impossible.\nIndiquer son chemin (menu paramètrage)." - self.encadre(texte) + if retourExtraire.__class__()=='': # si le retour est un texte alors erreur, probablement création du répertoire impossible + self.encadre (_("Impossible de créer le répertoire de travail.") + "\n" + + _("Vérifier les droits en écriture sous le répertoire des photos") + "\n"+str(retourExtraire)) + return + if retourExtraire==0: # extraction et positionne self.repertoireDesPhotos, et les listes de photos avec et sanschemin (photosAvecChemin et photosSansChemin) + self.encadre (_("Aucun JPG, PNG, BMP, TIF, ou GIF sélectionné,") + "\n" + + _("le répertoire et les photos restent inchangés.") + "\n") + return + # paramètres de tapioca : MultiScale 300 * MulScale (Line est disqualifié par la sélection des photos, All est trop lourd) + self.modeTapioca.set('MulScale')# Mode (All, MulScale, Line) + self.echelle2.set('300') + self.echelle3.set('-1') + # Paramètre de Tapas : + self.modeCheckedTapas.set('RadialBasic') # mode par défaut depuis la v 2.23 du 14 mars 2016 + self.arretApresTapas.set(0) # 1 : on arrête le traitement après Tapas, 0 on poursuit + # pas encore suvegardé : + self.etatSauvegarde = "*" # chantier modifié + self.etatDuChantier = 1 + self.afficheEtat() + + def nbMeilleuresKO(self): + self.encadre(_("Abandon")) + pass + + ##################### expression régulière de la liste des meilleures photos autour d'une image maitresse (on explore le répertoire Homol + + def meilleuresPhotosAutourMaitresse(self,maitresse,nombre): + if nombre==-1: return - + repertoireHomol = os.path.join(self.repTravail,"Homol") # répertoire des homologues + if os.path.isdir(repertoireHomol)==False: + return + listeTaille = list() + os.chdir(repertoireHomol) + for e in os.listdir(): # balaie tous les fichiers contenant les points homologues + if maitresse.upper() in e.upper(): + os.chdir(os.path.join(repertoireHomol,e)) + for f in os.listdir(): + listeTaille.append((f, os.path.getsize(f))) # répertoire, nom du fichier et taille + os.chdir(self.repTravail) + listeTaille.sort(key= lambda e: e[1],reverse=True) # trie la liste des fichiers par taille + # supprime l'extension du fichier (toto1234.JPG.dat ou .txt) et garde les N plus grands + listeCorrigee = [os.path.splitext(e)[0] for e,f in listeTaille[0:nombre] if os.path.exists(os.path.join(self.repTravail,os.path.splitext(e)[0]))] + listeCorrigee.append(maitresse) + return "|".join(listeCorrigee) + + ###################### Stratégie APERODEDENIS pour trouver les maitresses et les images associées. (dépend des noms de répertoire et fichiers donnés par micmac) + # renvoie une liste de tuple : maitresse, liste des photos associées + + def maltApero(self): + # liste des paires de photos et taille + listeTaille = list() + self.maitressesEtPhotoApero = list() + repertoireHomol = os.path.join(self.repTravail,"Homol") # répertoire des homologues + if os.path.exists(repertoireHomol)==False: + return + os.chdir(repertoireHomol) + for e in os.listdir(): # balaie tous les fichiers contenant les points homologues + os.chdir(os.path.join(repertoireHomol,e)) + for f in os.listdir(): + listeTaille.append((e.replace("Pastis",""), os.path.splitext(f)[0], os.path.getsize(f))) # répertoire (pastis+nomphoto), nom du fichier(nomphoto+.dat ou .txt) et taille + os.chdir(self.repTravail) + listeTaille.sort(key= lambda e: e[2],reverse=True) # trie la liste des fichiers par taille + listeFixe = list(listeTaille) + # première maitresse = e de la paire la plus importante, associée à f + while listeTaille.__len__(): + e = listeTaille[0][0] + f = listeTaille[0][1] + t = listeTaille[0][2] + self.maitressesEtPhotoApero.append([e,f]) # on ajoute la maitresse et la photo associée + # Suppression de la liste de toutes les paires comportant e ou f + [listeTaille.remove((g,h,i)) for (g,h,i) in listeFixe if (e==g or e==h or f==g or f==h) and (g,h,i) in listeTaille] + self.listeDesMaitressesApero = [e for e,f in self.maitressesEtPhotoApero] # MaltApero renvoit la liste des maîtresses sous forme (maitresse, photo) + + + ###################### Appareil photo : affiche le nom de l'appareil de la première photo, la focale, la taille du capteur dans dicocamera + + def outilAppareilPhoto(self,silence=None): + self.encadre(_("Patience...")) + if self.pasDePhoto():return + if self.pasDeExiftool():return - texte = " ******\nCaractéristiques de l'appareil photo : \n\n" + texte = " ******\n" + _("Caractéristiques de l'appareil photo : ") + "\n\n" self.fabricant = self.tagExif("Make") if self.fabricant!=str(): - texte = texte + "fabricant : "+self.fabricant+"\n" + texte += _("fabricant : ")+self.fabricant+"\n" self.nomCamera = self.tagExif("Model") if self.nomCamera==str(): - self.encadre ("Nom de l'appareil photo inacessible.") - return + texte += _("Nom de l'appareil photo inacessible.") else: - texte = texte+"Nom de l'appareil photo : "+self.nomCamera+"\n" + texte += _("Nom de l'appareil photo : ")+self.nomCamera+"\n" + + self.numeroSerieCamera = self.tagExif("SerialNumber") + if self.numeroSerieCamera!=str(): + texte += _("Numéro de série de l'appareil photo : ")+self.numeroSerieCamera+"\n" self.focale35MM = self.tagExif("FocalLengthIn35mmFormat") self.focale = self.tagExif("FocalLength") if self.focale==str(): - texte = texte +("\nPas de focale dans l'exif.") + texte += ("\n" + _("Pas de focale dans l'exif.")) else: - texte = texte+"\nFocale : "+ self.focale+"\n" + texte += "\n" + _("Focale : ")+ self.focale+"\n" if self.focale35MM=="" and "35" not in self.focale: - texte = texte +("Pas de focale équivalente 35 mm dans l'exif :\nPrésence de la taille du capteur dans DicoCamera nécesssaire.") + texte += ("\n" + _("Pas de focale équivalente 35 mm dans l'exif :") + "\n" + _("Présence de la taille du capteur dans DicoCamera nécesssaire.")) else: if self.focale35MM=="": - texte = texte+"\nFocale équivalente 35 mm absente de l'exif\n" + texte += "\n" + _("Focale équivalente 35 mm absente de l'exif") + "\n" else: - texte = texte+"\nFocale équivalente 35 mm : "+ self.focale35MM+"\n" + texte += "\n" + _("Focale équivalente 35 mm : ")+ self.focale35MM+"\n" if not os.path.isfile(self.CameraXML): - texte = texte+"DicoCamera.xml non trouvé : paramètrer au préalable le chemin de MicMac\\bin." + texte += "\n" + _("DicoCamera.xml non trouvé : paramètrer au préalable le chemin de MicMac\\bin.") else: self.tailleCapteurAppareil() if self.tailleCapteur==str(): - texte = texte + "\n\nL'appareil est inconnu dans DicoCamera.XML.\n\n" + texte += "\n" + _("L'appareil est inconnu dans DicoCamera.XML.") + "\n" + else: + texte += "\n" + _("L'appareil est connu dans DicoCamera.XML.") + "\n"+\ + _("Taille du capteur en mm : ")+"\n\n"+self.tailleCapteur+"." + + self.controlePhotos() + if self.dimensionsDesPhotos: + if self.dimensionsOK: + texte += "\nDimensions des photos en pixel :\n"+str(self.dimensionsDesPhotos[0][1][0])+" - "+str(self.dimensionsDesPhotos[0][1][1]) else: - texte = texte + "\n\nL'appareil est connu dans DicoCamera.XML.\n\n"+\ - "Taille du capteur en mm : \n\n"+self.tailleCapteur+"." + lesDimensions = set([y for (x,y) in self.dimensionsDesPhotos]) + texte += "\n\nPlusieurs dimensions pour les photos :\n"+str(lesDimensions) - # écriture du résultat dans le fichier trace et présentation à l'écran self.effaceBufferTrace() - self.ajoutLigne("\n\nAppareil photo :\n"+texte) - self.ecritureTraceMicMac() + self.ajoutLigne("\n\n" + _("Appareil photo :") + "\n"+texte) + + if silence!=None: + return self.encadre(texte) + if self.nombreDeExifTagDifferents("Model")>1: + message = "\n\n"+_("Attention : les photos proviennent de plusieurs appareils différents.\n Voir l'item 'toutes les focales...' et le menu expert.") + self.ajoutLigne(message) + self.encadrePlus(message) + + self.ecritureTraceMicMac() - # tag dans l'exif : renvoi la valeur du tag 'tag' dans l'exif de la première photo (on suppose qu'elles sont identiques pour toutes les photos) + # tag dans l'exif : renvoi la valeur du tag 'tag' dans l'exif d'une photo + # si pas de photo précise : la première photo (on suppose qu'elles sont identiques pour toutes les photos) - def tagExif(self,tag): - if os.path.exists(self.exiftool)==False: - texte = "L'outil exiftool n'a pas été trouvé. Traitement impossible.\nIndiquer son chemin (menu paramètrage)." - return texte + def tagExif(self,tag,photo=""): + if photo=="":photo=self.photosAvecChemin[0] + if (tag,photo) in self.lesTagsExif: + return self.lesTagsExif[tag,photo] self.tag = str() - if self.pasDePhoto():return self.tag - if os.path.exists(self.exiftool): - exif = (self.exiftool, - "-"+tag, - self.photosAvecChemin[0]) - self.lanceCommande(exif, - self.FiltreTag) + exif = [self.exiftool, + "-"+tag, + photo] + self.lanceCommande(exif, + filtre=self.FiltreTag) + self.effaceBufferTrace() + self.lesTagsExif[tag,photo] = self.tag return self.tag def FiltreTag(self, ligne): # ne retourne rien (pour éviter la trace, mais positionne si possible self.tag if "can't open" in ligne: - return "Erreur dans exiftool : "+ligne + return _("Erreur dans exiftool : ")+ligne try: self.tag = ligne.split(":")[1].strip() # pour récupérer le nom, et supprimer le retour chariot de fin de ligne - except: pass + except Exception as e: print(_("erreur tagExif : "),str(e)) return None # tags dans l'exif : renvoi la valeur du tag 'tag' dans l'exif de toutes les photos def tagsExif(self,tag): - if os.path.exists(self.exiftool)==False: - texte = "L'outil exiftool n'a pas été trouvé. Traitement impossible.\nIndiquer son chemin (menu paramètrage)." - return texte - + self.tags = list() - if os.path.exists(self.exiftool): - exif = (self.exiftool, - "-"+tag, - os.path.join(self.repTravail,"*"+self.extensionChoisie)) - self.lanceCommande(exif, - self.FiltreTags) + if self.systeme=='nt': + exif = [self.exiftool, + "-"+tag, + os.path.join(self.repTravail,"*"+self.extensionChoisie)] + else: + exif = [self.exiftool, + "-"+tag, + os.path.join(self.repTravail)] + self.lanceCommande(exif, + filtre=self.FiltreTags) return self.tags def FiltreTags(self, ligne): @@ -3695,14 +6393,19 @@ def FiltreTags(self, ligne): self.tags.append(ajout+"\n") # pour récupérer le nom, et supprimer le retour chariot de fin de ligne return None - # taille du capteur, si le nom est connu + # retour 1 et positionne la taille du capteur dans self.tailleCapteur, si le nom est connu + # retour -1 si pas de nom d'appareil + # retour -2 si pas de fichier dicocamera + # retour None si appareil absent dans dicocamera - def tailleCapteurAppareil(self): + def tailleCapteurAppareil(self,appareil=""): self.tailleCapteur = str() # par défaut retour "" - if self.nomCamera == str(): # si pas de nom d'appareil : retour - return -1 - + if appareil == str(): # si pas de nom d'appareil : retour + appareil=self.nomCamera + if appareil==str(): + return + self.dicoCamera = str() if os.path.exists(self.CameraXML): # si pas de fichier dicoCamera : retour (il est vrai que la taille pourrait être ailleurs !) with open(self.CameraXML) as infile: @@ -3710,59 +6413,97 @@ def tailleCapteurAppareil(self): else: return -2 texte = str() + rechercher=""+appareil+"" + rechercher=rechercher.replace(" ","") for e in self.dicoCamera: # recherche du nom de l'appareil dans dicoCamera if texte=="vu": if "SzCaptMm" in e: # le nom est repéré, voit-on la taille ? - self.tailleCapteur = e.replace("","").replace("","").strip().replace(" "," mm - ")+" mm" + self.tailleCapteur = e.replace("","").replace("","").strip().replace(" "," mm - ",1)+" mm" return 1 # la taille est trouvée : on quitte if "" in e: # pas de taille trouvée sous ce nom texte = str() # on poursuit - if self.nomCamera in e: # nom trouvé + if rechercher in e.replace(" ",""): # le nom de l'appareil est trouvé texte="vu" - # Mise à jour de DicoCamera def miseAJourDicoCamera(self): if self.pasDePhoto():return - - if os.path.exists(self.exiftool)==False: - texte = "L'outil exiftool n'a pas été trouvé. Traitement impossible." - self.encadre(texte) - return - - self.nomCamera = self.tagExif("Model") - if self.nomCamera==str(): - self.encadre("Pas trouvé de nom d'appareil photo dans l'exif.") - return + if self.pasDeMm3d():return + if self.pasDeExiftool():return if not os.path.isfile(self.CameraXML): - self.encadre("DicoCamera.xml non trouvé : paramètrer au préalable le chemin de MicMac\\bin.") + self.encadre(_("DicoCamera.xml non trouvé : paramètrer au préalable le chemin de MicMac\\bin.")) return - if self.tailleCapteurAppareil()==1: - self.encadre( "Le fichier DicoCamera.xml contient la taille du capteur pour l'appareil :\n\n"+ - self.nomCamera+"\n\ntaille = "+self.tailleCapteur+ - "\n\nModification non prévue dans cette version de l'outil AperoDeDenis\n----------------") - return - + message = str() + self.encadre("Patience... recherche les noms de tous les appareils photos du chantier...") + nb = self.nombreDeExifTagDifferents("Model") self.menageEcran() - self.item1001.configure(text="Pour l'appareil "+self.nomCamera) - self.item1000.pack() - - def dimensionCapteurOK(self): + if nb == 0: + self.encadre(-("Pas de modèle d'appareil photo dans les exif.")) + self.nomCamera = self.lesTags[0] + if self.nomCamera==[]: + message=_("\Pas de nom d'appareil photo dans l'exif") + self.encadre(message) + if nb == 1: + if self.tailleCapteurAppareil()==1: + message =( _("\nLe fichier DicoCamera.xml contient déjà la taille du capteur pour l'appareil :") + "\n\n"+ + self.nomCamera+"\n\n"+ _("taille = ")+self.tailleCapteur+"\n\n"+_("Pas de modification possible.")) + self.encadre(message) + else: + self.menageEcran() + self.lesAppareilsPourDicocamera = [self.nomCamera] + self.item1001.configure(text=_("Pour l'appareil ")+self.nomCamera) + self.item1000.pack() + + if nb > 1: + self.choisirUnePhoto( + self.lesTags, + titre=_("Choisir le ou les appareils à mettre à jour"), + message=_("Liste des appareils du chantier : \n"), + mode='extended', + objets='appareils') + if self.selectionPhotosAvecChemin: + self.menageEcran() + self.lesAppareilsPourDicocamera = self.selectionPhotosAvecChemin + self.item1001.configure(text=_("Pour les appareils choisis :\n")+"\n".join(self.lesAppareilsPourDicocamera)) + self.item1000.pack() + # ne rien ajouter ici qui puisse fermer les boîtes de dialogue + + # écriture des dimensions du capteur dans dicocamera.xml + + def dimensionCapteurOK(self): if not os.path.isfile(self.CameraXML): - self.encadre("Paramètrer au préalable le chemin de MicMac\\bin.") - return - dimension = self.item1003.get() - # paragraphe à rajouter à DicoCamera : texte - texte = self.dicoCameraXMLTaille.replace("NomCourt",self.nomCamera) - texte = texte.replace("Nom",self.nomCamera) - texte = texte.replace("tailleEnMM",dimension) - + self.encadre(_("Paramètrer au préalable le chemin de MicMac\\bin.")) + return + # controle : + vals = self.item1003.get().split() + try: + float(vals[0]) + float(vals[1]) + except: + self.encadre("Dimensions capteur incorrectes : "+self.item1003.get()+"\n exemple correct : 7.5 12.3") + return + dimension = " ".join(vals) + # paragraphe à rajouter à DicoCamera : modif + modif = str() + message = str() + for nomCamera in self.lesAppareilsPourDicocamera: + if self.tailleCapteurAppareil(nomCamera)==1 and self.tailleCapteur!=" mm": + message +=(_("\nLe fichier DicoCamera.xml contient déjà la taille du capteur pour l'appareil :") + "\n\n"+ + nomCamera+"\n\n"+ _("taille = ")+self.tailleCapteur+"\n\n"+_("Pas de modification possible.")) + else: + texte = self.dicoCameraXMLTaille.replace(_("NomCourt"),nomCamera) + texte = texte.replace(_("Nom"),nomCamera) + texte = texte.replace(_("tailleEnMM"),dimension) + modif += texte #lecture dicocamera.xml : with open(self.CameraXML) as infile: self.dicoCamera = infile.readlines() #lecture dicoCamera.xml - # ajout du paragraphe enfin de xml : - newDico = "".join(self.dicoCamera).replace(self.dicoCameraXMLFin,texte+self.dicoCameraXMLFin) + # ajout du paragraphe enfin de xml : on vérifie d'abord sa présence parmi les 10 dernières lignes du fichier + if self.dicoCameraXMLFin not in "".join(self.dicoCamera[-10:]): + self.encadre(_("Fichier DicoCamera.xml invalide : balise de fin manquante : ")+"\n"+self.dicoCameraXMLFin) + return + newDico = "".join(self.dicoCamera).replace(self.dicoCameraXMLFin,modif+self.dicoCameraXMLFin) if os.path.getsize(self.CameraXML)>0: # pour éviter de copier un fichier "vide" try: shutil.copy(self.CameraXML,self.CameraXML+".sav") except: pass @@ -3771,34 +6512,293 @@ def dimensionCapteurOK(self): with open(self.CameraXML,mode="w") as outfile: outfile.write(newDico) except: - self.encadre("Erreur lors de l'écriture de DicoCamera.xml\nUne sauvegarde a été créée : DicoCamerra.xml.sav") + self.encadre(_("Erreur lors de l'écriture de DicoCamera.xml") + "\n" + _("Une sauvegarde a été créée : DicoCamera.xml.sav")) return else: - self.encadre("Dimensions du capteur non mis à jour\n") + self.encadre(_("Dimensions du capteur non mis à jour") + "\n") return - self.encadre("Dimensions du capteur mis à jour\n"+texte) + self.encadre(_("Mise à jour de dicocamera.xml : ") + "\n"+modif+"\n"+message) def dimensionCapteurKO(self): - self.encadre("Dimensions du capteur non mis à jour") - + self.encadre(_("Dimensions du capteur non mis à jour")) def toutesLesFocales(self): + self.encadre(_("Patience...")) + if self.pasDePhoto():return + if self.pasDeExiftool():return + texte = _("Les focales, les focales équivalentes en 35mm et le nom des appareils photos :")+"\n\n" + texte += "\n".join(self.tagsExif("FocalLength")) + texte += "\n".join(self.tagsExif("FocalLengthIn35mmFormat")) + texte += "\n".join(self.tagsExif("Model")) + self.cadreVide() + self.effaceBufferTrace() + self.ajoutLigne(texte) + self.texte201.see("1.1") + + + ################################## le menu Expert + + def lignesExpert(self): + self.ecritureTraceMicMac() + self.cadreVide() # ménage écran, ouverture trace + texte = _("Ceci est une console système : Saisir une ou plusieurs ligne(s) de commande") + "\n" + if self.etatDuChantier==0: + texte+="\n\n"+_("Attention : Le chantier n'existe pas.") + + bas = ( + _("Entrer soit une commande MicMac, par exemple : mm3d GCPBascule .*.JPG Arbitrary")+"\n"+ + _("soit une commande du système, par exemple sous windows : del /S /Q Tmp-MM-Dir")+"\n"+ + _("ou une commande mm3d interactive comme : mm3d vC3DC")+"\n"+ + _("Possibilité de copier une commande du fichier mm3d-LogFile.txt.")+"\n"+ + _("Le tout sous votre responsabilité")) + new = MyDialogTexte(fenetre,texte,basDePage=bas,boutonDialogueTexteOk="Exécuter") + if new.saisie=="": + return + lignes = new.saisie.split("\n") + self.cadreVide() + self.ecritureTraceMicMac() + for ligne in lignes: + if ligne: #si besoin on ajoute le chemin vers mm3d et on retire les " + if ligne[:4]=="mm3d":ligne=os.path.join(self.micMac,ligne) + self.lanceCommande(ligne.replace('"'," ").split()) + os.chdir(self.repTravail) # on ne sait pas ce qu'a fait l'utilisateur + self.texte201.see("1.1") # affichage du résultat + + + def filtreRien(self,ligne): + return ligne + + def lignesPython(self): + self.ecritureTraceMicMac() + self.cadreVide() # ménage écran, ouverture trace + texte = _("Ceci est une console python : Saisir une ou plusieurs ligne(s) de script python") + "\n" + if self.etatDuChantier==0: + texte+="\n\n"+_("Attention : Le chantier n'existe pas.") + + bas = ( + _("Entrer soit une commande python, par exemple : locals()")+"\n"+ + _("la commande sera éxécutée puis évaluée et les résultats affichés dans une fenetre")+"\n"+ + _("et aussi dans la trace synthétique.")+"\n"+ + _("Le tout sous votre responsabilité")) + new = MyDialogTexte(fenetre,texte,basDePage=bas,boutonDialogueTexteOk="Exécuter") + if new.saisie=="": + return + lignes = new.saisie.split("\n") + self.cadreVide() + self.ecritureTraceMicMac() + entete = "\n"+_("résultat de la commande python : ")+str(lignes)+"\n" + self.encadre(entete) + self.ajoutLigne(entete) + for ligne in lignes: + if ligne: #si besoin on ajoute le chemin vers mm3d et on retire les " + resul1 = str() + resul2 = str() + entete="\n"+_("commande : ")+ligne + self.encadrePlus("\n"+entete) + try: resul1=exec(ligne,globals(),locals()) + except Exception as e:print("erreur exec : ",e) + try: resul2=eval(ligne,globals(),locals()) + except Exception as e:print("erreur eval : ",e) + if resul1: + r=_("\nL'exécution de la commande python retourne la valeur : ")+"\n" + r+="\n".join(wrap(str(resul1),100)) #on coupe tout les 100 caractères + else: + r=_("\nL'éxécution de la commande python ne retourne pas de valeur") + self.encadrePlus("\n"+r) + if resul2: + r=_("\nL'évaluation de la commande python retourne la valeur : ")+"\n" + r+="\n".join(wrap(str(resul2),100)) #on coupe tout les 100 caractères + else: + r=_("\nL'évaluation de la commande python ne retourne pas de valeur") + self.encadrePlus("\n"+r) + self.ajoutLigne(r) + + self.ecritureTraceMicMac() + os.chdir(self.repTravail) # on ne sait pas ce qu'a fait l'utilisateur + + def ajoutPointsGPSAutreChantier(self): + + self.menageEcran() + bilan = self.choisirUnChantier(_("Choisir le chantier pour ajouter les points gps.")) # boite de dialogue de sélection du chantier à ouvrir, renvoi : self.selectionRepertoireAvecChemin + if bilan!=None: + self.afficheEtat(_("Aucun chantier choisi.") + "\n" + bilan + "\n") + return + fichierParamChantierAutre = os.path.join(self.selectionRepertoireAvecChemin,self.paramChantierSav) + if os.path.exists(fichierParamChantierAutre): + try: # s'il y a une sauvegarde alors on la restaure + sauvegarde1=open(fichierParamChantierAutre,mode='rb') + r=pickle.load(sauvegarde1) + sauvegarde1.close() + listePointsGPS = r[12] + dicoPointsGPSEnPlace = r[20] + idPointGPS = r[23] + + # pour assurer la compatibilité ascendante suite à l'ajout de l'incertitude dans la description des points GPS + # passage vers la version 2.60 de la liste des points GPS (un item de plus dans le tuple) + + if listePointsGPS.__len__()>0: + if listePointsGPS[0].__len__()==6: + listePointsGPS = [[a,nom,x,y,z,ident,"10 10 10"] for a,nom,x,y,z,ident in listePointsGPS] + except Exception as e: + self.encadre (_('Chantier choisi %s corrompu. Abandon.') % (self.selectionRepertoireAvecChemin)) + print(_("Erreur restauration points GPS : "),str(e)) + return + else: + self.encadre (_('Chantier choisi %s corrompu. Abandon.') % (self.selectionRepertoireAvecChemin)) + return + + # 3 variables : self.dicoPointsGPSEnPlace, self.listePointsGPS et self.idPointGPS pour le chantier en cours et idem (sans self.) pour le chantier a ajouter + # dicoPointsGPSEnPlace key = nom du point, photo, identifiant, value = x,y + # listePointsGPS : 7-tuples ( nom du point, x, y et z gps, booléen actif ou supprimé, identifiant,incertitude) + # idPointGPS : entier, identifiant du dernier point GPS + + # 1) Modifier la clé du dico lu : chemin de la photo et identifiant par ajout de la valeur de self.idPointGPS + # si la photo existe alors ajout dans le dico du chantier en cours + + for nom,photo,identifiant in dicoPointsGPSEnPlace.keys(): + nouvelId = identifiant + self.idPointGPS + nouveauNom = nom + "_" + str(nouvelId) + nouvellePhoto = os.path.join(self.repTravail,os.path.basename(afficheChemin(photo))) + + if os.path.exists(nouvellePhoto): + self.dicoPointsGPSEnPlace[nouveauNom,nouvellePhoto,nouvelId] = dicoPointsGPSEnPlace[nom,photo,identifiant] # la photo existe, on ajoute au dico des points en place l'identifiant change + + + # 2) Modifier la liste des points GPS : identifiant pat ajout de la valeur de self.idPointGPS, éviter les noms en double + nbAjout = 0 + for nom,b,c,d,e,identifiant,g in listePointsGPS: + nouvelId = identifiant + self.idPointGPS + nouveauNom = nom + "_"+ str(nouvelId) + self.listePointsGPS.append([nouveauNom,b,c,d,e,nouvelId,g]) + nbAjout += 1 + + # 3) Trouver la nouvelle valeur de self.idPointGPS + + self.idPointGPS = 1 + max ([f for a,b,c,d,e,f,g in self.listePointsGPS]) + + + # mise à jour de la liste des widgets pour saisie : + + self.optionsReperes() + + # Affichage de l'état du chantier avec les nouveaux points GPS + + self.encadre (str(nbAjout)+_(" points GPS ajoutés.")) + + + # Ajout de points GPS à partir d'un fichier de points : format = + # #F=N X Y Z Ix Iy Iz + # PP_5 3.6341 108.5261 38.8897 0.01 0.01 0.01 + + def ajoutPointsGPSDepuisFichier(self): + + self.menageEcran() + + fichierPointsGPS=tkinter.filedialog.askopenfilename(title=_('Liste de points GPS : Nom, X,Y,Z, dx,dy,dz (fichier texte séparteur espace) : '), + filetypes=[(_("Texte"),("*.txt")),(_("Tous"),"*")], + multiple=False) + + if len(fichierPointsGPS)==0: + return + nbAjout = 0 + with open(fichierPointsGPS, "r") as fichier: + for ligne in fichier: + if ligne[0]!="#": + self.idPointGPS += 1 + try: + nom,x,y,z,dx,dy,dz=ligne.split() + except: break + self.listePointsGPS.append([nom,x,y,z,True,self.idPointGPS,(" ").join([dx,dy,dz])]) + nbAjout += 1 + + + # Déterminer la nouvelle valeur de self.idPointGPS + + self.idPointGPS += 1 + + # mise à jour de la liste des widgets pour saisie : + + self.optionsReperes() + + # Affichage de l'état du chantieravec les nouveaux points GPS + + self.encadre (str(nbAjout)+_(" points GPS ajoutés.")) + if nbAjout>15: + self.encadre (str(nbAjout)+_(" points GPS ajoutés : c'est beaucoup, sans doute trop (pb affichage options GPS)")) + + def plusieursAppareils(self): + # y-a-il dans l'exif un numéro de série ? + nbModif = int() + nbConserve = int() + modif = _("AperoDeDenis propose l'ajout du préfixe (3 caractères) du nom des photos au tag model") + bouton = _("Ajout du préfixe du nom du fichier au tag model de l'exif") + self.menageEcran() + message = ( _("Lorque les photos choisies proviennent de plusieurs appareils photos") + "\n"+ + _("les TAGS 'model' doivent être différenciés dans l'exif des photos.") + "\n"+ + _("La calibration s'effectue alors pour chaque appareil.") + "\n\n"+ + _("AperoDeDenis propose l'ajout du préfixe (3 caractères) du nom des photos au tag model")+ "\n"+ + _("Cet ajout ne sera effectué qu'une seule fois.")+ "\n"+ + _("Le préfixe est un paramètre modifiable propre à chaque appareil photo")+ "\n\n") + if self.etatDuChantier not in [1,2]: # 1 = avec photo ; 2 = enregistré, plus = traitement effectué + message +=_("Cette modification ne sera prise en compte que pour les futurs traitements.") + if self.troisBoutons(_("Plusieurs appareils photos"),message,_("Ne rien faire"),bouton) == 0: + self.encadre(_("Abandon, le chantier n'est pas modifié.")) + return + # Modification des tags "model" demandée : + self.encadre(_("Modification du modèle de l'appareil photo en cours : ajout du préfixe du nom du fichier.")+"\n"+ + _("Attention : procédure longue si beaucoup de photos.")+"\n") + commande = [self.exiftool,] + for photo in self.photosSansChemin: + self.encadrePlus(".") + prefix = os.path.basename(photo)[:3] + model = self.tagExif("Model",photo) + if not prefix in model: + nbModif += 1 + nouveauTag = model+" "+prefix + commande.extend(["-Model="+nouveauTag,photo]) + self.lesTagsExif["Model",photo] = nouveauTag + supprimeFichier(photo+"_original") # exiftool crée des copies "_original" des fichiers initiaux, on les supprime ; + else: nbConserve += 1 + os.chdir(self.repTravail) + if nbModif: self.lanceCommande(commande) + message = "\n"+_("Modéle de l'appareil photo modifié : ajout du préfixe du nom de fichier sur 3 caractères.")+"\n\n" + message += _("Nombre de fichiers modifiés : %s") % str(nbModif) + "\n" + if nbConserve: + message += _("Nombre de fichiers conservés car déjà modifiés : %s") % str(nbConserve) + "\n" + self.encadre(message) + self.ajoutLigne(message) + self.ecritureTraceMicMac() - if self.pasDePhoto():return - - if os.path.exists(self.exiftool)==False: - texte = "L'outil exiftool n'a pas été trouvé. Traitement impossible." - self.encadre(texte) - return + def listeAppareils(self): + self.encadre(_("Recherche des noms d'appareil photos. Patience !.")) + nb = self.nombreDeExifTagDifferents("Model") + if nb>1: message = _("Les photos proviennent de ")+str(nb)+_(" appareils photos différents : ")+"\n\n"+"\n".join(self.lesTags) + elif nb==1: message = _("Les photos proviennent d'un seul appareil : ")+"\n\n"+"\n".join(self.lesTags) + else: message = _("L'exif des photos ne contient pas le nom de l'appareil photo.") + self.encadre(message) + self.ajoutLigne("Les appareils photos : \n"+message) + self.ecritureTraceMicMac() - texte=self.tagsExif("FocalLength") - texte=texte+["\n",]+self.tagsExif("FocalLengthIn35mmFormat") - self.effaceBufferTrace() - self.ajoutLigne(" ****** \nToutes les focales : \n\n"+"".join(texte)+"\n ****** \n") - self.ecritureTraceMicMac() - self.encadre(texte) + def logMm3d(self): + os.chdir(self.repTravail) + fichier = "mm3d-LogFile.txt" + if os.path.exists(fichier): + self.cadreVide() + trace=open(fichier,"r",encoding="utf-8") + try: + contenu=trace.read() + except: # pour compatibilité ascendante + trace.close + trace=open(fichier,"r",encoding="latin-1") + contenu=trace.read() + trace.close + self.ajoutLigne(contenu) + self.texte201.see("1.1") + else: + texte = _("Pas de trace du log !") + self.encadre(texte) ################################## Le menu AIDE ########################################################### # provisoirement retirés : @@ -3806,202 +6806,431 @@ def toutesLesFocales(self): #" - Nettoyer les photos : permet de délimiter les zones ""utiles"" des photos.\n" #" Cette option n'est pas active dans la version 1.0 de l'outil.\n" def aide(self): - aide1= "Interface graphique pour lancer les modules de MICMAC.\n\n"+\ - "Utilisable sous Linux, Windows, Mac OS.\n"+\ - "Logiciel libre diffusé sous licence CeCILL-B.\n"+\ + aide1 = _("Interface graphique du CEREMA pour lancer les modules de MICMAC.") + "\n\n"+\ + _("Utilisable sous Linux, Windows, Mac OS.") + "\n"+\ + _("Logiciel libre et open source diffusé sous licence CeCILL-B.") + "\n"+\ "-----------------------------------------------------------------------------------------------------------------\n\n"+\ - "La barre de titre présente le nom du chantier et la version de l'outil. Une * indique que le chantier est à sauvegarder.\n\n"+\ - "Menu Fichier :\n\n"+\ - " - Nouveau chantier : constitution d'un 'chantier' comportant les photos, les options d'exécution de Micmac et\n"+\ - " les résultats des traitements.\n"+\ - " Les paramètres du chantier sont conservés dans le fichier "+self.paramChantierSav+".\n"+\ - " Enregistrer le chantier crée une arborescence dont la racine est le répertoire des photos et le nom du chantier.\n\n"+\ - " - Ouvrir un chantier : revenir sur un ancien chantier pour le poursuivre ou consulter les résultats.\n\n"+\ - " - Enregistrer le chantier : enregistre le chantier en cours sans l'exécuter.\n"+\ - " Une * dans la barre de titre indique que le chantier a été modifié.\n"+\ - " Le chantier en cours, même non enregistré, est conservé lors de la fermeture de l'application.\n\n"+\ - " - Renommer le chantier : personnalise le nom du chantier.\n\n"+\ - " Le chantier est déplacé dans l'arborescence en indiquant un chemin absolu ou relatif.\n"+\ - " Par exemple : 'D:\\MonPremierChantier' nomme 'MonPremierChantier' sous la racine du disque D.\n"+\ - " Attention : le changement de disque n'est pas possible dans cette version de l'outil.\n\n"+\ - " - Du ménage ! : Supprimer les chantiers : Chaque chantier crée une arborescence de travail.\n"+\ - " Cet item permet de supprimer les répertoires devenu inutiles.\n"+\ - " Aprés un message demandant confirmation la suppression est définitive, sans récupération possible.\n\n"+\ - " - Quitter : quitte l'application, le chantier en cours est conservé et sera ouvert lors de la prochaine exécution.\n\n"+\ - "Menu Edition :\n\n"+\ - " - Afficher l'état du chantier : affiche les paramètres du chantier et son état d'exécution.\n"+\ - " Par défaut l'état du chantier est affiché lors du lancement de l'application.\n"+\ - " Cet item est utile après un message ou l'affichage d'une trace.\n\n"+\ - " - Plusieurs items permettent de consulter les photos, les traces et les vues 3D du chantier en cours.\n\n"+\ - " Visualiser toutes les photos sélectionnées : visualise les photos\n"+\ - " Visualiser les points GPS : visu des seules photos avec points GPS.\n"+\ - " Visualiser le masque 3D : visualise le masque 3D\n"+\ - " Visualiser le masque 2D et l'image maitre : visualise le masque 2D s'il existe et de l'image maître.\n"+\ - " Visualiser la ligne horizontale/verticale : visualise le repère Ox ou Oy.\n"+\ - " Visualiser la zone plane : visualise la zone plane\n"+\ - " Visualiser la distance : visualise de la distance et les points associés.\n"+\ + _("La barre de titre présente le nom du chantier et la version de l'outil. Une * indique que le chantier est à sauvegarder.") + "\n\n"+\ + _("Menu Fichier :") + "\n\n"+\ + _(" - Nouveau chantier : constitution d'un 'chantier' comportant les photos, les options d'exécution de Micmac et") + "\n"+\ + _(" les résultats des traitements.") +"\n"+\ + _(" Les paramètres du chantier sont conservés dans le fichier ")+self.paramChantierSav+".\n"+\ + _(" Enregistrer le chantier crée une arborescence dont la racine est le répertoire des photos et le nom du chantier.") + "\n\n"+\ + _(" - Ouvrir un chantier : revenir sur un ancien chantier pour le poursuivre ou consulter les résultats.") + "\n\n"+\ + _(" - Enregistrer le chantier : enregistre le chantier en cours sans l'exécuter.") + "\n"+\ + _(" Une * dans la barre de titre indique que le chantier a été modifié.") + "\n"+\ + _(" Le chantier en cours, même non enregistré, est conservé lors de la fermeture de l'application.") + "\n\n"+\ + _(" - Renommer le chantier : personnalise le nom du chantier.") + "\n\n"+\ + _(" Le chantier est déplacé dans l'arborescence en indiquant un chemin absolu ou relatif.") + "\n"+\ + _(" Par exemple : 'D:\\MonPremierChantier' nomme 'MonPremierChantier' sous la racine du disque D.") + "\n"+\ + _(" Attention : le changement de disque n'est pas possible dans cette version de l'outil.") + "\n\n"+\ + _(" - Exporter le chantier en cours : création d'une archive du chantier, qui permet :") + "\n"+\ + _(" - de conserver le chantier en l'état, pour y revenir.") + "\n"+\ + _(" - de l'importer sous un autre répertoire, un autre disque, un autre ordinateur, un autre système d'exploitation") + "\n\n"+\ + _(" - Importer un chantier :") + "\n"+\ + _(" - copie le chantier sauvegardé dans un nouvel environnement (ordinateur, système d'exploitation)") + "\n"+\ + _(" - un exemple d'intérêt : copier un chantier après tapas, lancer malt avec des options variées sans perdre l'original.") + "\n\n"+\ + _(" - Ajouter le répertoire d'un chantier :") + "\n"+\ + _(" - ajoute le chantier présent sous le répertoire indiqué. Alternative moins robuste à l'export/import)") + "\n"+\ + _(" - Du ménage ! : nettoyer ou supprimer les chantiers : chaque chantier crée une arborescence de travail assez lourde.") + "\n"+\ + _(" Le nettoyage ne garde que les photos, les modèles 3D résultats, les traces, les paramètres : gain de place assuré !.") + "\n"+\ + _(" La suppression supprime tout le chantier.") + "\n"+\ + _(" Un message demande confirmation avant la suppression définitive, sans récupération possible :") + "\n"+\ + _(" Toute l'arborescence est supprimée, même les archives exportées.") + "\n\n"+\ + _(" - Quitter : quitte l'application, le chantier en cours est conservé et sera ouvert lors du prochain lancement.") + "\n\n"+\ + _("Menu Edition :") + "\n\n"+\ + _(" - Afficher l'état du chantier : affiche les paramètres du chantier et son état d'exécution.") + "\n"+\ + _(" Par défaut l'état du chantier est affiché lors du lancement de l'application.") + "\n"+\ + _(" Cet item est utile après un message ou l'affichage d'une trace.") + "\n\n"+\ + _(" - Plusieurs items permettent de consulter les photos, les traces et les vues 3D du chantier en cours.") + "\n\n"+\ + _(" Visualiser toutes les photos sélectionnées : visualise les photos") + "\n"+\ + _(" Visualiser les photos pour la calibration intrinsèque") + "\n"+\ + _(" Visualiser les maitresses et les masques : visualise les masques 2D pour la densification Malt/géoimage.") + "\n"+\ + _(" Visualiser le masque sur mosaïque TARAMA : visualise le masque défini sur la mosaïque TARAMA.") + "\n"+\ + _(" Visualiser le masque 3D : visualise le masque 3D pour la densification C3DC") + "\n"+\ + _(" Visualiser les points GPS : visu des seules photos avec points GPS.") + "\n"+\ + "\n"+\ + _(" Visualiser la ligne horizontale/verticale : visualise le repère Ox ou Oy pour la mise à l'échelle.") + "\n"+\ + _(" Visualiser la zone plane : visualise la zone plane") + "\n"+\ + _(" Visualiser la distance : visualise de la distance et les points associés.") + "\n"+\ + "\n"+\ + _(" Afficher la trace complete du chantier : visualise la trace complète, standard micmac") + "\n"+\ + _(" Afficher la trace synthétique du chantier : visualise la trace filtrée par aperoDeDenis, moins bavarde") + "\n\n"+\ + "\n"+\ + _(" Afficher la mosaïque Tarama : si la mosaïque tarama est demandée dans l'onglet 'orientation'") + "\n"+\ + _(" Afficher l'ortho mosaïque Tawny : l'ortho mosaïque tawny est demandée dans l'onglet Densifisation/Malt/Ortho") + "\n"+\ "\n"+\ - " Afficher la trace complete du chantier : visualise la trace complète, standard micmac\n"+\ - " Afficher la trace synthétique du chantier : visualise la trace filtrée par aperoDeDenis, moins bavarde\n"+\ - " Afficher l'image 3D aprés Tapas : lance l'outil pour ouvrir les .PLY sur l'image 3D produite par Tapas\n"+\ - " Afficher l'image 3D aprés Malt : visualise l'image densifiée produite par Malt.\n\n"+\ - "Menu MicMac :\n\n"+\ - " - Choisir les photos : permet choisir les photos JPG pour le traitement.\n\n"+\ - " Remarque : les JPG doivent comporter un EXIF avec la focale utilisée pour la prise de vue..\n"+\ - " Consulter la documentation MicMac concernant les photos utilisables et le fichier DicoCamera.xml.\n\n"+\ - " - Options : choisir les options des modules Tapioca, Tapas (nuage non densifié) puis de Malt (nuage densifié) : \n\n"+\ - " Les 3 options suivantes concernent le calcul du nuage de points NON densifié :\n\n"+\ - " - Tapioca : options et sous options associées (échelles, fichier xml)\n"+\ - " - Tapas : Choix d'un mode de calcul, possibilité d'arrêter le traitement après tapas.\n"+\ - " L'arrêt après Tapas est nécessaire pour décrire le masque 3D de C3DCla.\n"+\ - " Produit une image 3D avec position des appareils photos.\n"+\ - " - Calibration : définir un axe, une zone plane, une distance pour définir le repère du chantier.\n\n"+\ - " Les 3 options suivantes concernent le calcul du nuage de points densifié :\n\n"+\ - " - Malt : choix du mode, désigner une image maitresse et dessiner le masque associé.\n"+\ - " Seuls les points visibles sur l'image maitre seront sur l'image 3D finale.\n"+\ - " Le masque limite la zone ""utile"" de l'image 3D finale.\n"+\ - " La molette permet de zoomer et le clic droit maintenu de déplacer l'image.\n"+\ - " Choisir une image maitresse réinitialise le masque.\n\n"+\ - " - C3DC : dessiner le masque 3D sur le nuage de points AperiCloud généré par Tapas..\n"+\ - " Les touches fonctions à utiliser sont décrites dans l'onglet.\n"+\ - " Le masque limite la zone en 3 dimensions de l'image finale.\n"+\ - " L'outil de saisie est issu de micmac.\n\n"+\ - " - GPS : Définir les points de calage GPS qui permettent de géolocaliser la scène.\n"+\ - " Pour être utilisé chaque point doit être placé sur au moins 2 photos.\n\n"+\ - " - Lancer MicMac : Enregistre le chantier et lance le traitement avec les options par défaut ou choisies par l'item 'options'.\n"+\ - " Relance micmac si l'arrêt a été demandé après tapas.\n"+\ - " Lancer micmac bloque les photos et les options du chantier.\n"+\ - " Pour débloquer le chantier il faut lancer micmac à nouveau et choisir le débloquage.\n\n"+\ - "menu Outils :\n\n"+\ - " - Nom et focale de l'appareil photo : fabricant, modéle et focale de la première photo.\n"+\ - " Il y a 2 types de focales : focale effective et focale équivalente 35 mm.\n"+\ - " Indique si l'appareil photo est connu dans '/XML MicMac/DicoCamera.xml' (uniquement dans ce fichier).\n"+\ - " - Toutes les focales des photos : focales et focales equivalentes en 35mm.\n"+\ - " Les focales doivent être identiques pour toutes les photos : si besoin créer plusieurs chantiers.\n"+\ - " - Mettre à jour DicoCamera.xml : ajouter la taille du capteur dans '/XML MicMac/DicoCamera.xml'.\n\n"+\ - " La taille du capteur dans DicoCamera.xml est requise si la focale équivalente 35mm est absente de l'exif.\n\n"+\ - " La taille du capteur facilite les calculs et améliore les résultats.\n\n"+\ - " - Qualité des photos 'Line' : calcule le nombre moyen de points homologues par photo en mode 'Line'.\n"+\ - " - Qualité des photos 'MulScale ou All' : calcule le nombre moyen de points homologues par photo.'.\n"+\ - " Ce nombre informe sur la qualité relative des photos au sein du chantier.\n"+\ - " La présence de photos avec peu de points homologues peu faire échouer le traitement.\n"+\ - " Il est préférable de traiter peu de photos mais de bonne qualité.\n\n"+\ - "menu Paramètrage :\n\n"+\ - " - Affiche les paramètres : visualise les chemins de micmac\\bin, d'exiftool et du fichier Meshlab ou Cloud Compare.\n"+\ - " Ces paramètres sont sauvegardés de façon permanente dans le fichier "+self.fichierParamMicmac+".\n\n"+\ - " - Désigner le répertoire MicMac\\bin : répertoire où se trouvent les modules de MicMac \n"+\ - " - Désigner l'application exiftool.\n"+\ - " - Désigner l'application ouvrant les .PLY. Ce peut être Meshlab, Cloud Compare ou autre.\n\n"+\ - " Sous Windows Meshlab se trouve sous un répertoire nommé VCG.\n\n"+\ - "menu Aide :\n\n"+\ - " - Aide \n"+\ - " - Quelques conseils : sur la prise de vue et les paramètres.\n"+\ - " - A propos\n\n\n"+\ - " Quelques précisions :\n"+\ - " Cette version a été développée sous Windows XP et Seven avec micmac rev 1963, puis rev 5508 d'avril 2015.\n"+\ - " L'utilisation d'autres versions de Micmac peut poser problème.\n"+\ - " Cette version n'admet que des photos au format JPG.\n"+\ - " L'outil libre XNView propose des conversions 'sans perte' à partir de multiples formats (via Imagemagick).\n\n"+\ - " Consulter la documentation de MicMac, outil réalisé par l'IGN.\n\n"+\ - " Consulter le guide d'installation et de prise en main d'AperoDeDenis.\n\n"+\ + _(" Afficher l'image 3D non densifiée : lance l'outil pour ouvrir les .PLY sur l'image 3D produite par Tapas") + "\n"+\ + _(" Afficher l'image 3D densifiée : lance l'outil pour ouvrir les .PLY sur l'image 3D produite par Malt ou C3DC") + "\n"+\ + "\n"+\ + _(" Lister Visualiser les images 3D : liste la pyramide des images 3D, créées à chaque étape de Malt") + "\n"+\ + _(" Fusionner des images 3D : permet de fusionner plusieurs PLY en un seul") + "\n\n"+\ + _("Menu MicMac :") + "\n\n"+\ + _(" - Choisir les photos : permet choisir les photos JPG, GIF, TIF ou BMP pour le traitement.") + "\n\n"+\ + _(" Les photos GIF et BMP seront converties en JPG (nécessite la présence de l'outil convert).") + "\n"+\ + _(" Un EXIF avec la focale utilisée pour la prise de vue est nécessaire : si besoin l'ajouter (menu Outil/ajout exif).") + "\n"+\ + _(" Remarques : 1) Si l'exif ne comporte pas la focale équivalente en 35 mm alors ")+ "\n"+\ + _(" le fichier DicoCamera.xml doit comporter la taille du capteur de l'appareil (voir menu Outils)") + "\n\n"+\ + _(" 2) Si les photos proviennent de plusieurs appareils alors les tags 'model' des exif doivent") + "\n"+\ + _(" être différenciés (voir menu Expert)") + "\n\n"+\ + _(" - Options : choisir les options des modules Tapioca, Tapas, GPS (nuage non densifié) puis de densification : ") + "\n\n"+\ + _(" Consulter le wiki MicMac pour obtenir de l'info sur les options, par exemple : https://micmac.ensg.eu/index.php/Tapas") + "\n\n"+\ + _(" Les options suivantes concernent le calcul du nuage de points NON densifié :") + "\n\n"+\ + _(" - Points homologues : Tapioca : options et sous options associées (échelles, fichier xml)")+ "\n"+\ + _(" Voir la documentation MicMac sur Tapioca.") + "\n"+\ + _(" - Orientation : Tapas : choix d'un type d'appareil photo , possibilité d'arrêter le traitement après tapas.") + "\n"+\ + _(" Le type d'appareil photo détermine le nombre de paramètres décrivant l'optique et le capteur.") + "\n"+\ + _(" Si plusieurs appareils photos alors il faut les distinguer, voir menu expert.") + "\n"+\ + _(" La calibration intrinsèque permet de déterminer les caractéristiques de l'appareil sur des photos spécifiques :") + "\n"+\ + _(" Par exemple photos d'un angle de batiment avec une grande longueur de mur.")+ "\n"+\ + _(" Ces photos ne servent pas nécessairement pour la suite du chantier.")+ "\n"+\ + _(" L'arrêt après Tapas est nécessaire pour décrire le masque 2D ou 3D.") + "\n"+\ + _(" Produit une image 3D non densifiée avec position des appareils photos.") + "\n\n"+\ + _(" - Mise à l'échelle : définir un axe, une zone plane, une distance pour définir le repère du chantier.") + "\n\n"+\ + _(" cette mise à l'échelle s'effectue sur le nuage de points homologues") + "\n\n"+\ + _(" - GPS : définir les points de calage (coordonnées GPS ou repère local) qui permettent de (géo)localiser la scène.") + "\n"+\ + _(" Une première ligne permet de définir les options du module CAMPARI qui améliore la précision des calculs.") + "\n"+\ + _(" Il faut indiquer la précision des cibles GPS (en unité du GPS) et la précision des points images (en pixels).") + "\n"+\ + _(" CAMPARI ne sera lancé que si les points GPS sont corrects ainsi que les 2 paramètres ci-dessus.") + "\n\n"+\ + _(" Pour être utilisé chaque point GPS, au minimum 3, doit être placé sur au moins 2 photos.") + "\n"+\ + _(" Le bouton 'appliquer' permet de calibrer le modèle non densifié immédiatement sur le nuage de points homologues.") + "\n\n"+\ + _(" - Densification : choix du module de densification : C3DC (récent) ou Malt (ancien).") + "\n"+\ + _(" - Malt : Si le mode est GeomImage : ") + "\n"+\ + _(" désigner une ou plusieurs images maîtresses") + "\n"+\ + _(" dessiner si besoin le ou les masques associés.") + "\n"+\ + _(" Seuls les points visibles sur les images maitres seront sur l'image 3D finale.") + "\n"+\ + _(" Le masque limite la zone utile de l'image 3D finale.") + "\n"+\ + _(" La molette permet de zoomer et le clic droit maintenu de déplacer l'image.") + "\n"+\ + _(" Supprimer une image maîtresse de la liste réinitialise le masque.") + "\n\n"+\ + _(" Nombre de photos utiles autour de l'image maîtresse :") + "\n"+\ + _(" Permet de limiter les recherches aux images entourant chaque image maîtresse.") + "\n\n"+\ + _(" Choix du niveau de densification final : 8,4,2 ou 1.") + "\n"+\ + _(" Le niveau 1 est le plus dense. ") + "\n"+\ + _(" La géométrie est revue à chaque niveau et de plus en plus précise : ") + "\n"+\ + _(" la densification s'accroît, et la géométrie s'affine aussi.") + "\n\n"+\ + _(" - C3DC : choix par défaut.") + "\n"+\ + _(" Possibilité de dessiner un masque 3D sur le nuage de points non dense.") + "\n"+\ + _(" Les touches fonctions à utiliser sont décrites dans l'onglet.") + "\n"+\ + _(" Le masque limite la zone en 3 dimensions de l'image finale.") + "\n"+\ + _(" L'outil de saisie est issu de micmac.") + "\n\n"+\ + _(" - Lancer MicMac : enregistre le chantier et lance le traitement avec les options par défaut ou choisies par l'item 'options'.") + "\n"+\ + _(" Relance micmac si l'arrêt a été demandé après tapas.") + "\n"+\ + _(" Lancer micmac bloque les photos et les options du chantier.") + "\n"+\ + _(" Pour débloquer le chantier il faut lancer micmac à nouveau et choisir le débloquage.") + "\n"+\ + _(" Le débloquage permet de relancer Malt sans relancer tapioca/tapas tout en conservant le modèle densifié, renommé.") + "\n\n"+\ + _("menu Vidéo :") + "\n\n"+\ + _(" - Options : indiquer le nom de la camera (GoPro, smartphone...), sa focale, sa focale equivalente 35mm") + "\n"+\ + _(" et le nombre d'images à conserver par seconde de film") + "\n"+\ + _(" Le nom permet de faire le lien avec DicoCamera.xml qui contient la taille du capteur.") + "\n"+\ + _(" Les focales seront recopiées dans l'exif des images.") + "\n"+\ + _(" Le nombre d'images par seconde sera utilisé pour la sélection des meilleures images.") + "\n\n"+\ + _(" Remarque :") + "\n"+\ + _(" Il faut indiquer dans DicoCamera la taille du capteur effectivement utilisée par la fonction camera,") + "\n"+\ + _(" taille qui peut être inférieure à la taille du capteur utilisée pour les photos.") + "\n"+\ + _(" Voir par exemple pour une camera Gopro :") + "\n"+\ + " http://www.kolor.com/wiki-en/action/view/Autopano_Video_-_Focal_length_and_field_of_view#About_GoPro_focal_length_and_FOV" + "\n\n"+\ + _(" - Nouveau chantier : choisir une video : choisir un fichier video issu d'une camera ou d'une GoPro.") + "\n"+\ + _(" La vidéo sera décompactée en images, l'exif sera créé avec les informations en options.") + "\n"+\ + _(" Cette étape nécessite la présence de l'outil ffmpeg sous le répertoire bin de MicMac (dépend de la version de MicMac).") + "\n"+\ + _(" Un nouveau chantier est créé avec les options suivante : Line pour Tapioca et FishEyeBasic pour Tapas.") + "\n\n"+\ + _(" - Sélection des images : il est raisonnable de ne garder que quelques images par seconde de film.") + "\n"+\ + _(" Le nombre d'images conservées par seconde est indiqué dans les options.") + "\n"+\ + _(" Chaque seconde de film les 'meilleures' images seront retenues, les autres effacées.") + "\n"+\ + _(" Attention : cette étape n'est pas effective pour toutes les versions de MicMac. La version mercurial 5508 fonctionne.") + "\n\n"+\ + _(" Une fois les images sélectionnées le chantier est créé : utiliser le menu MicMac comme pour un chantier normal.") + "\n\n"+\ + _("menu Outils :") + "\n\n"+\ + _(" - Info extraites de l'exif : fabricant, modèle, focale et dimensions en pixels de la première photo.") + "\n"+\ + _(" Il y a 2 types de focales : focale effective et focale équivalente 35 mm.") + "\n"+\ + _(" Indique si l'appareil photo est connu dans '/XML MicMac/DicoCamera.xml'.") + "\n\n"+\ + _(" - Afficher toutes les focales des photos : focales et focales equivalentes en 35mm.") + "\n"+\ + _(" Si les focales ne sont pas identiques pour toutes les photos : utiliser la calibration intrinséque de tapas.") + "\n"+\ + _(" Affiche aussi le nom de l'appareil photo pour chaque photo.") + "\n\n"+\ + _(" - Mettre à jour DicoCamera.xml : ajouter la taille du capteur dans '/XML MicMac/DicoCamera.xml'.") + "\n"+\ + _(" La taille du capteur dans DicoCamera.xml est requise si la focale équivalente 35mm est absente de l'exif.") + "\n"+\ + _(" La taille du capteur facilite les calculs et améliore les résultats.") + "\n"+\ + _(" La taille du capteur se trouve sur le site du fabricant ou sur http://www.dpreview.com.") + "\n\n"+\ + _(" - Qualité des photos du dernier traitement : calcule le nombre moyen de points homologues par photo.") + "\n"+\ + _(" Si des photos présentent des moyennes très faibles elles peuvent faire échouer le traitement.") + "\n\n"+\ + _(" - Qualité des photos 'Line' : calcule le nombre moyen de points homologues par photo en mode 'Line', taille 1000.") + "\n\n"+\ + _(" - Qualité des photos 'MulScale ou All' : calcule le nombre moyen de points homologues par photo, taille 1000.'.") + "\n"+\ + _(" Ce nombre informe sur la qualité relative des photos au sein du chantier.") + "\n"+\ + _(" La présence de photos avec peu de points homologues peut faire échouer le traitement.") + "\n"+\ + _(" Il est parfois préférable de traiter peu de photos mais de bonne qualité.") + "\n\n"+\ + _(" - Modifier l'exif des photos : permet la création et la modification des exifs des photos du chantier.") + "\n\n"+\ + _(" - Modifier les options par défauts : les valeurs par défaut de certains paramètres sont modifiables.") + "\n"+\ + _(" Les paramètres concernés sont ceux des onglets du menu MicMac/options : 'Points homologues',... : .") + "\n\n"+\ + _("menu Expert :") + "\n\n"+\ + _(" - Ouvrir une console permettant de passer des commandes système et MicMac (mm3d).") + "\n\n"+\ + _(" - Ouvrir une console permettant de passer des commandes Python (ex. : afficher une variable.") + "\n\n"+\ + _(" - Insérer de points GPS à partir d'un fichier texte, séparateur espace, format : X Y Z dx dy dz ") + "\n"+\ + _(" Le caractère # en début de ligne signale un commentaire.") + "\n\n"+\ + _(" - Recopier des points GPS à partir d'un autre chantier.") + "\n\n"+\ + _(" - Définir plusieurs appareils photos.") + "\n"+\ + _(" Si le lot de photos provient de plusieurs appareils de même type il faut informer MicMac de cette situation.") + "\n"+\ + _(" Plusieurs solutions existent dans MicMac.") + "\n"+\ + _(" AperoDeDenis propose de modifier le tag 'model' de l'exif des photos :") + "\n"+\ + _(" - en utilisant le numéro de série de l'appareil présent dans l'exif") + "\n"+\ + _(" - à défaut en utilisant 3 caractères du préfixe des noms de fichiers, que l'utilisateur a préparé de telle sorte") + "\n"+\ + _(" que chaque préfixe corresponde à un appareil. Certains appareil proposent de modifier qyqtématiquement ce préfixe.") + "\n\n"+\ + _(" - Lister les appareils photos présents dans le lot de photos.") + "\n\n"+\ + _(" - Consulter le fichier de logging MicMac : mm3d-logFile.txt.") + "\n\n"+\ + _("menu Paramétrage :") + "\n\n"+\ + _(" - Afficher les paramètres : visualise les chemins de micmac\\bin, d'exiftool, du fichier pour visualiser les .ply (Meshlab ou Cloud Compare),") + "\n"+\ + _(" ainsi que le répertoire où se trouve les fichiers paramètres de l'interface.") + "\n"+\ + _(" Ces paramètres sont sauvegardés de façon permanente dans le fichier :")+\ + " "+self.fichierParamMicmac+"." + "\n\n"+\ + _(" - Désigner le répertoire MicMac\\bin : répertoire où se trouvent les modules de MicMac ") + "\n"+\ + _(" Si plusieurs versions sont installées cet item permet de changer facilement la version de MicMac utilisée.") + "\n\n"+\ + _(" - Désigner l'application exiftool, utile pour modifier les exif (elle se trouve sous micMac\\binaire-aux).") + "\n\n"+\ + _(" - Désigner l'application convert d'ImageMagick, utile pour convertir les gif, tif et bmp en jpg (elle se trouve sous micMac\\binaire-aux).") + "\n\n"+\ + _(" - Désigner l'application ouvrant les fichiers .PLY. Ce peut être Meshlab, CloudCompare ou autre.") + "\n"+\ + _(" Sous Windows Meshlab se trouve sous un répertoire nommé VCG.") + "\n\n"+\ + _(" - Activer/désactiver le 'tacky' message de lancement")+ "\n\n"+\ + _("menu Aide :") + "\n\n"+\ + _(" - Pour commencer : à lire lors de la prise en main de l'interface.") + "\n\n"+\ + _(" - Aide : le détail des items de menu.") + "\n\n"+\ + _(" - Quelques conseils : sur la prise de vue et les options.") + "\n\n"+\ + _(" - Historique : les nouveautés de chaque version.") + "\n\n"+\ + _(" - A propos") + "\n\n\n"+\ + _(" Quelques précisions :") + "\n"+\ + _(" Cette version a été développée sous Windows XP et Seven avec micmac rev 5508 d'avril 2015.") + "\n"+\ + _(" L'utilisation d'autres versions de Micmac a été testée, jusqu'à la version 6219.") + "\n\n"+\ + _(" Le fonctionnement sous Ubuntu Trusty a été vérifié.") + "\n\n"+\ + _(" Consulter la documentation de MicMac, outil réalisé par l'IGN.") + "\n\n"+\ + _(" Consulter le guide d'installation et de prise en main d'AperoDeDenis.") + "\n\n"+\ "--------------------------------------------- "+self.titreFenetre+" ---------------------------------------------" self.cadreVide() + self.effaceBufferTrace() self.ajoutLigne(aide1) + fenetre.state('zoomed') self.texte201.see("1.1") def conseils(self): - aide2= "Interface graphique pour lancer les modules de MICMAC : quelques conseils.\n\n"+\ - "Prises de vue :\n"+\ - " - Le sujet doit être immobile durant toutes la séance de prise de vue.\n"+\ - " - Les photos doivent être nettes : attention à la profondeur de champ.\n"+\ - " Les photos de personnes ou d'objet en mouvement sont déconseillées\n"+\ - " Les surfaces lisses ou réfléchissantes sont défavorables.\n"+\ - " - Si le sujet est central prendre une photo tous les 20°, soit 9 photos pour un 'demi-tour', 18 pour un tour complet.\n"+\ - " - Si le sujet est en 'ligne' le recouvrement entre photos doit être des 2/3 au minimum.\n"+\ - " - Tester la 'qualité' des photos au sein du chantier (voir les items du menu Outils).\n"+\ - " les photos ayant un mauvais score doivent être supprimées du chantier : elle peuvent faire échouer le traitement.\n"+\ - " - La présence des dimensions du capteur de l'appareil dans DIcoCamera.xml améliore le traitement.\n"+\ - " Cette présence est obligatoire si l'exif ne présente pas la focale équivalente 35mm.\n"+\ - " Pour ajouter la taille du capteur utiliser le menu 'Outils//metre à jour DicoCamera'.\n"+\ - "Précautions : \n" +\ - " Toutes les photos doivent être prises avec la même focale, ne pas utiliser la fonction autofocus.\n"+\ - " Eviter aussi la fonction 'anti tremblement' qui agit en modfiant la position du capteur.\n\n" +\ - "Options :\n"+\ - " - Tapioca : Si le sujet est central conserver les paramètres par défaut.\n" +\ - " - Tapioca : Si le sujet est en ligne choisir 'line' dans les options de Tapioca, \n" +\ - " puis delta = 1, si les photos se recouvrent au 2/3, \n" +\ - " ou delta = 2 voire +, si le recouvrement est plus important.\n\n" +\ - " - Tapas : Si l'appareil photo est un compact ou un smartphone choisir RadialBasic, \n" +\ - " Si l'appareil photo est un reflex haut de gamme choisir RadialExtended \n" +\ - " Si l'appareil photo est de moyenne gamme choisir RadialStd \n" +\ - " L'arrêt aprés Tapas est conseillé : la visualisation du nuage de points non densifié\n" +\ - " permet de définir un masque, 2D ou 3D, pour l'étape suivante.\n\n" +\ - " - Calibration : permet de définir un repère et une métrique(axe, plan et distance obligatoires).\n\n"+\ - " - Malt : pour le mode GeomImage indiquer une image maitresse, choisir la plus représentative du résultat souhaité.\n" +\ - " Seuls les points visibles sur cette image seront conservés dans le nuage de points.\n" +\ - " Sur cette image maitresse tracer le masque en 2 Dimensions délimitant la partie 'utile' de la photo.\n"+\ - " Le traitement avec masque sera accéléré et le résultat plus 'propre'.\n\n" +\ - " - C3DC : propose de définir un masque en 3D qui conservera tout le volume concerné.\n" +\ - " Alternative à Malt, le traitement est beaucoup plus rapide. Nécessite la dernière version de MicMac.\n\n"+\ - " - GPS : définir des points cotés et les placer sur 2 photos. La trace indique s'ils sont pris en compte\n"+\ + aide2 = _("Interface graphique pour lancer les modules de MICMAC : quelques conseils.") + "\n\n"+\ + _("Prises de vue :") + "\n"+\ + _(" - Le sujet doit être immobile durant toutes la séance de prise de vue.") + "\n"+\ + _(" - Le sujet doit être unique et d'un seul tenant") + "\n"+\ + _(" - Le sujet doit être bien éclairé, la prise de vue en plein jour doit être recherchée.") + "\n"+\ + _(" - Les photos doivent être nettes, attention à la profondeur de champ :") + "\n"+\ + _(" utiliser la plus petite ouverture possible (nombre F le plus grand, par exemple 22).") + "\n"+\ + _(" - Utiliser la calibration intrinsèque des appareils photos (item MicMac/Options/Orientation ).") + "\n"+\ + _(" - Les photos de personnes ou d'objet en mouvement sont déconseillées") + "\n"+\ + _(" - Les surfaces lisses ou réfléchissantes sont défavorables.") + "\n"+\ + _(" - Si le sujet est central prendre une photo tous les 20°, soit 9 photos pour un 'demi-tour', 18 pour un tour complet.") + "\n"+\ + _(" - Si le sujet est en 'ligne' le recouvrement entre photos doit être des 2/3.") + "\n"+\ + _(" - Tester la 'qualité' des photos au sein du chantier (voir les items du menu Outils).") + "\n"+\ + _(" les photos ayant un mauvais score (voir le menu Outils/Qualité des photos 'All') doivent être supprimées du chantier : ")+ "\n"+\ + _(" une seule mauvaise photo peut faire échouer le traitement.") + "\n"+\ + _(" - La présence des dimensions du capteur de l'appareil dans DicoCamera.xml améliore le traitement.") + "\n"+\ + _(" Cette présence est obligatoire si l'exif ne présente pas la focale équivalente 35mm.") + "\n"+\ + _(" Pour ajouter la taille du capteur utiliser le menu 'Outils//mettre à jour DicoCamera'.") + "\n\n"+\ + _(" Précautions : ") + "\n"+\ + _(" Ne pas utiliser la fonction autofocus. Deux focales différentes maximum pour un même chantier.") + "\n"+\ + _(" Eviter aussi la fonction 'anti tremblement' qui agit en modfiant la position du capteur.") + "\n\n" +\ + _("Options :") + "\n"+\ + _(" - Points homologues : ") + "\n" +\ + _(" L'échelle est la taille en pixels de l'image (ou -1 pour l'image entière) pour la recherche des points homologues.") + "\n" +\ + _(" Si le sujet est en ligne choisir 'line' dans les options de Tapioca, ") + "\n" +\ + _(" puis delta = 1, si les photos se recouvrent à moitiè, ") + "\n" +\ + _(" ou delta = 2 voire +, si le recouvrement est plus important.") + "\n\n" +\ + _(" L'option ALl recherche les points homologues sur toutes les paires de photos (ce qui peut faire beaucoup !)") + "\n" +\ + _(" L'option MulScale recherche les points homologues en 2 temps :") + "\n" +\ + _(" 1) sur toutes les paires avec une taille de photo réduite (typiquement 300)") + "\n" +\ + _(" 2) Seules les paires de photos ayant eu au moins 2 points homologues à cette échelle seront") + "\n" +\ + _(" retenues pour rechercher les points homologues à la seconde échelle. Gain de temps important possible.") + "\n" +\ + _(" - Orientation : si l'appareil photo est un compact ou un smartphone choisir RadialBasic, ") + "\n"+\ + _(" si l'appareil photo est un reflex haut de gamme choisir RadialExtended ") + "\n" +\ + _(" si l'appareil photo est de moyenne gamme choisir RadialStd") + "\n" +\ + _(" Ces conseils ne sont pas toujours vérifiés : modifeir votre choix s'il échoue. ") + "\n"+\ + _(" L'arrêt après l'orientation permet de définir un masque 3D, pour la densification par C3DC.") + "\n" +\ + _(" - Mise à l'échelle : permet de définir un repère et une métrique (axe, plan et distance, tous obligatoires).") + "\n\n"+\ + _(" - Points GPS: définir au moins 3 points cotés et les placer sur 2 photos. L'état du chantier indique s'ils sont pris en compte") + "\n\n"+\ + _(" - Densification par Malt : pour le mode GeomImage indiquer une ou plusieurs images maîtresses.") + "\n" +\ + _(" Seuls les points visibles sur ces images seront conservés dans le nuage de points.") + "\n" +\ + _(" Sur ces images maîtresses tracer les masque délimitant la partie 'utile' de la photo.") + "\n"+\ + _(" Le résultat sera mis en couleur suivant les images maitresses.") + "\n"+\ + _(" (éviter trop de recouvrement entre les maîtresses !).") + "\n"+\ + _(" Le traitement avec masque sera accéléré et le résultat plus 'propre'.") + "\n\n" +\ + _(" - Densification par C3DC : propose de définir un masque en 3D qui conservera tout le volume concerné.") + "\n" +\ + _(" Alternative à Malt, le traitement est parfois plus rapide. Nécessite une version récente de MicMac.") + "\n\n"+\ + _("Si MicMac ne trouve pas d'orientation ou pas de nuage de points :") + "\n\n"+\ + _(" - Examiner la trace et la qualité des photos (utiliser le menu outils/Qualité des photos): .") + "\n"+\ + _(" 0) Prenez un pastis") + "\n"+\ + _(" 1) si erreur dans la trace : 'Radiale distorsion abnormaly high' :") + "\n"+\ + _(" modifier le type d'appareil pour l'orientation (radialstd ou radialbasic ou RadialExtended ou...)") + "\n"+\ + _(" 2) Eliminer les photos ayant les plus mauvais scores, les photos ou groupe de photos 'isolées") + "\n"+\ + _(" 3) si ce n'est pas suffisant ne garder que les meilleures photos (typiquement : moins de 10)") + "\n"+\ + _(" Penser que des photos floues ou avec un sujet brillant, lisse, mobile, transparent, vivant sont défavorables.")+ "\n"+\ + _(" 4) Augmenter l'échelle des photos pour tapioca, mettre -1 au lieu de la valeur par défaut.") + "\n"+\ + _(" 5) Utiliser la calibration intrinsèque sur des photos adaptées") + "\n"+\ + _(" 6) Si plusieurs appareils photos sont utilisés il faut les distinguer dans l'exif (voir menu expert)") + "\n"+\ + _(" et prendre des photos spécifiques pour la calibration intrinsèque de chaque appareil.") + "\n"+\ + _(" 7) vérifier la taille du capteur dans dicocamera, nécessaire si la focale equivalente 35 mm est absente de l'exif") + "\n"+\ + _(" 8) examiner la trace synthétique et la trace complète : MicMac donne quelques informations") + "\n"+\ + _(" si la trace compléte contient : 'Error: -- Input line too long, increase MAXLINELENGTH'") + "\n"+\ + _(" alors tenter, sans certitude, de modifier le fichier /binaire-aux/windows/startup/local.mk") + "\n"+\ + _(" ou, sous windows, limiter la longueur du chemin menant aux fichiers en recopiant les photos sous la racine du disque.") + "\n"+\ + _(" si la trace synthétique contient'Not Enouh Equation in ElSeg3D::L2InterFaisceaux' alors choisir 'radialbasic'.") + "\n"+\ + _(" 9) consulter le wiki micmac (https://micmac.ensg.eu/index.php)") + "\n"+\ + _(" 10) consulter le forum micmac (http://forum-micmac.forumprod.com)") + "\n"+\ + _(" 11) faites appel à l'assistance de l'interface (voir adresse dans l'a-propos)") + "\n\n"+\ "--------------------------------------------- "+self.titreFenetre+" ---------------------------------------------" - self.encadre (aide2,50,aligne='left',nouveauDepart='non') + self.cadreVide() + self.effaceBufferTrace() + self.ajoutLigne(aide2) + fenetre.state('zoomed') + self.texte201.see("1.1") def commencer(self): - aide3= \ - " Pour commencer avec l'interface graphique MicMac :\n\n"+\ - " Tout d'abord : Installer MicMac.\n"+\ - " Puis : Installer Meshlab ou CloudCompare (pour afficher les nuages de points)\n\n"+\ - " Ensuite, dans cette interface graphique :\n\n"+\ - "1) Paramétrer l'interface : indiquer ou se trouvent le répertoire bin de MicMac et l'éxécutable Meshlab ou CloudCompare.\n"+\ - "2) Choisir quelques photos, pas plus de 5 pour commencer (menu MicMac).\n"+\ - "3) Lancer MicMac en laissant les paramètres par défaut (menu MicMac).\n"+\ - " Si tout va bien une vue en 3D non densifiée doit s'afficher, patience : cela peut être long.\n"+\ - "4) Si tout va bien alors modifier les paramétres pour la suite du traitement (Malt ou C3DC) (voir la doc).\n"+\ - " Puis re lancer MicMac pour obtenir une vue 3D densifiée.\n\n"+\ - "5) Si tout ne va pas bien re 'lancer MicMac' et annuler le traitement, puis :\n"\ - " Lire 'quelques conseils' (menu Aide).\n"+\ - " Tester la qualité des photos (menu Outils, aprés avoir paramètré exiftool).\n"+\ - " Examiner les traces (menu Edition),\n"+\ - " Consulter l'aide (menu Aide),\n"+\ - " Consulter le guide d'installation et de prise en main de l'interface.\n"+\ - " Consulter le forum MicMac sur le net, consulter la doc MicMac.\n"+\ - "6) Si une solution apparaît : modifier les options (menu MicMac).\n"+\ - " puis relancer le traitement.\n"+\ - "7) Si le problème persiste faire appel à l'assistance de l'interface (adresse mail dans l'A-propos)\n" - self.encadre (aide3,50,aligne='left',nouveauDepart='non') + aide3 = \ + _(" Pour commencer avec l'interface graphique MicMac :") + "\n\n"+\ + _(" Tout d'abord : installer MicMac. Consulter le wiki MicMac : https://micmac.ensg.eu/index.php") + "\n"+\ + _(" Puis : installer CloudCompare (ou Meshlab) (pour afficher les nuages de points)") + "\n\n"+\ + _(" Ensuite, dans cette interface graphique :") + "\n\n"+\ + _("1) Paramètrer l'interface : indiquer ou se trouvent le répertoire bin de MicMac et l'éxécutable CloudCompare (ou Meshlab).") + "\n"+\ + _(" Indiquer éventuellement ou se trouvent exiftool et convert d'ImageMagick (en principe sous MicMac\\binaire-aux).") + "\n"+\ + _(" Vérifier en affichant les paramètres (menu paramètrage).") + "\n\n"+\ + _("2) Choisir quelques photos (4 à 6) pour commencer (menu MicMac/choisir des photos).") + "\n\n"+\ + _("3) Lancer MicMac en laissant les paramètres par défaut (menu MicMac/lancer Micmac).") + "\n"+\ + _(" Si tout va bien une vue en 3D non densifiée doit s'afficher, puis une vue 3D densifiée. Patience : cela peut être long.") + "\n\n"+\ + _("4) Si tout ne va pas bien prendre un pastis puis :") + "\n"+\ + _(" Lire 'quelques conseils' (menu Aide).") + "\n"+\ + _(" Tester la qualité des photos (menu Outils).") + "\n"+\ + _(" Examiner les traces (menu Edition),") + "\n"+\ + _(" Consulter l'aide (menu Aide),") + "\n"+\ + _(" Consulter le guide d'installation et de prise en main de l'interface.") + "\n"+\ + _(" Consulter le forum MicMac sur le net, consulter la doc MicMac.") + "\n\n"+\ + _("5) Si une solution apparaît : modifier les options (menu MicMac/options).") + "\n"+\ + _(" puis relancer le traitement.") + "\n\n"+\ + _("6) Si le problème persiste faire appel à l'assistance de l'interface (adresse mail dans Aide/A-propos)") + "\n" + self.encadre (aide3,50,aligne='left') + + def historiqueDesVersions(self): + aide4 = \ + _("Historique des versions diffusées sur le site de l'IGN") + "\n"+\ + "----------------------------------------------------------"+\ + "\n" + _("Version 1.5 : première version diffusée sur le site de l'IGN le 23/11/2015.") + "\n"+\ + "\n" + _("Version 1.55 : sous Windows le fichier paramètre est placé sous le répertoire APPDATA de l'utilisateur,") + "\n"+\ + chr(9)+chr(9)+_("ce qui règle les questions relatives aux droits d'accès en écriture. Mise en ligne le 04/12/2015.") + "\n"+\ + "\n" + _("Version 1.60 : ajout des fonctions :") + "\n"+\ + chr(9)+chr(9)+_("- Qualité des photos lors du dernier traitement") + "\n"+\ + chr(9)+chr(9)+_("- Exporter le chantier en cours") + "\n"+\ + chr(9)+chr(9)+_("- Importer un chantier (permet de recopier le chantier sur un autre répertoire, disque, ordinateur, système d'exploitation)") + "\n"+\ + chr(9)+chr(9)+_("- Les fichiers 'trace' sont enregistrés au format utf-8.") + "\n\n"+\ + _("Version 2.00 : ajout des fonctions :") + "\n"+\ + chr(9)+chr(9)+_("- Choix de photos pour la calibration intrinsèque par Tapas.") + "\n"+\ + chr(9)+chr(9)+_("- Possibilité de relancer Malt sans relancer Tapioca/Tapas tout en conservant les images 3D générées.") + "\n"+\ + chr(9)+chr(9)+_("- Conservation de plusieurs fichiers modele3D.ply après Malt pour un même chantier.") + "\n"+\ + chr(9)+chr(9)+_("- Choix du niveau de zoom d'arrêt de la procédure Malt : de 1 (par défaut) à 8.") + "\n"+\ + chr(9)+chr(9)+_("- Création de tous les fichiers .ply correspondants à tous les niveaux de zoom calculés.") + "\n"+\ + chr(9)+chr(9)+_("- Ajout d'un item du menu édition listant et visualisant toutes les images 3D générées.") + "\n"+\ + chr(9)+chr(9)+_("- Choix du nombre de photos à retenir autour de l'image maître pour Malt.") + "\n"+\ + chr(9)+chr(9)+_("- Traitement des vidéos (par exemple GoPro) : décompactage, sélection, mise à jour de l'exif") + "\n"+\ + chr(9)+chr(9)+_("- Ajout de deux contrôles sur le lot des photos : mêmes dimensions, même focale.") + "\n"+\ + chr(9)+chr(9)+_("- Ajout d'un item 'historique' dans le menu Aide.") + "\n"+\ + "\n" + _("Version 2.10")+chr(9)+_("- Ajout d'un item du menu édition fusionnant les images 3D.") + "\n"+\ + chr(9)+chr(9)+_("- Plusieurs images maîtresses, plusieurs masques.") + "\n"+\ + chr(9)+chr(9)+_("- Conversion automatique des fichiers PNG, BMP, GIF, TIF en JPG") + "\n"+\ + chr(9)+chr(9)+_("- Ajout d'un item du menu Outils permettant de modifier les exifs. Diffusion restreinte à la DTer NC le 16/02/2016") + "\n"+\ + "\n" + _("Version 2.20 :")+chr(9)+_("- Maintien des options compatibles lors du choix de nouvelles photos. Février 2016") + "\n"+\ + "\n" + _("Version 2.30 : ")+\ + chr(9)+_("- Modification des options par défaut dans le menu outils.") + "\n"+\ + "\n" + _("Version 2.40 :")+chr(9)+_("- Choix de l'option (Statue ou QuickMac) pour C3DC. Avril 2016") + "\n"+\ + "\n" + _("Version 2.45 :")+chr(9)+_("- Référentiel GPS calculé après Tapas (et toujours avant Malt). La virgule est un séparateur décimal accepté.") + "\n"+\ + chr(9)+chr(9)+_("- Possiblité d'appliquer la calibration GPS sans relancer malt. Mai 2016") + "\n"+\ + "\n" + _("Version 2.50 :")+chr(9)+_("- Ajout de Tawny après Malt en mode Ortho, désactivation du message de lancement. Juin 2016") + "\n"+\ + "\n" + _("Version 3.00 :")+chr(9)+_("- Version bilingue Français/Anglais. Octobre 2016") + "\n"+\ + "\n" + _("Version 3.10 :")+chr(9)+_("- Choix des N meilleures photos pour un nouveau dossier. Novembre 2016") + "\n"+\ + "\n" + _("Version 3.20 :")+chr(9)+_("janvier 2017") + "\n"+\ + chr(9)+chr(9)+_("- Ajout d'un choix pour Malt : AperoDeDenis, l'interface recherche pour vous les maîtresses et les photos correspondantes") + "\n"+\ + chr(9)+chr(9)+_("- Item de sélection des meilleures images pour créer un nouveau chantier. janvier 2017") + "\n"+\ + chr(9)+chr(9)+_("- Possibilité de saisir une unité avec la distance.") + "\n"+\ + chr(9)+chr(9)+_("- Lancement de Tapas accéléré : suppression du controle des photos") + "\n"+\ + chr(9)+chr(9)+_("- Les photos autour de la maîtresse pour Malt sont choisies parmi les meilleures en correspondances") + "\n"+\ + chr(9)+chr(9)+_("- Controle affiné des points GPS, message informatif détaillé") + "\n"+\ + chr(9)+chr(9)+_("- Possibilité de supprimer UN seul point GPS sur une photo") + "\n"+\ + "\n" + _("Version 3.30 :")+chr(9)+_("janvier 2017") + "\n"+\ + chr(9)+chr(9)+_("- Ajout de tarama : création d'une mosaïque après Tapas.") + "\n"+\ + chr(9)+chr(9)+_("- le mode Ortho de Malt utilise la mosaïque tarama, avec masque") + "\n"+\ + chr(9)+chr(9)+_("- drapage du nuage densifié par l'ortho mosaïque obtenue par Tawny") + "\n"+\ + chr(9)+chr(9)+_("- Possibilité d'inverser les masques 2D") + "\n"+\ + chr(9)+chr(9)+_("- Ouverture des mosaïques Tarama et Tawny par menu") + "\n"+\ + chr(9)+chr(9)+_("- Ajout d'un menu 'expert' permettant de saisir une ligne de commande.") + "\n"+\ + "\n" + _("Version 3.31 :")+chr(9)+_("février 2017") + "\n"+\ + chr(9)+chr(9)+_("- Ajout d'un item du menu 'expert' : recopie les points GPS d'un chantier à un autre.") + "\n"+\ + "\n" + _("Version 3.34 :")+chr(9)+_("Janvier 2018") + "\n"+\ + chr(9)+chr(9)+_("- Du ménage! permet de conserver les résultats OU de supprimer tout le chantier.") + "\n"+\ + chr(9)+chr(9)+_("- Affichage de la taille du dossier.") + "\n"+\ + chr(9)+chr(9)+_("- Correction de régressions de la V 3.20.") + "\n"+\ + chr(9)+chr(9)+_("Remarque : la version 4.11 de décembre 2017 ajoute un item métier de calcul d'indice surfacique,") + "\n"+\ + "\n" + _("Version 5.0 :")+chr(9)+_("Janvier 2018") + "\n"+\ + chr(9)+chr(9)+_("la version suivante 5.0 supprime l'item 'indices surfaciques'.") + "\n"+\ + "\n" + _("Version 5.1 :")+chr(9)+_("décembre 2018") + "\n"+\ + chr(9)+chr(9)+_("- permet d'oublier les photos ayant servies à la calibration de l'appareil pour l'exécution de Tapas.") + "\n"+\ + chr(9)+chr(9)+_("- insertion d'un fichier texte de points GPS par le menu expert (séparateur espace : nom,x,y,z,dx,dy,dz.") + "\n"+\ + chr(9)+chr(9)+_("- affichage des dimensions des photos dans le menu outils/nom de l'appareil photo") + "\n"+\ + chr(9)+chr(9)+_("- Amélioration de libellés de boites de dialogue, suppression du polysème 'calibration'") + "\n"+\ + "\n" + _("Version 5.2 :")+chr(9)+_("janvier 2019") + "\n"+\ + chr(9)+chr(9)+_("- ajout du modulé CAMPARI après chaque géolocalisation par points GPS (améliore les valeurs des Z).") + "\n"+\ + chr(9)+chr(9)+_("- répartition des photos provenant de plusieurs appareils par modification du 'model' dans l'exif (menu expert)") + "\n"+\ + chr(9)+chr(9)+_("- affichage des noms des appareils photos présents dans le chantier (menu expert)") + "\n"+\ + chr(9)+chr(9)+_("- affichage du log des traitement MicMac : mm3d-logFile.txt (menu expert)") + "\n"+\ + chr(9)+chr(9)+_("- amélioration de la fonction console système (Expert/Exécuter une commande)") + "\n"+\ + "\n" + _("Version 5.21 :")+chr(9)+_("février 2019") + "\n"+\ + chr(9)+chr(9)+_("- Argument de Tapas aprés calibration : Figee (au lieu de Autocal)") + "\n"+\ + chr(9)+chr(9)+_("- Ajout dans le menu expert d'un console python") + "\n"+\ + "\n" + _("Version 5.22 :")+chr(9)+_("11 février 2019") + "\n"+\ + chr(9)+chr(9)+_("- fix 2 issues remontées sur github, numéro de version inchangée : 5.21") + "\n"+\ + "\n" + _("Version 5.30 :")+chr(9)+_("21 février 2019") + "\n"+\ + chr(9)+chr(9)+_("- dans les items 'Outils/Qualité des photos' ajout des photos 'isolées', en disjontion de toutes les autres.") + "\n"+\ + chr(9)+chr(9)+_(" Ces photos font 'planter' la recherche de l'orientation.") + "\n"+\ + chr(9)+chr(9)+_("- Suite à la recherche des points homologues vérification de l'unicité de la scène photographiée.") + "\n"+\ + chr(9)+chr(9)+_(" Plusieurs scènes sans point homologue commun font planter la recherche d'une orientation.") + "\n"+\ + chr(9)+chr(9)+_(" Cette fonction est ajoutée à l'item 'Outils/Qualité des photos'.") + "\n"+\ + chr(9)+chr(9)+_("- Lorsque le message MAXLINELENGTH est émis par Tapioca il est affiché et expliqué dans la trace synthétique.") + "\n"+\ + chr(9)+chr(9)+_("- prise en compte de l'issue concernant la fonction filedialog sous Mac-Os lors des recherche de programmes (exiftool...).") + "\n"+\ + chr(9)+chr(9)+_("- Ajout d'un item dans paramètrage : recherche d'une nouvelle version GitHub.") + "\n"+\ + "\n" + _("Version 5.31 :")+chr(9)+_("8 mars 2019") + "\n"+\ + chr(9)+chr(9)+_("- Les échelles par défaut de Tapioca sont calculées suivant les photos : 60% de la dimension maxi des photos.") + "\n"+\ + chr(9)+chr(9)+_("- suppresssion des items de menu outils\qualité des photos line et qualité des photos ALL.") + "\n"+\ + chr(9)+chr(9)+_("- Arrêt de Tapioca MulScele aprés le premier passage si la scène n'est pas unique, rendant l'échec certain.") + "\n"+\ + chr(9)+chr(9)+_("- Ajout de 1 item outils/retirer des photos.") + "\n"+\ + "----------------------------------------------------------" + + self.cadreVide() + self.effaceBufferTrace() + self.ajoutLigne(aide4) + fenetre.state('zoomed') + self.texte201.see("1.1") def aPropos(self): - aide2=self.titreFenetre+("\n\nRéalisation Denis Jouin 2015\n\nLaboratoire Régional de Rouen\n\n"+ - "Direction Territoriale Normandie Centre\n\n CEREMA\n\ninterface-micmac@cerema.fr") + aide5=self.titreFenetre+("\n\n" + _("Réalisation Denis Jouin 2015-2019") + "\n\n" + _("Laboratoire Régional de Rouen") + "\n\n"+ + _("CEREMA Normandie Centre") + "\n\n" + "mail : interface-micmac@cerema.fr") - self.encadre (aide2,aligne='center',nouveauDepart='non') + self.encadre (aide5,aligne='center') #ajout du logo du cerema si possible try: - self.logo = ttk.Frame(self.resul100) # cadre dans la fenetre ; affiche la photo sélectionnée - self.canvasLogo = tkinter.Canvas(self.logo,width = 225, height = 80) # Canvas pour revevoir l'image self.canvasLogo.pack(fill='both',expand = 1) self.logo.pack() self.imageLogo = Image.open(self.logoCerema) self.img = self.imageLogo.resize((225,80)) self.imgTk = ImageTk.PhotoImage(self.img) self.imgTk_id = self.canvasLogo.create_image(0,0,image = self.imgTk,anchor="nw") # affichage effectif de la photo dans canvasPhoto - ttk.Label(self.logo,text="MicMac est une réalisation de l'IGN").pack(pady=5) - except: - pass + if self.labelIgn.winfo_manager()!="pack": + self.labelIgn.pack(pady=5) + + except Exception as e: print(_("erreur canvas logo cerema : ")+str(e)) #ajout du logo IGN si possible if os.path.exists(self.logoIGN): - try: - self.logoIgn = ttk.Frame(self.resul100) # cadre dans la fenetre ; affiche la photo sélectionnée - self.canvasLogoIGN = tkinter.Canvas(self.logoIgn,width = 149, height = 162) # Canvas pour revevoir l'image + try: self.canvasLogoIGN.pack(fill='both',expand = 1) - self.logoIgn.pack(pady=5) - self.imageLogoIGN = Image.open(self.logoIGN) # self.logoIGN = nom du fichier png + self.logoIgn.pack(pady=5) + self.imageLogoIGN = Image.open(self.logoIGN) # self.logoIGN = nom du fichier png (ne pas confondre avec logoIgn en minuscule= frame) self.imgIGN = self.imageLogoIGN.resize((149,162)) self.imgTkIGN = ImageTk.PhotoImage(self.imgIGN) self.imgTk_idIGN = self.canvasLogoIGN.create_image(0,0,image = self.imgTkIGN,anchor="nw") # affichage effectif de la photo dans canvasPhoto @@ -4011,16 +7240,18 @@ def aPropos(self): ################################## Le menu FICHIER : nouveau, Ouverture, SAUVEGARDE ET RESTAURATION, PARAMETRES, outils divers ########################################################### - def sauveParam(self): # La sauvegarde ne concerne que 2 fichiers; fixes, sous le répertoire d'aperodedenis, - # pour les paramètres généraux : self.fichierParamMicmac - # pour le chantier en cours : self.fichierParamChantierEnCours + def sauveParam(self): # La sauvegarde ne concerne que 2 fichiers; fixes, sous le répertoire des paramètres, + # - pour les paramètres généraux : self.fichierParamMicmac + # - pour le chantier en cours : self.fichierParamChantierEnCours + # pour enregistrer le chantier en cours utiliser : + # - copierParamVersChantier() self.sauveParamMicMac() self.sauveParamChantier() def sauveParamChantier(self): - - try: - sauvegarde1=open(self.fichierParamChantierEnCours,mode='wb') + essai = (self.fichierParamChantierEnCours+"essai") # pour éviter d'écraser le fichier si le disque est plein + try: + sauvegarde1=open(essai,mode='wb') pickle.dump(( self.repertoireDesPhotos, self.photosAvecChemin, @@ -4038,55 +7269,96 @@ def sauveParamChantier(self): self.modeMalt.get(), self.fichierMasqueXML, self.repTravail, - self.photosPropresAvecChemin, + self.photosAvecChemin, # a supprimer (doublon avec r2) self.extensionChoisie, - self.nomMaitreSansExtension, + self.maitreSansExtension, self.etatDuChantier, self.dicoPointsGPSEnPlace, self.maitre, - self.masque, + self.mercurialMicMac, self.idPointGPS, self.dicoLigneHorizontale, self.dicoLigneVerticale, self.dicoCalibre, self.distance.get(), - self.monImage_MaitrePlan, # Nom de l'image maitresse du plan repere (sans extension) + self.monImage_MaitrePlan, # Nom de l'image maîtresse du plan repere (sans extension) self.monImage_PlanTif, # nom du masque correspondant self.etatSauvegarde, self.modeCheckedTapas.get(), - self.echelle4.get() + self.echelle4.get(), + self.photosPourCalibrationIntrinseque, + self.calibSeule.get(), + self.zoomF.get(), + self.photosUtilesAutourDuMaitre.get(), + self.modele3DEnCours, + self.typeDuChantier, + self.listeDesMaitresses, + self.listeDesMasques, + self.choixDensification.get(), + self.modeC3DC.get(), + self.tawny.get(), + self.tawnyParam.get(), + version, + None, #supprimé en v 5.2 + self.lancerTarama.get(), + self.incertitudeCibleGPS.get(), + self.incertitudePixelImage.get(), + self.chantierNettoye, + self.lesTagsExif, ), sauvegarde1) sauvegarde1.close() + supprimeFichier(self.fichierParamChantierEnCours) + os.rename(essai,self.fichierParamChantierEnCours) except Exception as e: - print ('erreur sauveParamChantier : ',e) + print (_('erreur sauveParamChantier : '),str(e)) def sauveParamMicMac(self): - + essai = (self.fichierParamMicmac+"essai") # pour éviter d'écraser le fichier si le disque est plein try: - sauvegarde2=open(self.fichierParamMicmac,mode='wb') - pickle.dump((self.micMac, - self.meshlab, + sauvegarde2=open(essai,mode='wb') + repertoire = self.verifParamRep() + pickle.dump((repertoire[0], + repertoire[1], self.indiceTravail, self.tousLesChantiers, - self.exiftool, - self.mm3d + repertoire[2], + repertoire[3], + repertoire[4], + self.tacky, + version, + langue, + repertoire[5], + versionInternet, # dernière version lue sur Internet + # permet de repérer les nouvelles versions et de réactiver le message + self.messageVersion # bool : si vrai on prévient l'utilisateur qu'il y a une nouvelle version (si pas la même, sinon pas ), sauvegarde2) - sauvegarde2.close() + sauvegarde2.close() + supprimeFichier(self.fichierParamMicmac) + os.rename(essai,self.fichierParamMicmac) except Exception as e: # Controle que le programme a accès en écriture dans le répertoire d'installation - print ('erreur sauveParamMicMac : ',e) - texte = "L'interface doit être installée dans un répertoire ou vous avez les droits d'écriture.\n\n"+\ - "Installer l'interface AperoDeDenis à un emplacement ou vous avez ce droit.\n\n"+\ - "Répertoire actuel : "+self.repertoireScript+".\n\n"+\ - "Erreur rencontrée : "+str(e) - self.deuxBoutons(titre="Problème d'installation",question=texte,b1='OK',b2='') # b1 renvoie 0, b2 renvoie 1 ; fermer fenetre = -1 + print (_('erreur sauveParamMicMac : '),str(e)) + texte = _("L'interface doit être installée dans un répertoire ou vous avez les droits d'écriture.") + "\n\n"+\ + _("Installer l'interface AperoDeDenis à un emplacement ou vous avez ce droit.") + "\n\n"+\ + _("Répertoire actuel : ")+self.repertoireData+".\n\n"+\ + _("Erreur rencontrée : ")+str(e)+str(repertoire) + self.troisBoutons(titre=_("Problème d'installation"),question=texte,b1='OK',b2='') # b1 renvoie 0, b2 renvoie 1 ; fermer fenetre = -1 fin(1) - ###### Restauration paramètres : la restauration d'un chantier peut concerner un chantier archivé, dans ce cas on restaure un fichier dont le nom est passé en paramètre - + def verifParamRep(self): #Vérifie s'il existe un répertoire pour les outils de micmac et gère leur absence lors de la sauvegarde. + repertoire = [self.micMac, self.meshlab, self.exiftool, self.mm3d, self.convertMagick, self.ffmpeg] + cpt = 0 + while(cpt < 6): + if(repertoire[cpt] == self.noRep[cpt]): + repertoire[cpt] = "N\\A" ##Empêche de se retrouver avec une langue inconnue dans ses paramètres. + cpt +=1 + return repertoire + + ###### Restauration paramètres : + def restaureParamEnCours(self): try: @@ -4094,19 +7366,54 @@ def restaureParamEnCours(self): sauvegarde2 = open(self.fichierParamMicmac,mode='rb') r2=pickle.load(sauvegarde2) sauvegarde2.close() - self.micMac = r2[0] - self.meshlab = r2[1] + r3 = [] + r3 = self.verifNARep(r2) # sépare ce qui doit être traduit ou pas + self.micMac = r3[0] + self.meshlab = r3[1] self.indiceTravail = r2[2] self.tousLesChantiers = r2[3] - self.exiftool = r2[4] - self.mm3d = r2[5] # spécifique linux/windows - - self.CameraXML = os.path.join(os.path.dirname(self.micMac),self.dicoCameraGlobalRelatif) - - except Exception as e: print("Erreur restauration param généraux : ",e) - - self.mm3dOK = verifMm3d(self.mm3d) # Booléen indiquant si la version de MicMac permet la saisie de masque 3D - + self.exiftool = r3[2] + self.mm3d = r3[3] # spécifique linux/windows + self.convertMagick = r3[4] + self.tacky = r2[7] + #r2[8] est la version : inutile pour l'instant (v3.00) + #r2[9] est la langue + self.ffmpeg = r3[5] + self.versionInternetAncienne = r2[11] # ne sert plus + self.messageVersion = r2[12] + except Exception as e: print(_("Erreur restauration param généraux : "),str(e)) + + threading.Thread(target=self.verifieVersion).start() + + # détermination du chemin pour dicocamera, de la version de mm3d, de la possibilité d'utiliser C3DC + + self.CameraXML = os.path.join(os.path.dirname(self.micMac),self.dicoCameraGlobalRelatif) + self.mercurialMicMac= mercurialMm3d(self.mm3d) # voir si cela va durer ! + self.mm3dOK = verifMm3d(self.mm3d) # Booléen indiquant si la version de MicMac permet la saisie de masque 3D + + # après plantage durant Malt ou fusion des photos ou ply peuvent manquer : on tente une restauration + try: + [os.rename(os.path.splitext(e)[0],e) for e in self.photosAvecChemin if (os.path.exists(os.path.splitext(e)[0]) and not (os.path.exists(e)))] + [os.rename(e,os.path.splitext(e)[0]+".ply") for e in os.listdir(self.repTravail) if os.path.splitext(e)[1]==".pyl"] # remise à l'état initial + except Exception as e: + print("erreur tentative restauration après plantage : ",str(e)) + # il reste le pb des photos déplacées pour la calibration + + def verifNARep(self, r2): + cpt = 0 + if r2.__len__()>10: repFfmpeg = r2[10] # pour assurer la compatibilité avec les anciennes versions ou self.ffmpeg n'était pas sauvé + else: repFfmpeg = self.ffmpeg + r3 = [r2[0], r2[1], r2[4], r2[5], r2[6], repFfmpeg] + while(cpt < 6): + if(r3[cpt] == "N\\A"): + r3[cpt] = self.noRep[cpt] + cpt +=1 + return r3 + + + ###### la restauration d'un chantier peut concerner un chantier archivé, + # dans ce cas on restaure un fichier dont le nom est passé en paramètre + def restaureParamChantier(self,fichier): # permet de restaurer les paramètres d'un chantier si besoin try: # s'il y a une sauvegarde alors on la restaure @@ -4119,42 +7426,84 @@ def restaureParamChantier(self,fichier): self.lesExtensions = r[3] self.maitreSansChemin = r[4] self.masqueSansChemin = r[5] - self.modeTapioca.set(r[6]) - self.echelle1.set(r[7]) - self.echelle2.set(r[8]) - self.delta.set(r[9]) - self.echelle3.set(r[10]) - self.arretApresTapas.set(r[11]) + self.modeTapioca.set (r[6]) + self.echelle1.set (r[7]) + self.echelle2.set (r[8]) + self.delta.set (r[9]) + self.echelle3.set (r[10]) + self.arretApresTapas.set (r[11]) self.listePointsGPS = r[12] - self.modeMalt.set(r[13]) + self.modeMalt.set (r[13]) self.fichierMasqueXML = r[14] self.repTravail = r[15] - self.definirFichiersTrace() self.chantier = os.path.basename(self.repTravail) - self.photosPropresAvecChemin = r[16] + photosAvecChemin = r[16] # a supprimer (doublon avec r2) self.extensionChoisie = r[17] - self.nomMaitreSansExtension = r[18] + self.maitreSansExtension = r[18] self.etatDuChantier = r[19] self.dicoPointsGPSEnPlace = r[20] - self.maitre = r[21] - self.masque = r[22] + self.maitre = r[21] # 22 disparu + self.mercurialMicMacChantier = r[22] self.idPointGPS = r[23] self.dicoLigneHorizontale = r[24] self.dicoLigneVerticale = r[25] self.dicoCalibre = r[26] - self.distance.set(r[27]) - self.monImage_MaitrePlan = r[28] # Nom de l'image maitresse du plan repere (sans extension) + self.distance.set (r[27]) + self.monImage_MaitrePlan = r[28] # Nom de l'image maîtresse du plan repere (sans extension) self.monImage_PlanTif = r[29] # nom du masque correspondant self.etatSauvegarde = r[30] - self.modeCheckedTapas.set(r[31]) - self.echelle4.set(r[32]) + self.modeCheckedTapas.set (r[31]) + self.echelle4.set (r[32]) + self.photosPourCalibrationIntrinseque = r[33] + self.calibSeule.set (r[34]) + self.zoomF.set (r[35]) + self.photosUtilesAutourDuMaitre.set(r[36]) + self.modele3DEnCours = r[37] + self.typeDuChantier = r[38] + self.listeDesMaitresses = r[39] + self.listeDesMasques = r[40] + self.choixDensification.set (r[41]) + self.modeC3DC.set (r[42]) + self.tawny.set (r[43]) + self.tawnyParam.set (r[44]) + # r[45] est la version : inutile pour l'instant (v2.61] + # r[46] devenu inutile v5.2 + self.lancerTarama.set (r[47]) + self.incertitudeCibleGPS.set (r[48]), + self.incertitudePixelImage.set (r[49]), + self.chantierNettoye = r[50] + self.lesTagsExif = r[51] + except Exception as e: print(_("Erreur restauration param chantier : "),str(e)) + + # pour assurer la compatibilité ascendante suite à l'ajout de l'incertitude dans la description des points GPS + # passage vers la version 2.60 de la liste des points GPS (un item de plus dans le tuple) + + if self.listePointsGPS.__len__()>0: + if self.listePointsGPS[0].__len__()==6: + self.listePointsGPS=[[a,nom,x,y,z,ident,"10 10 10"] for a,nom,x,y,z,ident in self.listePointsGPS] - self.item701.config(text="image maitresse = "+self.maitreSansChemin) - - except Exception as e: - pass + try: self.definirFichiersTrace() # attention : peut planter a juste titre si reptravail + except: print(_("erreur définir fichier trace, est normale lors d'une importation.")) + + # zoom OK, les valeurs 8,4,2,1 correspondent au nuage étape 5, 6, 7, 8 (la valeur 8 est initialisée par défaut + try: + if self.zoomF.get()=="8":self.etapeNuage = "5" + if self.zoomF.get()=="4":self.etapeNuage = "6" + if self.zoomF.get()=="2":self.etapeNuage = "7" + if self.zoomF.get()=="1":self.etapeNuage = "8" + except: pass + + # chemin constants pour la mosaique tarama + self.mosaiqueTaramaTIF = os.path.join(self.repTravail,"TA","TA_LeChantier.tif") + self.mosaiqueTaramaJPG = os.path.join(self.repTravail,"TA","TA_LeChantier.JPG") + self.masqueTarama = os.path.join(os.path.splitext(self.mosaiqueTaramaJPG)[0]+"_Masq.tif") + # Mise à jour des windgets pour les options de Malt (dépendent de la présence/absence de masques) + + self.miseAJourItem701_703() + self.photosCalibrationSansChemin = [os.path.basename(f) for f in self.photosPourCalibrationIntrinseque] + ########################### affiche les messages à l'écran : cadre, état, boites de dialogues standards, ménage def encadreEtTrace(self,texte,nbLignesmax=40,aligne='center'): @@ -4162,149 +7511,394 @@ def encadreEtTrace(self,texte,nbLignesmax=40,aligne='center'): self.ecritureTraceMicMac() # on écrit la trace self.encadre(texte,nbLignesmax,aligne) - def encadre(self,texte,nbLignesmax=38,aligne='center',nouveauDepart='oui'): + def encadre(self,texte,nbLignesmax=44,aligne='center',nouveauDepart='non'): + if texte.__class__==tuple().__class__: texte=' '.join(texte) if texte.__class__==list().__class__: texte=' '.join(texte) + if texte.count('\n')>nbLignesmax: # limitation à nbLignesmax du nombre de lignes affichées texte='\n'.join(texte.splitlines()[0:nbLignesmax-5]) +'\n.......\n'+'\n'.join(texte.splitlines()[-3:]) self.menageEcran() - self.nbEncadre+=1 - if self.nbEncadre>6 and nouveauDepart=='oui' and self.systeme=='nt': + if nouveauDepart=='oui': + self.nbEncadre+=1 + if self.nbEncadre>=6 and nouveauDepart=='oui' and self.systeme=='nt': self.messageNouveauDepart = texte - self.nouveauDepart() # lance une fenêtre nouvelle sous windows (l'actuelle peyt-être polluée par le traitement + self.nouveauDepart() # lance une fenêtre nouvelle sous windows (l'actuelle peut-être se polluer par certains traitements sous windows) return self.texte101.configure(text=texte,justify=aligne) - self.texte101Texte = texte # pour encadrePlus + self.texte101Texte = texte # pour encadrePlus self.resul100.pack() fenetre.title(self.etatSauvegarde+self.chantier+" - "+self.titreFenetre) - fenetre.focus_force() # force le focus (it is impolite !) + fenetre.focus_force() # force le focus (it is impolite !) fenetre.update() - def encadrePlus(self,plus): - self.texte101Texte+=plus - if len(self.texte101Texte.split("\n")[-1])>60: - self.texte101Texte+="\n" - self.texte101.configure(text=self.texte101Texte) - fenetre.update() - time.sleep(0.01) + def encadrePlus(self,plus,nbLignesmax=40): + try: + self.texte101Texte+=plus + if len(self.texte101Texte.split("\n")[-1])>60: + self.texte101Texte+="\n" + if self.texte101Texte.count('\n')>nbLignesmax: # limitation à nbLignesmax du nombre de lignes affichées + self.texte101Texte='\n'.join(self.texte101Texte.splitlines()[0:nbLignesmax-5]) +'\n-------\n'+'\n'.join(self.texte101Texte.splitlines()[-3:]) + self.texte101.configure(text=self.texte101Texte) + fenetre.update() + except Exception as e: + print("erreur encadre plus : "+str(e)) def menageEcran(self): # suppression écran (forget) de tous les FRAMES - self.listeFrames() - for a in self.l: - try: exec("self."+a+".pack_forget()") - except Exception as e : print("Erreur menage : ",e) - def listeFrames(self): # CREE LA LISTE DE TOUS LES FRAMES de la fenetre self - self.l=list() - for v,t in self.__dict__.items(): # un print (v,t) ici affiche l'identifiant arborescent des widgets (fenetre/frame/widget) - if t.__class__ in [ttk.Frame().__class__,ttk.Notebook().__class__]: - self.l.append(v) + # fermeture des écrans de saisie encore ouvert : + + self.fermerLaBoiteAOnglets() + self.fermerOptionsGoPro() + self.fermerModifExif() + + # fermeture des frames et notebook + + if self.item400.winfo_manager()=="pack": + self.item400.pack_forget() + if self.item450.winfo_manager()=="pack": + self.item450.pack_forget() + if self.item460.winfo_manager()=="pack": + self.item460.pack_forget() + if self.item470.winfo_manager()=="pack": + self.item470.pack_forget() + if self.item480.winfo_manager()=="pack": + self.item480.pack_forget() + + if self.item500.winfo_manager()=="pack": + self.item500.pack_forget() + if self.item510.winfo_manager()=="pack": + self.item510.pack_forget() + if self.item540.winfo_manager()=="pack": + self.item540.pack_forget() + if self.item520.winfo_manager()=="pack": + self.item520.pack_forget() + + if self.item600.winfo_manager()=="pack": + self.item600.pack_forget() + if self.item700.winfo_manager()=="pack": + self.item700.pack_forget() + if self.item710.winfo_manager()=="pack": + self.item710.pack_forget() + if self.item720.winfo_manager()=="pack": + self.item720.pack_forget() + if self.item730.winfo_manager()=="pack": + self.item730.pack_forget() + + if self.item800.winfo_manager()=="pack": + self.item800.pack_forget() + + if self.item950.winfo_manager()=="pack": + self.item950.pack_forget() + if self.item960.winfo_manager()=="pack": + self.item960.pack_forget() + if self.item965.winfo_manager()=="pack": + self.item965.pack_forget() + if self.item970.winfo_manager()=="pack": + self.item970.pack_forget() + if self.item975.winfo_manager()=="pack": + self.item975.pack_forget() + if self.item980.winfo_manager()=="pack": + self.item980.pack_forget() + if self.item990.winfo_manager()=="pack": + self.item990.pack_forget() + + if self.item1000.winfo_manager()=="pack": + self.item1000.pack_forget() + if self.item2000.winfo_manager()=="pack": + self.item2000.pack_forget() + if self.item3000.winfo_manager()=="pack": + self.item3000.pack_forget() + + if self.item9000.winfo_manager()=="pack": + self.item9000.pack_forget() + + if self.resul100.winfo_manager()=="pack": + self.resul100.pack_forget() + if self.resul200.winfo_manager()=="pack": + self.resul200.pack_forget() + if self.onglets.winfo_manager()=="pack": + self.onglets.pack_forget() + + if self.logo.winfo_manager()=="pack": + self.logo.pack_forget() + if self.logo1.winfo_manager()=="pack": + self.logo1.pack_forget() + if self.logoIgn.winfo_manager()=="pack": + self.logoIgn.pack_forget() + try: + if self.frame.winfo_manager()=="pack": + self.frame.pack_forget() + self.bulle.destroy() + except: pass + +## +## def listeFrames(self): # CREE LA LISTE DE TOUS LES FRAMES de la fenetre self +## self.l=list() +## for v,t in self.__dict__.items(): # un print (v,t) ici affiche l'identifiant arborescent des widgets (fenetre/frame/widget) +## if t.__class__ in [ttk.Frame().__class__,ttk.Notebook().__class__]: +## self.l.append(v) + + + def fermerLaBoiteAOnglets(self): # palliatif + # la boite à oglet n'est pas une fenêtre modale mais une frame.. + # on pallie à cela en proposant de la sauver ou pas lorsque l'on fait du ménage + # pour éviter de fermer brutalement + # la vraie solution serait de mettre la frame dans une fenêtre toplevel, modale, elle. + # le try récupére l'erreur si jamais l'interface n'existe plus. + try: + if self.fermetureOngletsEnCours == True: + return + if self.onglets.winfo_manager()=="": + return + self.fermetureOngletsEnCours = True + if self.troisBoutons(_("Fermer les options."),_("La boîte de dialogue 'options' est ouverte et va être fermée.\nVoulez-vous enregistrer les options saisies ?"),b1=_("enregistrer"),b2=_("abandon"))==0: + self.finOptionsOK() + else: + self.finOptionsKO() + self.fermetureOngletsEnCours = False + except: pass + + def fermerOptionsGoPro(self): + if self.fermetureOptionsGoProEnCours == True: + return + if self.item2000.winfo_manager()=="": + return + self.fermetureOptionsGoProEnCours = True + if self.troisBoutons(_("Fermer les options vidéo."),_("Enregistrer les options vidéos saisies ?"),b1=_("enregistrer"),b2=_("abandon"))==0: + self.optionsGoProOK() + else: + self.optionsGoProKO() + self.fermetureOptionsGoProEnCours = False - ################################## 2 outils : envoi retour chariot et compte le nombre d'extensions différentes dans une lister de fichiers + def fermerModifExif(self): + if self.fermetureModifExif == True: + return + if self.item3000.winfo_manager()=="": + return + self.fermetureModifExif = True + if self.troisBoutons(_("Fermer la modification des exifs."),_("Enregistrer les valeurs saisies ?"),b1=_("enregistrer"),b2=_("abandon"))==0: + self.exifOK() + else: + self.exifKO() + self.fermetureModifExif = False - def envoiRetourChariot(self,dest): # dest étant le processus ouvert par popen - dest.communicate(input='t\n') +######################### recherche de la dernière version d'aperodedenis sur le net - def nombreDExtensionDifferentes(self,liste): - lesExtensions=set([os.path.splitext(x)[1].upper() for x in liste]) # on vérifie l'unicité de l'extension : - self.lesExtensions=list(lesExtensions) # liste pour être slicable - return len(self.lesExtensions) + def verifieVersion(self): # va lire la version dans la page GitHub : doit être au début du fichier readme.txt + # Affiche un message si besoin. + # lancé par un thread (pour éviter le retard éventuel de connexion à internet si pas de connexion + # un seul lancement par session + + if compteur>1 or self.messageVersion==False: # inutile si relance de l'interface ou si l'utilisateur ne veut pas être averti + return + try: + sock = urllib.request.urlopen("https://github.com/micmacIGN/InterfaceCEREMA/tree/master/InterfaceCEREMA") + htmlLu = str(sock.read(100000)) + sock.close + except: + return + + # Y-a-t-il une nouvelle version sur internet ? Si oui faut-il un message ? - #################################### Supprime (ou conserve) les répertoires de travail + if numeroVersion not in htmlLu: # version utilisateur non trouvée dans version GitHub + self.avertirNouvelleVersion = True + + def avertissementNouvelleVersion(self): # n'apparait qu'une fois par session (role de avertirNouvelleVersion) + if self.avertirNouvelleVersion: + retour = self.troisBoutons(titre=_("Nouvelle version de l'interface AperoDeDenis"), + question=_("Nouvelle version disponible sur Internet : ")+"\n"+ + _("Téléchargement à l'adresse : ")+"\n\n"+ + "https://github.com/micmacIGN/InterfaceCEREMA/tree/master/InterfaceCEREMA", + b1=_("OK"), + b2=_("Ouvrir la page web"), + b3=_("Ne plus me le rappeler")) + if retour == 1: + threading.Thread(target=ouvrirPageWEBAperoDeDenis).start() # ouverture de la page WEB dans un thread + if retour == 2: + self.messageVersion = False + self.avertirNouvelleVersion = False + self.encadre(" page ouverte : https://github.com/micmacIGN/InterfaceCEREMA/tree/master/InterfaceCEREMA") + + def verifVersion(self): + self.encadre(_("Recherche sur internet en cours, patience...")) + try: + sock = urllib.request.urlopen("https://github.com/micmacIGN/InterfaceCEREMA/tree/master/InterfaceCEREMA/readme.txt") + htmlLu = str(sock.read(100000)) + sock.close + except Exception as e: + self.encadre(_("Erreur lors de la tentative de connexion à internet : ")+"\n"+str(e)) + return + + # Y-a-t-il une nouvelle version sur internet ? Si oui faut-il un message ? + + if numeroVersion not in htmlLu: # version utilisateur non trouvée dans version GitHub + retour = self.troisBoutons(titre=_("Nouvelle version de l'interface AperoDeDenis"), + question=_("Nouvelle version disponible sur Internet : ")+"\n"+ + _("Téléchargement à l'adresse : ")+"\n\n"+ + "https://github.com/micmacIGN/InterfaceCEREMA/tree/master/InterfaceCEREMA", + b1=_("OK"), + b2=_("Ouvrir la page web"), + b3=_("Lire le readme.txt" + )) + if retour == 1: + threading.Thread(target=ouvrirPageWEBAperoDeDenis).start() # ouverture de la page WEB dans un thread + if retour == 2: + threading.Thread(target=lireReadMe).start() # ouverture de la page WEB dans un thread + self.encadre(_("Nouvelle version disponible")) + else: + retour = self.troisBoutons(titre=_("Version de l'interface AperoDeDenis à jour"), + question=_("Version disponible sur Internet : ")+"\n"+ + _("Téléchargement à l'adresse : ")+"\n\n"+ + "https://github.com/micmacIGN/InterfaceCEREMA/tree/master/InterfaceCEREMA", + b1=_("Abandon"), + b2=_("Ouvrir la page web"), + ) + if retour == 1: + threading.Thread(target=ouvrirPageWEBAperoDeDenis).start() # ouverture de la page WEB dans un thread + self.encadre(_("Version actuelle à jour")) + + #################################### Supprime (ou conserve) les répertoires de travail def supprimeRepertoires(self): + self.menageEcran() + + # Y-a-t-il des chantiers ? if len(self.tousLesChantiers)==0: - texte='\nTous les répertoires de travail sont déjà supprimés.\n' + texte='\n' + _("Tous les chantiers sont déjà supprimés.") + "\n" self.encadre(texte) - return + return + + # Oui il y a des chantiers ! + supprime = list() conserve = list() texte = str() attention = str() - self.tousLesChantiers.sort(key=os.path.basename) # tri suivant le nom du chantier + espaceGagne = int() + chantierEnCours = self.repTravail + self.choisirUnePhoto(self.tousLesChantiers, - titre='Chantiers à supprimer', + titre=_('Chantiers à nettoyer ou supprimer'), mode='extended', - message="Multiselection possible.", - boutonDeux="Annuler", - objets='repertoires') # renvoi : self.selectionPhotosAvecChemi + message=_("Multiselection possible."), + boutonDeux=_("Annuler"), + objets=_('repertoires')) # renvoi : self.selectionPhotosAvecChemin + # rien à faire + if len(self.selectionPhotosAvecChemin)==0: return - + + # Nettoyage effectif à faire + if len(self.selectionPhotosAvecChemin)==1: - self.deuxBoutons('Suppression des répertoires de travail superflus', - 'Le répertoire suivant va être supprimé, sans mise en corbeille : \n\n'+'\n'.join(self.selectionPhotosAvecChemin), - 'Confimez', - 'Annuler') + self.troisBoutons(_('Suppression ou nettoyage des répertoires de travail superflus'), + _('Le chantier suivant va être supprimé ou nettoyé :') + '\n\n'+'\n'.join(self.selectionPhotosAvecChemin), + _('Supprimer totalement le chantier'), + _('Nettoyer le chantier, conserver les résultats'), + _('Annuler')) if len(self.selectionPhotosAvecChemin)>1: if self.repTravail in self.selectionPhotosAvecChemin: - attention="ATTENTION : le chantier en cours va être supprimé.\n\n" - self.deuxBoutons('Suppression des répertoires de travail superflus', - attention+'Vont être supprimés les répertoires suivants, sans mise en corbeille : \n\n'+'\n'.join(self.selectionPhotosAvecChemin), - 'Confimez','Annuler') - if self.bouton==1 or self.bouton==-1: #abandon par annulation (1) ou par fermeture de la fenêtre (-1) + attention=_("ATTENTION : le chantier en cours va être nettoyéé.") + "\n\n" + + self.troisBoutons(_('Suppression ou nettoyage des répertoires de travail superflus'), + _('Les chantiers suivant vont être supprimés ou nettoyés :') + '\n\n'+'\n'.join(self.selectionPhotosAvecChemin), + _('Supprimer totalement les chantiers'), + _('Nettoyer les chantier, conserver les résultats'), + _('Annuler')) + + if self.bouton==2 or self.bouton==-1: # abandon par annulation (1) ou par fermeture de la fenêtre (-1) return - for e in self.selectionPhotosAvecChemin: - if os.path.exists(e): - if self.repTravail == e: - self.etatDuChantier = -1 - texte="Le précédent chantier "" "+self.chantier+" "" est en cours de suppression.\n" - self.nouveauChantier() - time.sleep(0.1) - try: shutil.rmtree(e,False,self.echecSuppression(e)) # il semble que la racine reste présente il faut ensuite la supprimer - except: pass - try: os.rmdir(e) - except: pass - if os.path.exists(e): - ajout(conserve,e) + if self.bouton==0: # suppression totale des répertoires + self.encadre(_("Suppression en cours....")) + for e in self.selectionPhotosAvecChemin: + if os.path.exists(e): + espaceGagne+=sizeDirectoryMO(e) + if self.repTravail==e: + self.etatDuChantier = -1 + texte=_("Le chantier en cours %s est supprimé.") % (self.chantier)+ "\n" + self.nouveauChantier() + time.sleep(0.1) + try: shutil.rmtree(e) # il semble que la racine reste présente il faut ensuite la supprimer + except: pass + try: os.rmdir(e) + except: pass + if os.path.exists(e): + ajout(conserve,e) + else: + try: + ajout(supprime,e) + self.tousLesChantiers.remove(e) + except: pass + self.encadrePlus("...") + if len(supprime)>=1: + texte = texte+_("Compte rendu de la suppression :") + "\n\n" + _("Repertoires supprimés :") + "\n\n" + "\n".join(supprime)+"\n" else: - try: - ajout(supprime,e) - self.tousLesChantiers.remove(e) - except: pass - if len(supprime)>=1: - texte = texte+"Compte rendu de la suppression : \n\nRepertoires supprimés : \n\n"+'\n'.join(supprime)+"\n" - else: - texte = texte+"Compte rendu de la suppression : \n\nAucun répertoire supprimé.\n\n"+'\n'.join(supprime)+"\n" - - if len(conserve)==0: - texte = texte+'\n\nTous les chantiers demandés sont supprimés.' - elif len(conserve)==1: - texte = texte+'\n\nIl reste un chantier impossible à supprimer maintenant : \n\n'+'\n'.join(conserve) - else: - texte = texte+'\n\nIl reste des chantiers impossibles à supprimer maintenant : \n\n'+'\n'.join(conserve) - self.sauveParam() # mémorisation de la suppression - self.encadre(texte) + texte = texte+_("Compte rendu de la suppression :") + "\n\n" + _("Aucun répertoire supprimé.") + "\n\n"+'\n'.join(supprime)+"\n" + + if len(conserve)==0: + texte = texte+'\n\n' + _('Tous les chantiers demandés sont supprimés.') + elif len(conserve)==1: + texte = texte+'\n\n' + _('Il reste un chantier impossible à supprimer maintenant : ') + '\n\n'+'\n'.join(conserve) + else: + texte = texte+'\n\n' + _('Il reste des chantiers impossibles à supprimer maintenant : ') + '\n\n'+'\n'.join(conserve) + texte+="\n\n"+_("Espace disque récupéré : ")+str(espaceGagne)+" MO" + self.sauveParam() # mémorisation de la suppression + self.encadre(texte) + return + + # Nettoyage chantiers + + if self.bouton==1: # suppression des sous répertoires, conserve les résultats + self.encadre(_("Suppression des sous-répertoires en cours....")) + for e in self.selectionPhotosAvecChemin: + if os.path.exists(e): + rep = [f for f in os.listdir(e) if os.path.isdir(os.path.join(e, f))] + for r in rep: + espaceGagne+=sizeDirectoryMO(r) + try: + shutil.rmtree(r) + except: + espaceGagne-=sizeDirectoryMO(r) + texte = "Ménage effectué" + texte += "\n\n"+_("Espace disque récupéré : ")+str(espaceGagne)+" MO" + + self.encadre(texte) + return - def echecSuppression(self,e): - try: - time.sleep(0.05) - os.rmdir(e) - except: - pass + ############################### Message proposant une question et deux, trois ou 4 Boutons + # si b2="" alors pas de second bouton retour : 0, 1, 2, 3 : numéro du bouton + def troisBoutons(self,titre=_('Choisir'),question=_("Choisir : "),b1='OK',b2='KO',b3=None,b4=None): - ############################### Message proposant une question et deux Boutons OK, Annuler - # si b2="" alors pas de second bouton - def deuxBoutons(self,titre='Choisir',question="Choisir : ",b1='OK',b2='KO'): # b1 rennvoie 0, b2 renvoie 1 ; fermer fenetre = -1, + # positionne self.bouton et le renvoie : b1 = 0, b2 = 1 b3 = 2 b4 = 3; fermer fenetre = -1, try: self.bouton = -1 self.resul300 = tkinter.Toplevel(height=50,relief='sunken') fenetreIcone(self.resul300) self.resul300.title(titre) + if question.count('\n')>15: # limitation à nbLignesmax du nombre de lignes affichées + question='\n'.join(question.splitlines()[0:10]) +'\n.......\n'+'\n'.join(question.splitlines()[-3:]) self.texte301=ttk.Label(self.resul300, text=question) self.texte301.pack(pady=10,padx=10) self.texte302=ttk.Button(self.resul300, text=b1,command=self.bouton1) self.texte302.pack(pady=5) - if b2!="": # autorise un seul bouton + if b2!="": # autorise un seul bouton self.texte303=ttk.Button(self.resul300, text=b2,command=self.bouton2) self.texte303.pack(pady=5) + if b3!=None: # autorise un seul bouton + self.texte304=ttk.Button(self.resul300, text=b3,command=self.bouton3) + self.texte304.pack(pady=5) + if b4!=None: # autorise un seul bouton + self.texte305=ttk.Button(self.resul300, text=b4,command=self.bouton4) + self.texte305.pack(pady=5) self.resul300.transient(fenetre) # 3 commandes pour définir la fenêtre comme modale pour l'application self.resul300.grab_set() + self.resul300.focus_force() fenetre.wait_window(self.resul300) self.resul300.destroy() return self.bouton @@ -4320,20 +7914,23 @@ def bouton2(self): self.bouton = 1 self.resul300.destroy() + def bouton3(self): + self.bouton = 2 + self.resul300.destroy() + + def bouton4(self): + self.bouton = 3 + self.resul300.destroy() + ############################### Prépare un cadre pour Afficher une trace dans la fenêtre def cadreVide(self): self.menageEcran() - fenetre.update() # rafraichissement avant agrandissement - self.resul200 = ttk.Frame(fenetre,height=100,relief='sunken') # fenêtre texte pour afficher le bilan - self.scrollbar = ttk.Scrollbar(self.resul200) - self.scrollbar.pack(side='right',fill='y',expand=1) - self.texte201 = tkinter.Text(self.resul200,width=200,height=100,yscrollcommand = self.scrollbar.set,wrap='word') - self.texte201.pack() - self.resul200.pack() - self.scrollbar.config(command=self.yviewTexte) - + fenetre.update() # rafraichissement avant agrandissement + self.texte201.delete("0.0","end") + self.resul200.pack() + def yviewTexte(self, *args): if args[0] == 'scroll': self.texte201.yview_scroll(args[1],args[2]) @@ -4342,48 +7939,91 @@ def yviewTexte(self, *args): ################################## lance une procédure et éxécute une commande sur chaque ligne de l'output ################################################ - def lanceCommande(self,commande,filtre=lambda e: e,info="",attendre=True): + def lanceCommande(self,commande,filtre=lambda e: e,info="",attendre=True): commande = [e for e in commande if e.__len__()>0] # suppression des arguments "vides" commandeTexte=" ".join(commande) # Format concaténé des arguments - self.ajoutLigne("\n\n"+heure()+" : Lancement de "+commandeTexte+"\n\n"+info+"\n") - exe = subprocess.Popen(commande, - shell=self.shell, - stdout=subprocess.PIPE, # ne pas définir stdin car sinon il faut le satisfaire - #stdin=subprocess.PIPE, # en fait il faut sans doute.... doute... - stderr=subprocess.STDOUT, - universal_newlines=True) - - if not attendre: # par exemple pour lancer meshlab on n'attend pas la fin + self.ajoutLigne("\n\n"+heure()+_(" : lancement de ")+commandeTexte+"\n\n"+info+"\n") + self.ecritureTraceMicMac() + + # limitation à 8191 caractère de la ligne de commande sous windows : mais pas sur que cela marche + # par exemple pour exiftool les paramètres sont dépendants les uns des autres : il vont par groupe + # aussi avertissement utilisateur : + + if len(commandeTexte)>8000 and os.name=="nt": + texte = (_("Sous Windows la longueur d'une ligne de commande est limitée à 8191 caractères") +"\n"+ + _("AperoDeDenis essaie d'éxécuter la une commande dont la longueur est de %s") % len(commandeTexte) +"\n"+ + _("Il est possible que ce soit un échec : dans ce cas il faut utiliser un autre système d'exploitation") +"\n"+ + _("ou diminuer le nombre de photos, la longueur des chemins...") +"\n"+ + _("Voici les 200 premiers caractères de la commande :") +"\n"+ + commandeTexte[:200]+"\n"+ + _("Toute la commande se trouve dans la trace")) + self.troisBoutons(titre=_("Problème de longueur de commande"),question=texte,b1='OK') # b1 renvoie 0, b2 renvoie 1 ; fermer fenetre = -1 + + d = commande[1:] + while 1: + if len(d): + c = commande[0] + chaine=str() + while len(chaine)<8000: + if len(d): + if len(d[0])+len(chaine)<8000: + c.append(commande[i]) # ajout à la commande + chaine+=commande[i] # ajout à la chaine pour controler la longueur + del d[0] # pour s'arrêter si tout est épuisé + self.lanceCommande(self,c,filtre,attendre) + + # lance la commande + + try: + self.exe = subprocess.Popen(commande, + shell=self.shell, + stdout=subprocess.PIPE, # ne pas définir stdin car sinon il faut le satisfaire + stderr=subprocess.STDOUT, + universal_newlines=True) + except Exception as e: + self.ajoutLigne("\n"+_("erreur lors de l'éxécution de la commande :") + "\n"+str(e)+"\n") + self.ajoutLigne("\n"+heure()+_(" : fin de ")+commandeTexte+"\n") return - ligne=exe.stdout.readline() + if not attendre: # par exemple pour lancer meshlab on n'attend pas la fin du process + return + + ligne = self.exe.stdout.readline() # boucle sur l'output (y compris stderr) - while ligne: - '''if ligne.find('tape enter')>=0: - envoiRetourChariot(exe)''' - + while ligne: if ligne.__class__!=str().__class__: # doit être une chaine break # sinon pb majeur : on arrête - self.ajoutLigne(filtre(ligne),ligne) # on ajoute la ligne et la ligne filtrée dans les traces - - try: ligne=exe.stdout.readline() # ligne suivante, jusqu'à la fin du fichier, sauf décès (anormal) du processus père + self.ajoutLigne(filtre(ligne),ligne) # on ajoute la ligne et la ligne filtrée dans les traces + try: + ligne = self.exe.stdout.readline() # ligne suivante, jusqu'à la fin du fichier, sauf décès (anormal) du processus père except: - print("erreur lecture output : ",commandeTexte) break # si la lecture ne se fait pas c'est que le processus est "mort", on arrête - - while exe.poll()==None: # on attend la fin du process, si pas fini (en principe : fini) - time.sleep(0.1) - pass - self.ajoutLigne("\n"+heure()+" : Fin de "+commandeTexte+"\n") - - # Fichiers TRACE + self.ajoutLigne("\n"+heure()+_(" : fin de ")+commandeTexte+"\n") + self.ecritureTraceMicMac() + + ########################## Opérations sur les Fichiers TRACE - def definirFichiersTrace(self): # crée les fichiers à vide + def definirFichiersTrace(self): # affectation des noms des fichiers trace. pas de création : en effet le plus souvent ils existent déjà, il faut seulement les retrouver if self.repTravail != "": - self.TraceMicMacSynthese = self.repTravail+os.path.sep+'Trace_MicMac_Synthese.txt' - self.TraceMicMacComplete = self.repTravail+os.path.sep+'Trace_MicMac_Complete.txt' + self.TraceMicMacSynthese = os.path.join(self.repTravail,'Trace_MicMac_Synthese.txt') + self.TraceMicMacComplete = os.path.join(self.repTravail,'Trace_MicMac_Complete.txt') os.chdir(self.repTravail) # on se met dans le répertoire de travail, indispensable + + def initialisationFichiersTrace(self): # vide les fichiers et ecrit une nouvelle entête avec le nom des photos + open(self.TraceMicMacSynthese,'w').close() # création d'un fichier de trace, vide + open(self.TraceMicMacComplete,'w').close() # création d'un fichier de trace, vide + self.effaceBufferTrace() # RAZ d'un ahjoutLigne éventuel (notamment par affichage de la trace ) + self.ajoutLigne(heure()+" : "+self.titreFenetre+"\n-----------------------\n") + self.ajoutTraceComplete(_("Trace complète")) + self.ajoutTraceSynthese(_("Trace synthétique")) + self.ajoutLigne("\n-----------------------\n\n") + if len(self.photosAvecChemin)>0: + self.ajoutLigne(heure()+ "\n\n" + _("Choix des photos :") + "\n"+"\n".join(self.photosAvecChemin)) + self.ajoutLigne("\n\n" + _("répertoire du chantier :") + "\n"+self.repTravail+"\n\n") + self.ajoutLigne(_("Version MicMac : ")+self.mercurialMicMac+"\n") + self.ecritureTraceMicMac() + # ajout de lignes dans les traces @@ -4400,9 +8040,8 @@ def ajoutTraceComplete(self,lue=''): if lue==None: return self.lignePourTrace = self.lignePourTrace+str(lue) # la trace détaillée en fin de MicMac, dans le répertoire de travail, sous le nom traceTotale - print(lue) - except Exception as e: - print("Erreur ajout trace complète : ",str(lue)," erreur=",e) + except Exception as e: print(e) + def ajoutTraceSynthese(self,filtree=''): try: @@ -4410,35 +8049,41 @@ def ajoutTraceSynthese(self,filtree=''): return if filtree==None: return + # suppression des lignes comportant 2 * en début : info IGN répétitive + if filtree[0:2]=="**": + return + self.ligneFiltre = self.ligneFiltre+str(filtree) # la trace synthétique self.texte201.insert('end',str(filtree)) self.texte201.update() self.texte201.see('end') - except Exception as e: pass + except Exception as e: print(e) + def effaceBufferTrace(self): - + try: + self.texte201.delete("0.0",'end') + except: pass self.lignePourTrace = str() self.ligneFiltre = str() # écrire dans les traces def ecritureTraceMicMac(self): # écriture en Ajout des fichiers trace + self.definirFichiersTrace() try: - with open(self.TraceMicMacSynthese,'a') as infile: + with open(self.TraceMicMacSynthese,'a', encoding='utf-8') as infile: infile.write(self.ligneFiltre) - with open(self.TraceMicMacComplete,'a') as infile: + with open(self.TraceMicMacComplete,'a', encoding='utf-8') as infile: infile.write(self.lignePourTrace) - self.effaceBufferTrace() - except Exception as e: - print ('erreur ecritureTraceMicMac : ',e,"\ntraces : ",self.TraceMicMacSynthese," et ",self.TraceMicMacComplete) + print (_('erreur ecritureTraceMicMac : '),str(e),"\ntraces : ",self.TraceMicMacSynthese," et ",self.TraceMicMacComplete) - + self.effaceBufferTrace() - ############################### Choix d'une image dans la liste des images retenues avec scrollbar : charge self.selectionPhotosAvecChemin + ############################### Choix d'une image dans la liste des images retenues avec scrollbar : charge self.selectionPhotosAvecChemin, gadgets """ les deux autres présentations sous forme de dialogue : @@ -4446,42 +8091,48 @@ def ecritureTraceMicMac(self): # écrit # Mydialog """ -# en retour : self.selectionPhotosAvecChemin +# choix simple ou multiple dans une liste +# en retour une liste : self.selectionPhotosAvecChemin def choisirUnePhoto(self, # en retour liste : self.selectionPhotosAvecChemin - listeAvecChemin, - titre='Choisir une photo', - message="Cliquer pour choisir une ou plusieurs photos : ", - mode='extended', # autre mode = "single" - messageBouton="OK", + listeAvecChemin, # liste des noms de fichiers ou répertoires à afficher pour le choix + titre=_('Choisir une photo'), # titre de la fenêtre + message=_("Cliquer pour choisir une ou plusieurs photos : "), # entête de la liste + mode='extended', # par défaut sélection multiple, autre mode = "single" + messageBouton=_("OK"), # message sur le premier bouton boutonDeux=None, # texte d'un second bouton : fermeture, renvoyant une liste vide - dicoPoints=None, - objets='photos'): # défaut : pas de dictionnaire de points à afficher + dicoPoints=None, # dictionnaire de points à afficher : key = (nom point, photo, identifiant), value = (x,y) + objets='photos', # par défaut la liste est une liste de fichiers, alternative : répertoires, ply + bulles=dict()): # dictionnaires d'info bulle : key = photo, value = infobulle self.selectionPhotosAvecChemin = list() # sélection : vide pour l'instant ! - self.cherche = str() # recherche - self.fermerVisu = False # permet d'identifier la sortie par le second bouton si = True (!= sortie par fermeture fenêtre) if len(listeAvecChemin)==0: # pas de photos : on sort - self.encadre("Pas de photos pour cette demande.", - nouveauDepart="non") - return - l = [ e for e in listeAvecChemin if not os.path.exists(e)] #si des photos manquent : abandon ! - if len(l)>0 and objets=='photos': - texte="Les photos suivantes sont absentes du disque :"+"\n".join(l)+"\nDossier corrompu. Traitement interrompu." - self.encadre(texte,nouveauDepart="non") + self.encadre(_("Pas de photos pour cette demande.")) return - self.dicoPointsAAfficher = dicoPoints # pour passer l'info à retailleEtAffiche + if not os.path.exists(self.repTravail): + self.encadre(_("Le répertoire du chantier n'est pas accessible.")) + return + self.cherche = str() # recherche + self.fermerVisu = False # permet d'identifier la sortie par le second bouton si = True (!= sortie par fermeture fenêtre) + l = [ e for e in listeAvecChemin if not (os.path.exists(e))] # BIS : si des photos ou répertoires manquent encore : abandon ! + if len(l)>0 and objets in ('photos','ply'): + # les fichiers absents peuvent être des fichiers "pour calibration" : ils doivent alors être retirés de la liste + noCalib = [f for f in l if os.path.basename(f) not in [os.path.basename(g) for g in self.photosPourCalibrationIntrinseque]] + if len(noCalib)>0: + texte=_("Les fichiers suivants sont absents du disque :") + "\n\n"+"\n".join(l)+"\n\n" + _("Dossier corrompu. Traitement interrompu.") + self.encadre(texte) + return + # restriction de la liste aux fichiers non calibrant : + listeAvecChemin = [ h for h in listeAvecChemin if os.path.basename(h) not in [os.path.basename(i) for i in self.photosPourCalibrationIntrinseque]] + self.dicoPointsAAfficher = dicoPoints # pour passer l'info à afficherTousLesPointsDuDico + self.dicoInfoBullesAAfficher = bulles # pour passer l'info à afficherLesInfosBullesDuDico self.fermerVisuPhoto() # pour éviter les fenêtres multiples self.listeChoisir = list(set(listeAvecChemin)) # liste de choix par copie de la liste ou du tuple paramètre, sans doublons - self.listeChoisir.sort() #tri alpha + self.listeChoisir.sort(key=os.path.basename) # tri alpha listeSansChemin = [os.path.basename(e) for e in self.listeChoisir] self.topVisuPhoto = tkinter.Toplevel(fenetre,relief='sunken') # fenêtre principale de choix de la photo (maitre, ou autre) self.topVisuPhoto.title(titre) - self.topVisuPhoto.geometry("400x400+100+200") + self.topVisuPhoto.geometry("400x450+200+300") fenetreIcone(self.topVisuPhoto) - """textvariable : associe le texte du label à une variable de type StringVar. Si la variable change - de valeur, le texte change. Voir chapitre tk01 §7. Attention à l'utilisation des - StringVar : il faut créer la variable, l'affecter par la méthode set(), la consulter - par la méthode get().""" self.invitePhotoMessageInitial = message self.invitePhotoMessage = tkinter.StringVar() self.invitePhotoMessage.set(self.invitePhotoMessageInitial) @@ -4489,28 +8140,34 @@ def choisirUnePhoto(self, # en ret self.invitePhoto.pack(padx=5,pady=5,ipadx=5,ipady=5) frameSelect = ttk.Frame(self.topVisuPhoto) # cadre dans la fenêtre: pour afficher la boite à liste - scrollbar = ttk.Scrollbar(frameSelect, orient='vertical') #barre de défilement + scrollbar = ttk.Scrollbar(frameSelect, orient='vertical') # barre de défilement - self.selectionPhotos = tkinter.Listbox(frameSelect,selectmode=mode,yscrollcommand=scrollbar.set) + self.selectionPhotos = tkinter.Listbox(frameSelect, + selectmode=mode, + yscrollcommand=scrollbar.set, + width=min(250,(5+max([0]+[len (r) for r in listeSansChemin])))) self.selectionPhotos.select_set(1) self.selectionPhotos.bind("", self.upDown) self.selectionPhotos.bind("", self.upDown) self.selectionPhotos.bind("", self.upDown) self.selectionPhotos.bind("", self.upDown) - self.selectionPhotos.bind("", self.lettre) + self.selectionPhotos.bind("", self.lettre) self.selectionPhotos.pack(side='left', fill='both', expand=1) self.selectionPhotos.focus_set() - + scrollbar.config(command=self.yview) scrollbar.pack(side='right', fill='y') for i in listeSansChemin: # remplissage de la liste - self.selectionPhotos.insert('end',i) + self.selectionPhotos.insert('end',i) + l=[os.path.basename(e) for e in list(self.dicoInfoBullesAAfficher.keys())] + if i in l: + self.selectionPhotos.itemconfig("end",bg='yellow') frameSelect.pack() # fin de la boite à liste self.b1 = ttk.Button(self.topVisuPhoto,text=messageBouton,command=self.validPhoto) # le premier bouton (fermer ou OK if boutonDeux!=None: - c = ttk.Button(self.topVisuPhoto,text=boutonDeux,command=self.cloreVisuPhoto) #le second bouon si demandé + c = ttk.Button(self.topVisuPhoto,text=boutonDeux,command=self.cloreVisuPhoto) # le second bouon si demandé self.b1.pack(pady=5) c.pack(pady=5) else: @@ -4520,17 +8177,297 @@ def choisirUnePhoto(self, # en ret self.canvasPhoto = tkinter.Canvas(foto,width = 200, height = 200) # Canvas pour revevoir l'image self.canvasPhoto.pack(fill='both',expand = 1) foto.pack() + if bulles==dict(): + self.selectionPhotos.select_set(0) # si pas de dictionnaire sélection de la première photos (sinon colorisation &éventuelle de la première photo) + else: + self.retailleEtAffichePhoto(self.listeChoisir[0]) # pour afficher la première photo, même s'il n'y a pas de sélection + self.current = self.selectionPhotos.curselection() # sélection courante + self.list_has_changed(self.current) # la sélection est définie : on réagit + + ########################################################## + # poll : lance retaille et affiche la photo (retailleEtAffichePhoto), qui lance afficherTousLesPointsDuDico et afficherLesInfosBullesDuDico + # affiche les points du dictionnaire et une info bulle indiquant le nombre de points + # affiche les infos bulles de 'bulles' + # réagit aux changements de sélection par l'utilisateur + if objets in ('photos','ply',_("repertoires")): + self.poll() # essentiel : lance la boucle infinie d'attente + + ########################################################## + self.topVisuPhoto.protocol("WM_DELETE_WINDOW", self.fermerVisuPhoto) # Fonction a éxécuter lors de la sortie du programme + self.topVisuPhoto.transient(fenetre) # 3 commandes pour définir la fenêtre comme modale pour l'application + self.topVisuPhoto.grab_set() + fenetre.wait_window(self.topVisuPhoto) + try : self.bulle.destroy() + except: pass + +########################################## Traitement des données GoPro ############################################## + + + # saisie des options de la GoPro + + def optionsGoPro(self): + self.sauveOptionsGoPro() # en cas d'annulation par l'utilisateur + self.menageEcran() + self.item2000.pack() + + + return + + # après saisie des options de la GoPro : + + def optionsGoProOK(self): + self.item2000.pack_forget() # fermer l'item (pour évitr la question par menageEcran) + self.encadre(_("Options GoPro modifiées")) + + def optionsGoProKO(self): # l'utilisateur abandonne les modifs + + self.goProMaker.set(self.goProMakerSave) + self.goProFocale35.set(self.goProFocale35Save) + self.goProFocale.set(self.goProFocaleSave) + self.goProNomCamera.set(self.goProNomCameraSave) + self.goProNbParSec.set(self.goProNbParSecSave) # taux de conservation des photos pour DIV + self.goProEchelle.set(self.goProEchelleSave) # pour tapioca + self.goProDelta.set(self.goProDeltaSave) + self.item2000.pack_forget() # fermer l'item (pour évitr la question par menageEcran) + self.encadre(_("Abandon : options GoPro inchangées.")) + + def sauveOptionsGoPro(self): # l'utilisateur valide les modifs + + self.goProMakerSave = self.goProMaker.get() + self.goProFocale35Save = self.goProFocale35.get() + self.goProFocaleSave = self.goProFocale.get() + self.goProNomCameraSave = self.goProNomCamera.get() + self.goProNbParSecSave = self.goProNbParSec.get() # taux de conservation des photos pour DIV + self.goProEchelleSave = self.goProEchelle.get() # pour tapioca + self.goProDeltaSave = self.goProDelta.get() + + # Choix d'une vidéo et extraction des photos : + + def laVideo(self): # choix de la video + + self.fermerVisuPhoto() # s'il y a une visualisation en cours des photos ou du masque on la ferme + if verifierSiExecutable(self.ffmpeg)==False: + self.encadre(_("L'outil ffmpeg n'est pas installé sur votre ordinateur. Traitement des vidéo GoPro impossible.")) + return + + repIni = "" # répertoire initial de la boite de dialogue + if os.path.isdir(self.repertoireDesPhotos): + repIni = self.repertoireDesPhotos + + video = tkinter.filedialog.askopenfilename(title=_("Choisir la video issue d'un appareil %(GoProMaker)s %(GoProName)s (sinon modifier les options)") % {"GoProMaker" : self.goProMaker.get(), "GoProName" : self.goProNomCamera.get()}, + initialdir=repIni, + filetypes=[(_("Video"),("*.mp4","*.MP4","*.MOV","*.mov")),(_("Tous"),"*")], + multiple=False) + + if len(video)==0: + self.encadre(_("Abandon, aucune sélection,\n le chantier reste inchangé.") + "\n") + return + + if os.path.splitext(video)[1].upper() not in ".MP4": + self.encadre(_("La version actuelle ne traite que les videos au format MP4, or le format des photos est %s. Désolé.") % (os.path.splitext(video)[1])) + #return + + # Quel répertoire pour le chantier ? + + self.nouveauChantier() # Enregistre le chantier précédent, réinitialise les valeurs par défaut prépare un chantier vide avec le répertoire de travail par défaut + retour = self.quelChantier(video) # positionne un nouveau self.repTravail en fonction du répertoire de la video, donne un nom au chantier + if retour!=None: + self.encadre(retour) + return # y a un pb + os.chdir(self.repTravail) + + if retour!=None: + self.encadre(retour) + return + + # ouverture de la trace + + self.cadreVide() + self.ajoutLigne(_("Décompacte la vidéo")) + + # décompactage : extraction de toutes les photos : + self.extensionChoisie = ".JPG" # ou png + if self.lanceFfmpeg(video)==-1: # sous les noms : "\Im_0000_%5d_Ok"+self.extensionChoisie %5d = 5 chiffres décimaux + self.encadre(_("L'outil ffmpeg est absent.") + "\n" + _("Il convient de l'associer.") ) + return + + self.photosAvecChemin = [x for x in os.listdir(self.repTravail) if self.extensionChoisie in str(x) and os.path.isfile(x)] # listes des photos conservées + self.photosSansChemin = list([os.path.basename(x) for x in self.photosAvecChemin]) # liste des noms de photos copiès, sans le chemin. [tuple] + + if self.photosSansChemin.__len__()==0: + self.encadre(_("Aucune image décompactée : consulter la trace.")) + self.ecritureTraceMicMac() # on écrit les fichiers trace + return + + # ajout de l'exif : + + self.ajoutExifGoPro() + + self.etatDuChantier = 2 + # Type de chantier : c'est une liste de string (on pourrait aussi mettre un dictionnaire), avec : + # [0] = s'il s'agit de 'photos' ou d'une 'vidéo' + # [1] = s'il s'agit d'un chantier 'initial' ou 'renommé' + # [2] = 'original' ou "importé" + self.typeDuChantier [0] = 'vidéo' + self.copierParamVersChantier() # effectue d'abord sauveparam() + self.ecritureTraceMicMac() # on écrit les fichiers trace + + # charge les options pour Tapioca : les valeurs d'échelle et de Line sont celles par défaut + + self.modeTapioca.set('Line')# Mode (All, MulScale, Line) + + # charge les options pour Tapas : + + self.modeCheckedTapas.set('FishEyeBasic') + + # Message final : + + self.encadre(_("Les images de la video sont décompactées sous le répertoire :") + "\n\n" + self.repTravail+ + "\n\n" + _("Il y a %s images décompactées.") % (str(self.photosSansChemin.__len__())) + + "\n\n" + _("Lancer 'Sélection des images' pour sélectionner %s images par seconde de film.") % (self.goProNbParSec.get())+ + "\n\n" + _("La sélection choisira les 'meilleures' images")+ + "\n\n" + _("Les options Tapioca et Tapas ont été positionnées pour des images GoPro : modifier si besoin"),nouveauDepart='oui') + + return # fin : on a obtenu les photos avec un exif à partir d'une vidéo + + + + def ajoutExifGoPro(self): + + # mise à jour de l'exif des images décompactées : + + self.ajoutLigne(_("met à jour l'exif des JPG décompactés :") + "\n"+ + "F35="+self.goProFocale35.get()+"\n"+ + "F="+self.goProFocale.get()+"\n"+ + "Model="+self.goProNomCamera.get()+"\n"+ + "Make="+self.goProMaker.get()) + +## # pour format png +## if self.extensionChoisie=="png": +## setExif = [self.mm3d, +## "SetExif", +## ".*"+self.extensionChoisie, +## "F35="+self.goProFocale35.get(), +## "F="+self.goProFocale.get(), +## "Cam="+self.goProNomCamera.get()] + # pour format jpg + if self.extensionChoisie.upper()==".JPG": + setExif = [self.exiftool, + "-Make="+self.goProMaker.get(), + "-Model="+self.goProNomCamera.get(), + "-FocalLength="+self.goProFocale.get(), + "-FocalLengthIn35mmFormat="+self.goProFocale35.get(), + "*"+self.extensionChoisie] + + self.lanceCommande(setExif) + + # SetExit crée des copies "original" des fichiers initiaux, on les supprime ; + + [supprimeFichier(x) for x in os.listdir(self.repTravail) \ + if os.path.splitext(x)[1]!=self.extensionChoisie \ + and os.path.splitext(x)[0] not in self.photosSansChemin] + + def selectionGoPro(self): + + if self.typeDuChantier[0]!='vidéo': + self.encadre(_("Cette sélection de photos est réservé aux chantiers vidéos")) + return + + # on sélectionne un nombre d'image à la seconde en fonction de la qualité des images + + ################## Bizarrerie (bogue) : l'extension doit être png, même si le format est jpg################## + [os.rename(a,os.path.splitext(a)[0]+".png") for a in os.listdir(self.repTravail) if self.extensionChoisie in a] + ######################################################## + self.cadreVide() # ouvre la trace + self.ajoutLigne(_("Sélection d'un sous ensemble des images GoPro décompactées.")) + div = [self.mm3d, + "DIV", + "Im_0000_.*png", + "Rate="+self.goProNbParSec.get()] + self.lanceCommande(div) + + ################## Bizarrerie (bogue) : l'extension doit être png, même si le format est jpg################## + [os.rename(a,os.path.splitext(a)[0]+self.extensionChoisie) for a in os.listdir(self.repTravail) if 'png' in a] + ######################################################## + + # on supprime les intrus (les noms des fichiers intrus ont été marqué d'un N1, les autres d'un _Ok + self.ajoutLigne("\n".join([(_(" a supprimer : ")+x) for x in os.listdir(self.repTravail) if "Nl" in str(x)])) + + nbSuppressions = [supprimeFichier(x) for x in os.listdir(self.repTravail) if "Nl" in str(x)].__len__() + self.photosAvecChemin = [x for x in os.listdir(self.repTravail) if self.extensionChoisie in str(x) and os.path.isfile(x)] # listes des photos conservées + self.photosSansChemin = list([os.path.basename(x) for x in self.photosAvecChemin]) # liste des noms de photos copiès, sans le chemin. [tuple] + self.etatDuChantier = 2 + self.ecritureTraceMicMac() # on écrit les fichiers trace + if nbSuppressions==0: + self.encadre(_("Aucune sélection effectuée. La version de micmac ne propose peut-être pas cette fonction.") + "\n" + + _("Consulter la trace.") + "\n\n" + + _("Vous pouvez utiliser le menu 'outils/qualité des photos line'") + "\n" + + _("puis effectuer une sélection manuelle.")) + else: + self.afficheEtat(_("Images sélectionnées.") + "\n\n" + _("Vous pouvez lancer Micmac.")) + + ###################### Sélection des meilleures JPG (futur) + + def selectionJPG(self): + + if self.typeDuChantier[0]!='photos': + self.encadre(_("Cette sélection de photos est réservé aux chantiers photos")) + return + + # on sélectionne un nombre d'image à la seconde en fonction de la qualité des images + + ################## Bizarrerie (bogue) : l'extension doit être png, même si le format est jpg################## + [(os.rename(a,os.path.splitext(a)[0]+".png")) for a in os.listdir(self.repTravail) if self.extensionChoisie in a] + ######################################################## + self.cadreVide() # ouvre la trace + self.ajoutLigne(_("Sélection d'un sous ensemble des images GoPro décompactées.")) + + div = [self.mm3d, + "DIV", + "DSC.*png", + "Rate="+self.goProNbParSec.get()] + self.lanceCommande(div) + + ################## Bizarrerie (bogue) : l'extension doit être png, même si le format est jpg################## + [(os.rename(a,os.path.splitext(a)[0]+self.extensionChoisie)) for a in os.listdir(self.repTravail) if 'png' in a] + ######################################################## + + # on supprime les intrus (les noms des fichiers intrus ont été marqué d'un N1, les autres d'un _Ok + self.ajoutLigne("\n".join([(_(" a supprimer : ")+x) for x in os.listdir(self.repTravail) if "Nl" in str(x)])) + + nbSuppressions = [supprimeFichier(x) for x in os.listdir(self.repTravail) if "Nl" in str(x)].__len__() + self.photosAvecChemin = [x for x in os.listdir(self.repTravail) if self.extensionChoisie in str(x) and os.path.isfile(x)] # listes des photos conservées + self.photosSansChemin = list([os.path.basename(x) for x in self.photosAvecChemin]) # liste des noms de photos copiès, sans le chemin. [tuple] + self.etatDuChantier = 2 + self.ecritureTraceMicMac() # on écrit les fichiers trace + if nbSuppressions==0: + self.encadre(_("Aucune sélection effectuée.") + "\n" + _("Consulter la trace.") + "\n\n" + + _("Vous pouvez utiliser le menu 'outils/qualité des photos line'\npuis effectuer une sélection manuelle.")) + else: + self.afficheEtat(_("Images sélectionnées.") + "\n\n" + _("Vous pouvez lancer Micmac.")) + + + # ------------------ ffmpeg : extraction images d'une video ----------------------- - self.selectionPhotos.select_set(0) # sélection de la première photos - self.current = None # pas de photo choisie par l'utilisateur - self.poll() # lance la boucle infinie d'attente + def lanceFfmpeg(self,video): - self.topVisuPhoto.protocol("WM_DELETE_WINDOW", self.fermerVisuPhoto) # Fonction a éxécuter lors de la sortie du programme - self.topVisuPhoto.transient(fenetre) # 3 commandes pour définir la fenêtre comme modale pour l'application - self.topVisuPhoto.grab_set() - fenetre.wait_window(self.topVisuPhoto) - try : self.bulle.destroy() - except: pass + if os.path.exists(self.ffmpeg)==False: + return -1 + # Si on a un masque 3D on l'utilise et on ne cherche pas plus loin : + ffmpeg = [self.ffmpeg, + "-i", + video, + self.repTravail+"\Im_0000_%5d_Ok"+self.extensionChoisie] + self.lanceCommande(ffmpeg, + filtre=self.filtreFfmpeg, + info=_("ATTENTION : cette procédure est longue : patience !")) + + def filtreFfmpeg(self,ligne): + #if ligne[0:5]=="frame": + return ligne + + +########################################## Outils divers (raccourcis clavier, infobulle, afficher un dico de points....) def lettre(self,event): if event.char.isdigit(): # sinon on annule la recherche digit = chiffre @@ -4545,14 +8482,14 @@ def lettre(self,event): trouve = True break if trouve: - self.invitePhotoMessage.set(self.invitePhotoMessageInitial+"\nTrouvé : "+self.cherche) + self.invitePhotoMessage.set(self.invitePhotoMessageInitial+"\n" + _("Trouvé : ")+self.cherche) else: - self.invitePhotoMessage.set(self.invitePhotoMessageInitial+"\nNon trouvé : "+self.cherche) + self.invitePhotoMessage.set(self.invitePhotoMessageInitial+"\n" + _("Non trouvé : ")+self.cherche) else: self.cherche=str() self.invitePhotoMessage.set(self.invitePhotoMessageInitial) - def poll(self): # boucle srutant la valeur sélectionnée en cours, 10 fois par seconde + def poll(self): # boucle scrutant la valeur sélectionnée en cours, 10 fois par seconde try: now = self.selectionPhotos.curselection() if now != self.current: @@ -4564,9 +8501,11 @@ def poll(self): # bo def list_has_changed(self, selection): if len(selection)>0: self.current = selection - if self.retailleEtAffichePhoto(self.listeChoisir[selection[0]])=="KO": # prend l'image, la retaille et l'affiche - if self.messageSiPasDeFichier==1: - self.infoBulle(" Pas de fichier pour "+os.path.basename(self.listeChoisir[selection[0]])) # message si pas de photo + try: + if self.retailleEtAffichePhoto(self.listeChoisir[selection[0]])=="KO": # prend l'image, la retaille et l'affiche + if self.messageSiPasDeFichier==1: + self.infoBulle(_(" Pas de fichier pour ")+os.path.basename(self.listeChoisir[selection[0]])) # message si pas de photo + except: pass self.selectionPhotos.see(self.current) def infoBulle(self,texte=""): # affiche une infobulle sous le curseur. @@ -4583,9 +8522,8 @@ def infoBulle(self,texte=""): relief='solid') # texte, la taille de la fenêtre s'adapte au texte, style infobulle l.pack() self.bulle.update() - except Exception as e: - print("erreur infobulle : ",e," pour ",texte) + print(_("erreur infobulle : "),str(e)) def yview(self, *args): if args[0] == 'scroll': @@ -4615,7 +8553,8 @@ def fermerVisuPhoto(self): # fe def upDown(self,event=None): # modifie la sélection en cours après appui sur les flèches up ou Down (qui modifient seulement l'item "ACTIVE") - self.selectionPhotos.selection_clear(self.selectionPhotos.curselection()) + if self.selectionPhotos.curselection(): + self.selectionPhotos.selection_clear(self.selectionPhotos.curselection()) self.selectionPhotos.selection_set(self.selectionPhotos.index('active')) def afficherTousLesPointsDuDico(self): # affiche les points de l'imager en cours sur le canvas en cours @@ -4631,12 +8570,22 @@ def afficherTousLesPointsDuDico(self): # af nbpts+=1 if nbpts==0: - self.infoBulle("Aucun point placé sur cette photo") + self.infoBulle(_("Aucun point placé sur cette photo")) if nbpts==1: - self.infoBulle("Un point placé sur cette photo") + self.infoBulle(_("Un point placé sur cette photo")) if nbpts>1: - self.infoBulle(nbpts.__str__()+" points placés sur cette photo") - + self.infoBulle(nbpts.__str__()+_(" points placés sur cette photo")) + + def afficherLesInfosBullesDuDico(self): + if self.dicoInfoBullesAAfficher==None: + return + for e in self.dicoInfoBullesAAfficher: + if os.path.basename(e)==self.enCours: + message = str(self.dicoInfoBullesAAfficher[e]) + if message!=str(): + self.infoBulle(message) + + def xyJPGVersCanvas(self,xJPG,yJPG,bouton=None): # xJPG,yJPG : position dans l'image originale (Jpeg) couleurTexte = 'black' xFrame = xJPG * self.scale # xFrame,yFrame : position dans l'image dans le cadre @@ -4645,12 +8594,14 @@ def xyJPGVersCanvas(self,xJPG,yJPG,bouton=None): # xJPG, self.canvasPhoto.create_oval(xFrame-5, yFrame-5,xFrame+5, yFrame+5,fill='yellow',tag=bouton) ######################################## Retaille et Affiche : prépare une photo pour affichage dans une petite fenêtre 200*200 max + # attention : appelle afficherTousLesPointsDuDico et afficherLesInfosBullesDuDico qui nécessitent des variables existantes def retailleEtAffichePhoto(self,photo): # charge le canvas self.canvasPhoto - if not os.path.exists(photo): # erreur de paramètrage + self.enCours = os.path.basename(photo) + + if not os.path.exists(photo): # erreur de paramétrage try: self.canvasPhoto.delete(self.imgTk_id) # supprimer la photo dans le canvas si elle existe - except: pass - return "KO" + except: return "KO" self.dimMaxiCanvas = 200 self.hauteurCanvas = 200 self.largeurCanvas= 200 @@ -4667,13 +8618,17 @@ def retailleEtAffichePhoto(self,photo): self.img = self.imagePhoto.resize((self.largeurCanvas,self.hauteurCanvas)) self.imgTk = ImageTk.PhotoImage(self.img) self.imgTk_id = self.canvasPhoto.create_image(0,0,image = self.imgTk,anchor="nw") # affichage effectif de la photo dans canvasPhoto - self.enCours = os.path.basename(photo) + + #affichage des info bulles + try: self.bulle.destroy() + except: pass + self.afficherLesInfosBullesDuDico() self.afficherTousLesPointsDuDico() ############################### Choix d'un répertoire dans la liste des répertoires de travail, avec scrollbar : charge self.selectionPhotosAvecChemin - def choisirUnRepertoire(self,titre,mode='single'): # mode="single" ou 'extended' - self.retourChoixRepertoire="Abandon" + def choisirUnChantier(self,titre,mode='single'): # mode="single" ou 'extended' + self.retourChoixRepertoire=_("Abandon") self.fichierProposes = list() chantierSansParametre = list() for e in self.tousLesChantiers: # suppression des répertoires inexistants (parce que supprimés) @@ -4685,7 +8640,7 @@ def choisirUnRepertoire(self,titre,mode='single'): # mode="single" chantierSansParametre.insert(0,e) if len(self.fichierProposes)==0: - return "Aucun chantier mémorisé." + return _("Aucun chantier mémorisé.") self.selectionRepertoireAvecChemin=str() self.topRepertoire = tkinter.Toplevel() self.topRepertoire.title(titre) @@ -4693,10 +8648,10 @@ def choisirUnRepertoire(self,titre,mode='single'): # mode="single" fenetreIcone(self.topRepertoire) f = self.topRepertoire #ttk.Frame(self.topRepertoire) frameSelectRep = ttk.Frame(self.topRepertoire) - invite = ttk.Label(self.topRepertoire,text="Choisir le chantier à ouvrir :") + invite = ttk.Label(self.topRepertoire,text=_("Choisir le chantier à ouvrir :")) invite.pack(pady=10,padx=10,ipadx=5,ipady=5) - scrollbarV = ttk.Scrollbar(frameSelectRep, orient='vertical') - scrollbarH = ttk.Scrollbar(frameSelectRep, orient='horizontal') + scrollbarV = ttk.Scrollbar(frameSelectRep, orient=_('vertical')) + scrollbarH = ttk.Scrollbar(frameSelectRep, orient=_('horizontal')) self.selectionRepertoire = tkinter.Listbox(frameSelectRep, selectmode=mode, xscrollcommand=scrollbarH.set, @@ -4716,13 +8671,13 @@ def choisirUnRepertoire(self,titre,mode='single'): # mode="single" self.selectionRepertoire.pack(side='left', fill='both', expand=1) frameSelectRep.pack() self.selectionRepertoire.select_set(0) - b = ttk.Button(f,text="Ouvrir",command=self.validRepertoire) + b = ttk.Button(f,text=_("Ouvrir"),command=self.validRepertoire) b.pack(pady=5) - c = ttk.Button(f,text="Annuler",command=self.cancelRepertoire) + c = ttk.Button(f,text=_("Annuler"),command=self.cancelRepertoire) c.pack(pady=5) if len(chantierSansParametre)>0: - d = ttk.Label(f,text="Il y a des chantiers incomplets,\n le fichier "+self.fichierParamChantierEnCours+" est absent.\n"+ - "Ces chantiers ne peuvent être ouverts mais peuvent être supprimés :\n\n"+"\n".join(chantierSansParametre)) + d = ttk.Label(f,text=_("Il y a des chantiers incomplets,") + "\n" + _(" le fichier %s est absent.") % (self.paramChantierSav)+ "\n" + + _("Ces chantiers ne peuvent être ouverts mais peuvent être supprimés :") + "\n\n"+"\n".join(chantierSansParametre)) d.pack(pady=5) fenetre.wait_window(self.topRepertoire) return self.retourChoixRepertoire @@ -4747,73 +8702,589 @@ def validRepertoire(self): def cancelRepertoire(self): self.topRepertoire.destroy() - self.retourChoixRepertoire="Abandon utilisateur." + self.retourChoixRepertoire=_("Abandon utilisateur.") - def envPath(self): - return + ############################## Répertoire Orientation en cours ou futur et répertoire des points Homologues - def orientation(self): # définit le répertoire qui contient l'orientation la plus récente : - # soit Arbitrary soit echelle3d soit bascul + def orientation(self): # définit le répertoire qui contient l'orientation la plus récente : + # soit Arbitrary après tapas(même si absent) soit echelle3 après calibration par axe, plan et métrique + # soit bascul après calibration par points GPS + # soit campari après bascul et campari + - if os.path.exists(os.path.join(self.repTravail,"Ori-bascul")): - return "bascul" + if os.path.exists(os.path.join(self.repTravail,"Ori-campari")): # orientation obtenue après campari (bascule faite et campari aussi) + return "campari" - if os.path.exists(os.path.join(self.repTravail,"Ori-echelle3")): - orientation = "echelle3" + if os.path.exists(os.path.join(self.repTravail,"Ori-bascul")): # orientation obtenue après Tapas et GCPbascule (points GPS OK) + return "bascul" + + if os.path.exists(os.path.join(self.repTravail,"Ori-echelle3")): # # orientation obtenue après Tapas et calibration return "echelle3" + + return "Arbitrary" # si rien d'autre - return "Arbitrary" + ########## pour renommer homol - def pasDePhoto(self): + def repertoireHomol(self,homol): + # le paramètre permet d'utiliser un autre répertoire + try: os.rename(_("Homol"),_("HomolTemporaire")) + except Exception as e: + print(_("erreur renommage Homol en HomolTemporaire : "),str(e)) + return + try: + os.rename(homol,_("Homol")) + self.homolActuel = homol # Pour retourner à la situation originale si besoin + except Exception as e: print(_("erreur renommage %s en Homol : ") % (homol),str(e)) + + + def retourHomol(self): # pour l'instant inutilisé + + if self.homolActuel==str(): return + try: os.rename(_("Homol"),self.homolActuel) + except Exception as e: + print(_("erreur renommage Homol en : %s : ") % (self.homolActuel),str(e)) + return + try: os.rename(_("HomolTemporaire"),"Homol") + except Exception as e: + print(_("erreur renommage HomolTemporaire en Homol : "),str(e)) + return + self.homolActuel = str() + + #################### Examen du nombre de points homologues dans le répertoire homol sous le répertoire passé en paramètre, affichage + + def nombrePointsHomologues(self,repertoire="Homol"): + message = "" + nbGroupes = self.regroupementSuivantPointsHomologues(repertoire) + if not nbGroupes: + repertoire = "Homol_SRes" + nbGroupes = self.regroupementSuivantPointsHomologues(repertoire) # si nbGroupes == 0 + if ( ( nbGroupes>1 and not self.calibSeule.get() )or + ( nbGroupes>1 and self.calibSeule.get() and self.photosPourCalibrationIntrinseque.__len__()==0 ) or + ( nbGroupes>2 and self.calibSeule.get() ) + ) : + message = _("ATTENTION : Les photos définissent plusieurs scènes disjointes") + "\n"+\ + _("MicMac ne peut travailler que sur une seule scène : toutes les photos doivent former une seule scéne.") + "\n"+\ + _("Les photos se répartissent en :") + str(nbGroupes)+_(" groupes distincts (consulter la trace) : ")+"\n" +\ + "\n".join([str(e)[:100] for e in self.lesGroupesDePhotos]) + self.ajoutLigne(_("Les groupes de photos séparés : ")+"\n"+"\n".join([str(e) for e in self.lesGroupesDePhotos])) + self.ecritureTraceMicMac() + self.menageEcran() + repertoireHomol = os.path.join(self.repTravail,repertoire) # répertoire des homologues + if os.path.isdir(repertoireHomol)==False: + self.encadre(_("Lancer MicMac avant de pouvoir évaluer la qualité des photos.")) + return + if os.path.isdir(repertoireHomol)==False: + self.encadre(_("Le traitement n'a donné aucun point homologue.") + "\n\n" + message+ "\n\n"+ _("Consulter la trace.")) + return + + # somme des scores de chaque photo : préparation des données + homol = dict() + nb = dict() + moyenne = dict() + for photo in self.photosSansChemin: + homol[photo] = 0 # nombre total des points homologue de l'image + nb[photo] = 0 # nombre d'images "comparées" + moyenne[photo] = 0 + + os.chdir(repertoireHomol) + nbPoints = 0 + for e in os.listdir(): # balaie tous les fichiers contenant les points homologues + os.chdir(os.path.join(repertoireHomol,e)) + for f in os.listdir(): + if os.path.isfile(f): # fichier : on calcule le nombre de points homologues dans le fichier + nbPoints = 0 + if f[-3:]=="dat": + taille = os.path.getsize(f) + nbPoints = (taille-8)/44 # fichier binaire : 44 octets par point homologue + if f[-3:]=="txt": # fichier texte : une ligne par point homologue + with open(f) as infile: # il faut lire de fichier (longueur variable) + nbPoints = infile.readlines().__len__() + for photo in self.photosSansChemin: + if photo in e: # nom de la photo dans le nom du répertoire : on incrémente le nb points + homol[photo] += nbPoints + nb[photo] += 1 + moyenne[photo] = homol[photo]/nb[photo] + + # on crée le rapport : nombre moyen de points homologues, trié du + grand au plus petit : dans ajouLigne + + listeHomol = list(moyenne.items()) + listeHomol.sort(key=lambda e: e[1],reverse=True) + cas = _("dernier traitement : ")+self.modeTapioca.get() + self.effaceBufferTrace() # efface ajoutligne + self.ajoutLigne("\n" + _("Classement des photos par nombre de points homologues :") + "\n\n"+cas+"\n\n") + self.ajoutLigne(chr(9)+_("Photo ")+chr(9)+_("score")+chr(9)+_("nb photos en correspondance") + "\n\n") + for e in listeHomol: + self.ajoutLigne(e[0]+chr(9)+str(int(e[1]))+chr(9)+chr(9)+chr(9)+str(nb[e[0]])+"\n") + if len(listeHomol)==0: + self.ajoutLigne(_("Aucune photo n'a de point analogue avec une autre.") + "\n") + self.ajoutLigne("\n"+heure()+_(" : fin de la recherche sur la qualité des photos.")) + self.ajoutLigne("\n\n ******") + ligneFiltre = self.ligneFiltre # l'écriture de la trace efface self.ligneFiltre et encadre doit être en fin de paragraphe + self.ecritureTraceMicMac() + os.chdir(self.repTravail) + self.encadre(message+ligneFiltre) + + #################### Regroupement des photos reliées par des points homologues : renvoi le nombre de groupes + ## s'il y a plusieurs groupes isolés les uns des autres alors : pas d'orientation possible + # attention : lors de la commande Tapioca MulScale lors du premier passage il est créé un répertoire pour chaque photo dans Homol_SRes + # ce qui peut créer des groupes "vides" + # lors du second passage il n'est créé un répertoire que s'il y a des points homologues avec une autre photo + def regroupementSuivantPointsHomologues(self,rep="Homol"): + def ajout(groupe,liste): + for p in liste: + if p in dico and p not in exclure: + exclure.append(p) + ajout(groupe,dico[p]) + if p not in groupe: + groupe.append(p) + + repertoireHomol = os.path.join(self.repTravail,rep) + if os.path.isdir(repertoireHomol)==False: + return 0 + groupe = dict() # dico : [photo : liste des photos participant à la même scène] + dico = dict() # dico : [photo : liste des photos ayant des points homologues] (à partir du répertoire rep) + exclure = list() # liste des photos apparaisssant dans un groupe, chaque photo n'étant que dans un seul groupe + for e in os.listdir(repertoireHomol): # balaie tous les sous-répertoires de rep : crée une liste par répertoire + photo = e[6:] # nom de la photo + dico[photo] = list() + for f in os.listdir(os.path.join(repertoireHomol,e)): # sous-répertoire + dico[photo].append(f[:-4]) # nom des photos (sans prefixe/suffixe) dans un dictionnaires de listes + if rep=="Homol_SRes": + dico = {k: v for k, v in dico.items() if v} + for p in self.photosSansChemin: # recherche pour chaque photo du groupe d'appartenance + groupe[p] = list() # chaque photo n'appartient qu'à un seul groupe + if p in dico : ajout(groupe[p],dico[p]) # récursivité sur les listes de photos ayant des points homologues + else: groupe[p] = p # il faut ajouter les groupes avec une seule photo isolée (ignorés dans le répertoire rep): + # les regroupements sont faits : la variable groupe[p] est soit une liste vide, soit la liste de tous les éléments du groupe + self.lesGroupesDePhotos = [e for e in groupe.values() if e] + return self.lesGroupesDePhotos.__len__() + + +################## Sélection des N meilleures photos en fonction de leur nombre de points homologues.... +################## remarque : on sélectionne les meilleurs couples, avec un petit effort sur le premier item des éléments de listeTaille +################## Attention : suppose que les points homologues soient dans des fichiers .dat ( si variable self.exptxt="0") sinon des .txt + + def lesMeilleuresPhotos(self,nombre=0): # retourne la liste des N = nombre meilleures photos en nombre de points homologues. + self.menageEcran() + listeTaille = list() + repertoireHomol = os.path.join(self.repTravail,"Homol") # répertoire des homologues + if os.path.isdir(repertoireHomol)==False: + self.encadre(_("Lancer d'abord Tapioca/Tapas")) + return + + os.chdir(repertoireHomol) + for e in os.listdir(): # balaie tous les fichiers contenant les points homologues + os.chdir(os.path.join(repertoireHomol,e)) + for f in os.listdir(): + listeTaille.append((e,f, os.path.getsize(f))) # répertoire, nom du fichier et taille + os.chdir(self.repTravail) + + listeTaille.sort(key= lambda e: e[2],reverse=True) # trie la liste des fichiers par taille + if self.exptxt =="0" : typeFichier=".dat" + if self.exptxt =="1" : typeFichier=".txt" + liste = [(e[1].split(typeFichier)[0],e[0].split("Pastis")[-1]) for e in listeTaille] # liste des noms des plus gros fichiers des fichiers de l'arborescence Homol + listeSet=set() # chaque nom peut apparaitre plusieurs fois : on va utilsier un ensemble (set) + for e in liste : # on ne conserve que les n premiers + listeSet.add(e[0]) # ajout nom du répertoire = premiere photo(la lecture de la liste conserve l'ordre des tailles) + listeSet.add(e[1]) # ajout seconde photo + if len(listeSet)>=nombre: # le passage par un ensemble fait perdre l'ordre des tailles (sans importance : on ne retient que les meilleures) + break + listeOk = [e for e in listeSet if os.path.exists(e)] # liste limitée aux fichiers effectivement présents sous le répertoire de travail + return listeOk + +#################### Lister les fichiers Ply générés: + + def lister3DPly(self): + listePly = [e for e in os.listdir() if os.path.splitext(e)[1]==".ply"] + if listePly==list(): + self.encadre(_("Aucun nuage de points dans ce chantier.")) + return + self.choisirUnePhoto(listePly, + titre=_("Liste des nuages de points du chantier"), + message=_("les nuages (fichiers ply) :"), + messageBouton=_("Visualiser"), + boutonDeux=_("Fermer"), + mode='single') + if self.selectionPhotosAvecChemin.__len__()==1: + self.lanceCommande([self.meshlab,self.selectionPhotosAvecChemin[0]],attendre=False) + + #################### Fusionner des fichiers Ply : + + def choisirPuisFusionnerPly(self): + + listePly = [e for e in os.listdir() if os.path.splitext(e)[1]==".ply"] + if listePly==list(): + self.encadre(_("Aucun nuage de points dans ce chantier.")) + return + self.choisirUnePhoto(listePly, + titre=_("Fusion de nuages"), + message=_("Choisir les fichiers à fusionner :"), + messageBouton=_("Fusionner et visualiser"), + boutonDeux=_("Fermer"), + mode='extended') + if self.selectionPhotosAvecChemin.__len__()==0: + return + if self.selectionPhotosAvecChemin.__len__()==1: + self.encadre(_("Choisir au moins 2 nuages pour la fusion.")) + return + liste = "|".join([os.path.splitext(os.path.basename(x))[0] for x in self.selectionPhotosAvecChemin]) + self.mergePly = 'fusion.ply' + i = 0 + while os.path.exists(os.path.join(self.repTravail,self.mergePly))==True and i<20: + i+=1 + self.mergePly = 'fusion_'+str(i)+".ply" + self.fusionnerPly(self.selectionPhotosAvecChemin,self.mergePly) + + def fusionnerPly(self,liste,nomFinal): + + if liste.__len__()==0: + return + if liste.__len__()==1: + self.encadre(_("Choisir au moins 2 nuages pour la fusion.")) + return + if os.path.exists(liste[0])==False or os.path.exists(liste[1])==False: # la liste comprend au moins 2 fichiers : existent-t-ils ? + self.encadreEtTrace(_("Les ply attendus n'ont pas été créé.") + "\n" + _("Consulter la trace.")) + return + + supprimeFichier(nomFinal) # tentative de suppression du fichier résultat + # on va fusionner tous les ply, on dénomme ceux qui ne doivent pas l'être : + [os.rename(e,os.path.splitext(e)[0]+".pyl") for e in os.listdir(self.repTravail) if os.path.splitext(e)[1]=='.ply' and e not in liste] # pour ne traiter que le nécessaire (self.photosCalibrationSansChemin) + + mergePly = [self.mm3d, + "mergeply", + '.*.ply', + "Out="+nomFinal] + self.lanceCommande(mergePly) # fusion des ply : attention si types différents (xyz,xyzrgb), plante + [os.rename(e,os.path.splitext(e)[0]+".ply") for e in os.listdir(self.repTravail) if os.path.splitext(e)[1]==".pyl"] # remise à l'état initial + if os.path.exists(nomFinal): + self.lanceCommande([self.meshlab,nomFinal],attendre=False) + self.encadreEtTrace(_("Nuage fusionné :") + "\n\n" + nomFinal + "\n\n" + _("ajouté à la liste des nuages.") + "\n" + _("résultat de la fusion de :") + "\n\n" + +"\n"+"\n".join(liste)+"\n") + else: + self.encadreEtTrace(_("La fusion n'a pu se réaliser.") + "\n" + _("Consulter la trace.")) + + ################### Conversion au format jpg, information de l'Exif + + def conversionJPG(self,liste=list()): + + if self.pasDeConvertMagick(): + self.ajoutLigne(_("Le programme de conversion n'est pas présent.")) + return + if liste==list(): + liste = self.photosSansChemin + if liste.__len__()==0: + return + curdir = os.getcwd() + os.chdir(os.path.dirname(liste[0])) + for e in liste: + if os.path.isfile(e): + i=os.path.basename(e) + nouveauJPG = os.path.splitext(i)[0]+".JPG" + convert = [self.convertMagick,i,'-quality 100',nouveauJPG] + print(convert) + os.system(" ".join(convert)) + os.chdir(curdir) + + + + # mise à jour de l'exif : + + def majExif(self,liste=list()): + if self.pasDeExiftool():return + self.menageEcran() + self.outilAppareilPhoto(silence='oui') + self.menageEcran() + self.exifMaker.set(self.fabricant) + self.exifNomCamera.set(self.nomCamera) + self.exifFocale.set(self.focale) + self.exifFocale35.set(self.focale35MM) + self.item3000.pack() + return + + # lancé par item3000 : + + def exifOK(self): + if self.pasDeExiftool():return + listeTag = [('Make', self.exifMaker.get() ), + ('Model', self.exifNomCamera.get() ), + ('FocalLength', self.exifFocale.get() ), + ('FocalLengthIn35mmFormat', self.exifFocale35.get() ) + ] + + + self.informerExif(self.exiftool,self.photosSansChemin,listeTag) + self.item3000.pack_forget() # pour éviter la question par menageEcran + self.encadreEtTrace(_("Exifs mis à jour") + "\n"+ + _("Fabricant = ")+self.exifMaker.get()+"\n"+ + _("Modèle = ")+self.exifNomCamera.get()+"\n"+ + _("Focale = ")+self.exifFocale.get()+"\n"+ + _("Focale eq 35mm = ")+self.exifFocale35.get()+"\n") + self.nbFocales = 1 # une seule focale pour toutes les photos + self.lesTagsExif = dict() # supprimer les anciennes mémorisations des tags + self.sauveParamChantier() + + def exifKO(self): + self.item3000.pack_forget() # pour éviter la question par menageEcran + self.encadre(_("Abandon de la mise à jour des exifs")) + + + # après saisie de l'exif : + + def informerExif(self,exiftool,listeFichiers,listeTagInfo): # la liste peut être relative ou absolue, taginfo est une liste de tuple (tag,info) + + if self.pasDeExiftool():return + + if listeFichiers.__len__()==0: + return _("Aucune photo à mettre à jour.") + + if self.nombreDExtensionDifferentes(listeFichiers)!=1: + return _("La liste des fichiers comporte plusieurs extensions différentes : abandon.")+\ + "\n".join(listeFichiers) + + extension = os.path.splitext(listeFichiers[0])[1] + if extension.upper() not in ".JPG.JPEG": + interface.encadre(_("La version actuelle ne traite que les exif des photos au format JPG, or le format des photos est %s. Désolé, abandon.") % (extension) ) + return + + # Controle de l'existence des fichiers : + for e in listeFichiers: + if os.path.isfile(e)==False: + return _("Le fichier %s n'existe pas. Abandon") % (e) + + # mise à jour de l'exif des images décompactées : + + message = _("met à jour l'exif de ")+"\n".join(listeFichiers)+"\n" + + # Les fichiers sont ok on va pouvoir les traiter : + + listeModifs = ["-"+tag+"="+info for tag,info in listeTagInfo] + + # pour format jpg + + setExif = [exiftool]+listeModifs+["-ext .JPG", self.repTravail] # ["*"+extension] + + self.lanceCommande(setExif) + + # SetExit crée des copies "original" des fichiers initiaux, on les supprime ; + + [supprimeFichier(x) for x in os.listdir(self.repTravail) \ + if os.path.splitext(x)[1]!="."+extension \ + and os.path.splitext(x)[0] in listeFichiers] - if self.photosPropresAvecChemin.__len__()==0: - self.encadre("Choisir des photos au préalable.",nouveauDepart="non") + return "" + + + #################### Utilitaires : tests de la présence de photos, de mm3d, d'exiftool, envoi retour chariot et compte le nombre d'extensions différentes dans une list + + def pasDePhoto(self): + if self.photosAvecChemin.__len__()==0: + self.encadre(_("Choisir des photos au préalable.")) return True - liste = [e for e in self.photosPropresAvecChemin if os.path.exists(e)==False] + repertoireInitial = os.path.dirname(self.photosAvecChemin[0]) + if not os.path.isdir(repertoireInitial): + self.encadre(_("Répertoire du chantier non accessible")) + return + liste = [e for e in self.photosAvecChemin if os.path.exists(e)==False] if liste.__len__()>0: - texte="Attention les photos suivantes sont absentes sur disque : \n"+"\n".join(liste)+"\nElles sont supprimées." - self.photosPropresAvecChemin = liste = [e for e in self.photosPropresAvecChemin if os.path.exists(e)] - self.photosSansChemin =list([os.path.basename(x) for x in self.photosPropresAvecChemin]) - repertoireInitial = os.path.dirname(self.photosAvecChemin[0]) - self.photosAvecChemin = [os.path.join(repertoireInitial,e) for e in self.photosSansChemin] - self.deuxBoutons(titre="Problème de fichiers",question=texte,b1='OK',b2='') # b1 renvoie 0, b2 renvoie 1 ; fermer fenetre = -1 - + self.photosAvecChemin = [e for e in self.photosAvecChemin if os.path.exists(e)] + self.photosSansChemin = [os.path.basename(x) for x in self.photosAvecChemin] + if self.photosAvecChemin: + repertoireInitial = os.path.dirname(self.photosAvecChemin[0]) + texte=_("Attention les photos suivantes sont absentes sur disque : ") + "\n"+"\n".join(liste)+"\n" + _("Elles sont supprimées du chantier.") + self.troisBoutons(titre=_("Problème de fichiers"),question=texte,b1='OK',b2='') # b1 renvoie 0, b2 renvoie 1 ; fermer fenetre = -1 + else: + texte=_("Attention toutes les photos sont absentes sur disque et retirées du chantier: ") + self.troisBoutons(titre=_("Problème de fichiers"),question=texte,b1='OK',b2='') # b1 renvoie 0, b2 renvoie 1 ; fermer fenetre = -1 + + def pasDeMm3d(self): + if not os.path.exists(self.mm3d): + self.encadre("\n" + _("Bonjour !") + "\n\n" + _("Commencer par indiquer où se trouve MicMac :") + "\n\n"+ + _(" - menu Paramétrage/Associer le répertoire bin de MicMac") + "\n\n"+ + _("Ensuite consulter l'aide, item 'pour commencer'.") + "\n\n"+ + _("Si besoin :") + "\n"+ + _( " - Associer convert et exiftool s'ils ne sont pas trouvés automatiquement sous micmac/binaire-aux")+"\n"+ + _(" - Associer un outil (CloudCompare ou Meshlab) pour afficher les nuages de points 3D") + "\n\n"+ + _(" - Consulter la notice d'installation et de prise en main"), + aligne='left') + return True + + def pasDeExiftool(self): + if not os.path.exists(self.exiftool): + self.encadre(_("Désigner le fichier exiftool (menu paramétrage).")) + return True + + def pasDeConvertMagick(self): + if not os.path.exists(self.convertMagick): + self.encadre(_("Désigner le fichier convert, ou avconv, d'image Magick") + "\n" + + _("en principe sous micmac\\binaire-aux (menu paramétrage).")) + return True + + def pasDeFfmpeg(self): + if not os.path.exists(self.ffmpeg): + self.encadre(_("Désigner le fichier ffmpeg (possible sous micmac\\binaire-aux (menu paramétrage).")) + return True + def nombreDExtensionDifferentes(self,liste): + lesExtensions=set([os.path.splitext(x)[1].upper() for x in liste]) # on vérifie l'unicité de l'extension : + self.lesExtensions=list(lesExtensions) # liste pour être slicable + return len(self.lesExtensions) + + def nombreDePrefixes(self,liste,longueurPrefixe=3): + lesPrefixes=set([x[0:longueurPrefixe].upper() for x in liste]) # on vérifie l'unicité des préfixes : + self.lesPrefixes=list(lesPrefixes) # liste pour être slicable + return len(self.lesPrefixes) + + def nombreDeExifTagDifferents(self,tag="SerialNumber"): # on vérifie l'unicité des valeurs pour un tag (numéros de série par défaut) + lesTags = [[self.encadrePlus("."),self.tagExif(tag,photo)] for photo in self.photosAvecChemin] + lesTags = set([e1 for e0,e1 in lesTags]) + self.lesTags=[ tag for tag in lesTags if tag !=""] # abonde la liste des valeurs trouvées dans self.lesTags + return len (self.lesTags) # renvoie le nombre de valeurs différentes : 0, 1 , plus + +######################################################## Modifier les options par défaut + + + def majOptionsParDefaut(self): # Si les options ont déjà été modifiées + if os.path.exists(self.fichierSauvOptions): + retour = self.troisBoutons(titre=_("Modifier les options par défaut"), + question=self.messageSauvegardeOptions, + b1=_("Revenir aux options par défaut d'AperoDeDenis"), + b2=_("Utiliser les options du chantier en cours"), + b3=_("Ne rien changer")) + if retour == 0: + supprimeFichier(self.fichierSauvOptions) + self.encadre(_("Options par défaut réinitialisées")) + elif retour == 1: + optionsOK = self.sauveOptions() + if optionsOK==True: + self.encadre(_("Les options par défaut seront désormais celles du chantier en cours")) + else: + self.encadre(optionsOK) + else: + self.afficheEtat() + + else: # Si les options n'ont pas été modifiées + retour = self.troisBoutons(titre=_("Modifier les options par défaut"), + question=self.messageSauvegardeOptions+ + _("Les options par défaut actuelles sont les options par défaut d'AperoDeDenis"), + b1=_("Utiliser les options du chantier en cours"), + b2=_("Ne rien changer")) + if retour == 0: # choix b1 + optionsOK = self.sauveOptions() + if optionsOK==True: + self.encadre(_("Les options par défaut seront désormais celles du chantier en cours")) + else: + self.encadre(optionsOK) + else: + self.afficheEtat() + + def sauveOptions(self): + retour = self.controleOptions() + if retour!=True: + message = _("Options par défaut non sauvegardées car les options du chantier en cours sont invalides :") + "\n"+retour + return message + try: + sauvegarde3=open(self.fichierSauvOptions,mode='wb') + pickle.dump(( self.echelle1.get(), # nécessaire pour définir la variable obtenue le widget + self.echelle2.get(), + self.echelle3.get(), + self.echelle4.get(), + self.delta.get(), + self.file.get(), + self.modeTapioca.get(), + self.modeMalt.get(), + self.modeCheckedTapas.get(), + self.arretApresTapas.get(), + self.photosUtilesAutourDuMaitre.get(), + self.calibSeule.get(), + self.zoomF.get(), + self.modeC3DC.get(), + self.tawny.get(), + self.tawnyParam.get(), + version, + self.lancerTarama.get(), + self.incertitudeCibleGPS.get(), + self.incertitudePixelImage.get() + ), + sauvegarde3) + sauvegarde3.close() + except Exception as e: # Controle que le programme a accès en écriture dans le répertoire d'installation + print (_('erreur sauveOptions : '),str(e)) + texte = _("Erreur rencontrée lors de la sauvegarde des options : ")+str(e) + return texte + return True + + def restaureOptions(self): + if not os.path.exists(self.fichierSauvOptions): return + try: # s'il y a une sauvegarde alors on la restaure + sauvegarde4 = open(self.fichierSauvOptions,mode='rb') + r = pickle.load(sauvegarde4) + sauvegarde4.close() + self.echelle1.set(r[0]) # nécessaire pour définir la variable obtenue le widget + self.echelle2.set(r[1]) + self.echelle3.set(r[2]) + self.echelle4.set(r[3]) + self.delta.set(r[4]) + self.file.set(r[5]) + self.modeTapioca.set(r[6]) + self.modeMalt.set(r[7]) + self.modeCheckedTapas.set(r[8]) + self.arretApresTapas.set(r[9]) + self.photosUtilesAutourDuMaitre.set(r[10]) + self.calibSeule.set(r[11]) + self.zoomF.set(r[12]) + self.modeC3DC.set(r[13]) + self.tawny.set(r[14]) + self.tawnyParam.set(r[15]) + # R16 est la version d'aperodedenis, inutile pour l'instant + self.lancerTarama.set(r[17]) + self.incertitudeCibleGPS.set(r[18]), + self.incertitudePixelImage.set(r[19]) + except Exception as e: + print(_("erreur restauration options : ")+str(e)) + + - ######################################################## nouvelle fenêtre + ######################################################## nouvelle fenêtre (relance utile pour vider les traces d'exécution de mm3d et autres) def nouveauDepart(self): + try: self.copierParamVersChantier() # sauvegarde du chantier, des param... + except: pass + try: self.ecritureTraceMicMac() # on écrit les fichiers trace + except: pass - self.copierParamVersChantier() # sauvegarde du chantier, des param... - self.ecritureTraceMicMac() # on écrit les fichiers trace - -# faut-t-il différencier linux et windows ? +# faut-il différencier linux et windows ? if self.systeme=='posix': if self.messageNouveauDepart==str(): self.afficheEtat() else: - self.encadre(self.messageNouveauDepart) + self.encadre(self.messageNouveauDepart,nouveauDepart='oui') self.messageNouveauDepart = str() if self.systeme=='nt': global messageDepart - messageDepart = self.messageNouveauDepart - fenetre.destroy() - + messageDepart = self.messageNouveauDepart # ce message sera repris dans la nouvelle "interface" + print(heure()+"nouveau départ") + if "fenetre" in globals(): + time.sleep(0.2) + try: + fenetre.destroy() # relance une nouvelle "interface" + except: pass + # quitter def quitter(self): texte="" if self.etatDuChantier > 2 and self.etatSauvegarde =="*": - if self.deuxBoutons("Enregistrer le chantier "+self.chantier+" ?","Chantier modifé depuis la dernière sauvegarde. Voulez-vous l'enregistrer ?","Enregistrer","Ne pas enregistrer.") == 0: + if self.troisBoutons(_("Enregistrer le chantier %s ?") % (self.chantier), + _("Chantier modifié depuis la dernière sauvegarde. Voulez-vous l'enregistrer ?"), + _("Enregistrer"),_("Ne pas enregistrer.")) == 0: self.copierParamVersChantier() - texte="Chantier précédent enregistré : "+self.chantier+"\n" - print(heure()+" "+texte+" fin normale d'aperodedenis.") + texte=_("Chantier précédent enregistré : %s")% (self.chantier) + "\n" + print(heure()+" "+texte+_("fin normale d'aperodedenis.")) self.sauveParam() global continuer # pour éviter de boucler sur un nouveau départ - continuer = False + continuer = False # termine la boucle mainloop fenetre.destroy() - time.sleep(0.5) ################################## FIN DE LA CLASSE INTERFACE ########################################################### @@ -4827,28 +9298,30 @@ def pv(variable): # affiche le nom de la variable, sa classe et sa valeur print('\n------------------') if '))' in stack[0][3]: nomVariable = stack[0][3].replace('pv(', '').replace('))', ')') - typeVariable = "fonction" - valeurVariable = "valeur en retour : " + typeVariable = _("fonction") + valeurVariable = _("valeur en retour : ") else: nomVariable = stack[0][3].replace('pv(', '').replace(')', '') - typeVariable = "variable" - valeurVariable = "valeur : " - print ("Détail de la "+typeVariable+" : ",nomVariable, - '\nIdentifiant : ',id(variable), - '\nType : ',type(variable), - '\nclass = ',variable.__class__, - '\nLes attributs : ',dir(variable), - '\n\n'+valeurVariable,str(variable)) + typeVariable = _("variable") + valeurVariable = _("valeur : " ) + print (_("Détail de la %(typeVar)s : %(nomVar)s") % {"typeVar" : typeVariable, "nomVar" : nomVariable}, + '\n', _('Identifiant : '),id(variable), + '\n', _('Type : '),type(variable), + '\n', _('class = '),variable.__class__, + '\n', _('Les attributs : '),dir(variable), + '\n\n')+valeurVariable,str(variable) print('\n------------------') -def heure(): # time.struct_time(tm_year=2015, tm_mon=4, tm_mday=7, tm_hour=22, tm_min=56, tm_sec=23, tm_wday=1, tm_yday=97, tm_isdst=1) - return "le "+str(time.localtime()[2])+"/"+str(time.localtime()[1])+"/"+str(time.localtime()[0])+" à "+str(time.localtime()[3])+":"+str(time.localtime()[4]) def supprimeFichier(fichier): - try: - os.remove(fichier) - except: - return + try: os.remove(fichier) + except Exception as e: + return _("Erreur suppression fichier :")+str(e) + +def supprimeMasque(repertoire,masque): + for e in os.listdir(repertoire): + if masque in e: + supprimeFichier(e) def blancAuNoir(p): if p == 255: @@ -4866,24 +9339,56 @@ def ajout(liste,item): # ajout d'un item dns un for e in c: liste.append(e) except Exception as e: - print ("erreur ajout : ",liste,"+",item," : ",e) + print (_("erreur ajout : "),str(e)) def supprimeArborescenceSauf(racine,listeSauf=list()): # supprime toute une arborescence, sauf une liste de fichiers sous la racine listeSauf = [os.path.basename(e) for e in listeSauf] - for fichier in os.listdir(racine): chemin = os.path.join(racine,fichier) if fichier in listeSauf: if os.path.isdir(chemin): - shutil.rmtree(chemin) + try: shutil.rmtree(chemin) + except: pass else: if os.path.isfile(chemin): - os.remove(chemin) + try: + supprimeFichier(chemin) + except Exception as e: + print(_("erreur remove = "),str(e)) + return else: shutil.rmtree(chemin) # on supprime tous les sous répertoires 'calculs, temporaires...) +def zipdir(path): # path = chemin complet du répertoire à archiver, + # crée un zip qui contient tous les fichiers sauf les exports + # avec un nouveau nom de chantier = ancienNom(export) + try: + archive = os.path.join(path,os.path.basename(path)+".exp") # archive : nom du fichier dans lequel mettre l'archive + racine = os.path.dirname(path) # racine pour dezip + zipf = zipfile.ZipFile(archive, 'w') + + for root, dirs, files in os.walk(path): + for file in files: + if not os.path.splitext(archive)[1]==os.path.splitext(file)[1]: # les archives ne sont pas incluses dans le zip + fichier = os.path.join(root, file) # nom complet du fichier à archiver + cheminDezip = fichier.partition(racine)[2] # nom pour le dezippage (on change le nom du répertoire de travail relatif dans le chantier + cheminDezip = cheminDezip.replace(interface.chantier,interface.chantier+interface.suffixeExport,1) + zipf.write(fichier, + arcname=cheminDezip, + compress_type=zipfile.ZIP_DEFLATED ) + interface.encadrePlus(".") + zipf.close() + return os.path.getsize(archive) + except Exception as e: + print(_("erreur zip = "),str(e)) + return -1 + + -def afficheChemin(texte): #avant d'afficher un chemin on s'assure que le séparateur est bien le bon suivant l'OS +def afficheChemin(texte): # avant d'afficher un chemin on s'assure que le séparateur est bien le bon suivant l'OS + # normcase supprimé le 26 avril 2016 : affectait les noms de fichiers en minuscule + texte = str(texte) + texte = os.path.normpath(texte) return texte.replace(interface.separateurAutre,interface.separateurChemin) def format2Colonnes(col1,col2,largeurCol1EnPixels): @@ -4903,16 +9408,26 @@ def verifMm3d(mm3D): # Il faudrait que la version de MicMac autorise if "SaisieMasqQT" in helpMm3d: return True else: return False +def mercurialMm3d(mm3D): # Il faudrait que la version de MicMac autorise la saisie de masque en 3D, sinon ancienne version, susceptible de donner des erreurs. + if os.path.exists(mm3D)==False: return False + try: mercurialMm3d = subprocess.check_output([mm3D,"CheckDependencies"],universal_newlines=True) + except Exception as e: + print(_("erreur mercurial : %(e)s pour mm3D=%(mm3D)s") %{"mm3D" : mm3D, "e" : str(e)}) + return _("pas de version identifiée de MicMac") + else: return mercurialMm3d.splitlines()[0] + + def verifierSiExecutable(exe): try: subprocess.check_call(exe) return True - except: - return False - -def envoiRetourChariot(self,dest): # dest étant le processus ouvert par popen - dest.communicate(input='t\n') - + except Exception as e: + try: + subprocess.check_call([exe,"-h"]) + return True + except Exception as f: + return False + def open_file(filename): if sys.platform == "win32": os.startfile(filename) @@ -4923,13 +9438,23 @@ def open_file(filename): def fenetreIcone(fenetre=""): # Icone au format GIF pour être géré par tkinter sans utiliser Pillow if fenetre=="": - return + return photo = tkinter.PhotoImage(data=iconeTexte) fenetre.tk.call('wm', 'iconphoto', fenetre._w, photo) -def fin(codeRetour=0): - os._exit(codeRetour) - +def sizeDirectoryMO(path): + size = 0 + for root, dirs, files in os.walk(path): + for fic in files: + size += os.path.getsize(os.path.join(root, fic)) + return round(size/1000000) + +def ouvrirPageWEBAperoDeDenis(): + webbrowser.open("https://github.com/micmacIGN/InterfaceCEREMA/tree/master/InterfaceCEREMA") + +def lireReadMe(): + webbrowser.open("https://raw.githubusercontent.com/micmacIGN/InterfaceCEREMA/master/InterfaceCEREMA/readme.txt") + '''################################## Crée un fichier contenant l'icone de l'application et en renvoie le nom conserver pour exemple de ficheir temporaire def iconeGrainSel(): @@ -4939,25 +9464,27 @@ def iconeGrainSel(): f.write(iconeBin) return f.name ''' + + ################################## Classe : Dialogue minimum modal : demande une chaine de caractères ###########################" class MyDialog: - def __init__(self,parent,titre="Nouveau nom pour le chantier : ",basDePage='none'): + def __init__(self,parent,titre=_("Nouveau nom pour le chantier : "),basDePage='none'): self.saisie=str() - top = self.top = tkinter.Toplevel(parent,width=200,relief='sunken') + top = self.top = tkinter.Toplevel(parent,width=500,relief='sunken') top.transient(parent) - top.geometry("400x250+100+100") + top.geometry("600x300+100+100") fenetreIcone(self.top) l=ttk.Label(top, text=titre) l.pack(pady=10,padx=10) top.bind("",self.ok) - self.e = ttk.Entry(top,width=30) + self.e = ttk.Entry(top,width=60) self.e.pack() self.e.focus_set() - b = ttk.Button(top, text="OK", command=self.ok) + b = ttk.Button(top, text=_("OK"), command=self.ok) b.pack(pady=5) - c = ttk.Button(top, text="Annuler", command=self.ko) + c = ttk.Button(top, text=_("Annuler"), command=self.ko) c.pack(pady=5) if basDePage!="none": d = ttk.Label(top, text=basDePage) @@ -4974,7 +9501,152 @@ def ok(self,event='none'): def ko(self): self.top.destroy() return - + +################################## Classe : Dialogue modale : demande un texte #########################" + +class MyDialogTexte: + + def __init__(self,parent,titre=_("Console"),basDePage='none',boutonDialogueTexteOk='OK'): + self.saisie=str() + top = self.top = tkinter.Toplevel(parent,width=250,relief='sunken') + top.transient(parent) + top.geometry("600x400+100+100") + fenetreIcone(self.top) + l=ttk.Label(top, text=titre) + l.pack(pady=10,padx=10) + #top.bind("",self.ok) + # la fenetre pour afficher les textes (traces et aides) + + self.resul200 = ttk.Frame(top,height=100,relief='sunken') # fenêtre texte pour afficher le bilan + self.scrollbar = ttk.Scrollbar(self.resul200) + self.scrollbar.pack(side='right',fill='y',expand=1) + self.scrollbar.config(command=self.yviewTexte) + self.texte201 = tkinter.Text(self.resul200,width=60,height=5,yscrollcommand = self.scrollbar.set,wrap='word') + self.resul200.pack() + self.texte201.pack() + self.texte201.focus_set() + b = ttk.Button(top, text=_(boutonDialogueTexteOk), command=self.ok) + b.pack(pady=5) + c = ttk.Button(top, text=_("Abandon"), command=self.ko) + c.pack(pady=5) + if basDePage!="none": + d = ttk.Label(top, text=basDePage) + d.pack(pady=5) + top.grab_set() + fenetre.wait_window(top) + + def ok(self,event='none'): + self.saisie=self.texte201.get("0.0",'end') + self.top.destroy() + return + + + def ko(self): + self.top.destroy() + return + + def yviewTexte(self, *args): + if args[0] == 'scroll': + self.texte201.yview_scroll(args[1],args[2]) + elif args[0] == 'moveto': + self.texte201.yview_moveto(args[1]) + +################################## Classe : Dialogue minimum modal : choix dans une liste ###########################" + +class choisirDansUneListe: # mode="single" ou 'extended' + + def __init__(self,fenetreParent,listeDeChoix,titre,mode='extended',boutonOk="supprimer"): + if len(listeDeChoix)==0: + return + self.lesChoix = listeDeChoix + self.topChoix = tkinter.Toplevel(fenetreParent) # boite de dialogue + self.topChoix.transient(fenetreParent) + self.topChoix.title(titre) + self.topChoix.geometry("400x250+100+100") + fenetreIcone(self.topChoix) + f = self.topChoix # ttk.Frame(self.topChoix) + frameSelectRep = ttk.Frame(self.topChoix) + invite = ttk.Label(self.topChoix,text=("Choisir :")) + invite.pack(pady=10,padx=10,ipadx=5,ipady=5) + scrollbarV = ttk.Scrollbar(frameSelectRep, orient=('vertical')) + scrollbarH = ttk.Scrollbar(frameSelectRep, orient=('horizontal')) + self.selection = tkinter.Listbox(frameSelectRep, + selectmode=mode, + xscrollcommand=scrollbarH.set, + yscrollcommand=scrollbarV.set, + height= min(10,len(listeDeChoix)), + width= min(70,min(300,(5+max(len (r) for r in listeDeChoix))))) + + self.selection.select_set(1) + listeDeChoix.sort() + for i in listeDeChoix: + self.selection.insert('end',i) + if len(listeDeChoix)>10: + scrollbarV.config(command=self.yview) + scrollbarV.pack(side='right', fill='y') +## scrollbarH.config(command=self.xview) +## scrollbarH.pack(side='bottom', fill='y') + self.selection.pack(side='left', fill='both', expand=1) + frameSelectRep.pack() + self.selection.select_set(0) + b = ttk.Button(f,text=(boutonOk),command=self.valid) + b.pack(pady=5) + c = ttk.Button(f,text=("Annuler"),command=self.cancel) + c.pack(pady=5) + self.topChoix.grab_set() + fenetre.wait_window(self.topChoix) + + def yview(self, *args): + if args[0] == 'scroll': + self.selection.yview_scroll(args[1],args[2]) + elif args[0] == 'moveto': + self.selection.yview_moveto(args[1]) + + def xview(self, *args): + if args[0] == 'scroll': + self.selection.xview_scroll(args[1],args[2]) + elif args[0] == 'moveto': + self.selection.xview_moveto(args[1]) + + def valid(self): + selectionEnCours = self.selection.curselection() + self.topChoix.destroy() + self.selectionFinale = [self.lesChoix[e] for e in selectionEnCours] + + + def cancel(self): + self.topChoix.destroy() + self.selectionFinale = list() + + + +################################## Classe : Dialogue minimum modal : deux boutons OK KO ###########################" + + +def MyDialog_OK_KO(parent=None,titre=_("Question"),b1="OK",b2="KO"): + top = tkinter.Toplevel(parent,width=200,relief='sunken') + top.transient(parent) + top.geometry("400x250+100+100") + fenetreIcone(top) + l=ttk.Label(top, text=titre) + l.pack(pady=10,padx=10) + b = ttk.Button(top, text=b1, command=ok) + b.pack(pady=5) + c = ttk.Button(top, text=b2, command=ko) + c.pack(pady=5) + top.grab_set() + parent.wait_window(top) + parent.mainloop() + +def ok(event='none'): + print("OK") + try: f.destroy() + except: pass + return 1 + +def ko(event=None): + print("KO") + return 0 ################################## Style pur TTK ###########################" @@ -4982,15 +9654,8 @@ def monStyle(): pass ttk.Style().configure("TButton", padding=6, relief="flat",background="#ccc") - -################################## LANCEMENT DU PROGRAMME ########################################################### - -# si on ouvre ce script comme programme principal alors on instancie un objet de la classe Interface sur la fenêtre principale de l'outil : +################################### boucle sur l'interface tant que continuer est vrai : -continuer = True -messageDepart = str() -compteur = 0 -iconeTexte = "R0lGODlhIAAgAIcAMQQCBJSGJNTSPHQKBMTCpGxKBPziXJxmJIR6BOTCXPTybDwCBHR2TMTGhPTmjOzmpJxuBMy+pIRyLDweDPz+1MTGjOzuhDwmBMRaFPz+pHx6LKRiLPzibDQiDMzKZIxqTKR6NOy2fHxCBNTCdEwaBISGTPzqfBwCBPTmpJRuLMzCjKxqBPTmnKxuBOzqnNzGXJQ2BHxGBIx2FIR+fMzGfOTmtMS+vIRyPPz67PTubBQCBJyGJMTCtPzqVKRmHPzSfFQWBIRuTJxuFEQeBPz+vHx2RKxiLNTKXMzCnPzqZAQKBHROBHx6JPz+hPzihPTqfEwqLJxqLJR+XOS+bEwiBMzGhPzenAwCBIyKNNzKTMzCpHxyTOzqpIxyLEwqBJxmRMzKbKx6PIQ+BNTGdISCXMzGjIxCBNS6vPz+/PzqXKRqHPzeZGQOBPzqdPzmjMzOVGwSBMTGpGxGHIR6FPTyfKRuDMy+tDwiBPz+5MTGnEQqBPz+tIR2NKRmLDQiJMzOXJx6VEwWDIx6fPyubLR6FCwCBHRCHIx+BMy6vOS+hPzedPzilIxuPIR2PJSGNJR2hFQaBJRqPKxmFJyCNFwSBIR2JPTqjJQ+BPTqlOzmtKRuFNTOTHRKBIyGTCQCBNzGbJw2BIRGBPz+zPz+lFQiBHxyXMy6zPzmVMzKdPz+7PzuTEQiBHx6PPzuZPzmfKRyBAQGBHQOBJxqJMTKhDwqBKR+NEweBMzGnHRSBPTufMzKhAwGBIRCBPzuXIR+FPzmlFwWBMTCrPTydHR2VOzmrMy+rIRyNPz+3MTGlOzujPz+rHx6NDQiFIxqVNTCfPzqhPTmrMzClIRyRPTudMTCvKRmJIRuVJxuHEQeDPz+xNTKZOS+dIyKPOzqrIxyNNTGfISCZMzGlKRqJDwiDKRmNMzOZPzefPTqnOzmvMzKfPz+9PzubPzmhAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACwAAAAAIAAgAAcI/gABCBxIsKDBgwgTKlxI8MoVHVcYShT4cMIdHRAnKtRxwZIlGsa+eIqo0eAVCey0/fHATgSkEyRLUrwCjUg6MH9yHXECZKRMih0IVKjAZY+FUexCGAryU+AWPHiQVchTJsO0F26waNAASyaDVKkodCOAzMERDxb2uEiGJaZEcOrUUdDF5du2KZiq5EEGxsEQHROvlEqFRxSLADIKWPmGLFgeD09A2HKbUAc2JGUSxYDAScYYLqJE6bKwKY2XVRgpFzwxpNOiKNXqOBnTrUI4ZN2U5VCVZlKQOw5VUzTmwtEGYIyiEQDLgwcBLsqyCKNBjIsEWycQwlpGowslSoC0/qAZj0bdsVmoLCjTJSrbNyurhAOYlc0YpQWRpJwxVf5YmWQeoNIAHuqkcgw0KnBlECzdNNAFEJTY8gEUjyASgSi/vJCLI9DcslwceFSByS4HlZBMALL0pMMEzQTyxQa8qAFBFJM4kE4Nxxg4Ai0HLfNHG6SoYYsnhRQJBDBGqBGDDyI4sQMYZYCFQheUwaKBAr28UkcoK8DAhidgDmGLLCJIMogZTqCCRyploJARQRq8ccgSBpyyBgYDBIKRDid0YQ4hMEjyggsE8IBMFQ5cENMVdyCgwCZJNLEGKHlC9NAdbfTSQxJPVNAcMlx4kChgADjEhAe5ePCHKz/EUkhGfRjJIIAA08wSBw/mqeDCHtKQKtAuLrRHxCeKmLGBJ3ueoEcbROTIw3jF4ACVarAMEwc6RCRgDghyTKDDRU44k0p56lBjwyN+SFQEH3w4wkKbc1gSjXjqFGNNKSXBou8uy5TQgHrH8EDNDOPIpxEDeeSRCThNLaRvwxBHLFFAADs=" if __name__ == "__main__": while continuer: compteur += 1 @@ -4999,6 +9664,8 @@ def monStyle(): if messageDepart==str(): interface.afficheEtat() else: - interface.encadre(messageDepart) # affiche les infos restaurées : - fenetre.mainloop() # boucle tant que l'interface existe + interface.encadre(str(messageDepart)) # affiche les infos restaurées : + try: fenetre.mainloop() # boucle tant que l'interface existe + except: pass + diff --git a/InterfaceCEREMA/Changelog.md b/InterfaceCEREMA/Changelog.md new file mode 100644 index 0000000..f6e4214 --- /dev/null +++ b/InterfaceCEREMA/Changelog.md @@ -0,0 +1,42 @@ +## Version 5.32 (12 mars 2019) +- la recherche d'une nouvelle version sur le web propose la visualisation du fichier "readme.txt" (Outils/véifier la présence...) +- sous windows : avertissement si la longueur d'une ligne de commande dépasse 8191 caractères, risque de plantage +- correction bug lors de la définition de plusieurs appareils photos, amélioration de la vitesse du traitement + +## Version 5.31 (8 mars 2019) +- Les échelles par défaut de Tapioca sont calculées suivant les photos : 60% de la dimension maxi des photos +- suppresssion des items de menu outils\qualité des photos line et qualité des photos ALL, + maintient de la qualité des photos sur le dernier traitement +- Ajout d'un controle d'unicité de la scène aprés le premier passage, rapide, de Tapioca MultiScale : + évite de se lancer dans une recherche approfondie de points homologues si l'échec est prévu +- Ajout de 1 item au menu outils : retirer des photos au chantier +- optimisation de la fonction "Expert/plusieurs appareils" +- l'installateur msi pour Windows installe un item dans le menu démarrer, un raccourci sur le bureau et + ajoute le répertoire d'installation au path + +## Version 5.30 (février 2019) +- dans les items 'Outils/Qualité des photos' ajout des photos 'isolées', en disjontion de toutes les autres. + Ces photos font 'planter' la recherche de l'orientation. +- Suite à la recherche des points homologues vérification de l'unicité de la scène photographiée. + Plusieurs scènes sans points homologues communs font planter la recherche d'une orientation. + Cette fonction est ajoutée à l'item 'Outils/Qualité des photos'. +- Lorsque le message MAXLINELENGTH est émis par Tapioca il est affiché et expliqué dans la trace synthétique. +- prise en compte de l'erreur concernant la fonction filedialog sous Mac-Os lors des recherche de programmes (exiftool...). +- Ajout d'un item dans paramètrage : recherche d'une nouvelle version GitHub. + +## Version 5.2 +- lancement automatique de campari après GCP_bascul (menu MicMac/options/points gps) +- ajout de la consultation du log mm3d (menu expert) +- mise à jour de dicocamera.xml pour "tous" les appareils photos du lot de données (menu outils) +- ajout d'un chantier à partir d'un répertoire (menu fichier) +- ajout d'un item dans le menu expert : ouverture d'une console pour lancer des commandes "python" + +## Version 5.11 + +- menu MicMac/options : l'onglet "calibration" est renommé : "mise à l'échelle" +- menu MicMac/option/Tapas : les photos pour calibrer l'appareil photo sont, ou pas, indépendantes des photos utilisées pour construire le nuage +- menu outils/nom de l'appareil photo : affichage des dimensions des photos et du numéro de série de l'appareil (si présent dans l'exif) +- Menu Expert, nouveaux item : + - saisie des points GPS à partir d'un fichier texte (séparateur espace : nom, x,y,z, dx,dy,dz) + - possibilité de répartir les photos suivant plusieurs appareils photos + - liste des différents appareils photos présents dans le lot de photos diff --git a/InterfaceCEREMA/Documentation_AperoDeDenis.pdf b/InterfaceCEREMA/Documentation_AperoDeDenis.pdf new file mode 100644 index 0000000..a2a3051 Binary files /dev/null and b/InterfaceCEREMA/Documentation_AperoDeDenis.pdf differ diff --git a/InterfaceCEREMA/Interface graphique MicMac - instalaltion et prise en main.pdf b/InterfaceCEREMA/Interface graphique MicMac - instalaltion et prise en main.pdf deleted file mode 100644 index d4325a3..0000000 Binary files a/InterfaceCEREMA/Interface graphique MicMac - instalaltion et prise en main.pdf and /dev/null differ diff --git a/InterfaceCEREMA/LICENSE b/InterfaceCEREMA/LICENSE new file mode 100644 index 0000000..365263d --- /dev/null +++ b/InterfaceCEREMA/LICENSE @@ -0,0 +1,514 @@ +CeCILL-B FREE SOFTWARE LICENSE AGREEMENT + + + Notice + +This Agreement is a Free Software license agreement that is the result +of discussions between its authors in order to ensure compliance with +the two main principles guiding its drafting: + + * firstly, compliance with the principles governing the distribution + of Free Software: access to source code, broad rights granted to + users, + * secondly, the election of a governing law, French law, with which + it is conformant, both as regards the law of torts and + intellectual property law, and the protection that it offers to + both authors and holders of the economic rights over software. + +The authors of the CeCILL-B (for Ce[a] C[nrs] I[nria] L[ogiciel] L[ibre]) +license are: + +Commissariat à l'Energie Atomique - CEA, a public scientific, technical +and industrial research establishment, having its principal place of +business at 25 rue Leblanc, immeuble Le Ponant D, 75015 Paris, France. + +Centre National de la Recherche Scientifique - CNRS, a public scientific +and technological establishment, having its principal place of business +at 3 rue Michel-Ange, 75794 Paris cedex 16, France. + +Institut National de Recherche en Informatique et en Automatique - +INRIA, a public scientific and technological establishment, having its +principal place of business at Domaine de Voluceau, Rocquencourt, BP +105, 78153 Le Chesnay cedex, France. + + + Preamble + +This Agreement is an open source software license intended to give users +significant freedom to modify and redistribute the software licensed +hereunder. + +The exercising of this freedom is conditional upon a strong obligation +of giving credits for everybody that distributes a software +incorporating a software ruled by the current license so as all +contributions to be properly identified and acknowledged. + +In consideration of access to the source code and the rights to copy, +modify and redistribute granted by the license, users are provided only +with a limited warranty and the software's author, the holder of the +economic rights, and the successive licensors only have limited liability. + +In this respect, the risks associated with loading, using, modifying +and/or developing or reproducing the software by the user are brought to +the user's attention, given its Free Software status, which may make it +complicated to use, with the result that its use is reserved for +developers and experienced professionals having in-depth computer +knowledge. Users are therefore encouraged to load and test the +suitability of the software as regards their requirements in conditions +enabling the security of their systems and/or data to be ensured and, +more generally, to use and operate it in the same conditions of +security. This Agreement may be freely reproduced and published, +provided it is not altered, and that no provisions are either added or +removed herefrom. + +This Agreement may apply to any or all software for which the holder of +the economic rights decides to submit the use thereof to its provisions. + + + Article 1 - DEFINITIONS + +For the purpose of this Agreement, when the following expressions +commence with a capital letter, they shall have the following meaning: + +Agreement: means this license agreement, and its possible subsequent +versions and annexes. + +Software: means the software in its Object Code and/or Source Code form +and, where applicable, its documentation, "as is" when the Licensee +accepts the Agreement. + +Initial Software: means the Software in its Source Code and possibly its +Object Code form and, where applicable, its documentation, "as is" when +it is first distributed under the terms and conditions of the Agreement. + +Modified Software: means the Software modified by at least one +Contribution. + +Source Code: means all the Software's instructions and program lines to +which access is required so as to modify the Software. + +Object Code: means the binary files originating from the compilation of +the Source Code. + +Holder: means the holder(s) of the economic rights over the Initial +Software. + +Licensee: means the Software user(s) having accepted the Agreement. + +Contributor: means a Licensee having made at least one Contribution. + +Licensor: means the Holder, or any other individual or legal entity, who +distributes the Software under the Agreement. + +Contribution: means any or all modifications, corrections, translations, +adaptations and/or new functions integrated into the Software by any or +all Contributors, as well as any or all Internal Modules. + +Module: means a set of sources files including their documentation that +enables supplementary functions or services in addition to those offered +by the Software. + +External Module: means any or all Modules, not derived from the +Software, so that this Module and the Software run in separate address +spaces, with one calling the other when they are run. + +Internal Module: means any or all Module, connected to the Software so +that they both execute in the same address space. + +Parties: mean both the Licensee and the Licensor. + +These expressions may be used both in singular and plural form. + + + Article 2 - PURPOSE + +The purpose of the Agreement is the grant by the Licensor to the +Licensee of a non-exclusive, transferable and worldwide license for the +Software as set forth in Article 5 hereinafter for the whole term of the +protection granted by the rights over said Software. + + + Article 3 - ACCEPTANCE + +3.1 The Licensee shall be deemed as having accepted the terms and +conditions of this Agreement upon the occurrence of the first of the +following events: + + * (i) loading the Software by any or all means, notably, by + downloading from a remote server, or by loading from a physical + medium; + * (ii) the first time the Licensee exercises any of the rights + granted hereunder. + +3.2 One copy of the Agreement, containing a notice relating to the +characteristics of the Software, to the limited warranty, and to the +fact that its use is restricted to experienced users has been provided +to the Licensee prior to its acceptance as set forth in Article 3.1 +hereinabove, and the Licensee hereby acknowledges that it has read and +understood it. + + + Article 4 - EFFECTIVE DATE AND TERM + + + 4.1 EFFECTIVE DATE + +The Agreement shall become effective on the date when it is accepted by +the Licensee as set forth in Article 3.1. + + + 4.2 TERM + +The Agreement shall remain in force for the entire legal term of +protection of the economic rights over the Software. + + + Article 5 - SCOPE OF RIGHTS GRANTED + +The Licensor hereby grants to the Licensee, who accepts, the following +rights over the Software for any or all use, and for the term of the +Agreement, on the basis of the terms and conditions set forth hereinafter. + +Besides, if the Licensor owns or comes to own one or more patents +protecting all or part of the functions of the Software or of its +components, the Licensor undertakes not to enforce the rights granted by +these patents against successive Licensees using, exploiting or +modifying the Software. If these patents are transferred, the Licensor +undertakes to have the transferees subscribe to the obligations set +forth in this paragraph. + + + 5.1 RIGHT OF USE + +The Licensee is authorized to use the Software, without any limitation +as to its fields of application, with it being hereinafter specified +that this comprises: + + 1. permanent or temporary reproduction of all or part of the Software + by any or all means and in any or all form. + + 2. loading, displaying, running, or storing the Software on any or + all medium. + + 3. entitlement to observe, study or test its operation so as to + determine the ideas and principles behind any or all constituent + elements of said Software. This shall apply when the Licensee + carries out any or all loading, displaying, running, transmission + or storage operation as regards the Software, that it is entitled + to carry out hereunder. + + + 5.2 ENTITLEMENT TO MAKE CONTRIBUTIONS + +The right to make Contributions includes the right to translate, adapt, +arrange, or make any or all modifications to the Software, and the right +to reproduce the resulting software. + +The Licensee is authorized to make any or all Contributions to the +Software provided that it includes an explicit notice that it is the +author of said Contribution and indicates the date of the creation thereof. + + + 5.3 RIGHT OF DISTRIBUTION + +In particular, the right of distribution includes the right to publish, +transmit and communicate the Software to the general public on any or +all medium, and by any or all means, and the right to market, either in +consideration of a fee, or free of charge, one or more copies of the +Software by any means. + +The Licensee is further authorized to distribute copies of the modified +or unmodified Software to third parties according to the terms and +conditions set forth hereinafter. + + + 5.3.1 DISTRIBUTION OF SOFTWARE WITHOUT MODIFICATION + +The Licensee is authorized to distribute true copies of the Software in +Source Code or Object Code form, provided that said distribution +complies with all the provisions of the Agreement and is accompanied by: + + 1. a copy of the Agreement, + + 2. a notice relating to the limitation of both the Licensor's + warranty and liability as set forth in Articles 8 and 9, + +and that, in the event that only the Object Code of the Software is +redistributed, the Licensee allows effective access to the full Source +Code of the Software at a minimum during the entire period of its +distribution of the Software, it being understood that the additional +cost of acquiring the Source Code shall not exceed the cost of +transferring the data. + + + 5.3.2 DISTRIBUTION OF MODIFIED SOFTWARE + +If the Licensee makes any Contribution to the Software, the resulting +Modified Software may be distributed under a license agreement other +than this Agreement subject to compliance with the provisions of Article +5.3.4. + + + 5.3.3 DISTRIBUTION OF EXTERNAL MODULES + +When the Licensee has developed an External Module, the terms and +conditions of this Agreement do not apply to said External Module, that +may be distributed under a separate license agreement. + + + 5.3.4 CREDITS + +Any Licensee who may distribute a Modified Software hereby expressly +agrees to: + + 1. indicate in the related documentation that it is based on the + Software licensed hereunder, and reproduce the intellectual + property notice for the Software, + + 2. ensure that written indications of the Software intended use, + intellectual property notice and license hereunder are included in + easily accessible format from the Modified Software interface, + + 3. mention, on a freely accessible website describing the Modified + Software, at least throughout the distribution term thereof, that + it is based on the Software licensed hereunder, and reproduce the + Software intellectual property notice, + + 4. where it is distributed to a third party that may distribute a + Modified Software without having to make its source code + available, make its best efforts to ensure that said third party + agrees to comply with the obligations set forth in this Article . + +If the Software, whether or not modified, is distributed with an +External Module designed for use in connection with the Software, the +Licensee shall submit said External Module to the foregoing obligations. + + + 5.3.5 COMPATIBILITY WITH THE CeCILL AND CeCILL-C LICENSES + +Where a Modified Software contains a Contribution subject to the CeCILL +license, the provisions set forth in Article 5.3.4 shall be optional. + +A Modified Software may be distributed under the CeCILL-C license. In +such a case the provisions set forth in Article 5.3.4 shall be optional. + + + Article 6 - INTELLECTUAL PROPERTY + + + 6.1 OVER THE INITIAL SOFTWARE + +The Holder owns the economic rights over the Initial Software. Any or +all use of the Initial Software is subject to compliance with the terms +and conditions under which the Holder has elected to distribute its work +and no one shall be entitled to modify the terms and conditions for the +distribution of said Initial Software. + +The Holder undertakes that the Initial Software will remain ruled at +least by this Agreement, for the duration set forth in Article 4.2. + + + 6.2 OVER THE CONTRIBUTIONS + +The Licensee who develops a Contribution is the owner of the +intellectual property rights over this Contribution as defined by +applicable law. + + + 6.3 OVER THE EXTERNAL MODULES + +The Licensee who develops an External Module is the owner of the +intellectual property rights over this External Module as defined by +applicable law and is free to choose the type of agreement that shall +govern its distribution. + + + 6.4 JOINT PROVISIONS + +The Licensee expressly undertakes: + + 1. not to remove, or modify, in any manner, the intellectual property + notices attached to the Software; + + 2. to reproduce said notices, in an identical manner, in the copies + of the Software modified or not. + +The Licensee undertakes not to directly or indirectly infringe the +intellectual property rights of the Holder and/or Contributors on the +Software and to take, where applicable, vis-à-vis its staff, any and all +measures required to ensure respect of said intellectual property rights +of the Holder and/or Contributors. + + + Article 7 - RELATED SERVICES + +7.1 Under no circumstances shall the Agreement oblige the Licensor to +provide technical assistance or maintenance services for the Software. + +However, the Licensor is entitled to offer this type of services. The +terms and conditions of such technical assistance, and/or such +maintenance, shall be set forth in a separate instrument. Only the +Licensor offering said maintenance and/or technical assistance services +shall incur liability therefor. + +7.2 Similarly, any Licensor is entitled to offer to its licensees, under +its sole responsibility, a warranty, that shall only be binding upon +itself, for the redistribution of the Software and/or the Modified +Software, under terms and conditions that it is free to decide. Said +warranty, and the financial terms and conditions of its application, +shall be subject of a separate instrument executed between the Licensor +and the Licensee. + + + Article 8 - LIABILITY + +8.1 Subject to the provisions of Article 8.2, the Licensee shall be +entitled to claim compensation for any direct loss it may have suffered +from the Software as a result of a fault on the part of the relevant +Licensor, subject to providing evidence thereof. + +8.2 The Licensor's liability is limited to the commitments made under +this Agreement and shall not be incurred as a result of in particular: +(i) loss due the Licensee's total or partial failure to fulfill its +obligations, (ii) direct or consequential loss that is suffered by the +Licensee due to the use or performance of the Software, and (iii) more +generally, any consequential loss. In particular the Parties expressly +agree that any or all pecuniary or business loss (i.e. loss of data, +loss of profits, operating loss, loss of customers or orders, +opportunity cost, any disturbance to business activities) or any or all +legal proceedings instituted against the Licensee by a third party, +shall constitute consequential loss and shall not provide entitlement to +any or all compensation from the Licensor. + + + Article 9 - WARRANTY + +9.1 The Licensee acknowledges that the scientific and technical +state-of-the-art when the Software was distributed did not enable all +possible uses to be tested and verified, nor for the presence of +possible defects to be detected. In this respect, the Licensee's +attention has been drawn to the risks associated with loading, using, +modifying and/or developing and reproducing the Software which are +reserved for experienced users. + +The Licensee shall be responsible for verifying, by any or all means, +the suitability of the product for its requirements, its good working +order, and for ensuring that it shall not cause damage to either persons +or properties. + +9.2 The Licensor hereby represents, in good faith, that it is entitled +to grant all the rights over the Software (including in particular the +rights set forth in Article 5). + +9.3 The Licensee acknowledges that the Software is supplied "as is" by +the Licensor without any other express or tacit warranty, other than +that provided for in Article 9.2 and, in particular, without any warranty +as to its commercial value, its secured, safe, innovative or relevant +nature. + +Specifically, the Licensor does not warrant that the Software is free +from any error, that it will operate without interruption, that it will +be compatible with the Licensee's own equipment and software +configuration, nor that it will meet the Licensee's requirements. + +9.4 The Licensor does not either expressly or tacitly warrant that the +Software does not infringe any third party intellectual property right +relating to a patent, software or any other property right. Therefore, +the Licensor disclaims any and all liability towards the Licensee +arising out of any or all proceedings for infringement that may be +instituted in respect of the use, modification and redistribution of the +Software. Nevertheless, should such proceedings be instituted against +the Licensee, the Licensor shall provide it with technical and legal +assistance for its defense. Such technical and legal assistance shall be +decided on a case-by-case basis between the relevant Licensor and the +Licensee pursuant to a memorandum of understanding. The Licensor +disclaims any and all liability as regards the Licensee's use of the +name of the Software. No warranty is given as regards the existence of +prior rights over the name of the Software or as regards the existence +of a trademark. + + + Article 10 - TERMINATION + +10.1 In the event of a breach by the Licensee of its obligations +hereunder, the Licensor may automatically terminate this Agreement +thirty (30) days after notice has been sent to the Licensee and has +remained ineffective. + +10.2 A Licensee whose Agreement is terminated shall no longer be +authorized to use, modify or distribute the Software. However, any +licenses that it may have granted prior to termination of the Agreement +shall remain valid subject to their having been granted in compliance +with the terms and conditions hereof. + + + Article 11 - MISCELLANEOUS + + + 11.1 EXCUSABLE EVENTS + +Neither Party shall be liable for any or all delay, or failure to +perform the Agreement, that may be attributable to an event of force +majeure, an act of God or an outside cause, such as defective +functioning or interruptions of the electricity or telecommunications +networks, network paralysis following a virus attack, intervention by +government authorities, natural disasters, water damage, earthquakes, +fire, explosions, strikes and labor unrest, war, etc. + +11.2 Any failure by either Party, on one or more occasions, to invoke +one or more of the provisions hereof, shall under no circumstances be +interpreted as being a waiver by the interested Party of its right to +invoke said provision(s) subsequently. + +11.3 The Agreement cancels and replaces any or all previous agreements, +whether written or oral, between the Parties and having the same +purpose, and constitutes the entirety of the agreement between said +Parties concerning said purpose. No supplement or modification to the +terms and conditions hereof shall be effective as between the Parties +unless it is made in writing and signed by their duly authorized +representatives. + +11.4 In the event that one or more of the provisions hereof were to +conflict with a current or future applicable act or legislative text, +said act or legislative text shall prevail, and the Parties shall make +the necessary amendments so as to comply with said act or legislative +text. All other provisions shall remain effective. Similarly, invalidity +of a provision of the Agreement, for any reason whatsoever, shall not +cause the Agreement as a whole to be invalid. + + + 11.5 LANGUAGE + +The Agreement is drafted in both French and English and both versions +are deemed authentic. + + + Article 12 - NEW VERSIONS OF THE AGREEMENT + +12.1 Any person is authorized to duplicate and distribute copies of this +Agreement. + +12.2 So as to ensure coherence, the wording of this Agreement is +protected and may only be modified by the authors of the License, who +reserve the right to periodically publish updates or new versions of the +Agreement, each with a separate number. These subsequent versions may +address new issues encountered by Free Software. + +12.3 Any Software distributed under a given version of the Agreement may +only be subsequently distributed under the same version of the Agreement +or a subsequent version. + + + Article 13 - GOVERNING LAW AND JURISDICTION + +13.1 The Agreement is governed by French law. The Parties agree to +endeavor to seek an amicable solution to any disagreements or disputes +that may arise during the performance of the Agreement. + +13.2 Failing an amicable solution within two (2) months as from their +occurrence, and unless emergency proceedings are necessary, the +disagreements or disputes shall be referred to the Paris Courts having +jurisdiction, by the more diligent Party. + + +Version 1.0 dated 2006-09-05. diff --git a/InterfaceCEREMA/README.md b/InterfaceCEREMA/README.md new file mode 100644 index 0000000..6f566ba --- /dev/null +++ b/InterfaceCEREMA/README.md @@ -0,0 +1,14 @@ +L'interface CEREMA offre une interface graphique conviviale pour MICMAC, l'outil de photogrammétrie libre de l'IGN. + + +Pour plus de détail voir l'item de menu "Aide/historique" ou le code source. + +Des installateurs facilitent l'installation de certaines versions : + +Version 5.3 sous windows 64 bits +Version 5.0 sous windows 32 bits +Version 3 sous Linux (deb et rpm) + +Sous mac : voir la documentation + +L'application MicMac de l'IGN doit être installée ( https://github.com/micmacIGN ou http://logiciels.ign.fr/?Micmac ) diff --git a/InterfaceCEREMA/aperodedenis_3.14-2_amd64.deb b/InterfaceCEREMA/aperodedenis_3.14-2_amd64.deb new file mode 100644 index 0000000..3829674 Binary files /dev/null and b/InterfaceCEREMA/aperodedenis_3.14-2_amd64.deb differ diff --git a/InterfaceCEREMA/historique_des_versions.txt b/InterfaceCEREMA/historique_des_versions.txt new file mode 100644 index 0000000..b614ecf --- /dev/null +++ b/InterfaceCEREMA/historique_des_versions.txt @@ -0,0 +1,274 @@ +Historique des principales versions de l'interface CEREMA AperoDeDenis + + Version 1.5 : première version diffusée sur le site de l'IGN le 23/11/2015. + + Version 1.55 : décembre 2015 + Sous Windows le fichier paramètre est placé sous le répertoire APPDATA de l'utilisateur, + ce qui règle les questions relatives aux droits d'accès en écriture. + + Version 1.60 : + - Ajout des fonctions : + - Qualité des photos lors du dernier traitement + - Exportation du chantier en cours + - Importation d'un chantier (permet de recopier le chantier sur un autre répertoire, disque, ordinateur, système) + - Ajout d'un item du menu édition fusionnant les images 3D. + - Plusieurs images maîtresses, plusieurs masques. + - Choix possible de fichiers PNG, BMP, GIF, TIF. Ces fihiers sont convertit en JPG. + - Ajout d'un item du menu Outils permettant de modifier les exifs. + - Les fichiers 'trace' sont enregistrés au format utf-8. + + Version 2 : + - Choix de photos pour la calibration intrinsèque par Tapas + - Possibilité de relancer Malt sans relancer Tapioca/Tapas tout en conservant les images 3D générées. + - Modification possible des options par défaut dans le menu outils : + - les options du chantier en cours deviennent les options par défaut. + - Conservation de tous les fichiers modele3D.ply pour un même chantier. + - Choix du niveau de zoom d'arrêt de la procédure Malt : de 1 à 8. + - Création de tous les fichiers .ply correspondants à tous les niveaux de zoom calculés. + - Ajout d'un item du menu édition listant et visualisant toutes les images 3D générées. + - Choix du nombre de photos à retenir autour de l'image maître pour Malt. + - Traitement des vidéos (par exemple GoPro) : décompactage, sélection, mise à jour de l'exif. + - Ajout de deux contrôles sur le lot des photos : mêmes dimensions, même focale. + - Ajout d'un item 'historique' dans le menu Aide. + + Version 2.10 : février 2016 + - Ajout d'un item du menu édition fusionnant les images 3D. + - Plusieurs images maîtresses, plusieurs masques pour Malt. + - Choix possible de fichiers PNG, BMP, GIF, TIF. + - Ajout d'un item du menu Outils permettant de modifier les exifs. + + Version 2.20 : Février 2016 + - Maintien des options compatibles lors du choix de nouvelles photos. + + Version 2.30 : Mai 2016 + - Modification des options par défaut (menu outils). + - Référentiel GPS calculé après Tapas. + - La virgule devient un séparateur décimal accepté. + - Possiblité d'appliquer la calibration GPS sans relancer malt. + + Version 2.40 : Mai 2016 + - Ajout de l'option (Statue ou QuickMac) pour C3DC. + + Version 2.45 : Mai 2016 + - Référentiel GPS calculé après Tapas (et toujours avant Malt). + - La virgule est un séparateur décimal accepté.\n"+\ + + Version 2.5 : Juin 2016 + - Ajout de Tawny aprés Malt en mode Ortho + + Version 2.50 : Juin 2016 + - Item dans le menu paramètrage pour désactiver le message de lancement. + + Version 2.60 : juillet 2016 + - saisie des incertitudes sur la position des points gps + + Version 2.61 + - correction d'un bogue de compatibilité ascendante sur les points GPS + + Version 3.00 : novembre 2016 + - version bilingue : ajout de la langue anglaise, par Alexandre Courallet + La langue est demandée au premier lancement. + Un item du menu "paramètrage" ("Settings") permet de changer la langue utilisée. + + Version 3.10 : novembre 2016 + - Ajout d'un item permettant de sélectionner les meilleures photos suivant les points homologues + (compléte et différe du choix des meilleures images vidéos) + + Version 3.13 décembre 2016 + - la distance de la calibration accepte une unité + - lancement de Tapas accéléré + - diverses corrections de bogues + + Version 3.14 30 décembre 2016 + - correction d'une régression au démarrage + + Version 3.20 : 17 janvier 2017 + - Les photos autour de la maitresse pour Malt ne sont plus "autour" mais choisies parmi les meilleures en correspondances + - Ajout d'un choix pour Malt : AperoDeDenis, l'interface recherche les maitresses et les photos correspondantes + - Ajout filtre pour afficher l'erreur max sur gcpbascule (erreur positionnement des points GPS. + - controle affiné des points gps : + on indique ceux qui ne sont placés sur une seule photo et on vérifie la présence de 3 points sur 2 photos + - Aprés plantage durant malt ou fusion : on renomme les JPG et les PLY lors du rédémarrage (reste pb semblable pour calibration intrinsèque) + - Suppression d'un point GPS sur une photo (avant : suppression de tous les points) + - Affichage dans l'état du chantier des points GPS positionnés sur une seule photo + - Non mise dans le xml des points gps positionnés une seule fois. + - Si le controle des points GPS est négatif alors les fichiers xml ne sont pas créés + + Version 3.30 :26 janvier 2017 + - Nouveauté : faire un masque sur une mosaique Tarama pour le mode Ortho de Malt et draper le résultat avec une orthomosaïque tawny. + - Possibilité de créer une mosaique aprés tapas sur toutes les photos par "Tarama" + - Saisir un masque sur la mosaïque créée : par l'outil de saisie de masque + - Lancer Malt option Ortho : attention les photos doivent concerner un terrain naturel tel que z=f(x,y) (un seul z pour tout (x,y) + - Lancer Tawny pour créer une ortho-mosaïque sur le résultat de malt, pour draper le nuage densifié + - Le masque Malt peut être inversé : la sélection concerne l'extérieur du polygone au lieu de l'intérieur. + - menu edition : affichage des mosaïques Tarama et Tawny + - Un item de menu "expert" permettant de saisir et d'exécuter des commandes en mode "console" + + Version 3.32 : 7 février 2017 + - Possibilité de copier des points gps d'un chantier à un autre (menu expert) + + Version 4.0 : 4 avril 2017 + + - Ajout d'un item de menu : Indices_surfaciques proposant 3 fonctions (Réalisation : Dhia Eddine Stambouli) + - Calcul d'un maillage régulier à partir d'un modéle 3D représentant une surface calibrée ou géoréférencée. + Ce maillage est affiché, la tortuosité et la rugosité sont calculées. + - La profondeur moyenne de profil ainsi que la profondeur moyenne de texture équivalente sont calculées. + Les profils sont affichés sur la surface ou figurés par une courbe. + - Le pas du maillage est déterminé par l'utilisateur, dans l'unité du modéle 3D. + - Deux méthodes sont proposées pour le calcul de l'interpolation + + Version 4.10 : octobre 2017 + + - Affichage de la taille disque du chantier, en MO, dans l'état du chantier. + - La fonction "Du ménage" propose un choix : nettoyer le chantier ou le supprimer totalement + - Nouvelle icone pour la fenêtre : logo du cerema. + - Correction de 2 bugs concernant : + - la fonction "renommer un chantier" + - Un message parfois non pertinent sur l'absence de focales + + Version 4.11 : Noël 2017 + - Diffusion de la version 4.10 sur GitHub + + Version 5.0 : janvier 2018 + - Suppression de l'item "Indices surfaciques" de la version 4.0 + Version 5.1 : 4 décembre 2018 : + - Options/Tapas : ajout du widget pour éliminer les photos ayant servis à la calibration de l'appareil photo + - ajout d'un item dans le menu expert : copier les coordonnées des points gps à partir d'un fichier texte + - modification des onglets Malt et C3DC, réunis dans un même onglet "Densification" + - renommage de l'onglet "calibration" en "mise à l'échelle" + Version 5.2 janvier 2019 : + - ajout des paramètres pour Campari dans la fenêtre options/points GPS + - ajout dans le menu expert de la consultation du log mm3d + - possibilité de renommer dans l'exif des appareils photos différents + - mise à jour de dico camera pour "tous" les appareils photos du lot de données + - ajout de l'item " ajout d'un chantier à partir d'un répertoire" dans le menu fichier + version 5.21 février 2019 : + - ajout possibilité de passer une commande "python" dans le menu expert + - Modification de l'option "Autocal" de Tapas : Figee (au lieu de Autocal) : permet de 'figer' la calibration initiale + version 5.30 21 février 2019 : + - dans les items 'Outils/Qualité des photos' ajout des photos 'isolées', en disjontion de toutes les autres. + Ces photos font 'planter' la recherche de l'orientation. + - Suite à la recherche des points homologues vérification de l'unicité de la scène photographiée. + Plusieurs scènes sans points homologues communs font planter la recherche d'une orientation. + Cette fonction est ajoutée à l'item 'Outils/Qualité des photos'. + - Lorsque le message MAXLINELENGTH est émis par Tapioca il est affiché et expliqué dans la trace synthétique. + - prise en compte de l'erreur concernant la fonction filedialog sous Mac-Os lors des recherche de programmes (exiftool...). + - Ajout d'un item dans paramètrage : recherche d'une nouvelle version GitHub. + +----------------------------------------------------------------------- +History of the main versions of the CEREMA AperoDeDenis interface + + Version 1.5: first version diffused on the site of the IGN the 23/11/2015. + + Version 1.55: December 2015 + Under Windows the parameter file is placed under the APPDATA directory of the user, + Which resolves issues related to write access rights. + + Version 1.60: + - Added functions: + - Quality of photos during the last treatment + - Export of the site in progress + - Import a site (allows to copy the site on another directory, disk, computer, system) + - Added a menu item editing the 3D images. + - Several master images, several masks. + - Possible selection of PNG, BMP, GIF, TIF files. These files are converted to JPG. + - Added an item in the Tools menu to modify exifs. + - 'trace' files are saved in utf-8 format. + + Version 2: + - Choice of photos for intrinsic calibration by Tapas + - Possibility to restart Malt without restarting Tapioca / Tapas while retaining the 3D images generated. + - Possible modification of the default options in the tool menu: + - the current job options become the default options. + - Preservation of all files model3D.ply for the same site. + - Choice of the stop zoom level of the Malt procedure: from 1 to 8. + - Create all corresponding .ply files at all calculated zoom levels. + - Added an item from the edit menu listing and viewing all generated 3D images. + - Choice of the number of photos to remember around the master image for Malt. + - Processing of videos (for example GoPro): unpacking, selection, update of exif. + - Added two controls on the batch of photos: same dimensions, even focal length. + - Added a 'history' item in the Help menu. + + Version 2.10: February 2016 + - Added a menu item editing the 3D images. + - Several master images, several masks for Malt. + - Possible selection of PNG, BMP, GIF, TIF files. + - Added an item in the Tools menu to modify exifs. + + Version 2.20: February 2016 + - Maintain compatible options when choosing new photos. + + Version 2.30: May 2016 + - Changing the default options (tool menu). + - GPS baseline calculated after Tapas. + - The comma becomes an accepted decimal separator. + - Possibility to apply GPS calibration without restarting malt. + + Version 2.40: May 2016 + - Added option (Statue or QuickMac) for C3DC. + + Version 2.45: May 2016 + - GPS baseline calculated after Tapas (and always before Malt). + - The comma is an accepted decimal separator. \ N "+ \ + + Version 2.5: June 2016 + - Added Tawny after Malt in Ortho mode + + Version 2.50: June 2016 + - Item in the setup menu to disable the launch message. + + Version 2.60: July 2016 + - entering uncertainties on the position of gps points + + Version 2.61 + - Fixed an upward compatibility bug on GPS points + + Version 3.00: November 2016 + - bilingual version: addition of the English language, by Alexandre Courallet + Language is requested at first launch. + An item in the "Settings" menu allows you to change the language used. + + Version 3.10: November 2016 + - Added an item to select the best photos following the homologous points + (Complete and different from the choice of the best video images) + + Version 3.13 December 2016 + - the calibration distance accepts one unit + - launch of Tapas acceleré + - various bug fixes + + Version 3.14 30 December 2016 + - correction of a regression at start-up + + Version 3.30: 26 January 2017 + New: make a mask on a Tarama mosaic for the Malt Ortho mode and drape the result with a tawny orthomosaic. + 1) Possibility of creating a mosaic after tapas on all the photos by "Tarama" + 2) enter a mask on the mosaic created: by the mask input tool + 3) Launch Malt option Ortho: be careful the photos must relate to a natural terrain such as z = f (x, y) (a single z for all (x, y) + 4) Launch Tawny to create an ortho-mosaic on the malt result, to drape the densified cloud + The Malt mask can be inverted: the selection concerns the outside of the polygon instead of the inside. + Menu edition: displaying Tarama and Tawny mosaics + An "expert" menu item for entering and executing commands in "console" mode + + Version 3.32 : 7 february 2017 + - Ability to copy gps points from one project to another (expert menu) + + Version 4.0 : 4 avril 2017 + + Add menu item : Indices_surfaciques. + + Calcul d'un maillage régulier à partir d'un modéle 3D représentant une surface calibrée ou géoréférencée. + Ce maillage est affiché, la tortuosité et la rugosité sont calculées. + La profondeur moyenne de profil ainsi que la profondeur moyenne de texture équivalente est calculée. + les profils sont affichés sur la surface ou exposés en détails. + Le pas du maillage est exprimé dans l'unité du modéle. + + Version 4.10 octobre 2017 + + Affichage de la taille du chantier en MO dans l'état du chantier. + La fonction "Du ménage" propose un choix : nettoyer le chantier ou le supprimer totalement + Nouvelle icone pour la fenêtre : logo du cerema. + Correction de 2 bugs : renommer et message parfois non pertinent sur l'absence de focales. + + Version 4.11 Noël 2017 + \ No newline at end of file diff --git a/InterfaceCEREMA/locale/en/LC_MESSAGES/AperoDeDenis.mo b/InterfaceCEREMA/locale/en/LC_MESSAGES/AperoDeDenis.mo new file mode 100644 index 0000000..46f2108 Binary files /dev/null and b/InterfaceCEREMA/locale/en/LC_MESSAGES/AperoDeDenis.mo differ diff --git a/InterfaceCEREMA/locale/en/LC_MESSAGES/AperoDeDenis.po b/InterfaceCEREMA/locale/en/LC_MESSAGES/AperoDeDenis.po new file mode 100644 index 0000000..1af6a19 --- /dev/null +++ b/InterfaceCEREMA/locale/en/LC_MESSAGES/AperoDeDenis.po @@ -0,0 +1,8403 @@ +# SOME DESCRIPTIVE TITLE. +# Copyright (C) YEAR ORGANIZATION +# FIRST AUTHOR , YEAR. +# +msgid "" +msgstr "" +"Project-Id-Version: \n" +"POT-Creation-Date: 2019-02-21 14:42+0100\n" +"PO-Revision-Date: 2019-02-21 16:07+0100\n" +"Last-Translator: \n" +"Language-Team: \n" +"Language: en\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Generated-By: pygettext.py 1.5\n" +"X-Generator: Poedit 2.1.1\n" +"Plural-Forms: nplurals=2; plural=(n != 1);\n" + +#: AperoDeDenis.py:303 +msgid " lancement d'aperodedenis" +msgstr " Launching AperoDeDenis" + +#: AperoDeDenis.py:312 +msgid "Tracer le masque" +msgstr "Draw the mask" + +#: AperoDeDenis.py:314 +msgid "Saisie sur la photo : " +msgstr "Drawing on picture:" + +#: AperoDeDenis.py:363 +msgid "Inverser" +msgstr "Reverse" + +#: AperoDeDenis.py:364 AperoDeDenis.py:676 +msgid "Valider" +msgstr "Confirm" + +#: AperoDeDenis.py:365 AperoDeDenis.py:679 AperoDeDenis.py:3347 +#: AperoDeDenis.py:3590 AperoDeDenis.py:4987 AperoDeDenis.py:5036 +#: AperoDeDenis.py:5056 AperoDeDenis.py:5066 AperoDeDenis.py:5076 +#: AperoDeDenis.py:5092 AperoDeDenis.py:5107 AperoDeDenis.py:5129 +#: AperoDeDenis.py:6297 AperoDeDenis.py:8667 AperoDeDenis.py:9711 +msgid "Abandon" +msgstr "Abort" + +#: AperoDeDenis.py:368 +msgid "molette de la souris = zoom," +msgstr "scroll button = zoom" + +#: AperoDeDenis.py:369 +msgid "utilisable avant ET pendant le tracé" +msgstr "usable before AND during drawing" + +#: AperoDeDenis.py:370 +msgid "glisser-déposer actif avant le tracé=" +msgstr "active slip-drop before the drawing =" + +#: AperoDeDenis.py:371 +msgid "Tracer :" +msgstr "Draw:" + +#: AperoDeDenis.py:372 +msgid "" +"Clic gauche : ajouter un point;\n" +" double clic gauche : fermer le polygone," +msgstr "Left click: add a point; double left clic: close the polygon," + +#: AperoDeDenis.py:373 +msgid "Touche Del pour supprimer un point ou le polygone," +msgstr "Use Del to delete a point or the polygon," + +#: AperoDeDenis.py:450 +msgid "Il faut au moins 2 points dans le polygone." +msgstr "There must be at least 2 points in the polygon" + +#: AperoDeDenis.py:480 AperoDeDenis.py:768 +msgid "Zoom maximum atteint" +msgstr "Maximum zoom reached" + +#: AperoDeDenis.py:566 +msgid "Erreur suppression d'info bulle : " +msgstr "Tooltip deleting error:" + +#: AperoDeDenis.py:628 +msgid "Calibration GPS " +msgstr "GPS calibration" + +#: AperoDeDenis.py:629 +msgid "Position des points sur la photo : " +msgstr "Position of the points on the picture:" + +#: AperoDeDenis.py:678 +msgid "Supprimer un ou plusieurs points" +msgstr "Delete one or more points" + +#: AperoDeDenis.py:686 +msgid "Changer la couleur des libellés" +msgstr "Change the color of the text." + +#: AperoDeDenis.py:693 +msgid "Utiliser la molette pour zoomer/dezoomer pendant la saisie." +msgstr "Use the scroll button to zoom/unzoom when drawing" + +#: AperoDeDenis.py:710 +msgid "Placer le point " +msgstr "Place the point" + +#: AperoDeDenis.py:713 +msgid "Point " +msgstr "Point" + +#: AperoDeDenis.py:921 AperoDeDenis.py:922 +msgid " : une interface graphique pour MicMac..." +msgstr ": a Graphical User Interface for MicMac..." + +#: AperoDeDenis.py:926 +msgid "Fermeture inatendue de la fenêtre." +msgstr "Unexpected closure of the window" + +#: AperoDeDenis.py:929 +msgid "Erreur initialisation de la fenêtre principale : " +msgstr "Error initialising the main window:" + +#: AperoDeDenis.py:949 AperoDeDenis.py:6266 +msgid "Nouveau chantier" +msgstr "New project" + +#: AperoDeDenis.py:950 +msgid "Ouvrir un chantier" +msgstr "Open project" + +#: AperoDeDenis.py:952 +msgid "Enregistrer le chantier en cours" +msgstr "Save current project" + +#: AperoDeDenis.py:953 +msgid "Renommer ou déplacer le chantier en cours" +msgstr "Rename or move current project" + +#: AperoDeDenis.py:955 +msgid "Exporter le chantier en cours" +msgstr "Export current project" + +#: AperoDeDenis.py:956 +msgid "Importer un chantier" +msgstr "Import project" + +#: AperoDeDenis.py:958 +msgid "Ajouter un chantier à partir d'un répertoire" +msgstr "Add a project from a directory" + +#: AperoDeDenis.py:960 +msgid "Du ménage !" +msgstr "Let's clean!" + +#: AperoDeDenis.py:962 +msgid "Quitter" +msgstr "Exit" + +#: AperoDeDenis.py:967 +msgid "Afficher l'état du chantier" +msgstr "Display project progress" + +#: AperoDeDenis.py:969 +msgid "Visualiser toutes les photos sélectionnées" +msgstr "Diplay all selected pictures" + +#: AperoDeDenis.py:970 +msgid "Visualiser les photos pour la calibration intrinsèque" +msgstr "Display pictures for intrinsic calibration" + +#: AperoDeDenis.py:971 +msgid "Visualiser les maîtresses et les masques" +msgstr "Display master pictures and masks" + +#: AperoDeDenis.py:972 +msgid "Visualiser le masque sur mosaique Tarama" +msgstr "View the mask on mosaic Tarama" + +#: AperoDeDenis.py:973 +msgid "Visualiser le masque 3D" +msgstr "Display 3D mask" + +#: AperoDeDenis.py:974 +msgid "Visualiser les points GPS" +msgstr "Display GPS points" + +#: AperoDeDenis.py:976 +msgid "Visualiser la ligne horizontale/verticale" +msgstr "Display horizontal/vertical line" + +#: AperoDeDenis.py:977 +msgid "Visualiser la zone plane" +msgstr "Display plane area" + +#: AperoDeDenis.py:978 +msgid "Visualiser la distance" +msgstr "Display distance" + +#: AperoDeDenis.py:980 +msgid "Afficher la trace complète du chantier" +msgstr "Display the complete project log" + +#: AperoDeDenis.py:981 +msgid "Afficher la trace synthétique du chantier" +msgstr "Display the synthetic project log" + +#: AperoDeDenis.py:983 +msgid "Afficher la mosaïque Tarama" +msgstr "Display mosaic Tarama" + +#: AperoDeDenis.py:984 +msgid "Afficher l'ortho mosaïque Tawny" +msgstr "Display ortho mosaic Tawny" + +#: AperoDeDenis.py:986 +msgid "Afficher l'image 3D non densifiée" +msgstr "Display undensified 3D picture" + +#: AperoDeDenis.py:987 +msgid "Afficher l'image 3D densifiée" +msgstr "Display densified 3D picture" + +#: AperoDeDenis.py:989 +msgid "Lister-Visualiser les images 3D" +msgstr "List-Display 3D pictures" + +#: AperoDeDenis.py:990 +msgid "Fusionner des images 3D" +msgstr "Merge 3D pictures" + +#: AperoDeDenis.py:997 AperoDeDenis.py:3357 +msgid "Choisir des photos" +msgstr "Select pictures" + +#: AperoDeDenis.py:998 +msgid "Options" +msgstr "Options" + +#: AperoDeDenis.py:1000 +msgid "Lancer MicMac" +msgstr "Launch MicMac" + +#: AperoDeDenis.py:1005 +msgid "Options (GoPro par défaut)" +msgstr "Options (Default GoPro)" + +#: AperoDeDenis.py:1007 +msgid "Nouveau chantier : choisir une vidéo GoPro, ou autre" +msgstr "New project : choose a GoPro video, or else" + +#: AperoDeDenis.py:1008 +msgid "Sélection des meilleures images" +msgstr "Select the best pictures" + +#: AperoDeDenis.py:1014 +msgid "Nom et focale de l'appareil photo, dimension des photos" +msgstr "Camera name and focal length, size of photos" + +#: AperoDeDenis.py:1015 +msgid "Toutes les focales et les noms des appareils photos" +msgstr "All focal length and name of camera" + +#: AperoDeDenis.py:1016 +msgid "Mettre à jour DicoCamera.xml" +msgstr "Update DicoCamera.xml" + +#: AperoDeDenis.py:1018 +msgid "Qualité des photos du dernier traitement" +msgstr "Quality of the pictures of last process" + +#: AperoDeDenis.py:1019 +msgid "Sélectionner les N meilleures photos" +msgstr "Select the N best pictures" + +#: AperoDeDenis.py:1021 +msgid "Qualité des photos 'line'" +msgstr "Quality of 'line' pictures" + +#: AperoDeDenis.py:1022 +msgid "Qualité des photos 'All' " +msgstr "Quality of 'All' pictures." + +#: AperoDeDenis.py:1024 +msgid "Modifier l'exif des photos" +msgstr "Edit exif of pictures" + +#: AperoDeDenis.py:1026 AperoDeDenis.py:9333 AperoDeDenis.py:9351 +msgid "Modifier les options par défaut" +msgstr "Change default options" + +#: AperoDeDenis.py:1031 +msgid "Exécuter une ligne de commande système" +msgstr "Run a system command line" + +#: AperoDeDenis.py:1032 +msgid "Exécuter une commande python" +msgstr "Run a python command" + +#: AperoDeDenis.py:1034 +msgid "Ajouter les points GPS à partir d'un fichier" +msgstr "Add GPS points from a file" + +#: AperoDeDenis.py:1035 +#, fuzzy +#| msgid "Ajouter les points GPS d'un chantier" +msgid "Ajouter les points GPS d'un autre chantier" +msgstr "Add GPS points from an other project" + +#: AperoDeDenis.py:1037 +msgid "Définir plusieurs appareils photos" +msgstr "Set more than one camera" + +#: AperoDeDenis.py:1038 +msgid "Liste des appareils photos" +msgstr "Camera List" + +#: AperoDeDenis.py:1040 +msgid "Consulter le fichier mm3d-LogFile.txt" +msgstr "See the file Mm3d-LogFile. txt" + +#: AperoDeDenis.py:1046 +msgid "Désactiver le 'tacky' message de lancement" +msgstr "Desactivate the launching 'tacky' message." + +#: AperoDeDenis.py:1048 +msgid "Activer le 'tacky' message de lancement" +msgstr "Activate the launching 'tacky' message." + +#: AperoDeDenis.py:1051 +msgid "Afficher les paramètres" +msgstr "Display settings" + +#: AperoDeDenis.py:1053 +msgid "Associer le répertoire bin de MicMac" +msgstr "Link the MicMac\\bin directory" + +#: AperoDeDenis.py:1054 +msgid "Associer 'exiftool'" +msgstr "Link the 'exiftool' directory" + +#: AperoDeDenis.py:1055 +msgid "Associer 'convert' d'ImageMagick" +msgstr "Link the ImageMagick's 'convert' directory" + +#: AperoDeDenis.py:1056 +msgid "Associer 'ffmpeg (décompacte les vidéos)" +msgstr "Link the 'ffmpeg' (unpacks videos) directory" + +#: AperoDeDenis.py:1057 +msgid "Associer 'Meshlab' ou 'CloudCompare'" +msgstr "Link the 'Meshlab' or 'CloudCompare' directory" + +#: AperoDeDenis.py:1059 +msgid "Changer la langue" +msgstr "Change language" + +#: AperoDeDenis.py:1061 +msgid "Désactive/Active le tacky message de lancement..." +msgstr "Desactivate/Activate launching 'tacky' message..." + +#: AperoDeDenis.py:1063 +msgid "Vérifie la présence d'une nouvelle version sur GitHub" +msgstr "Check the presence of a new version on GitHub" + +#: AperoDeDenis.py:1068 +msgid "Affichage de la surface interpolée" +msgstr "Display the interpolated area" + +#: AperoDeDenis.py:1069 +msgid "Calcul des indices" +msgstr "Parameters calculation" + +#: AperoDeDenis.py:1070 +msgid "Calcul de la PMP" +msgstr "PMP calculation" + +#: AperoDeDenis.py:1075 +msgid "Pour commencer..." +msgstr "Get started" + +#: AperoDeDenis.py:1076 +msgid "Aide sur les menus" +msgstr "Help on Menus" + +#: AperoDeDenis.py:1077 +msgid "Quelques conseils" +msgstr "Advices" + +#: AperoDeDenis.py:1078 +msgid "Historique" +msgstr "Changelog" + +#: AperoDeDenis.py:1079 +msgid "A Propos" +msgstr "About" + +#: AperoDeDenis.py:1083 +msgid "Fichier" +msgstr "File" + +#: AperoDeDenis.py:1084 +msgid "Edition" +msgstr "Edit" + +#: AperoDeDenis.py:1086 +msgid "Vidéo" +msgstr "Video" + +#: AperoDeDenis.py:1087 +msgid "Outils" +msgstr "Tools" + +#: AperoDeDenis.py:1088 +msgid "Expert" +msgstr "Expert" + +#: AperoDeDenis.py:1089 +msgid "Paramétrage" +msgstr "Settings" + +#: AperoDeDenis.py:1091 +msgid "Aide" +msgstr "Help" + +#: AperoDeDenis.py:1124 +msgid "Pas de répertoire désigné pour MicMac\\bin" +msgstr " No designated directory for MicMac\\bin" + +#: AperoDeDenis.py:1125 +msgid "Pas de fichier désigné pour ouvrir les .PLY" +msgstr "No designated programm to open .PLY files." + +#: AperoDeDenis.py:1126 +msgid "Pas de chemin pour ExifTool" +msgstr "No path for exiftool" + +#: AperoDeDenis.py:1127 +msgid "Pas de fichier pour mm3d" +msgstr "No file for mm3d" + +#: AperoDeDenis.py:1128 +msgid "Pas de fichier pour ffmpeg" +msgstr "No file for ffmpeg" + +#: AperoDeDenis.py:1129 +msgid "Pas de version MicMac" +msgstr "No MicmMac's version" + +#: AperoDeDenis.py:1131 +msgid "Pas de version Image Magick" +msgstr "No ImageMagick's version" + +#: AperoDeDenis.py:1251 +msgid "" +"Tapioca recherche les points homologues entre photos : indiquer l'échelle ou " +"les échelles utilisées" +msgstr "" +"Tapioca looks for peer points between photos: Indicate the scale or scales " +"used" + +#: AperoDeDenis.py:1266 AperoDeDenis.py:1286 +msgid "Echelle image (-1 pour l'image entière) :" +msgstr "Picture scale (-1 for the whole picture)" + +#: AperoDeDenis.py:1274 +msgid "Echelle image réduite : " +msgstr "Reduced scale picture:" + +#: AperoDeDenis.py:1278 +msgid "Seconde Echelle (-1 pour l'image entière) :" +msgstr "Second scale (-1 for the whole picture)" + +#: AperoDeDenis.py:1288 +msgid "Delta (nombre d'images se recouvrant, avant et après) : " +msgstr "Delta (number of pictures covering themselves, before and after)" + +#: AperoDeDenis.py:1299 +msgid "" +"Tapas positionne les appareils photos sur le nuage de points homologues. " +"Préciser le type d'appareil." +msgstr "" +"Tapas positions the camera on the cloud of peer points. Specify the type of " +"camera." + +#: AperoDeDenis.py:1300 +msgid "" +"Quelques photos avec une grande profondeur d'image aident à calibrer " +"l'optique des appareils photos." +msgstr "" +"Some photos with a great depth of image help to calibrate the optics of the " +"cameras." + +#: AperoDeDenis.py:1321 +msgid "Choisir quelques photos pour la calibration intrinsèques" +msgstr "Choose some pictures for the intrinsic calibration" + +#: AperoDeDenis.py:1324 +msgid " N'utiliser ces photos que pour la calibration" +msgstr "Use these picture for the calibration only" + +#: AperoDeDenis.py:1325 +#, fuzzy +#| msgid "Toutes ces photos doivent avoir la même focale," +msgid "Toutes ces photos doivent avoir la même focale." +msgstr "All of theses pictures must have the same focal length," + +#: AperoDeDenis.py:1327 +msgid "" +"lancer Tarama après TAPAS : mosaique pouvant définir un masque pour Malt/" +"ortho)" +msgstr "" +"Launch Tarama after TAPAS: make mosaic to define a mask for Malt / ortho" + +#: AperoDeDenis.py:1330 +msgid "Arrêter le traitement après TAPAS" +msgstr "Stop processing after TAPAS." + +#: AperoDeDenis.py:1345 +msgid "" +"Définition d'un référentiel et d'une métrique sur le nuage de points " +"homologues." +msgstr "Definition of a repository and metric on the cloud of peer points." + +#: AperoDeDenis.py:1346 +msgid "Une ligne, un plan et la distance entre 2 points sont nécessaires." +msgstr "A line, a plane and the distance between 2 points are necessary." + +#: AperoDeDenis.py:1358 AperoDeDenis.py:1393 +msgid "Choisir entre :" +msgstr "Choose between:" + +#: AperoDeDenis.py:1361 +msgid "Ligne horizontale" +msgstr "Horizontal line" + +#: AperoDeDenis.py:1365 AperoDeDenis.py:1400 +msgid "ou" +msgstr "or" + +#: AperoDeDenis.py:1368 +msgid "Ligne verticale" +msgstr "Vertical line" + +#: AperoDeDenis.py:1381 AperoDeDenis.py:1415 +msgid "ET :" +msgstr "AND:" + +#: AperoDeDenis.py:1396 +msgid "Zone plane horizontale" +msgstr "Plane horizontal area" + +#: AperoDeDenis.py:1403 +msgid "Zone plane verticale" +msgstr "Plane vertical area" + +#: AperoDeDenis.py:1426 +msgid "Distance entre les 2 points :" +msgstr "Distance between the 2 points:" + +#: AperoDeDenis.py:1431 +msgid "Placer 2 points identiques sur 2 photos" +msgstr "Position of 2 identical points on 2 pictures" + +#: AperoDeDenis.py:1441 +msgid "Pour annuler la calibration mettre la distance = 0" +msgstr "To abort calibration, set the distance to 0" + +#: AperoDeDenis.py:1448 +msgid "Utiliser C3DC" +msgstr "Use C3DC" + +#: AperoDeDenis.py:1449 +msgid "Utiliser MALT" +msgstr "Use MALT" + +#: AperoDeDenis.py:1458 +msgid "Option de Malt :" +msgstr "Malt Option:" + +#: AperoDeDenis.py:1461 +msgid "UrbanMNE pour photos urbaines" +msgstr "UrbanMNE for urban pictures" + +#: AperoDeDenis.py:1462 +msgid "GeomImage pour photos du sol ou d'objets" +msgstr "GeomImage for pictures of ground or objects " + +#: AperoDeDenis.py:1463 +msgid "Ortho pour orthophotos de terrain naturel [f(x,y)=z)]" +msgstr "Ortho for orthophotos of natural ground [f (x, y) = z)]" + +#: AperoDeDenis.py:1464 +msgid "AperoDeDenis choisit pour vous les options de GeomImage" +msgstr "AperoDeDenis chooses for you the options of GeomImage" + +#: AperoDeDenis.py:1485 AperoDeDenis.py:4229 +msgid "Choisir les maîtresses" +msgstr "Choose master pictures" + +#: AperoDeDenis.py:1487 AperoDeDenis.py:1521 +msgid "Tracer les masques" +msgstr "Draw masks" + +#: AperoDeDenis.py:1488 +msgid "Attention : Le masque 3D de C3DC a la priorité sur Malt" +msgstr "Warning: 3D mask from C3DC has priority over Malt." + +#: AperoDeDenis.py:1488 +msgid "Pour supprimer un masque : supprimer la maitresse" +msgstr "To delete a mask, delete the master picture." + +#: AperoDeDenis.py:1490 +msgid "Nombre de photos à retenir autour de l'image maitresse (-1 = toutes) :" +msgstr "Number of photos to use around the image maitresse (-1 = All):" + +#: AperoDeDenis.py:1497 +msgid "Zoom final : 8, 4, 2 ou 1 (8=le plus rapide, 1=le plus précis)" +msgstr "Final zoom: 8,4,2 or 1 (8 = fastest, 1 = most accurate)" + +#: AperoDeDenis.py:1504 +msgid "Lancer tawny après MALT" +msgstr "Launch Tawny after MALT" + +#: AperoDeDenis.py:1505 +msgid "Tawny génère une ortho mosaïque qui sera drapée sur le nuage densifié." +msgstr "" +"Tawny generates an ortho mosaic ortho that will be draped over the densified " +"cloud." + +#: AperoDeDenis.py:1506 +msgid "Saisir si besoin les paramètres facultatifs, exemple :" +msgstr "Enter optional settings here. For instance:" + +#: AperoDeDenis.py:1509 +msgid "Liste des paramètres facultatifs nommés :" +msgstr "Named optional settings list:" + +#: AperoDeDenis.py:1513 +msgid "Tracer un masque sur la mosaïque Tarama" +msgstr "Plot a mask on the Tarama mosaic" + +#: AperoDeDenis.py:1519 +#, fuzzy +#| msgid "La saisie des masques n'est active qu'aprés Tapas." +msgid "La saisie des masques n'est active qu'après Tapas." +msgstr "Draw masks is only activated after Tapas." + +#: AperoDeDenis.py:1520 AperoDeDenis.py:2712 AperoDeDenis.py:4282 +#: AperoDeDenis.py:4283 +msgid "Pas de masque." +msgstr "No mask" + +#: AperoDeDenis.py:1522 +msgid "" +"Pour supprimer un masque : supprimer la maitresse dans l'option GeomImage" +msgstr "To remove a mask: remove the mistress in the GeomImage option" + +#: AperoDeDenis.py:1523 +msgid "Consulter la documentation." +msgstr "Consult the documentation." + +#: AperoDeDenis.py:1549 +msgid "Option de C3DC :" +msgstr "C3DC Options:" + +#: AperoDeDenis.py:1550 +#, fuzzy +#| msgid "Statue - avec drapage" +msgid "Forest - avec drapage, rapide" +msgstr "Statue - with drape" + +#: AperoDeDenis.py:1551 +msgid "Statue - avec drapage" +msgstr "Statue - with drape" + +#: AperoDeDenis.py:1552 +msgid "QuickMac - rapide, sans drapage" +msgstr "QuickMac - quick, without drape" + +#: AperoDeDenis.py:1553 +#, fuzzy +#| msgid "QuickMac - rapide, sans drapage" +msgid "MicMac - sans drapage" +msgstr "QuickMac - quick, without drape" + +#: AperoDeDenis.py:1554 +#, fuzzy +#| msgid "QuickMac - rapide, sans drapage" +msgid "BigMac - précis, sans drapage" +msgstr "QuickMac - quick, without drape" + +#: AperoDeDenis.py:1561 +#, fuzzy +#| msgid "Tracer le masque" +msgid "Tracer un masque 3D" +msgstr "Draw the mask" + +#: AperoDeDenis.py:1563 +msgid "Supprimer le masque 3D" +msgstr "Delete the 3D mask" + +#: AperoDeDenis.py:1566 +msgid "Dans la boîte de dialogue pour tracer le masque : " +msgstr "In the dialog box to trace the mask:" + +#: AperoDeDenis.py:1567 +msgid "Définir le masque : F9 " +msgstr "Define the mask: F9" + +#: AperoDeDenis.py:1568 +msgid "Ajouter un point : clic gauche" +msgstr "Add a point: left click" + +#: AperoDeDenis.py:1569 +msgid "Fermer le polygone : clic droit" +msgstr "Close the polygon: right click" + +#: AperoDeDenis.py:1570 +msgid "Sélectionner : touche espace" +msgstr "Select: space" + +#: AperoDeDenis.py:1571 +msgid "Sauver le masque : Ctrl S." +msgstr "Save mask: Ctrl S" + +#: AperoDeDenis.py:1572 +msgid "Quitter : Ctrl Q." +msgstr "Exit: Ctrl A" + +#: AperoDeDenis.py:1573 +msgid "Agrandir les points : Maj +" +msgstr "Enlarge points: Maj +" + +#: AperoDeDenis.py:1574 +msgid "Saisie simultanée de plusieurs masques disjoints possible" +msgstr "Simultaneous multiple disjoint masks draw possible." + +#: AperoDeDenis.py:1593 +msgid " Valider les options" +msgstr "Confirm options" + +#: AperoDeDenis.py:1596 AperoDeDenis.py:1618 AperoDeDenis.py:1676 +#: AperoDeDenis.py:1723 AperoDeDenis.py:1797 AperoDeDenis.py:1824 +msgid " Annuler" +msgstr " Abort" + +#: AperoDeDenis.py:1609 +msgid "Indiquer les dimensions du capteur, en mm." +msgstr "Enter the dimensions of the sensor, in mm" + +#: AperoDeDenis.py:1610 +msgid "par exemple :" +msgstr "for instance:" + +#: AperoDeDenis.py:1611 +msgid "Le site :" +msgstr "Website:" + +#: AperoDeDenis.py:1612 +msgid "fournit les dimensions de tous les appareils photos." +msgstr "Provides dimensions of all cameras." + +#: AperoDeDenis.py:1615 AperoDeDenis.py:1673 AperoDeDenis.py:1821 +msgid " Valider" +msgstr " Confirm" + +#: AperoDeDenis.py:1651 AperoDeDenis.py:1777 +msgid "Marque de l'appareil : " +msgstr "Brand of the camera" + +#: AperoDeDenis.py:1655 +msgid "Nom de la camera : " +msgstr "Name of the camera : " + +#: AperoDeDenis.py:1659 AperoDeDenis.py:1785 +msgid "Focale en mm:" +msgstr "Focal length in mm :" + +#: AperoDeDenis.py:1663 AperoDeDenis.py:1789 +msgid "Focale équivalente 35mm :" +msgstr "Equivalent focal length 35mm:" + +#: AperoDeDenis.py:1667 +msgid "Nombre d'images à conserver par seconde :" +msgstr "Number of pictures to record per second:" + +#: AperoDeDenis.py:1709 AperoDeDenis.py:1732 +msgid "linéaire" +msgstr "linear" + +#: AperoDeDenis.py:1710 +msgid "cubique" +msgstr "cubic" + +#: AperoDeDenis.py:1713 +msgid " Choisir la méthode d'interpolation " +msgstr " Choose the interpolation method" + +#: AperoDeDenis.py:1715 +msgid " Choisir le pas du maillage " +msgstr " Choose the steps of the mesh." + +#: AperoDeDenis.py:1720 AperoDeDenis.py:1753 +msgid "Valider " +msgstr "Confirm" + +#: AperoDeDenis.py:1749 +msgid "Choisir profil à afficher " +msgstr "Choose the profile to display" + +#: AperoDeDenis.py:1756 +msgid "Annuler " +msgstr "Abort" + +#: AperoDeDenis.py:1777 +msgid "Modification des Exif" +msgstr "Exif edit" + +#: AperoDeDenis.py:1781 +msgid "Modèle de l'appareil: " +msgstr "Camera model:" + +#: AperoDeDenis.py:1794 +msgid "Valider et mettre à jour" +msgstr "Confirm and update" + +#: AperoDeDenis.py:1816 +msgid "Indiquer le nombre de photos à retenir." +msgstr "How many pictures to select ?" + +#: AperoDeDenis.py:1817 +msgid "" +"Un nouveau chantier sera créé avec les photos ayant, par paire, le plus de " +"points homologues" +msgstr "" +"A new project will be created with the photos having, by pairs, the more tie-" +"points" + +#: AperoDeDenis.py:1818 +msgid "Ce choix est différent du nombre moyen de points homologues par photo." +msgstr "" +"This ranking is different from the average number of corresponding tie-point " +"per photo." + +#: AperoDeDenis.py:1839 +msgid "" +"MicMac est une réalisation de\n" +" Marc Pierrot-Deseilligny, IGN" +msgstr "MicMac is an achievement by Marc Pierrot-Deseilligny, IGN" + +#: AperoDeDenis.py:2126 +msgid "Quelles options par défaut utiliser pour les nouveaux chantiers ?" +msgstr "Which default options do you want to use for new projects ?" + +#: AperoDeDenis.py:2127 +msgid "Les options par défaut concernent :" +msgstr "Default options relates:" + +#: AperoDeDenis.py:2128 +msgid "Points homologues : All, MulScale, line ,les échelles et delta" +msgstr "Homologous Points: All, MulScale, line, scales and Delta" + +#: AperoDeDenis.py:2129 +#, fuzzy +#| msgid "" +#| "Tapas : RadialExtended,RadialStandard, Radialbasic, arrêt aprés Tapas" +msgid "" +"Orientation : RadialExtended,RadialStandard, Radialbasic, arrêt après Tapas" +msgstr "Tapas: RadialExtended,RadialStandard, Radialbasic, stop after Tapas" + +#: AperoDeDenis.py:2130 +msgid "Points GPS : options de CAMPARI" +msgstr "GPS Points: CAMPARI options" + +#: AperoDeDenis.py:2131 +msgid "" +"Densification Malt : mode, zoom final, nombre de photos autour de la " +"maîtresse" +msgstr "" +"Malt Densification: Fashion, Final zoom, number of photos around the mistress" + +#: AperoDeDenis.py:2132 +msgid "Densification Malt Ortho : Tawny et ses options en saisie libre" +msgstr "Ortho Malt Densification: Tawny and its options for free seizure" + +#: AperoDeDenis.py:2133 +msgid "Densification C3DC : mode (Statue ou QuickMac)" +msgstr "C3DC Densification: Mode (Statue or QUICKMAC)" + +#: AperoDeDenis.py:2176 +msgid "Pas de répertoire pour les photos" +msgstr "No pictures directory" + +#: AperoDeDenis.py:2282 AperoDeDenis.py:2304 +msgid "Enregistrer le chantier ?" +msgstr "Save project ?" + +#: AperoDeDenis.py:2283 AperoDeDenis.py:2305 +msgid "Chantier non encore enregistré. Voulez-vous l'enregistrer ?" +msgstr "Project not saved. Do you want to save it?" + +#: AperoDeDenis.py:2284 AperoDeDenis.py:2292 AperoDeDenis.py:2306 +#: AperoDeDenis.py:2313 AperoDeDenis.py:9464 +msgid "Enregistrer" +msgstr "Save" + +#: AperoDeDenis.py:2285 AperoDeDenis.py:2293 AperoDeDenis.py:2307 +#: AperoDeDenis.py:2314 AperoDeDenis.py:9464 +msgid "Ne pas enregistrer." +msgstr "Don't save" + +#: AperoDeDenis.py:2287 AperoDeDenis.py:2295 AperoDeDenis.py:2309 +#: AperoDeDenis.py:2316 AperoDeDenis.py:9466 +#, python-format +msgid "Chantier précédent enregistré : %s" +msgstr "Last project saved: %s" + +#: AperoDeDenis.py:2290 AperoDeDenis.py:2311 AperoDeDenis.py:9462 +#, python-format +msgid "Enregistrer le chantier %s ?" +msgstr "Save project %s?" + +#: AperoDeDenis.py:2291 AperoDeDenis.py:2312 AperoDeDenis.py:9463 +msgid "" +"Chantier modifié depuis la dernière sauvegarde. Voulez-vous l'enregistrer ?" +msgstr "Project not saved. Do you want to save it?" + +#: AperoDeDenis.py:2317 +msgid "Choisir un chantier." +msgstr "Select a project." + +#: AperoDeDenis.py:2319 AperoDeDenis.py:6698 +msgid "Aucun chantier choisi." +msgstr "No selected project." + +#: AperoDeDenis.py:2327 AperoDeDenis.py:6717 AperoDeDenis.py:6721 +#, python-format +msgid "Chantier choisi %s corrompu. Abandon." +msgstr "" +"Selected project %s corrupted. Aborting\n" +"." + +#: AperoDeDenis.py:2331 +msgid "Chantier enregistré" +msgstr "Project saved." + +#: AperoDeDenis.py:2336 +msgid "Indiquer les photos à traiter avant d'enregistrer le chantier." +msgstr "Select the pictures to process before saving project." + +#: AperoDeDenis.py:2346 +msgid "Le chantier est en cours de définition." +msgstr "The project is being defined." + +#: AperoDeDenis.py:2346 +msgid "Il n'a pas encore de nom, il ne peut être renommé." +msgstr "It has no name yet, so he can't be renamed." + +#: AperoDeDenis.py:2346 +msgid "Commencer par choisir les photos" +msgstr "Start by choosing the pictures." + +#: AperoDeDenis.py:2348 +#, python-format +msgid "Nouveau nom ou nouveau chemin pour le chantier %s :" +msgstr "New name or path for the project %s:" + +#: AperoDeDenis.py:2349 +#, fuzzy +#| msgid "Nouveau nom pour le chantier : " +msgid "Donner le nouveau nom du chantier" +msgstr "New project's name:" + +#: AperoDeDenis.py:2350 +#, fuzzy +#| msgid "Un chemin absolu sur la même unité disque est valide" +msgid "" +"Un chemin absolu sur la même unité disque ou relatif au répertoire pére est " +"valide" +msgstr "An absolute path on the same disk is valid." + +#: AperoDeDenis.py:2351 +msgid "Aucun fichier de l'arborescence du chantier ne doit être ouvert." +msgstr "No files from the tree of the project must be opened." + +#: AperoDeDenis.py:2352 +#, fuzzy +#| msgid "Chemin du chantier :" +msgid "Chemin actuel : " +msgstr "Project path:" + +#: AperoDeDenis.py:2361 +msgid "Nouveau nom = ancien nom ; Abandon" +msgstr "New name = old name; Abandonment" + +#: AperoDeDenis.py:2365 +#, fuzzy, python-format +#| msgid "Le nom du nouveau chantier %s existe déjà. Abandon." +msgid "Le nom du nouveau chantier %s est déjà un chantier. Abandon." +msgstr "The choosen name for the project %s already exists. Aborting." + +#: AperoDeDenis.py:2368 +msgid "Le nouveau répertoire " +msgstr "The new directory" + +#: AperoDeDenis.py:2368 +msgid "implique un changement de disque." +msgstr "imply a disk change." + +#: AperoDeDenis.py:2368 +msgid "Utiliser l'Export-Import." +msgstr "Use export-import." + +#: AperoDeDenis.py:2371 AperoDeDenis.py:2374 +msgid "Le répertoire" +msgstr "The directory" + +#: AperoDeDenis.py:2371 +msgid "pour le chantier est déjà utilisé." +msgstr "for the project is already used." + +#: AperoDeDenis.py:2371 AperoDeDenis.py:2374 +msgid "Choisissez un autre nom." +msgstr "Choose another name." + +#: AperoDeDenis.py:2374 +msgid "désigne un sous-répertoire du chantier en cours." +msgstr "designate a sub-directory of the current project." + +#: AperoDeDenis.py:2386 +msgid "Le renommage du chantier ne peut se faire actuellement," +msgstr "Can't rename the project now," + +#: AperoDeDenis.py:2386 +msgid "soit le nom fourni est incorrect," +msgstr "either the name is incorrect," + +#: AperoDeDenis.py:2387 +msgid "soit un fichier du chantier est ouvert par une autre application." +msgstr "or a file from the project is opened by anoter application." + +#: AperoDeDenis.py:2388 +msgid "soit l'explorateur explore l'arborescence." +msgstr "or the explorer is in the tree." + +#: AperoDeDenis.py:2388 +msgid "erreur : " +msgstr "error:" + +#: AperoDeDenis.py:2404 +msgid "Chantier :" +msgstr "Project:" + +#: AperoDeDenis.py:2404 +msgid "renommé en :" +msgstr "renamed into:" + +#: AperoDeDenis.py:2404 +msgid "Répertoire : " +msgstr "Directory:" + +#: AperoDeDenis.py:2471 +msgid "Pas de chantier en cours" +msgstr "No current project" + +#: AperoDeDenis.py:2473 +msgid "Patience : chantier en cours d'archivage..." +msgstr "Please wait: the project is being archived." + +#: AperoDeDenis.py:2475 +msgid "Archive " +msgstr "Archive" + +#: AperoDeDenis.py:2475 +msgid "créée sous " +msgstr "created in" + +#: AperoDeDenis.py:2475 +msgid "Taille =" +msgstr "Size =" + +#: AperoDeDenis.py:2480 +msgid "Choisir le nom de l'archive à importer." +msgstr "Choose the name of the archive to import." + +#: AperoDeDenis.py:2482 +msgid "Export" +msgstr "Export" + +#: AperoDeDenis.py:2482 AperoDeDenis.py:3203 AperoDeDenis.py:3226 +#: AperoDeDenis.py:3248 AperoDeDenis.py:3271 AperoDeDenis.py:3359 +#: AperoDeDenis.py:6772 AperoDeDenis.py:8299 +msgid "Tous" +msgstr "All" + +#: AperoDeDenis.py:2484 +msgid "Chantier à importer" +msgstr "Project to import." + +#: AperoDeDenis.py:2486 +msgid "Importation abandonnée." +msgstr "Import aborted." + +#: AperoDeDenis.py:2489 +msgid " n'est pas un fichier d'export valide" +msgstr "is not a valid export file" + +#: AperoDeDenis.py:2490 +msgid "ou alors, sous ubuntu,il lui manque le droit d'exécution." +msgstr "" +"or if you use unbuntu, you probably don't have the execution permission." + +#: AperoDeDenis.py:2494 +msgid "Choisir le répertoire dans lequel recopier le chantier." +msgstr "Select the directory in which you want to copy the project." + +#: AperoDeDenis.py:2498 +msgid " n'est pas un répertoire valide." +msgstr "is not a valid directory." + +#: AperoDeDenis.py:2501 +msgid "Recopie en cours dans" +msgstr "Copying in" + +#: AperoDeDenis.py:2501 +msgid "Patience !" +msgstr "Please wait !" + +#: AperoDeDenis.py:2509 +msgid "Le répertoire destination" +msgstr "Destination directory" + +#: AperoDeDenis.py:2509 +msgid "existe déjà. Abandon" +msgstr "already exists. Aborting" + +#: AperoDeDenis.py:2520 AperoDeDenis.py:2529 +msgid "Erreur copie lors d'un import : " +msgstr "Copy error during an import:" + +#: AperoDeDenis.py:2521 AperoDeDenis.py:2530 +msgid "L'importation a échouée. Erreur : " +msgstr "Import failed. Error:" + +#: AperoDeDenis.py:2545 +msgid " absent" +msgstr " missing" + +#: AperoDeDenis.py:2561 +msgid "Chantier importé :" +msgstr "Imported project:" + +#: AperoDeDenis.py:2561 +msgid "Répertoire :" +msgstr "Directory:" + +#: AperoDeDenis.py:2561 +msgid "Vous pouvez le renommer si besoin." +msgstr "You can rename it if necessary" + +#: AperoDeDenis.py:2564 +#, fuzzy, python-format +#| msgid "Version de MicMac avant l'import : %s" +msgid "Version de MicMac avant l'import : %s" +msgstr "MicMac version before import:" + +#: AperoDeDenis.py:2565 +#, python-format +msgid "Version de MicMac : %s" +msgstr "MicMac version: %s" + +#: AperoDeDenis.py:2568 +msgid "erreur affichage version lors de l'import d'un chantier : " +msgstr "Error display version when importing a project:" + +#: AperoDeDenis.py:2570 +msgid "Anomalie lors de l'importation : " +msgstr "Anomaly when importing:" + +#: AperoDeDenis.py:2581 +#, python-format +msgid "" +"Le répertoire du nouveau chantier \n" +" %s \n" +" est déjà un chantier.\n" +" Abandon." +msgstr "" +"The directory of the new shipyard %s is already a construction site.\n" +" Abandonment." + +#: AperoDeDenis.py:2583 +msgid "Répertoire correct. Patience..." +msgstr "Correct directory. Patience..." + +#: AperoDeDenis.py:2595 +#, fuzzy +#| msgid "Le répertoire %s ne contient pas le fichier mm3d. Abandon" +msgid "Le répertoire ne contient pas le fichier :\n" +msgstr "The % s directory does not contain the mm3d file. Abort" + +#: AperoDeDenis.py:2595 +msgid "" +"\n" +"Ce n'est pas un chantier.\n" +"Abandon." +msgstr "" +"\n" +"Ce n'est pas un chantier.\n" +"Abandon." + +#: AperoDeDenis.py:2603 +#, python-format +msgid "erreur copie fichier param chantier : %(param)s vers %(rep)s erreur=" +msgstr "Error copying project settings file: %(param)s to %(rep)s error:" + +#: AperoDeDenis.py:2606 +msgid "Erreur lors de la copie du fichier paramètre chantier" +msgstr "Error when copying project settings file " + +#: AperoDeDenis.py:2606 +msgid "vers" +msgstr "to" + +#: AperoDeDenis.py:2606 +msgid "erreur :" +msgstr "error:" + +#: AperoDeDenis.py:2627 +msgid "Répertoire des photos :" +msgstr "Pictures directory:" + +#: AperoDeDenis.py:2629 +msgid "Répertoire de la vidéo :" +msgstr "Video directory:" + +#: AperoDeDenis.py:2631 +msgid "Aucune photo sélectionnée." +msgstr "No pictures selected." + +#: AperoDeDenis.py:2634 +msgid " photos sélectionnées" +msgstr " selected pictures" + +#: AperoDeDenis.py:2634 +msgid "(sans calibration si tapas executé) : " +msgstr "(without calibration if Tapas executed)" + +#: AperoDeDenis.py:2636 +msgid " photos sélectionnées : " +msgstr " pictures selected:" + +#: AperoDeDenis.py:2639 +msgid "ATTENTION : plusieurs extensions différentes dans les photos choisies !" +msgstr "Warning: several extensions formats choosen in selected pictures !" + +#: AperoDeDenis.py:2639 +msgid "Le traitement ne se fera que sur un type de fichier." +msgstr "Processing can be done on only one file type." + +#: AperoDeDenis.py:2644 AperoDeDenis.py:2658 AperoDeDenis.py:2701 +msgid "Mode : " +msgstr "Mod: " + +#: AperoDeDenis.py:2646 AperoDeDenis.py:2648 +msgid "Echelle 1 : " +msgstr "Scale 1:" + +#: AperoDeDenis.py:2649 +msgid "Echelle 2 : " +msgstr "Scale 2:" + +#: AperoDeDenis.py:2651 +msgid "Echelle : " +msgstr "Scale:" + +#: AperoDeDenis.py:2652 +msgid "Delta : " +msgstr "Delta:" + +#: AperoDeDenis.py:2660 +msgid "Nombre de photos pour calibration intrinsèque : " +msgstr "Number of pictures for intrinsic calibration:" + +#: AperoDeDenis.py:2662 +msgid "Ces photos servent uniquement à la calibration." +msgstr "These pictures will be used for calibration only." + +#: AperoDeDenis.py:2664 +#, fuzzy +#| msgid "Tarama demandé aprés Tapas" +msgid "Tarama demandé après Tapas" +msgstr "Tarama requested after Tapas" + +#: AperoDeDenis.py:2666 +msgid "Arrêt demandé après Tapas" +msgstr "Stop asked after Tapas." + +#: AperoDeDenis.py:2671 +msgid "Mise à l'échelle présente" +msgstr "Scaling Presents" + +#: AperoDeDenis.py:2674 +msgid "Mise à l'échelle invalide : distance=0" +msgstr "Invalid scaling: Distance = 0" + +#: AperoDeDenis.py:2676 +msgid "Mise à l'échelle incomplète :" +msgstr "Incomplete scaling:" + +#: AperoDeDenis.py:2681 +#, fuzzy +#| msgid "Saisie incomplète : les points ne seront pas pris en compte" +msgid "Points GPS : Saisie complète, les points seront pris en compte" +msgstr "Incomplete entry : points will no be considered." + +#: AperoDeDenis.py:2683 +#, fuzzy +#| msgid "Saisie incomplète : les points ne seront pas pris en compte" +msgid "Points GPS : Saisie incomplète, les points ne seront pas pris en compte" +msgstr "Incomplete entry : points will no be considered." + +#: AperoDeDenis.py:2688 +msgid "La version installée de Micmac n'autorise pas les masques en 3D" +msgstr "MicMac's installed version does not allow 3D mask" + +#: AperoDeDenis.py:2694 +msgid "Densification : C3DC avec masque 3D" +msgstr "Densification: C3DC with 3d mask" + +#: AperoDeDenis.py:2696 +msgid "Densification : C3DC sans Masque" +msgstr "Densification: C3DC without mask" + +#: AperoDeDenis.py:2704 +#, fuzzy +#| msgid "Pas d'image maîtresse" +msgid "Pas d'image maîtresse\n" +msgstr "No master picture" + +#: AperoDeDenis.py:2706 AperoDeDenis.py:2724 +msgid "Image maîtresse : " +msgstr "Master picture:" + +#: AperoDeDenis.py:2708 AperoDeDenis.py:2726 AperoDeDenis.py:4276 +#: AperoDeDenis.py:4279 +msgid " images maîtresses" +msgstr "Master pictures:" + +#: AperoDeDenis.py:2710 +msgid "1 masque" +msgstr "One mask" + +#: AperoDeDenis.py:2714 AperoDeDenis.py:4290 AperoDeDenis.py:4291 +msgid " masques" +msgstr "masks" + +#: AperoDeDenis.py:2716 +#, python-format +msgid "%s photos utiles autour de la maîtresse" +msgstr "%s useful photos around the mistress" + +#: AperoDeDenis.py:2720 +#, fuzzy +#| msgid "Tawny lancé aprés Malt" +msgid "Tawny lancé après Malt" +msgstr "Tawny launched after Malt" + +#: AperoDeDenis.py:2728 +msgid "arrêt au zoom : " +msgstr "Stop at zoom level: " + +#: AperoDeDenis.py:2733 +msgid "Chantier en cours de définition." +msgstr "The project is beig defined." + +#: AperoDeDenis.py:2751 +msgid "Chantier nettoyé." +msgstr "Site cleaned." + +#: AperoDeDenis.py:2758 +msgid "Chantier : " +msgstr "Project: " + +#: AperoDeDenis.py:2764 +msgid "Chemin du chantier :" +msgstr "Project path:" + +#: AperoDeDenis.py:2766 +msgid "Chantier en attente d'enregistrement." +msgstr "Project waiting to be saved." + +#: AperoDeDenis.py:2768 +msgid "Chantier enregistré." +msgstr "Project saved." + +#: AperoDeDenis.py:2770 +msgid "Options du chantier modifiables." +msgstr "Project options editable." + +#: AperoDeDenis.py:2772 +msgid "Chantier interrompu suite à erreur." +msgstr "Project interrupted by an error." + +#: AperoDeDenis.py:2772 +msgid "Relancer micmac." +msgstr "Relaunch MicMac." + +#: AperoDeDenis.py:2774 +msgid "Options de Malt/C3DC modifiables." +msgstr "Malt/C3DC options editable." + +#: AperoDeDenis.py:2776 +msgid "Chantier terminé." +msgstr "Project completed." + +#: AperoDeDenis.py:2778 +msgid "Chantier exécuté puis débloqué." +msgstr "Project executed and unblocked." + +#: AperoDeDenis.py:2780 +msgid "La densification a echoué : pas de nuage dense généré." +msgstr "Densification has failed: no dense cloud generated." + +#: AperoDeDenis.py:2785 +msgid "Nuage de point non densifié généré après Tapas." +msgstr "Undensified point cloud generated after Tapas." + +#: AperoDeDenis.py:2789 +#, fuzzy +#| msgid "Nuage de point densifié généré après %s" +msgid "Nuage de point densifié généré." +msgstr "Densified point cloud generated after %s" + +#: AperoDeDenis.py:2792 +msgid "Aucun nuage de point généré." +msgstr "No point cloud generated." + +#: AperoDeDenis.py:2801 +msgid "Les caractéristiques du chantier précédent" +msgstr "Characteristics from last project " + +#: AperoDeDenis.py:2801 +msgid "n'ont pas pu être lues correctement." +msgstr "couldn't be read properly." + +#: AperoDeDenis.py:2802 +msgid "" +"Le fichier des paramètres est probablement incorrect ou vous avez changé la " +"version de l'interface." +msgstr "Settings files is incorrect or GUI's version has changed." + +#: AperoDeDenis.py:2803 +msgid "Certaines fonctions seront peut_être défaillantes." +msgstr "Some functions will maybe fail." + +#: AperoDeDenis.py:2804 +msgid "Désolé pour l'incident." +msgstr "Sorry for the inconvenience." + +#: AperoDeDenis.py:2805 +msgid "Erreur : " +msgstr "Error:" + +#: AperoDeDenis.py:2833 AperoDeDenis.py:2834 AperoDeDenis.py:2837 +msgid "Toutes les photos" +msgstr "All pictures" + +#: AperoDeDenis.py:2836 +msgid "Toutes les photos utiles" +msgstr "All useful pictures" + +#: AperoDeDenis.py:2837 +#, python-format +msgid "sans les %s photos pour calibration intrinseque" +msgstr "without %s pictures for intrinsic calibration." + +#: AperoDeDenis.py:2843 AperoDeDenis.py:2854 AperoDeDenis.py:2865 +#: AperoDeDenis.py:2877 AperoDeDenis.py:2892 AperoDeDenis.py:2915 +#: AperoDeDenis.py:2939 AperoDeDenis.py:2956 AperoDeDenis.py:2967 +#: AperoDeDenis.py:2985 AperoDeDenis.py:3003 AperoDeDenis.py:8942 +#: AperoDeDenis.py:8959 +msgid "Fermer" +msgstr "Close" + +#: AperoDeDenis.py:2848 +msgid "Aucun point GPS saisi." +msgstr "No GPS point entered." + +#: AperoDeDenis.py:2851 +msgid "Affichage des photos avec points GPS" +msgstr "Display pictures with GPS points." + +#: AperoDeDenis.py:2853 +msgid "seules les photos avec points sont montrées." +msgstr "Only pictures with points will be displayed." + +#: AperoDeDenis.py:2862 +msgid "Liste des images maîtresses et des masques " +msgstr "List of master pictures and masks" + +#: AperoDeDenis.py:2862 +msgid "communs à GeomImage et AperoDedenis" +msgstr "Common to GeomImage and AperoDedenis" + +#: AperoDeDenis.py:2864 +msgid "Images maîtresses et masques" +msgstr "Master picture and masks" + +#: AperoDeDenis.py:2868 +msgid "Pas de maîtresses définies pour ce chantier" +msgstr "No master picture defined for this project" + +#: AperoDeDenis.py:2874 +msgid "Mosaique Tarama et masque " +msgstr "Tarama : mosaic ans mask" + +#: AperoDeDenis.py:2874 +msgid "Option Ortho de Malt" +msgstr "Option Ortho for Malt" + +#: AperoDeDenis.py:2876 +msgid "Image maîtresse et masque" +msgstr "Master picture and mask" + +#: AperoDeDenis.py:2883 +msgid "Pas de masque 3D pour ce chantier." +msgstr "No 3D mask for this project." + +#: AperoDeDenis.py:2890 +msgid "Visaliser le masque 3D" +msgstr "Display 3D mask" + +#: AperoDeDenis.py:2894 +msgid "Affichage du masque 3D :" +msgstr "Viewing 3D mask:" + +#: AperoDeDenis.py:2895 +msgid "Les points blancs du nuage sont dans le masque" +msgstr "Point cloud's white point are in the mask" + +#: AperoDeDenis.py:2896 +msgid "Ce masque C3DC a la priorité sur le masque 2D de Malt" +msgstr "C3DC mask has priority over 2D mask from Malt" + +#: AperoDeDenis.py:2897 +msgid "ATTENTION : pour continuer FERMER la fenêtre 3D" +msgstr "Warning : to continue close windows 3D." + +#: AperoDeDenis.py:2898 +msgid "puis cliquer si besoin sur le bouton FERMER ci-dessus." +msgstr "Then click on the CLOSE button above." + +#: AperoDeDenis.py:2908 +msgid "horizontale" +msgstr "horizontal" + +#: AperoDeDenis.py:2910 +msgid "verticale" +msgstr "vertical" + +#: AperoDeDenis.py:2912 +msgid "Visualiser l'image maîtresse et le plan horizontal ou vertical" +msgstr "Display master picture and horizontal or vertical plane" + +#: AperoDeDenis.py:2914 +msgid "Zone plane " +msgstr "Plane area" + +#: AperoDeDenis.py:2920 +msgid "Pas de plan horizontal ou vertical défini pour ce chantier" +msgstr "No horizontal or vertical plane defined for this project." + +#: AperoDeDenis.py:2930 +msgid "HORIZONTALE" +msgstr "HORIZONTAL" + +#: AperoDeDenis.py:2933 +msgid "VERTICALE" +msgstr "VERTICAL" + +#: AperoDeDenis.py:2936 +msgid "Affichage des photos avec ligne horizontale ou verticale" +msgstr "Display pictures with horizontal or vertical plane" + +#: AperoDeDenis.py:2938 +msgid "ligne " +msgstr "line" + +#: AperoDeDenis.py:2942 +msgid "Pas de ligne horizontale ou verticale définie pour ce chantier" +msgstr "No horizontal or vertical line defined for this project" + +#: AperoDeDenis.py:2948 +msgid "Pas de distance correcte définie pour ce chantier." +msgstr "No correct distance defined for this project." + +#: AperoDeDenis.py:2953 +msgid "Visualiser les photos avec distance" +msgstr "Display pictures with distance" + +#: AperoDeDenis.py:2955 +msgid "Valeur de la distance : " +msgstr "Distance value:" + +#: AperoDeDenis.py:2961 +msgid "Pas de photos pour la calibration intrinsèque par Tapas." +msgstr "No pictures for intrinsic calibration by Tapas." + +#: AperoDeDenis.py:2964 +msgid "Les photos pour calibration intrinsèque (Tapas)" +msgstr "Pictures for intrinsic calibration (Tapas)" + +#: AperoDeDenis.py:2966 +msgid "Calibration intrinsèque" +msgstr "Intrinsic calibration" + +#: AperoDeDenis.py:2972 +msgid "Pas de mosaique. Choisir l'option Tarama de tapas." +msgstr "No mosaic. Choose Tarama's option of Tapas." + +#: AperoDeDenis.py:2978 +msgid "Echec de la conversion mosaique en JPG." +msgstr "Failed mosaic conversion to JPG." + +#: AperoDeDenis.py:2982 +msgid "Mosaique créée par Tarama" +msgstr "Mosaic generates by Tarama" + +#: AperoDeDenis.py:2990 +msgid "Pas d' ortho mosaique par Tawny. Choisir l'option Tawny de Malt." +msgstr "No mosaic. Choose Tawny's option of Malt" + +#: AperoDeDenis.py:2996 +msgid "Echec de la conversion de la mosaïque TIF en JPG." +msgstr "Failed mosaic conversion to JPG." + +#: AperoDeDenis.py:3000 +msgid "Ortho mosaique créée par Tawny" +msgstr "Ortho Mosaic generates by Tawny." + +#: AperoDeDenis.py:3027 +msgid "Pas de trace de la trace !" +msgstr "No log found !" + +#: AperoDeDenis.py:3038 +msgid "Pas de nuage de points non densifié." +msgstr "No cloud of non-densified points." + +#: AperoDeDenis.py:3040 +msgid "Programme pour ouvrir les .PLY non trouvéé." +msgstr ".PLY opener program not found." + +#: AperoDeDenis.py:3045 +msgid "Pas de nuage de points densifié." +msgstr "No cloud of densified points." + +#: AperoDeDenis.py:3047 AperoDeDenis.py:5357 +msgid "Programme pour ouvrir les .PLY non trouvé." +msgstr ".PLY opener program not found." + +#: AperoDeDenis.py:3053 +msgid "Répertoire bin de MicMac : " +msgstr "Directory of MicMac\\bin:" + +#: AperoDeDenis.py:3055 +msgid "Version MicMac :" +msgstr "MicMac version:" + +#: AperoDeDenis.py:3057 +msgid "Outil exiftool :" +msgstr "exiftool tool:" + +#: AperoDeDenis.py:3059 +msgid "Outil convert d'ImageMagick :" +msgstr "Convert ImageMagick tool:" + +#: AperoDeDenis.py:3061 +msgid "Outil pour afficher les .ply :" +msgstr "Tool used to display .ply:" + +#: AperoDeDenis.py:3063 +msgid "Outil pour décompacter les vidéos (ffmpeg):" +msgstr "Toll used to unpack videos (ffmpeg):" + +#: AperoDeDenis.py:3065 +msgid "Répertoire d'AperoDeDenis :" +msgstr "AperoDeDenis's directory:" + +#: AperoDeDenis.py:3067 +msgid "Répertoire des paramètres :" +msgstr "Settings directory:" + +#: AperoDeDenis.py:3077 +msgid "Répertoire bin sous MICMAC : " +msgstr "Directory of MicMac\\bin:" + +#: AperoDeDenis.py:3086 +msgid "Désigner le répertoire bin sous Micmac " +msgstr "Designate the directory of MicMac\\bin:" + +#: AperoDeDenis.py:3088 AperoDeDenis.py:3095 AperoDeDenis.py:3209 +#: AperoDeDenis.py:3232 AperoDeDenis.py:3254 AperoDeDenis.py:3277 +msgid "Abandon, pas de changement." +msgstr "Abort, no change." + +#: AperoDeDenis.py:3088 AperoDeDenis.py:3095 +msgid "Répertoire bin de Micmac :" +msgstr "Directory of MicMac\\bin: " + +#: AperoDeDenis.py:3093 +msgid "" +"Le chemin du répertoire bin de micmac ne doit pas comporter le caractère " +"'espace'." +msgstr "" +"The path of the directory of MicMac\\bin must not include the 'space' " +"character. " + +#: AperoDeDenis.py:3094 +msgid "Renommer le répertoire de MicMac." +msgstr "Rename the MicMac's directory." + +#: AperoDeDenis.py:3109 +#, python-format +msgid "Le répertoire %s ne contient pas le fichier mm3d.exe. Abandon" +msgstr "The %s directory does not contain the mm3d.exe file. abort" + +#: AperoDeDenis.py:3155 +#, python-format +msgid "Le répertoire %s ne contient pas le fichier mm3d. Abandon" +msgstr "The % s directory does not contain the mm3d file. Abort" + +#: AperoDeDenis.py:3168 +msgid "Nouveau répertoire de Micmac :" +msgstr "New MicMac's directory:" + +#: AperoDeDenis.py:3173 +msgid "Le programme mm3d est présent mais ne peut s'exécuter." +msgstr "mm3d found but can't be executed." + +#: AperoDeDenis.py:3173 +msgid "Vérifier si la version est compatible avec le système. :" +msgstr "Please check if the current version is compatible with this system." + +#: AperoDeDenis.py:3175 +msgid "Le programme mm3d est absent du répertoire choisi :" +msgstr "MM3d is not to be found in the choosen directory:" + +#: AperoDeDenis.py:3175 +msgid "Répertoire bin sous MicMac incorrect." +msgstr "Wrong directory for MicMac\\bin. " + +#: AperoDeDenis.py:3175 +msgid "Abandon." +msgstr "Aborting." + +#: AperoDeDenis.py:3180 +msgid "Chemin de exiftool :" +msgstr "exiftool path:" + +#: AperoDeDenis.py:3182 +msgid "Chemin de convert d'image Magick :" +msgstr "ImageMafick's convert path:" + +#: AperoDeDenis.py:3184 +msgid "Chemin de ffmpeg :" +msgstr "Path to ffmpeg" + +#: AperoDeDenis.py:3189 +msgid "Pas de version identifiée de MicMac" +msgstr "Not identificated version of MicMac" + +#: AperoDeDenis.py:3190 +msgid "Nouvelle version de MicMac : " +msgstr "New version of MicMac:" + +#: AperoDeDenis.py:3197 +msgid "Pas de chemin pour le programme exiftool" +msgstr "No path for exiftool program" + +#: AperoDeDenis.py:3199 AperoDeDenis.py:3214 +msgid "Programme exiftool :" +msgstr "Exiftool program: " + +#: AperoDeDenis.py:3207 +msgid "Recherche exiftool" +msgstr "exiftool search" + +#: AperoDeDenis.py:3209 +msgid "Fichier exiftool inchangé :" +msgstr "Exiftool file unchanged." + +#: AperoDeDenis.py:3220 +msgid "Pas de chemin pour le programme convert d'ImageMagick" +msgstr "No patch for ImageMagick's convert program" + +#: AperoDeDenis.py:3222 AperoDeDenis.py:3237 +msgid "Programme convert :" +msgstr "Convert program:" + +#: AperoDeDenis.py:3230 +msgid "Recherche convert" +msgstr "Convert search" + +#: AperoDeDenis.py:3232 +msgid "Fichier convert inchangé :" +msgstr "Exiftool file unchanged:" + +#: AperoDeDenis.py:3243 +msgid "Pas de chemin pour le programme ouvrant les .PLY" +msgstr "No patch for the .PLY opener program. " + +#: AperoDeDenis.py:3245 AperoDeDenis.py:3259 +msgid "Programme ouvrant les .PLY :" +msgstr ".PLY opener program:" + +#: AperoDeDenis.py:3248 +msgid "meshlab ou CloudCompare" +msgstr "meshlab or CloudCompare" + +#: AperoDeDenis.py:3252 +msgid "Recherche fichier Meshlab sous VCG, ou CloudCompare" +msgstr "Meshlab under VCG or CloudCompare file search" + +#: AperoDeDenis.py:3254 +msgid "Fichier Meshlab ou cloud compare :" +msgstr "Meshlab or CloudCompare file:" + +#: AperoDeDenis.py:3265 +msgid "Pas de chemin pour le programme Ffmpeg" +msgstr "No path for ffmpeg program" + +#: AperoDeDenis.py:3267 AperoDeDenis.py:3282 +msgid "Programme ffmpeg :" +msgstr "ffmpeg program:" + +#: AperoDeDenis.py:3275 +msgid "Recherche ffmpeg" +msgstr "ffmpeg search:" + +#: AperoDeDenis.py:3277 +msgid "Fichier ffmpeg inchangé :" +msgstr "ffmpeg file unchanged." + +#: AperoDeDenis.py:3288 +msgid "Tacky message au lancement activé" +msgstr "Launching tacky message activated." + +#: AperoDeDenis.py:3290 +msgid "Tacky message au lancement désactivé" +msgstr "Launching tacky message desactivated." + +#: AperoDeDenis.py:3294 +msgid "Sélectionnez la langue à utiliser. L'application sera redémarrée." +msgstr "" +"Select the language you want to use. The application will be restarted." + +#: AperoDeDenis.py:3302 +msgid "Appliquer" +msgstr "Apply" + +#: AperoDeDenis.py:3305 AperoDeDenis.py:3311 +msgid "Français" +msgstr "French" + +#: AperoDeDenis.py:3306 +msgid "Anglais" +msgstr "English" + +#: AperoDeDenis.py:3331 +msgid "" +"Avant de choisir les photos associer le répertoire bin de micmac (Menu " +"Paramétrage\\associer le répertoire bin de MicMac)." +msgstr "" +"Please link the MicMac\\bin directory before choosing pictures (Settings menu" +"\\Link the MicMac\\bin directory)." + +#: AperoDeDenis.py:3335 +msgid "" +"Avant de choisir les photos associer le chemin du programme exiftool (Menu " +"trage\\Associer exiftool)." +msgstr "" +"Please association the exiftool programm directory before choosing pictures " +"(Settings menu\\Link the 'exiftool' directory)." + +#: AperoDeDenis.py:3343 +msgid "Nouvelles photos pour le meme chantier" +msgstr "New pictures for the same project" + +#: AperoDeDenis.py:3344 +msgid "Choisir de nouvelles photos réinitialisera le chantier." +msgstr "Choosing new pictures will reset the project." + +#: AperoDeDenis.py:3345 +msgid "Les traces et l'arborescence des calculs seront effacées." +msgstr "Logs and calculations tree will be deleted." + +#: AperoDeDenis.py:3346 +msgid "Les options compatibles avec les nouvelles photos seront conservées." +msgstr "Compatibles options with the new pictures will be preserved." + +#: AperoDeDenis.py:3348 +msgid "Réinitialiser le chantier" +msgstr "Reset project" + +#: AperoDeDenis.py:3349 AperoDeDenis.py:6816 +msgid "Abandon, le chantier n'est pas modifié." +msgstr "Aborting, the project is unchanged." + +#: AperoDeDenis.py:3359 +msgid "Photos" +msgstr "Pictures" + +#: AperoDeDenis.py:3363 +msgid "Abandon, aucune sélection de fichier image," +msgstr "Aborting, no picture file selected, " + +#: AperoDeDenis.py:3363 AperoDeDenis.py:3427 AperoDeDenis.py:6282 +msgid "le répertoire et les photos restent inchangés." +msgstr "directory and pictures unchanged." + +#: AperoDeDenis.py:3367 AperoDeDenis.py:3390 +msgid "Aucune extension acceptable pour des images. Abandon." +msgstr "No compatible extension for these pictures. Aborting." + +#: AperoDeDenis.py:3371 +msgid "Plusieurs extensions différentes :" +msgstr "Several different extensions: " + +#: AperoDeDenis.py:3371 +msgid "Impossible dans cette version. Abandon." +msgstr "Impossible in this version. Aborting." + +#: AperoDeDenis.py:3376 +msgid "Info : format des photos" +msgstr "Info : pictures format" + +#: AperoDeDenis.py:3376 +msgid "La version actuelle ne traite que les photos au format JPG," +msgstr "The current version can only process JPG files," + +#: AperoDeDenis.py:3376 +msgid "or le format des photos est : " +msgstr "but these pictures format is:" + +#: AperoDeDenis.py:3377 +msgid "les photos vont être converties au format JPG." +msgstr "the pictures will be converted into JPG format." + +#: AperoDeDenis.py:3378 +msgid "Convertir en JPG" +msgstr "Convert into JPG" + +#: AperoDeDenis.py:3379 AperoDeDenis.py:3407 +msgid "Abandonner" +msgstr "Abort" + +#: AperoDeDenis.py:3382 +msgid "Désigner l'outil de conversation 'convert' d'ImageMagick" +msgstr "Designate the ImageMagick's convert conversation tool. " + +#: AperoDeDenis.py:3382 +msgid "(Menu Paramétrage)" +msgstr "(Settings menu)" + +#: AperoDeDenis.py:3404 +msgid "ATTENTION !" +msgstr "WARNING !" + +#: AperoDeDenis.py:3404 +msgid "" +"ATTENTION : des points GPS ont été précedemment placés sur des photos non " +"choisies pour ce chantier." +msgstr "" +"Warning : some GPS points have been placed on pictures which have not being " +"choosen for this project." + +#: AperoDeDenis.py:3405 +msgid "" +"Les emplacements de ces points vont être supprimés si vous validez cette " +"sélection de photos." +msgstr "Points location will be deleted if you confirm this picture selection." + +#: AperoDeDenis.py:3406 +msgid "Valider la sélection de photos" +msgstr "Confirm picture selection" + +#: AperoDeDenis.py:3415 +msgid "Copie des photos en cours... Patience" +msgstr "Pictures copy... Please wait..." + +#: AperoDeDenis.py:3424 AperoDeDenis.py:6279 +msgid "Impossible de créer le répertoire de travail." +msgstr "Impossible to create working directory. " + +#: AperoDeDenis.py:3424 AperoDeDenis.py:6279 +msgid "Vérifier les droits en écriture sous le répertoire des photos" +msgstr "Please check write permission on the pictures directory." + +#: AperoDeDenis.py:3427 AperoDeDenis.py:6282 +msgid "Aucun JPG, PNG, BMP, TIF, ou GIF sélectionné," +msgstr "No JPG, PNG, BMP, TIF or GIF selected, " + +#: AperoDeDenis.py:3438 +msgid "Les focales sont absentes des exif." +msgstr "Focal length absent from exif." + +#: AperoDeDenis.py:3438 +msgid "Mettez à jour les exifs avant de lancer MicMac." +msgstr "Please update exifs before launching MicMac." + +#: AperoDeDenis.py:3439 +msgid "Utiliser le menu Outils/Modifier l'exif des photos." +msgstr "Use Tools/Edit pictures exif." + +#: AperoDeDenis.py:3441 +msgid "Attention : Les focales des photos ou ne sont pas toutes identiques." +msgstr "Warning: the focal length of the pictures are not all the same." + +#: AperoDeDenis.py:3443 +msgid "Attention : les dimensions des photos ne sont pas toutes identiques." +msgstr "Warning: the dimensions of the pictures are not all the same." + +#: AperoDeDenis.py:3444 +msgid "Le traitement par MicMac ne sera peut-être pas possible." +msgstr "MicMac's processing will maybe not be possible." + +#: AperoDeDenis.py:3455 +msgid "De nouvelles photos ont été sélectionnés sur un chantier pré-existant." +msgstr "New pictures were selected on an already existing project." + +#: AperoDeDenis.py:3456 +msgid "" +"Les anciennes options compatibles avec les nouvelles photos ont été " +"conservées." +msgstr "Former compatibles options with new pictures were preserved." + +#: AperoDeDenis.py:3507 +msgid "erreur lors de la copie du fichier" +msgstr "Error when copying" + +#: AperoDeDenis.py:3507 +msgid "dans le répertoire " +msgstr "in the directory" + +#: AperoDeDenis.py:3507 +msgid "libellé de l'erreur :" +msgstr "Error:" + +#: AperoDeDenis.py:3507 +msgid "Causes possibles : manque d'espace disque ou droits insuffisants." +msgstr "Possibles causes: no enough space or you don't have the permissions." + +#: AperoDeDenis.py:3573 +msgid "Impossible de créer le répertoire de travail : erreur = " +msgstr "Can't create the work directory, error:" + +#: AperoDeDenis.py:3587 +#, python-format +msgid "Le chantier %s a été interrompu en cours d'exécution." +msgstr "Project %s has ben interrupted because of an execution." + +#: AperoDeDenis.py:3588 AperoDeDenis.py:5090 +msgid "Le chantier est interrompu." +msgstr "Project interrupted. " + +#: AperoDeDenis.py:3588 AperoDeDenis.py:5090 AperoDeDenis.py:5105 +msgid "Vous pouvez le débloquer," +msgstr "You can unblock it, " + +#: AperoDeDenis.py:3589 AperoDeDenis.py:5091 +msgid "ce qui permettra de modifier les options et de le relancer." +msgstr "which will allow to edit options and relaunch it." + +#: AperoDeDenis.py:3590 AperoDeDenis.py:5092 AperoDeDenis.py:5107 +msgid "Débloquer le chantier" +msgstr "Unblock project" + +#: AperoDeDenis.py:3596 AperoDeDenis.py:5098 AperoDeDenis.py:5113 +#: AperoDeDenis.py:5141 +#, python-format +msgid "Chantier %s de nouveau modifiable, paramètrable et exécutable." +msgstr "Project %s is editable, configurable and executable anew." + +#: AperoDeDenis.py:3606 +#, python-format +msgid "Le chantier %(x)s est terminé." +msgstr "The %(x)s project reached his end." + +#: AperoDeDenis.py:3607 +msgid "Le chantier est terminé après " +msgstr "The project reached his end after" + +#: AperoDeDenis.py:3608 +msgid "Vous pouvez :" +msgstr "You could:" + +#: AperoDeDenis.py:3609 +#, fuzzy +#| msgid "Modifier les options de Tapioca et Tapas" +msgid " - Modifier les options de Tapioca et Tapas" +msgstr "Edit Tapioca and Tapas options" + +#: AperoDeDenis.py:3610 +msgid "" +" - Conserver les traitements de Tapioca/Tapas pour relancer la densification" +msgstr "-Keep the Tapioca/Tapas treatments to revive densification" + +#: AperoDeDenis.py:3611 +msgid " - Ne rien faire." +msgstr "- Do nothing" + +#: AperoDeDenis.py:3612 +msgid "Modifier les options de Tapioca et Tapas" +msgstr "Edit Tapioca and Tapas options" + +#: AperoDeDenis.py:3613 +msgid "Modifier les options de la densification" +msgstr "Change densification options" + +#: AperoDeDenis.py:3614 AperoDeDenis.py:6814 +msgid "Ne rien faire" +msgstr "Do nothing." + +#: AperoDeDenis.py:3643 AperoDeDenis.py:4182 +msgid "Nombre de photos choisies : " +msgstr "Number of choosen pictures:" + +#: AperoDeDenis.py:3667 +msgid "" +"La version de Micmac installée ne propose pas le module C3DC. Choisir MALT." +msgstr "" + +#: AperoDeDenis.py:3671 +#, fuzzy +#| msgid "pas de fichier AperiCloud.ply pour construire le masque :" +msgid "Pas de nuage Apericloud : pour construire un masque" +msgstr "No AperiCloud.ply file to build the mask:" + +#: AperoDeDenis.py:3671 +#, fuzzy +#| msgid "Lancer d'abord tapioca/tapas" +msgid "lancer Tapioca/tapas." +msgstr "Launch Tapioca/Tapas first" + +#: AperoDeDenis.py:3676 AperoDeDenis.py:4464 +msgid "Masque 3D créé" +msgstr "3D mask created" + +#: AperoDeDenis.py:3678 +msgid "Pas de masque 3D" +msgstr "No 3D mask" + +#: AperoDeDenis.py:3713 AperoDeDenis.py:5461 +msgid "Option incorrecte :" +msgstr "Wrong option: " + +#: AperoDeDenis.py:3726 +msgid "Points GPS non conformes. Nom est absent ou en double. Vérifiez." +msgstr "" +"GPS points nonconforming. Name of point is missing or duplicated. Check." + +#: AperoDeDenis.py:3733 AperoDeDenis.py:6568 +msgid "Nom" +msgstr "Name" + +#: AperoDeDenis.py:3752 +msgid "NomPhoto" +msgstr "PictureName" + +#: AperoDeDenis.py:3754 AperoDeDenis.py:3760 +msgid "NomPoint" +msgstr "PointName" + +#: AperoDeDenis.py:3783 +msgid "Pas de points GPS." +msgstr "No GPS points." + +#: AperoDeDenis.py:3788 +#, python-format +msgid "%s points GPS placés" +msgstr "%s GPS point placed" + +#: AperoDeDenis.py:3789 +#, python-format +msgid "pour %s points GPS définis" +msgstr "for %s GPS points given" + +#: AperoDeDenis.py:3791 +msgid "" +"Attention : il faut au moins 3 points pour qu'ils soient pris en compte." +msgstr "Warning : to consider those, there must be at least three points." + +#: AperoDeDenis.py:3810 +msgid "" +"Il n'y a pas 3 points placés sur 2 photos : les points GPS seront ignorés." +msgstr "" +"There are no 3 points placed on 2 photos: the GPS points will be ignored." + +#: AperoDeDenis.py:3813 +msgid "" +"Anomalie : les points suivants ne sont placés que sur une seule photo : " +msgstr "Anomaly: The following points are placed on a single photo:" + +#: AperoDeDenis.py:3816 +msgid "Anomalie : le point suivant n'est placé que sur une seule photo : " +msgstr "Anomaly: the next point is placed on a single photo:" + +#: AperoDeDenis.py:3823 +msgid "Attention : plusieurs points GPS ont les mêmes coordonnées." +msgstr "Warning: several GPS points have the same coordinates." + +#: AperoDeDenis.py:3826 +msgid "Saisie incomplète : les points GPS ne seront pas pris en compte" +msgstr "Incomplete entry: GPS points will not be taken into account" + +#: AperoDeDenis.py:3841 +msgid "La ligne horizontale ou verticale ne comporte pas 2 points" +msgstr "Horizontal or vertical line does not include two points." + +#: AperoDeDenis.py:3844 +msgid "Pas de maitre plan horizontal ou vertical" +msgstr "No horizontal or vertcial master plan." + +#: AperoDeDenis.py:3848 +msgid "Pas de plan horizontal ou vertical" +msgstr "No horizontal or vertical planes" + +#: AperoDeDenis.py:3853 +#, python-format +msgid "%(x)s Distance %(y)s invalide." +msgstr "%(x)s Distance %(y)s invalid." + +#: AperoDeDenis.py:3855 +msgid "Calibration annulée." +msgstr "Calibration aborted." + +#: AperoDeDenis.py:3857 +#, python-format +msgid "%s Pas de distance." +msgstr "%s No distance." + +#: AperoDeDenis.py:3863 +msgid "La distance n'est pas mesurée par 2 points repérés sur 2 photos." +msgstr "Distance not measured by two points on two pictures." + +#: AperoDeDenis.py:3866 AperoDeDenis.py:3869 +#, python-format +msgid "La photo avec distance %s est absente." +msgstr "Picture with distance %s not found." + +#: AperoDeDenis.py:3871 +msgid "Pas de distance pour la calibration." +msgstr "No distance for calibration." + +#: AperoDeDenis.py:3888 +msgid "Fichiers" +msgstr "Files" + +#: AperoDeDenis.py:3979 +#, python-format +msgid "" +"L'échelle pour le mode All de Tapioca est invalide, une valeur par défaut, " +"%s, est affectée." +msgstr "Scale for Tapioca's All mode invalid, default value, %s, affected." + +#: AperoDeDenis.py:3983 +msgid "Echelle pour le mode All de Tapioca trop petite :" +msgstr "Scale for Tapiocas's All mode too small." + +#: AperoDeDenis.py:3983 AperoDeDenis.py:4022 +msgid "Minimum = 50" +msgstr "Minimum = 50" + +#: AperoDeDenis.py:3995 +#, python-format +msgid "" +"L'échelle 1 pour MulScale de Tapioca est invalide, une valeur par défaut, " +"%s, est affectée." +msgstr "" +"Scale 1 from Tapioca's MulScale is invalid, a default value, %s, is affected." + +#: AperoDeDenis.py:3999 +msgid "L'échelle 1 de MulScale ne doit pas être -1." +msgstr "Scale 1 from MulScal can't be -1." + +#: AperoDeDenis.py:3999 +msgid "Elle est mise à 300." +msgstr "Its value is assigned to 300." + +#: AperoDeDenis.py:4006 +msgid "L'échelle 1 pour le mode MulScale de Tapioca est trop petite : " +msgstr "Scale 1 for Tapioca's MulScale mode too small:" + +#: AperoDeDenis.py:4006 +msgid "Minimum = 50, maximum conseillé : 300" +msgstr "Minimum = 50, indicated maximum = 300" + +#: AperoDeDenis.py:4018 +#, python-format +msgid "" +"L'échelle 2 pour le mode MulScale de Tapioca est invalide, une valeur par " +"défaut, %s, est affectée." +msgstr "" +"Scale 2 from Tapioca's MulScale is invalid, a default value, %s, is affected." + +#: AperoDeDenis.py:4022 +msgid "L'échelle 2 pour le mode MulScale de Tapioca est trop petite :" +msgstr "Scale 2 for Tapioca's MulScale mode too small:" + +#: AperoDeDenis.py:4030 +msgid "L'échelle 2 de MulScale pour tapioca" +msgstr "Scale 2 of Tapioca's MulScale " + +#: AperoDeDenis.py:4030 +msgid "plus petite que l'échelle 1 :" +msgstr "is smaller than scale 1:" + +#: AperoDeDenis.py:4042 +#, python-format +msgid "" +"L'échelle pour le mode Line de tapioca est invalide, une valeur par défaut, " +"%s, est affectée." +msgstr "Scale for Tapioca's line invalid. A default value, %s, is affected." + +#: AperoDeDenis.py:4046 +msgid "Echelle pour le mode Line de tapioca trop petite : " +msgstr "Scale for Taopioca's Line mod too small:" + +#: AperoDeDenis.py:4058 +msgid "La valeur de delta pour le mode Line de Tapioca est invalide," +msgstr "Delta value from Tapioca's Line is invalid," + +#: AperoDeDenis.py:4058 +#, python-format +msgid "une valeur par défaut, %s, est affectée." +msgstr "a default value, %s, is affected." + +#: AperoDeDenis.py:4062 +msgid "Delta trop petit :" +msgstr "Delta too small:" + +#: AperoDeDenis.py:4062 +msgid "Minimum = 1" +msgstr "Minimum = 1" + +#: AperoDeDenis.py:4069 +#, python-format +msgid "Le zoom final pour MALT n'est pas 1,2,4 ou 8 : %s" +msgstr "Final zoom for Malt isn't 1, 2, 4 or 8: %s" + +#: AperoDeDenis.py:4083 AperoDeDenis.py:4085 +msgid "Malt mode Geomimage :" +msgstr "Malt mode GeomImage:" + +#: AperoDeDenis.py:4083 +#, python-format +msgid "" +"Le nombre de photos utiles autour de l'image maîtresse est trop petit : %s" +msgstr "Number of useful pictures around the master picture is too small: %s" + +#: AperoDeDenis.py:4085 +msgid "" +"Le nombre de photos utiles autour de l'image centrale n'est pas numérique : " +msgstr "Number of useful pictures around central picture is not numerical." + +#: AperoDeDenis.py:4085 +msgid "Il est mis à 5." +msgstr "It is set to 5." + +#: AperoDeDenis.py:4093 +#, python-format +msgid "La photo %s n'existe plus." +msgstr "The picture named %s does not exist." + +#: AperoDeDenis.py:4098 +msgid "Inutile et ralenti le traitement. Modifier." +msgstr "Useless and slow the process. Edit." + +#: AperoDeDenis.py:4102 +msgid "L'échelle pour le mode All de tapioca = " +msgstr "Scale for the Tapioca's All mode = " + +#: AperoDeDenis.py:4102 +msgid ", est plus grande que la dimension maxi de la photo : " +msgstr ", is bigger than the maximum dimension of the picture:" + +#: AperoDeDenis.py:4106 +msgid "L'échelle 2 pour le mode MulScale de tapioca= " +msgstr "Scale 2 for the Tapioca's MulScale mode = " + +#: AperoDeDenis.py:4106 AperoDeDenis.py:4110 +msgid "est plus grande que la dimension maxi de la photo :" +msgstr "is bigger than the maximum dimension of the picture:" + +#: AperoDeDenis.py:4110 +msgid "L'échelle pour le mode Line de tapioca = " +msgstr "Scale for Tapioca's Line mode = " + +#: AperoDeDenis.py:4166 AperoDeDenis.py:4307 AperoDeDenis.py:4340 +#: AperoDeDenis.py:4690 AperoDeDenis.py:4774 AperoDeDenis.py:4816 +#: AperoDeDenis.py:4857 AperoDeDenis.py:4888 AperoDeDenis.py:4919 +msgid "Choisir d'abord les photos du chantier." +msgstr "Choose the pictures of the project first." + +#: AperoDeDenis.py:4170 +msgid "Pour calibrer l'appareil photo" +msgstr "To calibrate the camera" + +#: AperoDeDenis.py:4171 +msgid "Quelques photos, convergentes, d'angles écartés" +msgstr "Some pictures, convergent, apart from angles" + +#: AperoDeDenis.py:4171 +msgid "en jaune la calibration actuelle" +msgstr "in yellow, the current calibration." + +#: AperoDeDenis.py:4172 +msgid "Supprimer" +msgstr "Delete" + +#: AperoDeDenis.py:4175 +msgid "Pas de photos de calibration intrinseque." +msgstr "No instrinsic calibrated pictures." + +#: AperoDeDenis.py:4179 +msgid "Choix inchangé." +msgstr "Unchanged choice." + +#: AperoDeDenis.py:4215 +msgid "Image maitresse avec masque" +msgstr "Master picture with mask" + +#: AperoDeDenis.py:4230 +msgid "Choisir une ou plusieurs image(s) maîtresse(s)" +msgstr "Select one or several master pictures. " + +#: AperoDeDenis.py:4230 +msgid "en jaune : les maitresses actuelles" +msgstr "Current master pictures are in yellow." + +#: AperoDeDenis.py:4230 +msgid "Une info bulle informe de la présence d'un masque" +msgstr "A tooltip informs of the presence of a mask. " + +#: AperoDeDenis.py:4231 +msgid "Supprimer les images maîtresses" +msgstr "Delete master pictures" + +#: AperoDeDenis.py:4242 +msgid "Abandon. Choix inchangé." +msgstr "Aborting. Choices unchanged." + +#: AperoDeDenis.py:4261 +msgid "Image maitresse obligatoire pour GeomImage." +msgstr "A master picture is needed for GeomImage" + +#: AperoDeDenis.py:4263 +msgid "Exécuter Tapioca/Tapas pour saisir des masques avec cette option." +msgstr "Run Tapioca / Tapas to enter masks with this option." + +#: AperoDeDenis.py:4269 AperoDeDenis.py:4272 +msgid "image maîtresse = " +msgstr "Master picture =" + +#: AperoDeDenis.py:4286 AperoDeDenis.py:4287 +msgid "un seul masque : " +msgstr "Only one mask:" + +#: AperoDeDenis.py:4294 +msgid "Pas de mosaique Tarama : pas de masque." +msgstr "No Tarama's mosaic. No mask." + +#: AperoDeDenis.py:4297 +msgid "Tracer un nouveau masque sur la mosaique Tarama" +msgstr "Plot a new mask on the mosaic Tarama" + +#: AperoDeDenis.py:4300 +msgid "Tracer un masque sur la mosaique Tarama" +msgstr "Plot a mask on the mosaic Tarama" + +#: AperoDeDenis.py:4303 +msgid "erreur dans miseAJour701_703 : " +msgstr "error in setting miseAJour701_703 : " + +#: AperoDeDenis.py:4312 AperoDeDenis.py:4379 +msgid "Il faut au moins une image maîtresse pour définir un masque." +msgstr "You need at least one master picture to define a mask." + +#: AperoDeDenis.py:4319 AperoDeDenis.py:4355 +msgid "Un masque existe déjà" +msgstr "There's already a mask" + +#: AperoDeDenis.py:4321 AperoDeDenis.py:4357 AperoDeDenis.py:4389 +msgid "Choisir l'image pour le masque" +msgstr "Choose a picture for the mask." + +#: AperoDeDenis.py:4322 AperoDeDenis.py:4358 +msgid "" +"Choisir une image maîtresse pour le masque\n" +"en jaune = un masque existe" +msgstr "" +"Choose a master picture for the mask.\n" +"Yellow one already have one." + +#: AperoDeDenis.py:4343 +msgid "Exécuter d'abord Tapioca/Tapas." +msgstr "First run Tapioca / Tapas." + +#: AperoDeDenis.py:4347 +msgid "Pas d'image maîtresse. Bizarre." +msgstr "No master image. Bizarre." + +#: AperoDeDenis.py:4390 +msgid "Choisir une image maîtresse pour le masque" +msgstr "Choose a master picture for the mask." + +#: AperoDeDenis.py:4408 +msgid "pas de masque" +msgstr "no mask" + +#: AperoDeDenis.py:4410 +msgid "Il faut une image maîtresse pour définir un masque." +msgstr "You need a master picture to define a mask." + +#: AperoDeDenis.py:4467 +msgid "Abandon : pas de masque créé." +msgstr "Aborting: no mask created." + +#: AperoDeDenis.py:4475 +msgid "Masque 3D supprimé." +msgstr "3D mask deleted." + +#: AperoDeDenis.py:4495 +#, fuzzy +#| msgid "3 points minimum, chaque point doit être placé sur au moins 2 photos" +msgid "3 points doivent être placés sur au moins 2 photos" +msgstr "" +"At least three points, each point must be placed on at least two pictures." + +#: AperoDeDenis.py:4496 +msgid "Les points GPS sont prioritaires sur la mise à l'échelle.\n" +msgstr "" + +#: AperoDeDenis.py:4504 +msgid "CAMPARI : incertitude cible GPS :" +msgstr "" + +#: AperoDeDenis.py:4506 +msgid "incertitude pixel image :" +msgstr "" + +#: AperoDeDenis.py:4520 +#, fuzzy +#| msgid "Incertitude" +msgid "Incertitude sur X,Y,Z" +msgstr "Std deviations" + +#: AperoDeDenis.py:4525 +msgid "Ajouter un point" +msgstr "Add a point" + +#: AperoDeDenis.py:4526 +msgid "Supprimer des points" +msgstr "Delete points" + +#: AperoDeDenis.py:4527 +msgid "Placer les points" +msgstr "Place points" + +#: AperoDeDenis.py:4528 +msgid "Appliquer au " +msgstr "Apply on" + +#: AperoDeDenis.py:4528 +msgid "nuage non densifié" +msgstr "undensified point cloud" + +#: AperoDeDenis.py:4591 +msgid "Agrandissez la fenêtre avant d'ajouter un point GPS !" +msgstr "Extend the window before adding a GPS point !" + +#: AperoDeDenis.py:4591 +msgid "(ou si impossible : supprimer un point)" +msgstr "(or if impossible: remove a point)" + +#: AperoDeDenis.py:4595 +msgid "Soyez raisonnable : pas plus de 30 points GPS !" +msgstr "Be rational: no more than 30 GPS points !" + +#: AperoDeDenis.py:4608 +msgid "Aucun point à supprimer !" +msgstr "No points to delete!" + +#: AperoDeDenis.py:4616 +msgid "Points à supprimer" +msgstr "Points to delete" + +#: AperoDeDenis.py:4618 AperoDeDenis.py:7846 +msgid "Multiselection possible." +msgstr "Multi selection available." + +#: AperoDeDenis.py:4620 AperoDeDenis.py:7847 AperoDeDenis.py:7861 +#: AperoDeDenis.py:7870 AperoDeDenis.py:8712 AperoDeDenis.py:9668 +msgid "Annuler" +msgstr "Abort" + +#: AperoDeDenis.py:4702 +msgid "Choisir une photo pour placer les points GPS : " +msgstr "Choose a picture to place GPS points:" + +#: AperoDeDenis.py:4730 +#, fuzzy +#| msgid "Attention : des points portent le même nom : corriger !" +msgid "Impossible : des points portent le même nom : modifier ou supprimer !" +msgstr "Warning : several points have the same name : please correct it !" + +#: AperoDeDenis.py:4732 +msgid "Attention : un point n'a pas de nom. " +msgstr "Warning: a point does not have a name." + +#: AperoDeDenis.py:4734 +msgid "controle points : " +msgstr "Control points:" + +#: AperoDeDenis.py:4745 +msgid "Lancer d'abord tapioca/tapas" +msgstr "Launch Tapioca/Tapas first" + +#: AperoDeDenis.py:4745 +msgid "pour obtenir un nuage non densifié." +msgstr "to obtain a undensified point cloud." + +#: AperoDeDenis.py:4752 AperoDeDenis.py:4756 +msgid "Points GPS non conformes :" +msgstr "Improper GPS points: " + +#: AperoDeDenis.py:4759 +msgid "Patienter :" +msgstr "Please wait:" + +#: AperoDeDenis.py:4759 +msgid "le nuage est en cours de calibration" +msgstr "The point cloud is being calibrated." + +#: AperoDeDenis.py:4776 +msgid "Origine Ox" +msgstr "Ox start" + +#: AperoDeDenis.py:4776 +msgid "Extrémité Ox" +msgstr "Ox end" + +#: AperoDeDenis.py:4783 +msgid "Placer une ligne horizontale sur une seule photo : " +msgstr "Draw an horizontal line on a single picture:" + +#: AperoDeDenis.py:4808 +msgid "il faut placer les 2 points." +msgstr "You must place two points." + +#: AperoDeDenis.py:4824 +msgid "Placer une ligne verticale sur une seule photo : : " +msgstr "Draw a vertical line on a single picture:" + +#: AperoDeDenis.py:4835 +msgid "Origine Oy" +msgstr "Oy start" + +#: AperoDeDenis.py:4835 +msgid "Extrémité Oy" +msgstr "Oy end" + +#: AperoDeDenis.py:4849 +msgid "il faut placer exactement 2 points." +msgstr "You must place two points." + +#: AperoDeDenis.py:4861 AperoDeDenis.py:4892 +msgid "Plan vertical" +msgstr "Vertical plane" + +#: AperoDeDenis.py:4863 AperoDeDenis.py:4894 +msgid "Plan horizontal" +msgstr "Horizontal plane" + +#: AperoDeDenis.py:4866 +msgid "Une photo pour placer le plan vertical : " +msgstr "A picture to draw the vertical plane." + +#: AperoDeDenis.py:4884 +msgid "Délimiter un plan vertical" +msgstr "Determine a vertical plane." + +#: AperoDeDenis.py:4897 +msgid "Une photo pour placer le plan horizontal : " +msgstr "A picture to place the horizontal plane:" + +#: AperoDeDenis.py:4915 +msgid "Délimiter un plan horizontal" +msgstr "Delimit an horizontal plane" + +#: AperoDeDenis.py:4925 +msgid "Choisir deux fois une photo pour placer les 2 points : " +msgstr "Chose two times a picture to place both points:" + +#: AperoDeDenis.py:4941 +msgid "" +"Il y a dèjà 2 images avec des points 'distance'. Supprimer les points sur " +"une des 2 images." +msgstr "" +"Two pictures already have the \"distance\" points. Please remove points from " +"one of the two pictures." + +#: AperoDeDenis.py:4958 +#, python-format +msgid "Le chantier %(chant)s est terminé après %(densif)s" +msgstr "Project %(chant)s has ended after %(densif)s" + +#: AperoDeDenis.py:4959 +msgid "Vous pouvez modifier les options puis relancer MicMac." +msgstr "You can edit options and then relaunch MicMac." + +#: AperoDeDenis.py:4978 +msgid "Options incorrectes : corriger" +msgstr "Wrong options: please correct it." + +#: AperoDeDenis.py:4984 +msgid "Avec 2 photos MicMac construira difficilement un nuage de point dense." +msgstr "" +"With two pictures, MicMac will build a densified point cloud with difficulty." + +#: AperoDeDenis.py:4984 +msgid "Utiliser l'échelle -1 dans Tapioca pour obtenir un nuage optimal." +msgstr "Use scale -1 in Tapioca to obtain an optimal cloud." + +#: AperoDeDenis.py:4985 +msgid "Avertissement : 2 photos seulement" +msgstr "Warning: only two pictures" + +#: AperoDeDenis.py:4987 AperoDeDenis.py:5036 AperoDeDenis.py:5056 +#: AperoDeDenis.py:5066 AperoDeDenis.py:5076 +msgid "Continuer" +msgstr "Continue" + +#: AperoDeDenis.py:4997 +#, fuzzy +#| msgid "" +#| "Toutes les photos\n" +#| "sans les %s photos pour calibration intrinseque" +msgid "" +"Nombre de photos insuffisant après retrait des photos pour la calibration : " +msgstr "" +"All pictures \n" +"without %s pictures for intrinsic calibration." + +#: AperoDeDenis.py:5004 +#, fuzzy +#| msgid "Une seule photo pour la calibration intrinsèque : insuffisant." +msgid "" +"Une seule photo pour la calibration intrinsèque de l'appareil photo. C'est " +"insuffisant.\n" +msgstr "Only one picture for intrinsic calibration: insufficient." + +#: AperoDeDenis.py:5005 +#, fuzzy +#| msgid " N'utiliser ces photos que pour la calibration" +msgid "Modifier la liste des photos pour calibration." +msgstr "Use these picture for the calibration only" + +#: AperoDeDenis.py:5022 +#, fuzzy +#| msgid "Une seule photo pour la calibration intrinsèque : insuffisant." +msgid "Une seule photo pour la calibration de l'appareil " +msgstr "Only one picture for intrinsic calibration: insufficient." + +#: AperoDeDenis.py:5022 AperoDeDenis.py:5024 +msgid " c'est insuffisant.\n" +msgstr "" + +#: AperoDeDenis.py:5024 +#, fuzzy +#| msgid "Pas de photos pour la calibration intrinsèque par Tapas." +msgid "Aucune photo pour la calibration de l'appareil " +msgstr "No pictures for intrinsic calibration by Tapas." + +#: AperoDeDenis.py:5026 +#, fuzzy +#| msgid " N'utiliser ces photos que pour la calibration" +msgid "" +"\n" +"\n" +" Modifier la liste des photos pour calibration." +msgstr "Use these picture for the calibration only" + +#: AperoDeDenis.py:5027 +msgid "" +"\n" +"\n" +" Le menu 'expert/liste des appareils' fournit le nom de l'appareil pour " +"chaque photo." +msgstr "" + +#: AperoDeDenis.py:5032 +#, fuzzy +#| msgid "Choisir quelques photos pour la calibration intrinsèques" +msgid "Aucune photo pour la calibration intrinsèque des " +msgstr "Choose some pictures for the intrinsic calibration" + +#: AperoDeDenis.py:5032 +#, fuzzy +#| msgid "Appareil photo :" +msgid " appareils photos." +msgstr "Camera:" + +#: AperoDeDenis.py:5033 +#, fuzzy +#| msgid " puis relancer le traitement." +msgid "" +"\n" +"Cela peut rendre difficile les traitements." +msgstr " then relaunch the process." + +#: AperoDeDenis.py:5034 +#, fuzzy +#| msgid "- Choix de photos pour la calibration intrinsèque par Tapas." +msgid "" +"\n" +"\n" +"Conseil : prendre 2 photos pour la calibration de chaque appareil." +msgstr "- Pictures selection for intrinsic calibration by Tapas." + +#: AperoDeDenis.py:5036 AperoDeDenis.py:5056 AperoDeDenis.py:5076 +msgid "Avertissement" +msgstr "Warning" + +#: AperoDeDenis.py:5048 +msgid "" +"Controle des photos en cours....\n" +"Patienter jusqu'à la fin du controle." +msgstr "" +"Pictures control... \n" +"Please wait until the end." + +#: AperoDeDenis.py:5053 +msgid "Les dimensions des photos ne sont pas toutes identiques." +msgstr "The dimensions of the pictures are not all the same." + +#: AperoDeDenis.py:5054 +msgid "Le traitement par MicMac est incertain." +msgstr "MicMac processing is uncertain." + +#: AperoDeDenis.py:5062 +msgid "Absence de focales" +msgstr "Focal length not found." + +#: AperoDeDenis.py:5063 +msgid "Certaines photos n'ont pas de focales." +msgstr "Some pictures does not have focal length." + +#: AperoDeDenis.py:5064 +msgid "Le traitement echouera probablement." +msgstr "Processing will probably fail." + +#: AperoDeDenis.py:5065 +msgid "Mettre à jour les exifs (menu Outils)" +msgstr "Update exifs (Tools menu)" + +#: AperoDeDenis.py:5074 +msgid "Les focales des photos ne sont pas toutes identiques." +msgstr "Pictures focal length are not all the same." + +#: AperoDeDenis.py:5075 +#, fuzzy +#| msgid "" +#| "Le traitement par MicMac est possible en utilisant une focale pour la " +#| "calibration intrinsèque de Tapas." +msgid "" +"Le traitement par MicMac est préférable en utilisant une focale pour la " +"calibration intrinsèque." +msgstr "" +"MicMac processing is likely by using a focal length for Tapas intrinsic " +"calibration." + +#: AperoDeDenis.py:5082 +msgid "Pas assez de photos pour le traitement : il en faut au moins 2." +msgstr "No enought pictures to process: you need at least 2." + +#: AperoDeDenis.py:5089 +#, fuzzy, python-format +#| msgid "Le chantier %s a été interrompu en cours d'exécution." +msgid "Le chantier %s a été interrompu lors de Tapioca/Tapas." +msgstr "Project %s has ben interrupted because of an execution." + +#: AperoDeDenis.py:5104 +#, fuzzy, python-format +#| msgid "Le chantier %s a été interrompu en cours d'exécution." +msgid "Le chantier %s a été interrompu en cours densification." +msgstr "Project %s has ben interrupted because of an execution." + +#: AperoDeDenis.py:5105 +#, fuzzy +#| msgid "Le chantier %s a été interrompu en cours d'exécution." +msgid "Le chantier est interrompu en cours de densification." +msgstr "Project %s has ben interrupted because of an execution." + +#: AperoDeDenis.py:5106 +#, fuzzy +#| msgid "ce qui permettra de modifier les options et de le relancer." +msgid "" +"ce qui permettra de modifier les options et de le relancer la densification." +msgstr "which will allow to edit options and relaunch it." + +#: AperoDeDenis.py:5122 +#, python-format +msgid "Continuer le chantier %s après tapas ?" +msgstr "Continue the project %s after Tapas?" + +#: AperoDeDenis.py:5123 +msgid "Le chantier est arrêté après tapas. Vous pouvez :" +msgstr "The project is stopped after Tapas. You could:" + +#: AperoDeDenis.py:5124 +msgid " - lancer la densification" +msgstr "" + +#: AperoDeDenis.py:5125 +msgid " - débloquer le chantier pour modifier les paramètres de Tapioca/tapas" +msgstr " - Unblock the project to change Tapioca/Tapas settings" + +#: AperoDeDenis.py:5126 +msgid " - ne rien faire" +msgstr " - Do nothibg" + +#: AperoDeDenis.py:5127 +msgid "Lancer la densification " +msgstr "" + +#: AperoDeDenis.py:5128 +msgid "Débloquer le chantier - garder les résultats" +msgstr "Unblock project - keep the results." + +#: AperoDeDenis.py:5131 +msgid "abandon de Malt" +msgstr "Aborting Malt..." + +#: AperoDeDenis.py:5135 +#, fuzzy, python-format +#| msgid "" +#| " Reprise du chantier %s arrêté aprés TAPAS - La trace depuis l'origine " +#| "sera disponible dans le menu édition." +msgid "" +" Reprise du chantier %s arrêté après TAPAS - La trace depuis l'origine sera " +"disponible dans le menu édition." +msgstr "" +"Restarting project %s stopped after TAPAS - Log available in the Edit menu." + +#: AperoDeDenis.py:5204 AperoDeDenis.py:5213 AperoDeDenis.py:5227 +msgid "Pourquoi MicMac s'arrête : " +msgstr "Why is MicMac stopping: " + +#: AperoDeDenis.py:5213 +msgid "Aucun point en correspondance sur 2 images n'a été trouvé par Tapioca." +msgstr "No corresponding points on two pictures were found by Tapioca." + +#: AperoDeDenis.py:5214 +msgid "Parmi les raisons de cet échec il peut y avoir :" +msgstr "Among the causes of this failure, there can be:" + +#: AperoDeDenis.py:5215 +msgid "" +"soit l'exif des photos ne comporte pas la focale ou plusieurs focales sont " +"présentes" +msgstr "" +"Whether the exif of the pictures does not include focal length or include " +"several focal length" + +#: AperoDeDenis.py:5216 +msgid "Soit l'appareil photo est inconnu de Micmac" +msgstr "Whether the camera is unknown from MicMac" + +#: AperoDeDenis.py:5217 +msgid "soit la qualité des photos est en cause." +msgstr "Or else, the quality of the pictures is at fault" + +#: AperoDeDenis.py:5218 +msgid "" +"soit la trace compléte contient : 'Error: -- Input line too long, increase " +"MAXLINELENGTH' ." +msgstr "" + +#: AperoDeDenis.py:5219 +msgid "" +"alors tenter, sans certitude, de modifier le fichier /binaire-aux/windows/" +"startup/local.mk" +msgstr "" + +#: AperoDeDenis.py:5220 +msgid "Utiliser les items du menu 'outils' pour vérifier ces points." +msgstr "Use items from the \"Tools\" menu to check these points." + +#: AperoDeDenis.py:5227 +msgid "Les photos définissent plusieurs scènes disjointes" +msgstr "" + +#: AperoDeDenis.py:5228 AperoDeDenis.py:8796 +msgid "" +"MicMac ne peut travailler que sur une seule scène : toutes les photos " +"doivent former une seule scéne." +msgstr "" + +#: AperoDeDenis.py:5229 AperoDeDenis.py:8797 +msgid "Les photos se répartissent en :" +msgstr "" + +#: AperoDeDenis.py:5229 AperoDeDenis.py:8797 +msgid " groupes distincts (consulter la trace) : " +msgstr "" + +#: AperoDeDenis.py:5232 AperoDeDenis.py:8799 +msgid "Les groupes de photos séparés : " +msgstr "" + +#: AperoDeDenis.py:5243 +msgid "Pourquoi MicMac s'arrête :" +msgstr "Why is MicMac stopping:" + +#: AperoDeDenis.py:5243 +msgid "consulter la trace." +msgstr "see the log." + +#: AperoDeDenis.py:5257 +msgid "Calibration incomplète : " +msgstr "Incomplete calibration:" + +#: AperoDeDenis.py:5287 +msgid "Arrêt après Tapas " +msgstr "Stop after Tapas" + +#: AperoDeDenis.py:5287 +msgid ". Lancer MicMac pour reprendre le traitement." +msgstr ". Launch MicMac to resume processing." + +#: AperoDeDenis.py:5288 +#, fuzzy +#| msgid "Arrêt aprés Tapas sur demande utilisateur" +msgid "Arrêt après Tapas sur demande utilisateur" +msgstr "Stop after Tapas by user request" + +#: AperoDeDenis.py:5301 +msgid "Tapas n'a pas généré de nuage de points." +msgstr "Tapas didn't generate a point cloud" + +#: AperoDeDenis.py:5302 AperoDeDenis.py:5311 +msgid "Le traitement ne peut se poursuivre." +msgstr "The process cannot continue." + +#: AperoDeDenis.py:5303 +#, fuzzy +#| msgid "Consulter l'aide (quelques conseils)," +msgid "Consulter l'aide/quelques conseils." +msgstr "See Help (advices), " + +#: AperoDeDenis.py:5304 +msgid "" +"Vérifier la qualité des photos, modifier les paramètres et relancer tapioca-" +"tapas" +msgstr "" +"Check the quality of the pictures, change settings and relaunch Tapioca-" +"Tapas." + +#: AperoDeDenis.py:5310 +#, fuzzy +#| msgid "Pas de masque 3D, ou d'image maîtresse pour Malt." +msgid "Pas d'image maîtresse pour Malt option geoimage." +msgstr "No 3D mask, or master image for Malt." + +#: AperoDeDenis.py:5312 +msgid "Définir une image maîtresse" +msgstr "Define a master picture" + +#: AperoDeDenis.py:5313 +msgid "ou Changer le mode 'GeomImage' qui impose une image maîtresse" +msgstr "or change GeomImage mode which impose a master picture." + +#: AperoDeDenis.py:5333 +msgid "Le fichier modele3D.ply précédent est renommé en " +msgstr "modele3D.ply file renamed into" + +#: AperoDeDenis.py:5335 +msgid "erreur renommage ancien modele_3d en " +msgstr "Error renaming ancient modele_3D into" + +#: AperoDeDenis.py:5336 +msgid "" +"Le fichier Modele3D.ply précédent n'a pu être renommé. Il sera remplacé." +msgstr "Previous Modele3D.ply file couldn't be renamed. It will be replaced." + +#: AperoDeDenis.py:5352 +#, fuzzy +#| msgid "Pas de nuage de points aprés Malt ou C3DC." +msgid "Pas de nuage de points après Malt ou C3DC." +msgstr "No point cloud after Malt or C3DC." + +#: AperoDeDenis.py:5358 +msgid "Fin du traitement MicMac " +msgstr "End of MicMac processing" + +#: AperoDeDenis.py:5369 +msgid "Tapas non effectué, lancer Micmac depuis le menu. Etat du chantier = " +msgstr "Tapas not performed, launch MicMac from the menu. Project progress = " + +#: AperoDeDenis.py:5375 +msgid "Pourquoi MicMac est arrêté :" +msgstr "Why is MicMac stopping:" + +#: AperoDeDenis.py:5376 +msgid "Pas d'image maîtresse." +msgstr "No master picture." + +#: AperoDeDenis.py:5377 +msgid "Celle-ci est nécessaire pour l'option choisie geomImage de Malt." +msgstr "It is required for the Malt's GeomImage choosen option." + +#: AperoDeDenis.py:5378 +msgid "" +"Pour corriger modifier les options de Malt ou choississez un masque 3D avec " +"C3DC." +msgstr "Please edit Malt options or choose a 3D mask with C3DC" + +#: AperoDeDenis.py:5379 +msgid "Corriger." +msgstr "Correct." + +#: AperoDeDenis.py:5394 +msgid "Erreur copie modele3D.ply" +msgstr "Error copying modele3D.ply" + +#: AperoDeDenis.py:5415 +msgid "erreur malt GeomImage copy de nuage en modele3D : " +msgstr "Error Malt GeomImage copy of point cloud in modele3D: " + +#: AperoDeDenis.py:5415 AperoDeDenis.py:5418 AperoDeDenis.py:5437 +#: AperoDeDenis.py:5440 +msgid " pour : " +msgstr " for:" + +#: AperoDeDenis.py:5418 +msgid "erreur malt GeomImage fusion des nuages en modele3D : " +msgstr "error Malt GeomImage merging point cloud in modele 3D" + +#: AperoDeDenis.py:5437 +msgid "erreur malt AperoDeDenis copy de nuage en modele3D : " +msgstr "Malt error AperoDeDenis copy of cloud in model3D:" + +#: AperoDeDenis.py:5440 +msgid "erreur malt AperoDeDenis fusion des nuages en modele3D : " +msgstr "Error malt AperoDeDenis cloud merging in 3D model:" + +#: AperoDeDenis.py:5453 +msgid "Aucune photo choisie. Abandon." +msgstr "No choosent picture. Aborting." + +#: AperoDeDenis.py:5457 +msgid "Une seule photo choisie. Abandon." +msgstr "Only one choosen picture. Aborted." + +#: AperoDeDenis.py:5463 +msgid "TRACE DETAILLEE" +msgstr "DETAILED LOG" + +#: AperoDeDenis.py:5464 +msgid "TRACE SYNTHETIQUE" +msgstr "SYNTHETHIC LOG" + +#: AperoDeDenis.py:5466 +msgid "DEBUT DU TRAITEMENT MICMAC à " +msgstr "START OF MICMAC PROCESSING at" + +#: AperoDeDenis.py:5469 +msgid "Photos choisies :" +msgstr "Choosen pictures:" + +#: AperoDeDenis.py:5470 +msgid "Ces photos sont recopiées dans le répertoire du chantier :" +msgstr "Those pictures are copied in the project directory:" + +#: AperoDeDenis.py:5526 AperoDeDenis.py:5532 +#, python-format +msgid "" +"Recherche des points remarquables et des correspondances sur une image de " +"taille %s pixels." +msgstr "" +"Searching for tie-points and correspondences on a picture of %s pixels." + +#: AperoDeDenis.py:5530 +msgid "" +"Recherche des points remarquables et des correspondances sur l'image entière." +msgstr "" +"Searching for remarkable points and correspodences on the whole picture." + +#: AperoDeDenis.py:5535 +msgid "Trop de photos pour Windows. Une idée : Utiliser Linux." +msgstr "" + +#: AperoDeDenis.py:5544 +#, fuzzy +#| msgid "Une seule photo pour la calibration intrinsèque : insuffisant." +msgid "" +"Une seule photo pour un appareil pour la calibration intrinsèque : " +"insuffisant." +msgstr "Only one picture for intrinsic calibration: insufficient." + +#: AperoDeDenis.py:5561 +msgid "" +"Calibration intrinsèque, pour trouver les réglages de l'appareil photo sur " +"quelques photos" +msgstr "Intrinsic calibration, to find camera settings on some pictures." + +#: AperoDeDenis.py:5562 +#, fuzzy +#| msgid "Caractéristiques de l'appareil photo : " +msgid "Recherche des paramètres optiques des appareils sur les photos :\n" +msgstr "Camera characteristics:" + +#: AperoDeDenis.py:5571 +msgid "La calibration intrinsèque n'a pas permis de trouver une orientation." +msgstr "The intrinsic calibration couldn't find an orientation." + +#: AperoDeDenis.py:5573 +#, fuzzy +#| msgid "Calibration intrinsèque effectuée." +msgid "Calibration intrinsèque effectuée mais pas d'orientation trouvée." +msgstr "Intrinsic calibration done." + +#: AperoDeDenis.py:5577 +#, fuzzy +#| msgid "" +#| "Une seule photo pour Tapas sans les photos de calibration : insuffisant." +msgid "" +"Moins de 2 photos pour Tapas (sans les photos de calibration) : insuffisant." +msgstr "Only one picture for Tapas without calibration pictures: insufficient." + +#: AperoDeDenis.py:5581 +msgid "Calibration intrinsèque effectuée." +msgstr "Intrinsic calibration done." + +#: AperoDeDenis.py:5594 +#, fuzzy +#| msgid "Pour calibrer l'appareil photo" +msgid "Photos retenues pour calibrer les appareils :" +msgstr "To calibrate the camera" + +#: AperoDeDenis.py:5609 +msgid "Recherche l'orientation des prises de vues" +msgstr "Searching for shooting orientation" + +#: AperoDeDenis.py:5624 +msgid "Calibration, pour trouver les réglages intrinsèques de l'appareil photo" +msgstr "Calibration, to find intrinsic settings of the camera" + +#: AperoDeDenis.py:5624 +msgid "Recherche l'orientation des prises de vue." +msgstr "Searching for shooting orientation." + +#: AperoDeDenis.py:5627 +#, fuzzy +#| msgid "Recherche l'orientation des prises de vue." +msgid "Tapas n'a pu trouver d'orientation pour les prises de vue." +msgstr "Searching for shooting orientation." + +#: AperoDeDenis.py:5653 +msgid "" +"Fixe l'orientation (axe,plan et métrique) suivant les options de " +"'calibration'" +msgstr "" +"Set orientation (axis, plane and metric) following calibration options." + +#: AperoDeDenis.py:5672 +msgid "Positionne les appareils photos autour du sujet." +msgstr "Set cameras around the subject." + +#: AperoDeDenis.py:5672 +msgid "Création d'un nuage de points grossier." +msgstr "Creating rough point cloud." + +#: AperoDeDenis.py:5678 +msgid "ligne avec meta : " +msgstr "Line with meta:" + +#: AperoDeDenis.py:5679 +msgid "" +"ATTENTION : des metadonnées nécessaires sont absentes des photos. Vérifier " +"l'exif." +msgstr "" +"Warning : some required metadatas not found in the pictures. Check the exif." + +#: AperoDeDenis.py:5690 +msgid "Ouverture du nuage de points après Apericloud" +msgstr "Opening point cloud after AperiCloud" + +#: AperoDeDenis.py:5693 +msgid "Pas de fichier AperiCloud.ply généré." +msgstr "No AperiCloud.ply file generated." + +#: AperoDeDenis.py:5695 +msgid "" +"Consulter l'aide (quelques conseils),\n" +"Consulter la trace." +msgstr "" +"See Help (Advices),\n" +"See the log." + +#: AperoDeDenis.py:5701 +#, fuzzy +#| msgid "Tarama : mosaïque des photos d'aprés les tie points" +msgid "Tarama : mosaïque des photos d'après les tie points" +msgstr "Tarama: mosaic of the photos after the tie points" + +#: AperoDeDenis.py:5712 +msgid "" +"Prise en compte des points GPS : nécessite au minimum 3 points, chacun sur 2 " +"photos" +msgstr "" +"Consideration GPS points: there must be a minimum of three points, each " +"point on at least two pictures" + +#: AperoDeDenis.py:5714 +msgid "" +"Le nombre minimum de points placés sur les photos n'est pas atteint. Abandon." +msgstr "Minimum number of points on pictures not reached. Aborting." + +#: AperoDeDenis.py:5742 +msgid "Campari non lancé : paramètres incorrects : " +msgstr "" + +#: AperoDeDenis.py:5748 +msgid "Campari non lancé : pas d'orientation 'bascul'" +msgstr "" + +#: AperoDeDenis.py:5751 +msgid "Campari : correction points GPS" +msgstr "" + +#: AperoDeDenis.py:5772 +msgid "Préparation du lancement de Malt" +msgstr "Preparing Malt's launch." + +#: AperoDeDenis.py:5780 +msgid "Photos utiles pour malt GeomImage : " +msgstr "Photos useful for malt GeomImage:" + +#: AperoDeDenis.py:5782 +msgid "Malt sur toutes les photos" +msgstr "Malt on all photos" + +#: AperoDeDenis.py:5794 +msgid "Photos utiles pour malt AperoDeDenis : " +msgstr "Useful photos for malt AperoDeDenis:" + +#: AperoDeDenis.py:5805 +msgid "Mosaique et masque: " +msgstr "Mosaic and mask:" + +#: AperoDeDenis.py:5807 +msgid "Mosaique seule : " +msgstr "Mosaic alone:" + +#: AperoDeDenis.py:5828 AperoDeDenis.py:5991 AperoDeDenis.py:8499 +msgid "ATTENTION : cette procédure est longue : patience !" +msgstr "Warning: this process can be long." + +#: AperoDeDenis.py:5959 +msgid "lance Tawny" +msgstr "Launch Tawny" + +#: AperoDeDenis.py:5965 +msgid " : voir la trace complète." +msgstr " : see complete log." + +#: AperoDeDenis.py:6095 +#, python-format +msgid "Pas de fichier %s généré." +msgstr "No %s file generated." + +#: AperoDeDenis.py:6095 +msgid "Echec du traitement MICMAC" +msgstr "MicMac process failed. " + +#: AperoDeDenis.py:6103 +#, python-format +msgid "Nuage de points %s généré." +msgstr "Point cloud %s generated." + +#: AperoDeDenis.py:6133 +msgid "Détermine un indice de qualité des photos en mode 'line'" +msgstr "Set a quality level on pictures in 'line' mode" + +#: AperoDeDenis.py:6134 AperoDeDenis.py:6165 +msgid "Le résultat sera inscrit dans le fichier trace synthétique" +msgstr "The result will be written in the synthetic log file. " + +#: AperoDeDenis.py:6134 AperoDeDenis.py:6165 AperoDeDenis.py:6241 +#: AperoDeDenis.py:6354 AperoDeDenis.py:6600 +msgid "Patience..." +msgstr "Please wait..." + +#: AperoDeDenis.py:6136 +msgid "Debut de la recherche sur la qualité des photos mode 'Line'." +msgstr "Starting search on quality of the pictures in 'Line' mode." + +#: AperoDeDenis.py:6164 +msgid "Détermine un indice de qualité des photos en mode 'All' ou 'MulScale'" +msgstr "Set a quality level on pictures in 'All' or 'MulScale' mode" + +#: AperoDeDenis.py:6167 +msgid "" +"Debut de la recherche sur la qualité des photos, mode 'All' ou 'MulScale'." +msgstr "" +"Starting search on the quality of the pictures in 'All' or 'MulScale' mode." + +#: AperoDeDenis.py:6215 AperoDeDenis.py:8853 +msgid "Classement des photos par nombre de points homologues :" +msgstr "Pictures ranking by number of tie-points:" + +#: AperoDeDenis.py:6217 +msgid "photo " +msgstr "picture" + +#: AperoDeDenis.py:6217 +msgid " score = " +msgstr " score =" + +#: AperoDeDenis.py:6220 AperoDeDenis.py:8860 +msgid "Aucune photo n'a de point analogue avec une autre." +msgstr "No analagous points found between any pictures." + +#: AperoDeDenis.py:6224 +msgid "Qualité des photos suite au traitement : " +msgstr "Quality of the pictures after processing:" + +#: AperoDeDenis.py:6225 AperoDeDenis.py:8766 AperoDeDenis.py:8771 +#: AperoDeDenis.py:8779 +msgid "Homol" +msgstr "Homol" + +#: AperoDeDenis.py:6237 +msgid "Fin d'examen de qualité des photos." +msgstr "End of quality pictures examination." + +#: AperoDeDenis.py:6241 +msgid "Copie des photos dans un répertoire de test." +msgstr "Copying pictures in a test directory." + +#: AperoDeDenis.py:6266 +msgid "Créer un nouveau chantier avec les photos : " +msgstr "Create a new project with this pictures :" + +#: AperoDeDenis.py:6267 +msgid "Les paramètres de Tapioca/Malt seront optimisés." +msgstr "The parameters of Tapioca and Malt will be optimized." + +#: AperoDeDenis.py:6358 +msgid "Caractéristiques de l'appareil photo : " +msgstr "Camera characteristics:" + +#: AperoDeDenis.py:6361 +msgid "fabricant : " +msgstr "Manufacturer:" + +#: AperoDeDenis.py:6365 +msgid "Nom de l'appareil photo inacessible." +msgstr "Camera name unreachable." + +#: AperoDeDenis.py:6367 +msgid "Nom de l'appareil photo : " +msgstr "Camera name:" + +#: AperoDeDenis.py:6371 +#, fuzzy +#| msgid "Nom de l'appareil photo : " +msgid "Numéro de série de l'appareil photo : " +msgstr "Camera name:" + +#: AperoDeDenis.py:6377 +msgid "Pas de focale dans l'exif." +msgstr "No focal length in exif:" + +#: AperoDeDenis.py:6379 +msgid "Focale : " +msgstr "Focal length:" + +#: AperoDeDenis.py:6382 +msgid "Pas de focale équivalente 35 mm dans l'exif :" +msgstr "No equivalent focal length 35mm in the exif:" + +#: AperoDeDenis.py:6382 +msgid "Présence de la taille du capteur dans DicoCamera nécesssaire." +msgstr "The size of the sensor is required in DicoCamera." + +#: AperoDeDenis.py:6385 +msgid "Focale équivalente 35 mm absente de l'exif" +msgstr "No equivalent focal length 35mm in the exif:" + +#: AperoDeDenis.py:6387 +msgid "Focale équivalente 35 mm : " +msgstr "Equivalent focal length 35mm" + +#: AperoDeDenis.py:6390 AperoDeDenis.py:6507 +msgid "" +"DicoCamera.xml non trouvé : paramètrer au préalable le chemin de MicMac\\bin." +msgstr "DicoCamera.xml not found: please link the MicMac\\bin path." + +#: AperoDeDenis.py:6394 +msgid "L'appareil est inconnu dans DicoCamera.XML." +msgstr "The camera is not known by DicoCamera.xml" + +#: AperoDeDenis.py:6396 +msgid "L'appareil est connu dans DicoCamera.XML." +msgstr "The camera is known by DicoCamera.xml" + +#: AperoDeDenis.py:6397 +msgid "Taille du capteur en mm : " +msgstr "Sensor size in mm:" + +#: AperoDeDenis.py:6410 +msgid "Appareil photo :" +msgstr "Camera:" + +#: AperoDeDenis.py:6417 +msgid "" +"Attention : les photos proviennent de plusieurs appareils différents.\n" +" Voir l'item 'toutes les focales...' et le menu expert." +msgstr "" + +#: AperoDeDenis.py:6440 +msgid "Erreur dans exiftool : " +msgstr "Exiftool error:" + +#: AperoDeDenis.py:6442 +msgid "erreur tagExif : " +msgstr "TagExif error:" + +#: AperoDeDenis.py:6517 +#, fuzzy +#| msgid "Pas trouvé de nom d'appareil photo dans l'exif." +msgid "\\Pas de nom d'appareil photo dans l'exif" +msgstr "The name of the camera was not found in the exif." + +#: AperoDeDenis.py:6521 AperoDeDenis.py:6564 +#, fuzzy +#| msgid "" +#| "Le fichier DicoCamera.xml contient la taille du capteur pour l'appareil :" +msgid "" +"\n" +"Le fichier DicoCamera.xml contient déjà la taille du capteur pour " +"l'appareil :" +msgstr "The file DicoCamera.xml contains the size of the sensors:" + +#: AperoDeDenis.py:6522 AperoDeDenis.py:6565 +msgid "taille = " +msgstr "size =" + +#: AperoDeDenis.py:6522 AperoDeDenis.py:6565 +#, fuzzy +#| msgid "Multiselection possible." +msgid "Pas de modification possible." +msgstr "Multi selection available." + +#: AperoDeDenis.py:6527 +msgid "Pour l'appareil " +msgstr "For the camera" + +#: AperoDeDenis.py:6533 +#, fuzzy +#| msgid "Choisir le nom de l'archive à importer." +msgid "Choisir le ou les appareils à mettre à jour" +msgstr "Choose the name of the archive to import." + +#: AperoDeDenis.py:6534 +#, fuzzy +#| msgid "Liste des nuages de points du chantier" +msgid "Liste des appareils du chantier : \n" +msgstr "Project's point clouds list" + +#: AperoDeDenis.py:6540 +#, fuzzy +#| msgid "Pour l'appareil " +msgid "Pour les appareils choisis :\n" +msgstr "For the camera" + +#: AperoDeDenis.py:6548 +msgid "Paramètrer au préalable le chemin de MicMac\\bin." +msgstr "Please set MicMac\\bin path beforehand." + +#: AperoDeDenis.py:6567 +msgid "NomCourt" +msgstr "ShortName" + +#: AperoDeDenis.py:6569 +msgid "tailleEnMM" +msgstr "SizeInMM" + +#: AperoDeDenis.py:6576 +#, fuzzy +#| msgid "" +#| "Le fichier DicoCamera.xml contient la taille du capteur pour l'appareil :" +msgid "Fichier DicoCamera.xml invalide : balise de fin manquante : " +msgstr "The file DicoCamera.xml contains the size of the sensors:" + +#: AperoDeDenis.py:6587 +msgid "Erreur lors de l'écriture de DicoCamera.xml" +msgstr "Error writing in DicoCamera.xml" + +#: AperoDeDenis.py:6587 +#, fuzzy +#| msgid "Une sauvegarde a été créée : DicoCamerra.xml.sav" +msgid "Une sauvegarde a été créée : DicoCamera.xml.sav" +msgstr "Save have been created: DicoCamera.xml.sav" + +#: AperoDeDenis.py:6590 AperoDeDenis.py:6597 +msgid "Dimensions du capteur non mis à jour" +msgstr "The dimensions of the sensors were not updated." + +#: AperoDeDenis.py:6593 +#, fuzzy +#| msgid "Mettre à jour DicoCamera.xml" +msgid "Mise à jour de dicocamera.xml : " +msgstr "Update DicoCamera.xml" + +#: AperoDeDenis.py:6603 +msgid "" +"Les focales, les focales équivalentes en 35mm et le nom des appareils " +"photos :" +msgstr "" + +#: AperoDeDenis.py:6618 +#, fuzzy +#| msgid "Saisir une ou plusieurs ligne(s) de commande" +msgid "" +"Ceci est une console système : Saisir une ou plusieurs ligne(s) de commande" +msgstr "Enter one or more command line (s)" + +#: AperoDeDenis.py:6620 AperoDeDenis.py:6650 +msgid "Attention : Le chantier n'existe pas." +msgstr "Warning : no project." + +#: AperoDeDenis.py:6623 +msgid "" +"Entrer soit une commande MicMac, par exemple : mm3d GCPBascule .*.JPG " +"Arbitrary" +msgstr "" +"Enter either a MicMac command, for example: mm3d GCPBascule. * .JPG Arbitrary" + +#: AperoDeDenis.py:6624 +msgid "" +"soit une commande du système, par exemple sous windows : del /S /Q Tmp-MM-Dir" +msgstr "" +"Either a system command, for example under windows: del / S / Q Tmp-MM-Dir" + +#: AperoDeDenis.py:6625 +msgid "ou une commande mm3d interactive comme : mm3d vC3DC" +msgstr "" + +#: AperoDeDenis.py:6626 +msgid "Possibilité de copier une commande du fichier mm3d-LogFile.txt." +msgstr "" + +#: AperoDeDenis.py:6627 AperoDeDenis.py:6656 +#, fuzzy +#| msgid "Sous votre responsabilité" +msgid "Le tout sous votre responsabilité" +msgstr "Under your responsibility" + +#: AperoDeDenis.py:6648 +#, fuzzy +#| msgid "Saisir une ou plusieurs ligne(s) de commande" +msgid "" +"Ceci est une console python : Saisir une ou plusieurs ligne(s) de script " +"python" +msgstr "Enter one or more command line (s)" + +#: AperoDeDenis.py:6653 +#, fuzzy +#| msgid "" +#| "Entrer soit une commande MicMac, par exemple : mm3d GCPBascule .*.JPG " +#| "Arbitrary" +msgid "Entrer soit une commande python, par exemple : locals()" +msgstr "" +"Enter either a MicMac command, for example: mm3d GCPBascule. * .JPG Arbitrary" + +#: AperoDeDenis.py:6654 +msgid "" +"la commande sera éxécutée puis évaluée et les résultats affichés dans une " +"fenetre" +msgstr "" + +#: AperoDeDenis.py:6655 +#, fuzzy +#| msgid "Le résultat sera inscrit dans le fichier trace synthétique" +msgid "et aussi dans la trace synthétique." +msgstr "The result will be written in the synthetic log file. " + +#: AperoDeDenis.py:6663 +#, fuzzy +#| msgid "résultat de la fusion de :" +msgid "résultat de la commande python : " +msgstr "Merged result from:" + +#: AperoDeDenis.py:6670 +#, fuzzy +#| msgid "Mode : " +msgid "commande : " +msgstr "Mod: " + +#: AperoDeDenis.py:6677 +msgid "" +"\n" +"L'exécution de la commande python retourne la valeur : " +msgstr "" + +#: AperoDeDenis.py:6680 +msgid "" +"\n" +"L'éxécution de la commande python ne retourne pas de valeur" +msgstr "" + +#: AperoDeDenis.py:6683 +msgid "" +"\n" +"L'évaluation de la commande python retourne la valeur : " +msgstr "" + +#: AperoDeDenis.py:6686 +msgid "" +"\n" +"L'évaluation de la commande python ne retourne pas de valeur" +msgstr "" + +#: AperoDeDenis.py:6696 +msgid "Choisir le chantier pour ajouter les points gps." +msgstr "Choose the project to add the gps points." + +#: AperoDeDenis.py:6718 +msgid "Erreur restauration points GPS : " +msgstr "Error restoring GPS points:" + +#: AperoDeDenis.py:6760 AperoDeDenis.py:6799 +#, fuzzy +#| msgid "%s points GPS placés" +msgid " points GPS ajoutés." +msgstr "%s GPS point placed" + +#: AperoDeDenis.py:6771 +msgid "" +"Liste de points GPS : Nom, X,Y,Z, dx,dy,dz (fichier texte séparteur " +"espace) : " +msgstr "" + +#: AperoDeDenis.py:6772 +msgid "Texte" +msgstr "" + +#: AperoDeDenis.py:6801 +msgid "" +" points GPS ajoutés : c'est beaucoup, sans doute trop (pb affichage options " +"GPS)" +msgstr "" + +#: AperoDeDenis.py:6806 +#, fuzzy +#| msgid "Pour calibrer l'appareil photo" +msgid "Plusieurs appareils photos" +msgstr "To calibrate the camera" + +#: AperoDeDenis.py:6807 +#, fuzzy +#| msgid "fournit les dimensions de tous les appareils photos." +msgid "Lorque les photos choisies proviennent de plusieurs appareils photos" +msgstr "Provides dimensions of all cameras." + +#: AperoDeDenis.py:6808 +msgid "les TAGS 'model' doivent être différenciés dans l'exif des photos." +msgstr "" + +#: AperoDeDenis.py:6809 +msgid "La calibration s'effectue alors pour chaque appareil." +msgstr "" + +#: AperoDeDenis.py:6810 +msgid "AperoDeDenis propose de modifier ces tags soit : " +msgstr "" + +#: AperoDeDenis.py:6811 +msgid "" +" - en y ajoutant le numéro de série de l'appareil (parfois présent dans " +"l'exif" +msgstr "" + +#: AperoDeDenis.py:6812 +msgid " - en y ajoutant le préfixe du nom du fichier de la photo" +msgstr "" + +#: AperoDeDenis.py:6813 +msgid " le préfixe = les 3 premiers caractères du nom de fichier." +msgstr "" + +#: AperoDeDenis.py:6815 +#, fuzzy +#| msgid "Modifier les options de Malt ou C3DC" +msgid "Modifier les tags 'model'" +msgstr "Edit Malt or C3DC options" + +#: AperoDeDenis.py:6819 +msgid "" +"La prise en compte de plusieurs appareils photos doit se faire après la " +"selection des photos" +msgstr "" + +#: AperoDeDenis.py:6820 +msgid "" +"et AVANT tout traitement.\n" +"Choisir des photos ou créer un nouveau chantier." +msgstr "" + +#: AperoDeDenis.py:6822 +msgid "" +"Recherche des modifications possibles du modèle d'appareil photo. Patience !." +msgstr "" + +#: AperoDeDenis.py:6826 +msgid "Les photos proviennent déjà de plusieurs appareils différents." +msgstr "" + +#: AperoDeDenis.py:6829 +#, fuzzy +#| msgid "Pas de distance définie pour ce chantier." +msgid "Pas de modification du chantier" +msgstr "No distance defined for this project." + +#: AperoDeDenis.py:6827 +#, fuzzy +#| msgid "Marque de l'appareil : " +msgid "Liste des appareils :\n" +msgstr "Brand of the camera" + +#: AperoDeDenis.py:6836 +msgid "" +"Modification du modèle de l'appareil photo en cours : ajout du numéro de " +"série." +msgstr "" + +#: AperoDeDenis.py:6837 AperoDeDenis.py:6845 +msgid "Attention : procédure longue si beaucoup de photos." +msgstr "" + +#: AperoDeDenis.py:6841 +msgid "" +"Fin :\n" +"Modéle de l'appareil photo modifié par ajout du numéro de série." +msgstr "" + +#: AperoDeDenis.py:6844 +msgid "" +"Modification du modèle de l'appareil photo en cours : ajout du préfixe du " +"nom de fichier." +msgstr "" + +#: AperoDeDenis.py:6849 +msgid "" +"Fin : \n" +"Modéle de l'appareil photo modifié : ajout du préfixe du nom de fichier sur " +"3 caractères." +msgstr "" + +#: AperoDeDenis.py:6851 +#, fuzzy +#| msgid "Nom de l'appareil photo inacessible." +msgid "Modéle de l'appareil photo non modifiable :" +msgstr "Camera name unreachable." + +#: AperoDeDenis.py:6851 +#, fuzzy +#| msgid "Pas de répertoire pour les photos" +msgid "pas de numéro de série multiple pour les appareils photos," +msgstr "No pictures directory" + +#: AperoDeDenis.py:6852 +msgid "pas de préfixe multiple pour les noms de fichiers." +msgstr "" + +#: AperoDeDenis.py:6857 +#, fuzzy +#| msgid "Pas trouvé de nom d'appareil photo dans l'exif." +msgid "Recherche des noms d'appareil photos. Patience !." +msgstr "The name of the camera was not found in the exif." + +#: AperoDeDenis.py:6859 +msgid "Les photos proviennent de " +msgstr "" + +#: AperoDeDenis.py:6859 +#, fuzzy +#| msgid "Appareil photo :" +msgid " appareils photos différents : " +msgstr "Camera:" + +#: AperoDeDenis.py:6860 +msgid "Les photos proviennent d'un seul appareil : " +msgstr "" + +#: AperoDeDenis.py:6861 +msgid "L'exif des photos ne contient pas le nom de l'appareil photo." +msgstr "" + +#: AperoDeDenis.py:6881 +#, fuzzy +#| msgid "Pas de trace de la trace !" +msgid "Pas de trace du log !" +msgstr "No log found !" + +#: AperoDeDenis.py:6890 +#, fuzzy +#| msgid "Interface graphique pour lancer les modules de MICMAC." +msgid "Interface graphique du CEREMA pour lancer les modules de MICMAC." +msgstr "Graphical User Interface to launch MICMAC modules." + +#: AperoDeDenis.py:6891 +msgid "Utilisable sous Linux, Windows, Mac OS." +msgstr "Available on Linux, Windows and Mac OS." + +#: AperoDeDenis.py:6892 +#, fuzzy +#| msgid "Logiciel libre diffusé sous licence CeCILL-B." +msgid "Logiciel libre et open source diffusé sous licence CeCILL-B." +msgstr "A free software licensed CeCILL-B." + +#: AperoDeDenis.py:6894 +msgid "" +"La barre de titre présente le nom du chantier et la version de l'outil. Une " +"* indique que le chantier est à sauvegarder." +msgstr "" +"The title bar shows the current project's name and AperoDeDenis current " +"version. A * in the title bar means that the project has been modified and " +"should be saved." + +#: AperoDeDenis.py:6895 +msgid "Menu Fichier :" +msgstr "File menu:" + +#: AperoDeDenis.py:6896 +msgid "" +" - Nouveau chantier : constitution d'un 'chantier' comportant les " +"photos, les options d'exécution de Micmac et" +msgstr "" +" - New project: create a new project with pictures, MicMac execution " +"options and" + +#: AperoDeDenis.py:6897 +msgid " les résultats des traitements." +msgstr " processing results." + +#: AperoDeDenis.py:6898 +msgid " Les paramètres du chantier sont conservés dans le fichier " +msgstr " Project's settings are saved in the file" + +#: AperoDeDenis.py:6899 +msgid "" +" Enregistrer le chantier crée une arborescence dont la racine est le " +"répertoire des photos et le nom du chantier." +msgstr "" +" Save the project and create a tree whose root is the pictures " +"directory and the project's name." + +#: AperoDeDenis.py:6900 +msgid "" +" - Ouvrir un chantier : revenir sur un ancien chantier pour le " +"poursuivre ou consulter les résultats." +msgstr "" +" - Open project: open an ancient project to work on it or consult " +"view results." + +#: AperoDeDenis.py:6901 +msgid "" +" - Enregistrer le chantier : enregistre le chantier en cours sans " +"l'exécuter." +msgstr " - Save project: save current project without executing it." + +#: AperoDeDenis.py:6902 +msgid "" +" Une * dans la barre de titre indique que le chantier a été modifié." +msgstr "" +" A * in the title bar means that the project has been modified. " + +#: AperoDeDenis.py:6903 +msgid "" +" Le chantier en cours, même non enregistré, est conservé lors de la " +"fermeture de l'application." +msgstr "" +" Saved or not, the current project will be stored when closing the " +"application." + +#: AperoDeDenis.py:6904 +msgid " - Renommer le chantier : personnalise le nom du chantier." +msgstr " - Rename project: change project name." + +#: AperoDeDenis.py:6905 +msgid "" +" Le chantier est déplacé dans l'arborescence en indiquant un chemin " +"absolu ou relatif." +msgstr "" +" Project will be displaced in the tree giving an absolute or relative " +"path." + +#: AperoDeDenis.py:6906 +msgid "" +" Par exemple : 'D:\\MonPremierChantier' nomme 'MonPremierChantier' " +"sous la racine du disque D." +msgstr "" +" For instance: 'D:\\MyFirstProject' name 'MyFirstProject' Under D: " +"root. " + +#: AperoDeDenis.py:6907 +msgid "" +" Attention : le changement de disque n'est pas possible dans cette " +"version de l'outil." +msgstr " Warning: disk change is not available in this version." + +#: AperoDeDenis.py:6908 +msgid "" +" - Exporter le chantier en cours : création d'une archive du chantier, " +"qui permet :" +msgstr "" +" - Export current project: create a project archive, which allows:" + +#: AperoDeDenis.py:6909 +msgid " - de conserver le chantier en l'état, pour y revenir." +msgstr "" +" - To store the project in its current status, to work on it later" + +#: AperoDeDenis.py:6910 +msgid "" +" - de l'importer sous un autre répertoire, un autre disque, un " +"autre ordinateur, un autre système d'exploitation" +msgstr "" +" - to importer it in another directory, disk, computer or " +"operating system" + +#: AperoDeDenis.py:6911 +msgid " - Importer un chantier :" +msgstr " - Import project" + +#: AperoDeDenis.py:6912 +msgid "" +" - copie le chantier sauvegardé dans un nouvel environnement " +"(ordinateur, système d'exploitation)" +msgstr "" +" - Create a copy of a saved project in a new environnement " +"(computer, operating system)" + +#: AperoDeDenis.py:6913 +#, fuzzy +#| msgid "" +#| " - un exemple d'intérêt : copier un chantier aprés tapas, " +#| "lancer malt avec des options variées sans perdre l'original." +msgid "" +" - un exemple d'intérêt : copier un chantier après tapas, lancer " +"malt avec des options variées sans perdre l'original." +msgstr "" +" - for instance: copy a project after Tapas, launch Malt with " +"different options without loosing the original." + +#: AperoDeDenis.py:6914 +#, fuzzy +#| msgid "répertoire du chantier :" +msgid " - Ajouter le répertoire d'un chantier :" +msgstr "Project directory:" + +#: AperoDeDenis.py:6915 +msgid "" +" - ajoute le chantier présent sous le répertoire indiqué. " +"Alternative moins robuste à l'export/import)" +msgstr "" + +#: AperoDeDenis.py:6916 +#, fuzzy +#| msgid "" +#| " - Du ménage ! : supprimer les chantiers : chaque chantier crée une " +#| "arborescence de travail." +msgid "" +" - Du ménage ! : nettoyer ou supprimer les chantiers : chaque chantier " +"crée une arborescence de travail assez lourde." +msgstr "" +" - Let's clean ! : delete projects : each project create a work tree." + +#: AperoDeDenis.py:6917 +msgid "" +" Le nettoyage ne garde que les photos, les modèles 3D résultats, les " +"traces, les paramètres : gain de place assuré !." +msgstr "" + +#: AperoDeDenis.py:6918 +msgid " La suppression supprime tout le chantier." +msgstr "" + +#: AperoDeDenis.py:6919 +#, fuzzy +#| msgid "" +#| " Aprés un message demandant confirmation la suppression est " +#| "définitive, sans récupération possible :" +msgid "" +" Un message demande confirmation avant la suppression définitive, " +"sans récupération possible :" +msgstr "" +" You will be asked to confirm the suppression, then the project will " +"be deleted for good:" + +#: AperoDeDenis.py:6920 +#, fuzzy +#| msgid "" +#| " toute l'arborescence est supprimée, même les archives exportées." +msgid "" +" Toute l'arborescence est supprimée, même les archives exportées." +msgstr " the entire tree will be deleted, even exported archives." + +#: AperoDeDenis.py:6921 +#, fuzzy +#| msgid "" +#| " - Quitter : quitte l'application, le chantier en cours est " +#| "conservé et sera ouvert lors de la prochaine exécution." +msgid "" +" - Quitter : quitte l'application, le chantier en cours est conservé " +"et sera ouvert lors du prochain lancement." +msgstr "" +" - Exit: exit the application, current project is stored and will be " +"opened at the next execution." + +#: AperoDeDenis.py:6922 +msgid "Menu Edition :" +msgstr "Edit menu:" + +#: AperoDeDenis.py:6923 +msgid "" +" - Afficher l'état du chantier : affiche les paramètres du chantier et " +"son état d'exécution." +msgstr "" +" - Display project progress: display project settings and his " +"execution status." + +#: AperoDeDenis.py:6924 +msgid "" +" Par défaut l'état du chantier est affiché lors du lancement de " +"l'application." +msgstr "" +" The project progress is displayed by default when the application " +"is launched." + +#: AperoDeDenis.py:6925 +msgid "" +" Cet item est utile après un message ou l'affichage d'une trace." +msgstr " This option is usefull after a message or displaying a log." + +#: AperoDeDenis.py:6926 +msgid "" +" - Plusieurs items permettent de consulter les photos, les traces et " +"les vues 3D du chantier en cours." +msgstr "" +" - Several options allows to see pictures, logs and 3D view of the " +"current project." + +#: AperoDeDenis.py:6927 +msgid "" +" Visualiser toutes les photos sélectionnées : visualise les photos" +msgstr " Display all selected pictures: display pictures" + +#: AperoDeDenis.py:6928 +#, fuzzy +#| msgid "Visualiser les photos pour la calibration intrinsèque" +msgid " Visualiser les photos pour la calibration intrinsèque" +msgstr "Display pictures for intrinsic calibration" + +#: AperoDeDenis.py:6929 +#, fuzzy +#| msgid "" +#| " Visualiser le masque 2D et l'image maitre : visualise le " +#| "masque 2D s'il existe et de l'image maître." +msgid "" +" Visualiser les maitresses et les masques : visualise les " +"masques 2D pour la densification Malt/géoimage." +msgstr "" +" Display 2D mask and master picture: display the 2D mask if " +"existing and the master picture." + +#: AperoDeDenis.py:6930 +#, fuzzy +#| msgid "" +#| " Visualiser le masque 2D et l'image maitre : visualise le " +#| "masque 2D s'il existe et de l'image maître." +msgid "" +" Visualiser le masque sur mosaïque TARAMA : visualise le masque " +"défini sur la mosaïque TARAMA." +msgstr "" +" Display 2D mask and master picture: display the 2D mask if " +"existing and the master picture." + +#: AperoDeDenis.py:6931 +#, fuzzy +#| msgid "" +#| " Visualiser le masque 3D : visualise le " +#| "masque 3D" +msgid "" +" Visualiser le masque 3D : visualise le masque " +"3D pour la densification C3DC" +msgstr " Display 3D mask: display the 3D mask" + +#: AperoDeDenis.py:6932 +msgid "" +" Visualiser les points GPS : visu des seules " +"photos avec points GPS." +msgstr "" +" Display GPS points: display pictures which have GPS points." + +#: AperoDeDenis.py:6934 +#, fuzzy +#| msgid "" +#| " Visualiser la ligne horizontale/verticale : visualise le " +#| "repère Ox ou Oy." +msgid "" +" Visualiser la ligne horizontale/verticale : visualise le repère " +"Ox ou Oy pour la mise à l'échelle." +msgstr "" +" Display horizontal/vertical line: display the Ox or Oy frame." + +#: AperoDeDenis.py:6935 +msgid "" +" Visualiser la zone plane : visualise la zone " +"plane" +msgstr " Display the plane area: display the plane area" + +#: AperoDeDenis.py:6936 +msgid "" +" Visualiser la distance : visualise de la " +"distance et les points associés." +msgstr "" +" Display the distance: display the distance and associated points." + +#: AperoDeDenis.py:6938 +msgid "" +" Afficher la trace complete du chantier : visualise la trace " +"complète, standard micmac" +msgstr "" +" Display project's complete log: display the complete log, micmac " +"standard." + +#: AperoDeDenis.py:6939 +msgid "" +" Afficher la trace synthétique du chantier : visualise la trace " +"filtrée par aperoDeDenis, moins bavarde" +msgstr "" +" Display the project's synthetic log: display the synthethic log " +"from AperoDeDenis, less talkative." + +#: AperoDeDenis.py:6941 +msgid "" +" Afficher la mosaïque Tarama : si la mosaïque " +"tarama est demandée dans l'onglet 'orientation'" +msgstr "" + +#: AperoDeDenis.py:6942 +msgid "" +" Afficher l'ortho mosaïque Tawny : l'ortho mosaïque " +"tawny est demandée dans l'onglet Densifisation/Malt/Ortho" +msgstr "" + +#: AperoDeDenis.py:6944 +msgid "" +" Afficher l'image 3D non densifiée : lance l'outil pour " +"ouvrir les .PLY sur l'image 3D produite par Tapas" +msgstr "" +" Display the non densified 3D picture: launch the .PLY opener on " +"the 3D picture created by Tapas" + +#: AperoDeDenis.py:6945 +msgid "" +" Afficher l'image 3D densifiée : lance l'outil pour " +"ouvrir les .PLY sur l'image 3D produite par Malt ou C3DC" +msgstr "" +" Display the densified 3D picture: launch the .ply opener on the " +"3D picture created by Malt or C3DC" + +#: AperoDeDenis.py:6947 +msgid "" +" Lister Visualiser les images 3D : liste la pyramide " +"des images 3D, créées à chaque étape de Malt" +msgstr "" +" Display 3D pictures list: list the 3D pictures pyramid, created " +"by Malt at each of its steps." + +#: AperoDeDenis.py:6948 +msgid "" +" Fusionner des images 3D : permet de fusionner " +"plusieurs PLY en un seul" +msgstr " Merge 3D pictures: allow to merge several PLY in one file." + +#: AperoDeDenis.py:6949 +msgid "Menu MicMac :" +msgstr "MicMac menu:" + +#: AperoDeDenis.py:6950 +msgid "" +" - Choisir les photos : permet choisir les photos JPG, GIF, TIF ou BMP " +"pour le traitement." +msgstr "" +" - Select pictures: allow to select JPG, GIF, TIF or BMP pictures for " +"processing." + +#: AperoDeDenis.py:6951 +#, fuzzy +#| msgid "" +#| " Remarque : les photos GIF et BMP seront converties en JPG " +#| "(nécessite la présence de l'outil convert)." +msgid "" +" Les photos GIF et BMP seront converties en JPG (nécessite la " +"présence de l'outil convert)." +msgstr "" +" Note: GIF and BMP pictures will be converted into JPG (convert tool " +"required)" + +#: AperoDeDenis.py:6952 +msgid "" +" Un EXIF avec la focale utilisée pour la prise de vue est " +"nécessaire : si besoin l'ajouter (menu Outil/ajout exif)." +msgstr "" +" An exif with the used focal length is required: add it if needed " +"(Tools/Add exif)." + +#: AperoDeDenis.py:6953 +#, fuzzy +#| msgid "" +#| " Cette présence est obligatoire si l'exif ne présente " +#| "pas la focale équivalente 35mm." +msgid "" +" Remarques : 1) Si l'exif ne comporte pas la focale équivalente en " +"35 mm alors " +msgstr "" +" It is required if the exif does not have the equivalent " +"focal length 35mm." + +#: AperoDeDenis.py:6954 +#, fuzzy +#| msgid "" +#| " Le fichier DicoCamera.xml doit comporter la taille " +#| "du capteur de l'appareil (voir menu Outils)" +msgid "" +" le fichier DicoCamera.xml doit comporter la taille du " +"capteur de l'appareil (voir menu Outils)" +msgstr "" +" DicoCamera.xml must include the size of the captor of " +"the camera(see Tools menu)" + +#: AperoDeDenis.py:6955 +msgid "" +" 2) Si les photos proviennent de plusieurs appareils " +"alors les tags 'model' des exif doivent" +msgstr "" + +#: AperoDeDenis.py:6956 +msgid " être différenciés (voir menu Expert)" +msgstr "" + +#: AperoDeDenis.py:6957 +#, fuzzy +#| msgid "" +#| " - Options : choisir les options des modules Tapioca, Tapas (nuage " +#| "non densifié) puis de Malt (nuage densifié) : " +msgid "" +" - Options : choisir les options des modules Tapioca, Tapas, GPS " +"(nuage non densifié) puis de densification : " +msgstr "" +" - Options: choose options from Tapioca, Tapas (undensified point " +"cloud) and then Malt (densified point cloud) modules." + +#: AperoDeDenis.py:6958 +msgid "" +" Consulter le wiki MicMac pour obtenir de l'info sur les " +"options, par exemple : https://micmac.ensg.eu/index.php/Tapas" +msgstr "" + +#: AperoDeDenis.py:6959 +msgid "" +" Les options suivantes concernent le calcul du nuage de points NON " +"densifié :" +msgstr " Following options affect undensified point cloud:" + +#: AperoDeDenis.py:6960 +#, fuzzy +#| msgid "" +#| " - Tapioca : options et sous options associées " +#| "(échelles, fichier xml)" +msgid "" +" - Points homologues : Tapioca : options et sous options " +"associées (échelles, fichier xml)" +msgstr "" +" - Tapioca: options and associated sub-options (scales, " +"xml files)" + +#: AperoDeDenis.py:6961 +#, fuzzy +#| msgid "" +#| " L'outil de saisie est issu de micmac." +msgid "" +" Voir la documentation MicMac sur Tapioca." +msgstr " The entry tool is from MicMac." + +#: AperoDeDenis.py:6962 +#, fuzzy +#| msgid "" +#| " - Tapas : choix d'un mode de calcul, possibilité " +#| "d'arrêter le traitement après tapas." +msgid "" +" - Orientation : Tapas : choix d'un type d'appareil " +"photo , possibilité d'arrêter le traitement après tapas." +msgstr "" +" - Tapas : caluclation mode choice, allow to stop " +"processing after Tapas." + +#: AperoDeDenis.py:6963 +#, fuzzy +#| msgid "" +#| " Supprimer une image maîtresse de la " +#| "liste réinitialise le masque." +msgid "" +" Le type d'appareil photo détermine le nombre " +"de paramètres décrivant l'optique et le capteur." +msgstr "" +" Delete a master picture from the list will reset " +"the mask." + +#: AperoDeDenis.py:6964 +#, fuzzy +#| msgid "" +#| " Seuls les points visibles sur les " +#| "images maitres seront sur l'image 3D finale." +msgid "" +" Si plusieurs appareils photos alors il faut " +"les distinguer, voir menu expert." +msgstr "" +" Only the visible points on master pictures " +"will be displayed on the final 3D picture." + +#: AperoDeDenis.py:6965 +#, fuzzy +#| msgid "" +#| " La calibration intrinsèque permet de " +#| "lancer Tapas sur un premier lot de photos." +msgid "" +" La calibration intrinsèque permet de " +"déterminer les caractéristiques de l'appareil sur des photos spécifiques :" +msgstr "" +" Intrinsic calibration allows to launch Tapas " +"on a first package of pictures." + +#: AperoDeDenis.py:6966 +#, fuzzy +#| msgid "" +#| " Nombre de photos utiles autour de " +#| "l'image maîtresse :" +msgid "" +" Par exemple photos d'un angle de batiment " +"avec une grande longueur de mur." +msgstr "" +" Number of useful pictures around the master picture:" + +#: AperoDeDenis.py:6967 +#, fuzzy +#| msgid "" +#| " L'arrêt après Tapas est nécessaire pour " +#| "décrire le masque 2D ou 3D." +msgid "" +" Ces photos ne servent pas nécessairement " +"pour la suite du chantier." +msgstr "" +" Stop after Tapas is necessary to create 2D " +"or 3D mask." + +#: AperoDeDenis.py:6968 +msgid "" +" L'arrêt après Tapas est nécessaire pour " +"décrire le masque 2D ou 3D." +msgstr "" +" Stop after Tapas is necessary to create 2D " +"or 3D mask." + +#: AperoDeDenis.py:6969 +msgid "" +" Produit une image 3D non densifiée avec " +"position des appareils photos." +msgstr "" +" Create a undensified 3D picture with cameras " +"position." + +#: AperoDeDenis.py:6970 +#, fuzzy +#| msgid "" +#| " - Calibration : définir un axe, une zone plane, une " +#| "distance pour définir le repère du chantier." +msgid "" +" - Mise à l'échelle : définir un axe, une zone plane, une " +"distance pour définir le repère du chantier." +msgstr "" +" - Calibration: define an axis, a plane area, a distance " +"to define project's frame." + +#: AperoDeDenis.py:6971 +#, fuzzy +#| msgid "" +#| " L'option MulScale recherche les points " +#| "homologues en 2 temps :" +msgid "" +" cette mise à l'échelle s'effectue sur le " +"nuage de points homologues" +msgstr "" +" MulScale option search tie-point in 2 steps:" + +#: AperoDeDenis.py:6972 +#, fuzzy +#| msgid "" +#| " - GPS : définir les points de calage GPS qui " +#| "permettent de géolocaliser la scène." +msgid "" +" - GPS : définir les points de calage (coordonnées GPS ou " +"repère local) qui permettent de (géo)localiser la scène." +msgstr "" +" - GPS : define GPS points, which allow to geolocate the " +"scene." + +#: AperoDeDenis.py:6973 +msgid "" +" Une première ligne permet de définir les options " +"du module CAMPARI qui améliore la précision des calculs." +msgstr "" + +#: AperoDeDenis.py:6974 +msgid "" +" Il faut indiquer la précision des cibles GPS (en " +"unité du GPS) et la précision des points images (en pixels)." +msgstr "" + +#: AperoDeDenis.py:6975 +#, fuzzy +#| msgid "" +#| " dessiner si besoin le ou les masques " +#| "associés." +msgid "" +" CAMPARI ne sera lancé que si les points GPS sont " +"corrects ainsi que les 2 paramètres ci-dessus." +msgstr "" +" If needed, draw the associated masks." + +#: AperoDeDenis.py:6976 +#, fuzzy +#| msgid "" +#| " Pour être utilisé chaque point, minimum 3, " +#| "doit être placé sur au moins 2 photos." +msgid "" +" Pour être utilisé chaque point GPS, au minimum " +"3, doit être placé sur au moins 2 photos." +msgstr "" +" To be used, a minimum of three points must be " +"placed on at least two pictures." + +#: AperoDeDenis.py:6977 +#, fuzzy +#| msgid "" +#| " Le bouton 'appliquer' permet de calibrer " +#| "le modèle non densifié immédiatement." +msgid "" +" Le bouton 'appliquer' permet de calibrer le " +"modèle non densifié immédiatement sur le nuage de points homologues." +msgstr " The \"Apply\" button allows to " + +#: AperoDeDenis.py:6978 +#, fuzzy +#| msgid "" +#| " - Malt : choix du mode et du niveau de " +#| "densification." +msgid "" +" - Densification : choix du module de densification : " +"C3DC (récent) ou Malt (ancien)." +msgstr " - Malt: densification mode and level choice." + +#: AperoDeDenis.py:6979 +#, fuzzy +#| msgid " Si le mode est GeomImage : " +msgid " - Malt : Si le mode est GeomImage : " +msgstr " If GeomImage is the mod: " + +#: AperoDeDenis.py:6980 +msgid "" +" désigner une ou plusieurs images maîtresses" +msgstr "" +" select one or several master pictures" + +#: AperoDeDenis.py:6981 +msgid "" +" dessiner si besoin le ou les masques " +"associés." +msgstr "" +" If needed, draw the associated masks." + +#: AperoDeDenis.py:6982 +msgid "" +" Seuls les points visibles sur les images " +"maitres seront sur l'image 3D finale." +msgstr "" +" Only the visible points on master pictures " +"will be displayed on the final 3D picture." + +#: AperoDeDenis.py:6983 +msgid "" +" Le masque limite la zone utile de l'image " +"3D finale." +msgstr "" +" The mask limits the final 3D picture's useful area." + +#: AperoDeDenis.py:6984 +msgid "" +" La molette permet de zoomer et le clic " +"droit maintenu de déplacer l'image." +msgstr "" +" The scroll button allows to zoom and the right " +"click to move the picture." + +#: AperoDeDenis.py:6985 +msgid "" +" Supprimer une image maîtresse de la liste " +"réinitialise le masque." +msgstr "" +" Delete a master picture from the list will reset " +"the mask." + +#: AperoDeDenis.py:6986 +msgid "" +" Nombre de photos utiles autour de l'image " +"maîtresse :" +msgstr "" +" Number of useful pictures around the master picture:" + +#: AperoDeDenis.py:6987 +msgid "" +" Permet de limiter les recherches aux " +"images entourant chaque image maîtresse." +msgstr "" +" Allows to limite pictures searches to " +"pictures surrouding each master picture." + +#: AperoDeDenis.py:6988 +#, fuzzy +#| msgid "" +#| " Choix du niveau de densification final : " +#| "8,4,2 ou 1." +msgid "" +" Choix du niveau de densification final : " +"8,4,2 ou 1." +msgstr "" +" Final densification level choice: 8, 4, 2 or 1" + +#: AperoDeDenis.py:6989 +msgid " Le niveau 1 est le plus dense. " +msgstr " Level 1 is the densest." + +#: AperoDeDenis.py:6990 +msgid "" +" La géométrie est revue à chaque niveau et " +"de plus en plus précise : " +msgstr "" +" Geometry is reworked at each level and is " +"more and more precise:" + +#: AperoDeDenis.py:6991 +msgid "" +" la densification s'accroît, et la " +"géométrie s'affine aussi." +msgstr "" +" Densification increases, and geometry " +"refines." + +#: AperoDeDenis.py:6992 +#, fuzzy +#| msgid "" +#| " - Malt : choix du mode et du niveau de " +#| "densification." +msgid " - C3DC : choix par défaut." +msgstr " - Malt: densification mode and level choice." + +#: AperoDeDenis.py:6993 +#, fuzzy +#| msgid "" +#| " - C3DC : dessiner le masque 3D sur le nuage de " +#| "points AperiCloud généré par Tapas.." +msgid "" +" Possibilité de dessiner un masque 3D sur le " +"nuage de points non dense." +msgstr "" +" - C3DC: draw 3D mask on AperiCloud's point cloud " +"generated by Tapas." + +#: AperoDeDenis.py:6994 +msgid "" +" Les touches fonctions à utiliser sont " +"décrites dans l'onglet." +msgstr " Keys to use are described in the tab." + +#: AperoDeDenis.py:6995 +msgid "" +" Le masque limite la zone en 3 dimensions de " +"l'image finale." +msgstr "" +" The mask limits the final picture's 3D area." + +#: AperoDeDenis.py:6996 +msgid " L'outil de saisie est issu de micmac." +msgstr " The entry tool is from MicMac." + +#: AperoDeDenis.py:6997 +msgid "" +" - Lancer MicMac : enregistre le chantier et lance le traitement avec " +"les options par défaut ou choisies par l'item 'options'." +msgstr "" +" - Launch MicMac : save project et launch the processing with default " +"or choosen options from the 'options' item." + +#: AperoDeDenis.py:6998 +msgid "" +" Relance micmac si l'arrêt a été demandé après tapas." +msgstr "" +" Relaunch MicMac if stopping was asked after Tapas." + +#: AperoDeDenis.py:6999 +msgid "" +" Lancer micmac bloque les photos et les options du " +"chantier." +msgstr "" +" Launch MicMac block project's pictures and options." + +#: AperoDeDenis.py:7000 +msgid "" +" Pour débloquer le chantier il faut lancer micmac à " +"nouveau et choisir le débloquage." +msgstr "" +" To unblock the project, you must launch MicMac anew " +"and choose to unblock." + +#: AperoDeDenis.py:7001 +#, fuzzy +#| msgid "" +#| " Le débloquage permet de relancer Malt sans " +#| "relancer tapioca/tapas : " +msgid "" +" Le débloquage permet de relancer Malt sans relancer " +"tapioca/tapas tout en conservant le modèle densifié, renommé." +msgstr "" +" Unblock allows to relaunch Malt without relaunching " +"Tapioca/Tapas:" + +#: AperoDeDenis.py:7002 +msgid "menu Vidéo :" +msgstr "Video menu:" + +#: AperoDeDenis.py:7003 +msgid "" +" - Options : indiquer le nom de la camera (GoPro, smartphone...), sa " +"focale, sa focale equivalente 35mm" +msgstr "" +" Options: indicate the name of the camera(GoPro, smartphone...), its " +"focal length, its equivalent focal length 35mm" + +#: AperoDeDenis.py:7004 +msgid " et le nombre d'images à conserver par seconde de film" +msgstr " and the number of picture to keep by second of film" + +#: AperoDeDenis.py:7005 +msgid "" +" Le nom permet de faire le lien avec DicoCamera.xml qui contient la " +"taille du capteur." +msgstr "" +" The name allows to link with DicoCamera.xml which contains the size " +"of the sensors." + +#: AperoDeDenis.py:7006 +msgid " Les focales seront recopiées dans l'exif des images." +msgstr " Focal length will be copied to pictures exif." + +#: AperoDeDenis.py:7007 +msgid "" +" Le nombre d'images par seconde sera utilisé pour la sélection des " +"meilleures images." +msgstr "" +" The number of pictures per second will be used to select the best " +"pictures." + +#: AperoDeDenis.py:7008 +msgid " Remarque :" +msgstr " Note:" + +#: AperoDeDenis.py:7009 +msgid "" +" Il faut indiquer dans DicoCamera la taille du capteur " +"effectivement utilisée par la fonction camera," +msgstr "" +" You need to indicate the size of the sensors used by the camera " +"function in DicoCamera," + +#: AperoDeDenis.py:7010 +msgid "" +" taille qui peut être inférieure à la taille du capteur utilisée " +"pour les photos." +msgstr "" +" size which can be lower to the size of the sensors used to take " +"pictures." + +#: AperoDeDenis.py:7011 +msgid " Voir par exemple pour une camera Gopro :" +msgstr " For instance, for a GoPro camera:" + +#: AperoDeDenis.py:7013 +msgid "" +" - Nouveau chantier : choisir une video : choisir un fichier video " +"issu d'une camera ou d'une GoPro." +msgstr "" +" - New Project: choose a video: choose a video file from a camera or a " +"GoPro." + +#: AperoDeDenis.py:7014 +msgid "" +" La vidéo sera décompactée en images, l'exif sera créé avec les " +"informations en options." +msgstr "" +" The video will be uncompressed in picture, the exif will be create " +"with the options information." + +#: AperoDeDenis.py:7015 +msgid "" +" Cette étape nécessite la présence de l'outil ffmpeg sous le " +"répertoire bin de MicMac (dépend de la version de MicMac)." +msgstr "" +" This step require the ffmpeg tool in the directory of MicMac\\bin. " +"(Depend on MicMac's version)" + +#: AperoDeDenis.py:7016 +msgid "" +" Un nouveau chantier est créé avec les options suivante : Line pour " +"Tapioca et FishEyeBasic pour Tapas." +msgstr "" +" A new project is created with following options: Line for Tapioca " +"en FishEyeBasic for Tapas." + +#: AperoDeDenis.py:7017 +msgid "" +" - Sélection des images : il est raisonnable de ne garder que quelques " +"images par seconde de film." +msgstr "" +" - Pictures selection: it would be best if only a few pictures per " +"second of film are recorded." + +#: AperoDeDenis.py:7018 +msgid "" +" Le nombre d'images conservées par seconde est indiqué dans les " +"options." +msgstr "" +" The number of pictures stored per second can be found in the " +"options." + +#: AperoDeDenis.py:7019 +msgid "" +" Chaque seconde de film les 'meilleures' images seront retenues, les " +"autres effacées." +msgstr "" +" Each second of film, the best pictures will be kept, the others " +"removed." + +#: AperoDeDenis.py:7020 +msgid "" +" Attention : cette étape n'est pas effective pour toutes les " +"versions de MicMac. La version mercurial 5508 fonctionne." +msgstr "" +" Warning : this step does not work for all MicMac versions. The " +"mercurial 5508 version works." + +#: AperoDeDenis.py:7021 +msgid "" +" Une fois les images sélectionnées le chantier est créé : utiliser " +"le menu MicMac comme pour un chantier normal." +msgstr "" +" Once the pictures selected, the project is created: use the MicMac " +"menu to go on like a normal project." + +#: AperoDeDenis.py:7022 +msgid "menu Outils :" +msgstr "Tools menu:" + +#: AperoDeDenis.py:7023 +#, fuzzy +#| msgid "" +#| " - Affiche le nom et la focale de l'appareil photo : fabricant, " +#| "modèle et focale de la première photo." +msgid "" +" - Info extraites de l'exif : fabricant, modèle, focale et dimensions " +"en pixels de la première photo." +msgstr "" +" - Display the name and focal length of the camera: manufacturer, " +"model and focal length of the first picture." + +#: AperoDeDenis.py:7024 +msgid "" +" Il y a 2 types de focales : focale effective et focale équivalente " +"35 mm." +msgstr "" +" There are two focal length types: effective focal length and " +"equivalent focal length 35mm." + +#: AperoDeDenis.py:7025 +msgid "" +" Indique si l'appareil photo est connu dans '/XML MicMac/DicoCamera." +"xml'." +msgstr " Shows if the camera is known in '/XML MicMac/DicoCamera.xml'." + +#: AperoDeDenis.py:7026 +#, fuzzy +#| msgid "" +#| " - Affiche toutes les focales des photos : focales et focales " +#| "equivalentes en 35mm." +msgid "" +" - Afficher toutes les focales des photos : focales et focales " +"equivalentes en 35mm." +msgstr "" +" - Display all pictures focal length: effective focal length and " +"equivalent focal length 35mm." + +#: AperoDeDenis.py:7027 +msgid "" +" Si les focales ne sont pas identiques pour toutes les photos : " +"utiliser la calibration intrinséque de tapas." +msgstr "" +" If all focal length are not the same for all pictures: use Tapas's " +"intrinsic calibration." + +#: AperoDeDenis.py:7028 +#, fuzzy +#| msgid "" +#| " - Affiche le nom et la focale de l'appareil photo : fabricant, " +#| "modèle et focale de la première photo." +msgid " Affiche aussi le nom de l'appareil photo pour chaque photo." +msgstr "" +" - Display the name and focal length of the camera: manufacturer, " +"model and focal length of the first picture." + +#: AperoDeDenis.py:7029 +msgid "" +" - Mettre à jour DicoCamera.xml : ajouter la taille du capteur dans '/" +"XML MicMac/DicoCamera.xml'." +msgstr "" +"- Update DicoCamera.xml: add sensor size in '/XML MicMac/DicoCamera.xml'." + +#: AperoDeDenis.py:7030 +msgid "" +" La taille du capteur dans DicoCamera.xml est requise si la focale " +"équivalente 35mm est absente de l'exif." +msgstr "" +" The size of the sensors from DicoCamera.sml is required if the " +"equivalent focal length 35mm is not in the exif." + +#: AperoDeDenis.py:7031 +msgid "" +" La taille du capteur facilite les calculs et améliore les résultats." +msgstr "Sensor size ease calculations and improve results." + +#: AperoDeDenis.py:7032 +msgid "" +" La taille du capteur se trouve sur le site du fabricant ou sur " +"http://www.dpreview.com." +msgstr "" +" The size of the sensors can be found on the manufacturer website or " +"on http://www.dpreview.com." + +#: AperoDeDenis.py:7033 +msgid "" +" - Qualité des photos du dernier traitement : calcule le nombre moyen " +"de points homologues par photo." +msgstr "" +" - Last processing of the quality of the pictures: calculate the " +"average number of tie-points per picture." + +#: AperoDeDenis.py:7034 +msgid "" +" Si des photos présentent des moyennes très faibles elles peuvent " +"faire échouer le traitement." +msgstr "" +" If some pictures shows a very low average they can make the process " +"fails." + +#: AperoDeDenis.py:7035 +msgid "" +" - Qualité des photos 'Line' : calcule le nombre moyen de points " +"homologues par photo en mode 'Line', taille 1000." +msgstr "" +" - Quality of the 'Line' pictures: calculate the average number of tie-" +"points per picture in 'Line' mode, size 1000." + +#: AperoDeDenis.py:7036 +msgid "" +" - Qualité des photos 'MulScale ou All' : calcule le nombre moyen de " +"points homologues par photo, taille 1000.'." +msgstr "" +" - Quality of the 'MulScale' or 'All' pictures: calculate the average " +"number of tie-points per picture in 'Line' mode, size 1000." + +#: AperoDeDenis.py:7037 +msgid "" +" Ce nombre informe sur la qualité relative des photos au sein du " +"chantier." +msgstr "" +" This number gives an idea of pictures relative quality in this " +"project." + +#: AperoDeDenis.py:7038 +msgid "" +" La présence de photos avec peu de points homologues peut faire " +"échouer le traitement." +msgstr "" +" The lack of tie-points among pictures could make the process fails." + +#: AperoDeDenis.py:7039 +msgid "" +" Il est parfois préférable de traiter peu de photos mais de bonne " +"qualité." +msgstr " Il is sometimes better to use a few pictures of high-quality." + +#: AperoDeDenis.py:7040 +msgid "" +" - Modifier l'exif des photos : permet la création et la modification " +"des exifs des photos du chantier." +msgstr "" +" - Edit pictures exif: allows to create and edit pictures exif from " +"the project." + +#: AperoDeDenis.py:7041 +msgid "" +" - Modifier les options par défauts : les valeurs par défaut de " +"certains paramètres sont modifiables." +msgstr "" + +#: AperoDeDenis.py:7042 +msgid "" +" Les paramètres concernés sont ceux des onglets du menu MicMac/" +"options : 'Points homologues',... : ." +msgstr "" + +#: AperoDeDenis.py:7043 +#, fuzzy +#| msgid "menu Aide :" +msgid "menu Expert :" +msgstr "Help menu:" + +#: AperoDeDenis.py:7044 +msgid "" +" - Ouvrir une console permettant de passer des commandes système et " +"MicMac (mm3d)." +msgstr "" + +#: AperoDeDenis.py:7045 +msgid "" +" - Ouvrir une console permettant de passer des commandes Python (ex. : " +"afficher une variable." +msgstr "" + +#: AperoDeDenis.py:7046 +msgid "" +" - Insérer de points GPS à partir d'un fichier texte, séparateur " +"espace, format : X Y Z dx dy dz " +msgstr "" + +#: AperoDeDenis.py:7047 +msgid " Le caractère # en début de ligne signale un commentaire." +msgstr "" + +#: AperoDeDenis.py:7048 +#, fuzzy +#| msgid "Ajouter les points GPS d'un chantier" +msgid " - Recopier des points GPS à partir d'un autre chantier." +msgstr "Add GPS points from an other project" + +#: AperoDeDenis.py:7049 +msgid " - Définir plusieurs appareils photos." +msgstr "" + +#: AperoDeDenis.py:7050 +msgid "" +" Si le lot de photos provient de plusieurs appareils de même type il " +"faut informer MicMac de cette situation." +msgstr "" + +#: AperoDeDenis.py:7051 +msgid " Plusieurs solutions existent dans MicMac." +msgstr "" + +#: AperoDeDenis.py:7052 +msgid "" +" AperoDeDenis propose de modifier le tag 'model' de l'exif des " +"photos :" +msgstr "" + +#: AperoDeDenis.py:7053 +msgid "" +" - en utilisant le numéro de série de l'appareil présent dans " +"l'exif" +msgstr "" + +#: AperoDeDenis.py:7054 +msgid "" +" - à défaut en utilisant 3 caractères du préfixe des noms de " +"fichiers, que l'utilisateur a préparé de telle sorte" +msgstr "" + +#: AperoDeDenis.py:7055 +msgid "" +" que chaque préfixe corresponde à un appareil. Certains appareil " +"proposent de modifier qyqtématiquement ce préfixe." +msgstr "" + +#: AperoDeDenis.py:7056 +#, fuzzy +#| msgid "" +#| " Visualiser toutes les photos sélectionnées : visualise les " +#| "photos" +msgid " - Lister les appareils photos présents dans le lot de photos." +msgstr " Display all selected pictures: display pictures" + +#: AperoDeDenis.py:7057 +msgid " - Consulter le fichier de logging MicMac : mm3d-logFile.txt." +msgstr "" + +#: AperoDeDenis.py:7058 +msgid "menu Paramétrage :" +msgstr "Settings menu:" + +#: AperoDeDenis.py:7059 +#, fuzzy +#| msgid "" +#| " - Affiche les paramètres : visualise les chemins de micmac\\bin, " +#| "d'exiftool, du fichier pour visualiser les .ply (Meshlab ou Cloud " +#| "Compare)," +msgid "" +" - Afficher les paramètres : visualise les chemins de micmac\\bin, " +"d'exiftool, du fichier pour visualiser les .ply (Meshlab ou Cloud Compare)," +msgstr "" +" - Display settings: shows micmac\\bin, exiftool, .ply opener " +"(Meshlab or Cloud Compare) paths," + +#: AperoDeDenis.py:7060 +msgid "" +" ainsi que le répertoire où se trouve les fichiers paramètres de " +"l'interface." +msgstr " as the settings files directory of the GUI." + +#: AperoDeDenis.py:7061 +msgid "" +" Ces paramètres sont sauvegardés de façon permanente dans le " +"fichier :" +msgstr " These settings are permanently saved in the file:" + +#: AperoDeDenis.py:7063 +msgid "" +" - Désigner le répertoire MicMac\\bin : répertoire où se trouvent les " +"modules de MicMac " +msgstr "" +" - Select the MicMac\\bin directory: directory where MicMac modules " +"can be found." + +#: AperoDeDenis.py:7064 +msgid "" +" Si plusieurs versions sont installées cet item permet de changer " +"facilement la version de MicMac utilisée." +msgstr "" +" If several versions are installed, you can easily change the one " +"you want to use." + +#: AperoDeDenis.py:7065 +msgid "" +" - Désigner l'application exiftool, utile pour modifier les exif (elle " +"se trouve sous micMac\\binaire-aux)." +msgstr "" +" - Shows exiftool application, useful to edit exifs. (Can be found in " +"MicMac\\binaire-aux)." + +#: AperoDeDenis.py:7066 +msgid "" +" - Désigner l'application convert d'ImageMagick, utile pour convertir " +"les gif, tif et bmp en jpg (elle se trouve sous micMac\\binaire-aux)." +msgstr "" +" - Show ImageMagick's convert application, to convert gif, tig and bmp " +"into jpg. (Can be found in MicMac\\binaire-aux)." + +#: AperoDeDenis.py:7067 +msgid "" +" - Désigner l'application ouvrant les fichiers .PLY. Ce peut être " +"Meshlab, CloudCompare ou autre." +msgstr "" +" - Show the .ply opener. It can be Meshlab, CloudCompare or anything " +"else." + +#: AperoDeDenis.py:7068 +msgid " Sous Windows Meshlab se trouve sous un répertoire nommé VCG." +msgstr " On Windows, Meshlab can be found in a directory named 'VCG'." + +#: AperoDeDenis.py:7069 +msgid " - Activer/désactiver le 'tacky' message de lancement" +msgstr " - Activate/Desactivate the launching tacky message." + +#: AperoDeDenis.py:7070 +msgid "menu Aide :" +msgstr "Help menu:" + +#: AperoDeDenis.py:7071 +msgid "" +" - Pour commencer : à lire lors de la prise en main de l'interface." +msgstr "" +" - Get started: should be read to learn how to use the Graphical User " +"Interface." + +#: AperoDeDenis.py:7072 +msgid " - Aide : le détail des items de menu." +msgstr " - Help: détails about menu's items." + +#: AperoDeDenis.py:7073 +msgid " - Quelques conseils : sur la prise de vue et les options." +msgstr " - Advices: about options and shooting" + +#: AperoDeDenis.py:7074 +msgid " - Historique : les nouveautés de chaque version." +msgstr " - Changelog: what's new in each version" + +#: AperoDeDenis.py:7075 +msgid " - A propos" +msgstr " - About" + +#: AperoDeDenis.py:7076 +msgid " Quelques précisions :" +msgstr "A few détails:" + +#: AperoDeDenis.py:7077 +msgid "" +" Cette version a été développée sous Windows XP et Seven avec micmac rev " +"5508 d'avril 2015." +msgstr "" +"This version was developed on Windows Xp and Seven with micmac rev 5508 from " +"april 2015." + +#: AperoDeDenis.py:7078 +msgid "" +" L'utilisation d'autres versions de Micmac a été testée, jusqu'à la version " +"6219." +msgstr "Other MicMac versions were tested, to version 6219." + +#: AperoDeDenis.py:7079 +msgid " Le fonctionnement sous Ubuntu Trusty a été vérifié." +msgstr "Proper functioning was verified on Ubuntu Trusty." + +#: AperoDeDenis.py:7080 +msgid " Consulter la documentation de MicMac, outil réalisé par l'IGN." +msgstr "See MicMac documentation, a tool realised by the IGN." + +#: AperoDeDenis.py:7081 +msgid " Consulter le guide d'installation et de prise en main d'AperoDeDenis." +msgstr "See the AperoDeDenis's starting guide." + +#: AperoDeDenis.py:7091 +msgid "" +"Interface graphique pour lancer les modules de MICMAC : quelques conseils." +msgstr "Graphic User Interface to launch MICMAC modules: a few détails." + +#: AperoDeDenis.py:7092 +msgid "Prises de vue :" +msgstr "Shooting:" + +#: AperoDeDenis.py:7093 +msgid "" +" - Le sujet doit être immobile durant toutes la séance de " +"prise de vue." +msgstr "" +" - The subject must not move during the shooting session." + +#: AperoDeDenis.py:7094 +#, fuzzy +#| msgid "" +#| " - Le sujet doit être immobile durant toutes la séance de " +#| "prise de vue." +msgid " - Le sujet doit être unique et d'un seul tenant" +msgstr "" +" - The subject must not move during the shooting session." + +#: AperoDeDenis.py:7095 +msgid "" +" - Le sujet doit être bien éclairé, la prise de vue en plein " +"jour doit être recherchée." +msgstr "" +" - The subject must be well lightened, preferably by daylight." + +#: AperoDeDenis.py:7096 +msgid "" +" - Les photos doivent être nettes, attention à la profondeur " +"de champ :" +msgstr "" +" - Pictures must be clear, pay attention to the depth of " +"field:" + +#: AperoDeDenis.py:7097 +msgid "" +" utiliser la plus petite ouverture possible (nombre F le " +"plus grand, par exemple 22)." +msgstr " use the smallest gap you can (bigger F, like 22)" + +#: AperoDeDenis.py:7098 +msgid "" +" - Utiliser la calibration intrinsèque des appareils photos " +"(item MicMac/Options/Orientation )." +msgstr "" + +#: AperoDeDenis.py:7099 +msgid "" +" - Les photos de personnes ou d'objet en mouvement sont " +"déconseillées" +msgstr "" +" - Pictures of moving people or object are not indicated.." + +#: AperoDeDenis.py:7100 +msgid "" +" - Les surfaces lisses ou réfléchissantes sont défavorables." +msgstr " - Smooth or reflective surfaces are unsuitable." + +#: AperoDeDenis.py:7101 +msgid "" +" - Si le sujet est central prendre une photo tous les 20°, " +"soit 9 photos pour un 'demi-tour', 18 pour un tour complet." +msgstr "" +" - If the subject is in the center, take a picture by 20° " +"step, meaning that 9 pictures for a semi-circle around the subjet or 18 for " +"a whole full turn." + +#: AperoDeDenis.py:7102 +msgid "" +" - Si le sujet est en 'ligne' le recouvrement entre photos " +"doit être des 2/3." +msgstr "" +" - If the subject is in 'line', the overlap ratio must be " +"2/3." + +#: AperoDeDenis.py:7103 +msgid "" +" - Tester la 'qualité' des photos au sein du chantier (voir " +"les items du menu Outils)." +msgstr "" +" - Check the quality of the pictures in the project (in the " +"Tools menu)." + +#: AperoDeDenis.py:7104 +msgid "" +" les photos ayant un mauvais score (voir le menu Outils/" +"Qualité des photos 'All') doivent être supprimées du chantier : " +msgstr "" +" The pictures with a bad score (see the menu Tools / " +"Quality of photos 'All') must be removed from the project:" + +#: AperoDeDenis.py:7105 +msgid "" +" une seule mauvaise photo peut faire échouer le traitement." +msgstr "" +" A single bad picture may cause the processing to fail." + +#: AperoDeDenis.py:7106 +#, fuzzy +#| msgid "" +#| " - La présence des dimensions du capteur de l'appareil " +#| "dans DIcoCamera.xml améliore le traitement." +msgid "" +" - La présence des dimensions du capteur de l'appareil dans " +"DicoCamera.xml améliore le traitement." +msgstr "" +" - The size of the sensors of the camera in DicoCamera.xml " +"can improve processing." + +#: AperoDeDenis.py:7107 +msgid "" +" Cette présence est obligatoire si l'exif ne présente pas " +"la focale équivalente 35mm." +msgstr "" +" It is required if the exif does not have the equivalent " +"focal length 35mm." + +#: AperoDeDenis.py:7108 +msgid "" +" Pour ajouter la taille du capteur utiliser le menu " +"'Outils//mettre à jour DicoCamera'." +msgstr "" +" To add the size of the sensor, use the 'Tools/Update " +"DicoCamera' menu." + +#: AperoDeDenis.py:7109 +msgid " Précautions : " +msgstr " Cautions:" + +#: AperoDeDenis.py:7110 +msgid "" +" Ne pas utiliser la fonction autofocus. Deux focales " +"différentes maximum pour un même chantier." +msgstr "" +" Don't use autofocus. Two different focal length maximum for " +"a same project." + +#: AperoDeDenis.py:7111 +msgid "" +" Eviter aussi la fonction 'anti tremblement' qui agit en " +"modfiant la position du capteur." +msgstr "" +" Avoid to use the 'Anti-shake' function which changes the " +"position of the sensors." + +#: AperoDeDenis.py:7112 +msgid "Options :" +msgstr "Options:" + +#: AperoDeDenis.py:7113 +#, fuzzy +#| msgid " Précautions : " +msgid " - Points homologues : " +msgstr " Cautions:" + +#: AperoDeDenis.py:7114 +#, fuzzy +#| msgid "" +#| " L'échelle est la taille réduite de l'image (en " +#| "pixels, ou -1 pour l'image entière) pour la recherche des points " +#| "homologues." +msgid "" +" L'échelle est la taille en pixels de l'image (ou " +"-1 pour l'image entière) pour la recherche des points homologues." +msgstr "" +" The scale is the reduced size of the picture (in " +"pixels, or -1 for the whole picture) used for the tie-points search." + +#: AperoDeDenis.py:7115 +msgid "" +" Si le sujet est en ligne choisir 'line' dans les " +"options de Tapioca, " +msgstr "" +" If the subject is in " +"line, choose 'line' in Tapioca's options." + +#: AperoDeDenis.py:7116 +msgid "" +" puis delta = 1, si les " +"photos se recouvrent à moitiè, " +msgstr "" +" then delta = 1 if " +"pictures overlaps themselves to the half," + +#: AperoDeDenis.py:7117 +msgid "" +" ou delta = 2 voire +, " +"si le recouvrement est plus important." +msgstr "" +" or delta = 2 or more, if " +"they overlap themselves more." + +#: AperoDeDenis.py:7118 +msgid "" +" L'option ALl recherche les points homologues sur " +"toutes les paires de photos (ce qui peut faire beaucoup !)" +msgstr "" +" 'ALL' options will search tie-points on all " +"pictures pairs (whichcan beuch!)" + +#: AperoDeDenis.py:7119 +msgid "" +" L'option MulScale recherche les points homologues " +"en 2 temps :" +msgstr "" +" MulScale option search tie-point in 2 steps:" + +#: AperoDeDenis.py:7120 +msgid "" +" 1) sur toutes les paires avec une taille de " +"photo réduite (typiquement 300)" +msgstr "" +" 1) On all pairs with a picture size reduced " +"(typically 300)" + +#: AperoDeDenis.py:7121 +msgid "" +" 2) Seules les paires de photos ayant eu au " +"moins 2 points homologues à cette échelle seront" +msgstr "" +" 2) Only the pairs having at least two tie-" +"points on this scale will" + +#: AperoDeDenis.py:7122 +msgid "" +" retenues pour rechercher les points " +"homologues à la seconde échelle. Gain de temps important possible." +msgstr "" +" be used for the tie-points search on the " +"second scale. This can save a lot of time !" + +#: AperoDeDenis.py:7123 +#, fuzzy +#| msgid "" +#| " - Tapas : si l'appareil photo est un compact ou un " +#| "smartphone choisir RadialBasic, " +msgid "" +" - Orientation : si l'appareil photo est un compact ou un " +"smartphone choisir RadialBasic, " +msgstr "" +" - Tapas : if the camera is a compact or a smartphone, choose " +"RadialBasic," + +#: AperoDeDenis.py:7124 +msgid "" +" si l'appareil photo est un reflex haut de gamme " +"choisir RadialExtended " +msgstr "" +" if the camera is a top of the line reflex, choose " +"RadialExtended" + +#: AperoDeDenis.py:7125 +msgid "" +" si l'appareil photo est de moyenne gamme choisir " +"RadialStd" +msgstr "" +" if the camera is an average range camera, choose " +"RadialStd" + +#: AperoDeDenis.py:7126 +msgid "" +" Ces conseils ne sont pas toujours vérifiés : " +"modifeir votre choix s'il échoue. " +msgstr "" + +#: AperoDeDenis.py:7127 +#, fuzzy +#| msgid "" +#| " permet de définir un masque, 2D ou 3D, pour " +#| "l'étape suivante." +msgid "" +" L'arrêt après l'orientation permet de définir un " +"masque 3D, pour la densification par C3DC." +msgstr "" +" allow to create a 2D or 3D mask for the next step." + +#: AperoDeDenis.py:7128 +#, fuzzy +#| msgid "" +#| " - Calibration : permet de définir un repère et une " +#| "métrique (axe, plan et distance, tous obligatoires)." +msgid "" +" - Mise à l'échelle : permet de définir un repère et une " +"métrique (axe, plan et distance, tous obligatoires)." +msgstr "" +" - Calibration: allows to define a frame and a metric (axis, " +"plane and distance, all mandatory)" + +#: AperoDeDenis.py:7129 +#, fuzzy +#| msgid "" +#| " - GPS : définir au moins 3 points cotés et les placer sur " +#| "2 photos. La trace indique s'ils sont pris en compte" +msgid "" +" - Points GPS: définir au moins 3 points cotés et les placer " +"sur 2 photos. L'état du chantier indique s'ils sont pris en compte" +msgstr "" +" - GPS: allows to define at least three points and place it on " +"two pictures. The log shows if they're taken into account." + +#: AperoDeDenis.py:7130 +#, fuzzy +#| msgid "" +#| " - Malt : pour le mode GeomImage indiquer une ou plusieurs " +#| "images maîtresses." +msgid "" +" - Densification par Malt : pour le mode GeomImage indiquer " +"une ou plusieurs images maîtresses." +msgstr "" +" - Malt: for the GeomImage mode, select one or several master " +"pictures." + +#: AperoDeDenis.py:7131 +msgid "" +" Seuls les points visibles sur ces images seront " +"conservés dans le nuage de points." +msgstr "" +" Only the visible points on master pictures " +"will bie displayed in the point cloud." + +#: AperoDeDenis.py:7132 +msgid "" +" Sur ces images maîtresses tracer les masque " +"délimitant la partie 'utile' de la photo." +msgstr "" +" Draw the mask delimiting the useful area of these " +"pictures." + +#: AperoDeDenis.py:7133 +msgid "" +" Le résultat sera mis en couleur suivant les images " +"maitresses." +msgstr "" +" The result will be colored according to master " +"pictures." + +#: AperoDeDenis.py:7134 +msgid "" +" (éviter trop de recouvrement entre les maîtresses !)." +msgstr "" +" (avoid too many overlap between master pictures !)" + +#: AperoDeDenis.py:7135 +msgid "" +" Le traitement avec masque sera accéléré et le " +"résultat plus 'propre'." +msgstr "" +" Processing with a mask will be quicker and the " +"result will be cleaner." + +#: AperoDeDenis.py:7136 +#, fuzzy +#| msgid "" +#| " - C3DC : propose de définir un masque en 3D qui conservera " +#| "tout le volume concerné." +msgid "" +" - Densification par C3DC : propose de définir un masque en 3D " +"qui conservera tout le volume concerné." +msgstr "" +" - C3DC: allows to define a 3D mask keeping the concerned " +"volume." + +#: AperoDeDenis.py:7137 +#, fuzzy +#| msgid "" +#| " Alternative à Malt, le traitement est beaucoup " +#| "plus rapide. Nécessite la dernière version de MicMac." +msgid "" +" Alternative à Malt, le traitement est parfois plus " +"rapide. Nécessite une version récente de MicMac." +msgstr "" +" This options is a malt alternative in which the " +"process is far quicker. The last version of MicMac is required." + +#: AperoDeDenis.py:7138 +msgid "Si MicMac ne trouve pas d'orientation ou pas de nuage de points :" +msgstr "If MicMac can't find any orientation or point cloud:" + +#: AperoDeDenis.py:7139 +#, fuzzy +#| msgid "" +#| " - Examiner la qualité des photos (utiliser le menu outils/" +#| "Qualité des photos): ." +msgid "" +" - Examiner la trace et la qualité des photos (utiliser le " +"menu outils/Qualité des photos): ." +msgstr "" +" - Check the quality of the pictures (use the Tools/Quality of " +"the pictures):" + +#: AperoDeDenis.py:7140 +#, fuzzy +#| msgid " Le niveau 1 est le plus dense. " +msgid " 0) Prenez un pastis" +msgstr " Level 1 is the densest." + +#: AperoDeDenis.py:7141 +#, fuzzy +#| msgid " Si le mode est GeomImage : " +msgid "" +" 1) si erreur dans la trace : 'Radiale distorsion " +"abnormaly high' :" +msgstr " If GeomImage is the mod: " + +#: AperoDeDenis.py:7142 +#, fuzzy +#| msgid "" +#| " 4) modifier le type d'appareil pour Tapas " +#| "(radialstd ou radialbasic)" +msgid "" +" modifier le type d'appareil pour l'orientation " +"(radialstd ou radialbasic ou RadialExtended ou...)" +msgstr "" +" 4) Edit the camera type for Tapas (radialstd or " +"radialbasic)" + +#: AperoDeDenis.py:7143 +#, fuzzy +#| msgid "" +#| " 1) Eliminer les photos ayant les plus mauvais " +#| "scores" +msgid "" +" 2) Eliminer les photos ayant les plus mauvais " +"scores, les photos ou groupe de photos 'isolées" +msgstr " 1) Exclude pictures with the worst scores" + +#: AperoDeDenis.py:7144 +#, fuzzy +#| msgid "" +#| " 2) si ce n'est pas suffisant ne garder que les " +#| "meilleures photos (typiquement : moins de 10)" +msgid "" +" 3) si ce n'est pas suffisant ne garder que les " +"meilleures photos (typiquement : moins de 10)" +msgstr "" +" 2) If this is not enough, keep the best pictures " +"(less than 10)" + +#: AperoDeDenis.py:7145 +msgid "" +" Penser que des photos floues ou avec un sujet " +"brillant, lisse, mobile, transparent, vivant sont défavorables." +msgstr "" +" Keep in mind that blured pictures, or with a " +"shiny, smooth, transparent or moving subject must be avoided." + +#: AperoDeDenis.py:7146 +#, fuzzy +#| msgid "" +#| " 3) Augmenter l'échelle des photos pour tapioca, " +#| "mettre -1 au lieu de la valeur par défaut." +msgid "" +" 4) Augmenter l'échelle des photos pour tapioca, " +"mettre -1 au lieu de la valeur par défaut." +msgstr "" +" 3) Increase pictures scale for Tapioca, give it a -1 " +"value instead of the default value." + +#: AperoDeDenis.py:7147 +#, fuzzy +#| msgid "" +#| " Si il y a 2 focales différentes utiliser la calibration " +#| "intrinsèque de Tapas." +msgid "" +" 5) Utiliser la calibration intrinsèque sur des " +"photos adaptées" +msgstr "" +" If these are two different focal length, use Tapas " +"intrinsic calibration." + +#: AperoDeDenis.py:7148 +#, fuzzy +#| msgid "" +#| " Si l'appareil photo est un reflex haut de gamme " +#| "choisir RadialExtended " +msgid "" +" 6) Si plusieurs appareils photos sont utilisés il " +"faut les distinguer dans l'exif (voir menu expert)" +msgstr "" +" If the camera is a top of the line reflex, choose " +"RadialExtended" + +#: AperoDeDenis.py:7149 +#, fuzzy +#| msgid "" +#| " Si il y a 2 focales différentes utiliser la calibration " +#| "intrinsèque de Tapas." +msgid "" +" et prendre des photos spécifiques pour la " +"calibration intrinsèque de chaque appareil." +msgstr "" +" If these are two different focal length, use Tapas " +"intrinsic calibration." + +#: AperoDeDenis.py:7150 +#, fuzzy +#| msgid "" +#| " 5) vérifier la taille du capteur dans dicocamera, " +#| "nécessaire si la focale equivalente 35 mm est absente de l'exif" +msgid "" +" 7) vérifier la taille du capteur dans dicocamera, " +"nécessaire si la focale equivalente 35 mm est absente de l'exif" +msgstr "" +" 5) Check the sensor size in Dicocamera.xml, required " +"if the equivalent focal length 35mm is not in the exif" + +#: AperoDeDenis.py:7151 +#, fuzzy +#| msgid "" +#| " 6) examiner la trace synthétique et la trace " +#| "complète : MicMac donne quelques informations" +msgid "" +" 8) examiner la trace synthétique et la trace " +"complète : MicMac donne quelques informations" +msgstr "" +" 6) Check the syntethic and complete log: MicMac can " +"give you some important information" + +#: AperoDeDenis.py:7152 +msgid "" +" si la trace compléte contient : 'Error: -- Input " +"line too long, increase MAXLINELENGTH'" +msgstr "" + +#: AperoDeDenis.py:7153 +msgid "" +" alors tenter, sans certitude, de modifier le " +"fichier /binaire-aux/windows/startup/local.mk" +msgstr "" + +#: AperoDeDenis.py:7154 +#, fuzzy +#| msgid "" +#| " 7) consulter le forum micmac (http://forum-micmac." +#| "forumprod.com)" +msgid "" +" 9) consulter le wiki micmac (https://micmac.ensg.eu/" +"index.php)" +msgstr "" +" 7) Check MicMac forum (http://forum-micmac.forumprod." +"com)" + +#: AperoDeDenis.py:7155 +#, fuzzy +#| msgid "" +#| " 7) consulter le forum micmac (http://forum-micmac." +#| "forumprod.com)" +msgid "" +" 10) consulter le forum micmac (http://forum-micmac." +"forumprod.com)" +msgstr "" +" 7) Check MicMac forum (http://forum-micmac.forumprod." +"com)" + +#: AperoDeDenis.py:7156 +#, fuzzy +#| msgid "" +#| " 8) faites appel à l'assistance de l'interface " +#| "(voir adresse dans l'a-propos)" +msgid "" +" 11) faites appel à l'assistance de l'interface (voir " +"adresse dans l'a-propos)" +msgstr "" +" 8) Ask the GUI support (see mail in Help/About menu)" + +#: AperoDeDenis.py:7166 +msgid " Pour commencer avec l'interface graphique MicMac :" +msgstr " To get started with the MicMac's Graphical User Interface: " + +#: AperoDeDenis.py:7167 +msgid "" +" Tout d'abord : installer MicMac. Consulter le wiki MicMac : https://" +"micmac.ensg.eu/index.php" +msgstr "" + +#: AperoDeDenis.py:7168 +#, fuzzy +#| msgid "" +#| " Puis : installer Meshlab ou CloudCompare (pour afficher les nuages de " +#| "points)" +msgid "" +" Puis : installer CloudCompare (ou Meshlab) (pour afficher les nuages de " +"points)" +msgstr " Nest : install Meshlab or CloudCompare (to display point clouds)" + +#: AperoDeDenis.py:7169 +msgid " Ensuite, dans cette interface graphique :" +msgstr " Next, in the graphical User Interface:" + +#: AperoDeDenis.py:7170 +#, fuzzy +#| msgid "" +#| "1) Paramètrer l'interface : indiquer ou se trouvent le répertoire bin de " +#| "MicMac et l'éxécutable Meshlab ou CloudCompare." +msgid "" +"1) Paramètrer l'interface : indiquer ou se trouvent le répertoire bin de " +"MicMac et l'éxécutable CloudCompare (ou Meshlab)." +msgstr "" +"1) Interface parameters: set directory of MicMac\\bin and Meshlab or " +"Cloudcompare's executable." + +#: AperoDeDenis.py:7171 +msgid "" +" Indiquer éventuellement ou se trouvent exiftool et convert d'ImageMagick " +"(en principe sous MicMac\\binaire-aux)." +msgstr "" +" You can also indicate exiftool and ImageMagick's convert directories " +"(normally Under MicMac\\binaire-aux)." + +#: AperoDeDenis.py:7172 +#, fuzzy +#| msgid "Désigner le fichier exiftool (menu paramétrage)." +msgid " Vérifier en affichant les paramètres (menu paramètrage)." +msgstr "Select the exiftool file (settings menu)" + +#: AperoDeDenis.py:7173 +msgid "" +"2) Choisir quelques photos (4 à 6) pour commencer (menu MicMac/choisir des " +"photos)." +msgstr "" + +#: AperoDeDenis.py:7174 +#, fuzzy +#| msgid "" +#| "3) Lancer MicMac en laissant les paramètres par défaut (menu MicMac)." +msgid "" +"3) Lancer MicMac en laissant les paramètres par défaut (menu MicMac/lancer " +"Micmac)." +msgstr "3) Launch MicMac and choose default settings (MicMac menu)" + +#: AperoDeDenis.py:7175 +#, fuzzy +#| msgid "" +#| " Si tout va bien une vue en 3D non densifiée doit s'afficher, " +#| "patience : cela peut être long." +msgid "" +" Si tout va bien une vue en 3D non densifiée doit s'afficher, puis une vue " +"3D densifiée. Patience : cela peut être long." +msgstr "" +" If everything's fine, a non densified 3D view must be displayed: be " +"patient, it can be long." + +#: AperoDeDenis.py:7176 +#, fuzzy +#| msgid "" +#| "5) Si tout ne va pas bien re 'lancer MicMac' et annuler le traitement, " +#| "puis :" +msgid "4) Si tout ne va pas bien prendre un pastis puis :" +msgstr "5) If something doesn't work, cancel processing and then: " + +#: AperoDeDenis.py:7177 +msgid " Lire 'quelques conseils' (menu Aide)." +msgstr " Read 'Advices' (Help menu)" + +#: AperoDeDenis.py:7178 +msgid " Tester la qualité des photos (menu Outils)." +msgstr " Test the quality of the pictures (Tools menu)" + +#: AperoDeDenis.py:7179 +msgid " Examiner les traces (menu Edition)," +msgstr " Read logs (Edit menu)" + +#: AperoDeDenis.py:7180 +msgid " Consulter l'aide (menu Aide)," +msgstr " Read Help (Help menu)" + +#: AperoDeDenis.py:7181 +msgid "" +" Consulter le guide d'installation et de prise en main de l'interface." +msgstr " See installation and grip guide of the GUI" + +#: AperoDeDenis.py:7182 +msgid " Consulter le forum MicMac sur le net, consulter la doc MicMac." +msgstr " See MicMac forum and doc." + +#: AperoDeDenis.py:7183 +#, fuzzy +#| msgid "6) Si une solution apparaît : modifier les options (menu MicMac)." +msgid "" +"5) Si une solution apparaît : modifier les options (menu MicMac/options)." +msgstr "6) If a solution appear: edit options (MicMac menu)" + +#: AperoDeDenis.py:7184 +msgid " puis relancer le traitement." +msgstr " then relaunch the process." + +#: AperoDeDenis.py:7185 +#, fuzzy +#| msgid "" +#| "7) Si le problème persiste faire appel à l'assistance de l'interface " +#| "(adresse mail dans l'A-propos)" +msgid "" +"6) Si le problème persiste faire appel à l'assistance de l'interface " +"(adresse mail dans Aide/A-propos)" +msgstr "7) If you can't solve the problem, mail the assistance (mail in About)" + +#: AperoDeDenis.py:7190 +msgid "Historique des versions diffusées sur le site de l'IGN" +msgstr "History of published versions on IGN's website" + +#: AperoDeDenis.py:7192 +msgid "" +"Version 1.5 : première version diffusée sur le site de l'IGN le 23/11/2015." +msgstr "Version 1.5:" + +#: AperoDeDenis.py:7193 +msgid "" +"Version 1.55 : sous Windows le fichier paramètre est placé sous le " +"répertoire APPDATA de l'utilisateur," +msgstr "" +"Version 1.55 : On Windows, the settings file is saved in the user's APPDATA " +"directory," + +#: AperoDeDenis.py:7194 +msgid "" +"ce qui règle les questions relatives aux droits d'accès en écriture. Mise en " +"ligne le 04/12/2015." +msgstr "solving writing permissions problems. 04/12/2015." + +#: AperoDeDenis.py:7195 +msgid "Version 1.60 : ajout des fonctions :" +msgstr "Version 1.60 : Functions added :" + +#: AperoDeDenis.py:7196 +msgid "- Qualité des photos lors du dernier traitement" +msgstr "- Quality of the pictures of last process." + +#: AperoDeDenis.py:7197 +msgid "- Exporter le chantier en cours" +msgstr "-Export current project" + +#: AperoDeDenis.py:7198 +msgid "" +"- Importer un chantier (permet de recopier le chantier sur un autre " +"répertoire, disque, ordinateur, système d'exploitation)" +msgstr "" +"-Importing project (allow to copy the project in a new directory, disk, " +"computer or operating system)" + +#: AperoDeDenis.py:7199 +msgid "- Les fichiers 'trace' sont enregistrés au format utf-8." +msgstr "- Log files are now saved in utf-8 format." + +#: AperoDeDenis.py:7200 +msgid "Version 2.00 : ajout des fonctions :" +msgstr "Version 2.00 : Functions added :" + +#: AperoDeDenis.py:7201 +msgid "- Choix de photos pour la calibration intrinsèque par Tapas." +msgstr "- Pictures selection for intrinsic calibration by Tapas." + +#: AperoDeDenis.py:7202 +msgid "" +"- Possibilité de relancer Malt sans relancer Tapioca/Tapas tout en " +"conservant les images 3D générées." +msgstr "" +"- Possibility to relaunch Malt without relaunching Tapioca/Tapas and " +"conserving 3D pictures generated." + +#: AperoDeDenis.py:7203 +msgid "" +"- Conservation de plusieurs fichiers modele3D.ply après Malt pour un même " +"chantier." +msgstr "" +"- Retention of several 3Dmodels .ply files after Malt for a same project." + +#: AperoDeDenis.py:7204 +msgid "" +"- Choix du niveau de zoom d'arrêt de la procédure Malt : de 1 (par défaut) à " +"8." +msgstr "" +"- Choice in zoom level for stopping the Malt process: 1 (default) to 8." + +#: AperoDeDenis.py:7205 +msgid "" +"- Création de tous les fichiers .ply correspondants à tous les niveaux de " +"zoom calculés." +msgstr "" +" - Creation of all .ply files corresponding to the different zoom levels " +"calculated." + +#: AperoDeDenis.py:7206 +msgid "" +"- Ajout d'un item du menu édition listant et visualisant toutes les images " +"3D générées." +msgstr "" +" - Item added in the Edit menu which list and allows to display all 3D " +"generated pictures." + +#: AperoDeDenis.py:7207 +msgid "" +"- Choix du nombre de photos à retenir autour de l'image maître pour Malt." +msgstr "" +" - Choice of the number of pictures to use with the Malt's master picture." + +#: AperoDeDenis.py:7208 +msgid "" +"- Traitement des vidéos (par exemple GoPro) : décompactage, sélection, mise " +"à jour de l'exif" +msgstr "" +" - Video processing (with GoPro, for instance): unpacking, selecting, exif " +"update." + +#: AperoDeDenis.py:7209 +msgid "" +"- Ajout de deux contrôles sur le lot des photos : mêmes dimensions, même " +"focale." +msgstr "" +" - Two new controls of pictures pack: same dimensions and same focal length." + +#: AperoDeDenis.py:7210 +msgid "- Ajout d'un item 'historique' dans le menu Aide." +msgstr " - Item \"History log\" added to the Help menu." + +#: AperoDeDenis.py:7211 +msgid "Version 2.10" +msgstr "Version 2.10:" + +#: AperoDeDenis.py:7211 +msgid "- Ajout d'un item du menu édition fusionnant les images 3D." +msgstr " - Item \"Merge 3D pictures\" in the Edit menu." + +#: AperoDeDenis.py:7212 +msgid "- Plusieurs images maîtresses, plusieurs masques." +msgstr "- Several master pictures and masks." + +#: AperoDeDenis.py:7213 +msgid "- Conversion automatique des fichiers PNG, BMP, GIF, TIF en JPG" +msgstr "- Automatic conversion of fil formats PNG, BMP, GIF and TIF into JPG." + +#: AperoDeDenis.py:7214 +msgid "" +"- Ajout d'un item du menu Outils permettant de modifier les exifs. Diffusion " +"restreinte à la DTer NC le 16/02/2016" +msgstr "" +"- An item was added in the Tools menu, that allow to edit exifs. Restricted " +"diffusion at DTer NC on 16/02/2016" + +#: AperoDeDenis.py:7215 +msgid "Version 2.20 :" +msgstr "Version 2.20:" + +#: AperoDeDenis.py:7215 +msgid "" +"- Maintien des options compatibles lors du choix de nouvelles photos. " +"Février 2016" +msgstr "" +"- Maintaining compatibles options when choosing new pictures. February 2016" + +#: AperoDeDenis.py:7216 +msgid "Version 2.30 : " +msgstr "Version 2.30:" + +#: AperoDeDenis.py:7217 +msgid "- Modification des options par défaut dans le menu outils." +msgstr "- Default options can be edited in the Tools menu." + +#: AperoDeDenis.py:7218 +msgid "Version 2.40 :" +msgstr "Version 2.40:" + +#: AperoDeDenis.py:7218 +msgid "- Choix de l'option (Statue ou QuickMac) pour C3DC. Avril 2016" +msgstr " - Option choice (C3DC or QuickMac) for C3DC. April 2016" + +#: AperoDeDenis.py:7219 +msgid "Version 2.45 :" +msgstr "Version 2.45:" + +#: AperoDeDenis.py:7219 +msgid "" +"- Référentiel GPS calculé après Tapas (et toujours avant Malt). La virgule " +"est un séparateur décimal accepté." +msgstr "" +" - GPS repository calculated after Tapas (still before Malt). The comma is " +"accepted as a decimal separator." + +#: AperoDeDenis.py:7220 +msgid "" +"- Possiblité d'appliquer la calibration GPS sans relancer malt. Mai 2016" +msgstr " - GPS calibration can be applied without relaunching Malt. May 2016" + +#: AperoDeDenis.py:7221 +msgid "Version 2.50 :" +msgstr "Version 2.50:" + +#: AperoDeDenis.py:7221 +#, fuzzy +#| msgid "" +#| "- Ajout de Tawny aprés Malt en mode Ortho, désactivation du message de " +#| "lancement. Juin 2016" +msgid "" +"- Ajout de Tawny après Malt en mode Ortho, désactivation du message de " +"lancement. Juin 2016" +msgstr "" +" - Adding Tawny after Malt in Ortho mode, launching message can be " +"desactivated. June 2016" + +#: AperoDeDenis.py:7222 +msgid "Version 3.00 :" +msgstr "Version 3.00:" + +#: AperoDeDenis.py:7222 +msgid "- Version bilingue Français/Anglais. Octobre 2016" +msgstr "- Bilingual version French / English. October 2016" + +#: AperoDeDenis.py:7223 +msgid "Version 3.10 :" +msgstr "Version 3.10:" + +#: AperoDeDenis.py:7223 +msgid "- Choix des N meilleures photos pour un nouveau dossier. Novembre 2016" +msgstr "- Choice of N best photos for a new folder. November 2016" + +#: AperoDeDenis.py:7224 +msgid "Version 3.20 :" +msgstr "Version 3.20:" + +#: AperoDeDenis.py:7224 AperoDeDenis.py:7232 +msgid "janvier 2017" +msgstr "January 2017" + +#: AperoDeDenis.py:7225 +msgid "" +"- Ajout d'un choix pour Malt : AperoDeDenis, l'interface recherche pour vous " +"les maîtresses et les photos correspondantes" +msgstr "" +"- Added a choice for Malt: AperoDeDenis, the interface looks for you the " +"mistresses and the corresponding photos" + +#: AperoDeDenis.py:7226 +msgid "" +"- Item de sélection des meilleures images pour créer un nouveau chantier. " +"janvier 2017" +msgstr "" +"- Item of selection of the best images to create a new site. January 2017" + +#: AperoDeDenis.py:7227 +msgid "- Possibilité de saisir une unité avec la distance." +msgstr "- Ability to enter a unit with distance." + +#: AperoDeDenis.py:7228 +msgid "- Lancement de Tapas accéléré : suppression du controle des photos" +msgstr "- Launch of accelerated Tapas removal of pictures of control" + +#: AperoDeDenis.py:7229 +msgid "" +"- Les photos autour de la maîtresse pour Malt sont choisies parmi les " +"meilleures en correspondances" +msgstr "" +"- Photos around the mistress for Malt are chosen among the best in matches" + +#: AperoDeDenis.py:7230 +msgid "- Controle affiné des points GPS, message informatif détaillé" +msgstr "- Refined control of GPS points, detailed informative message" + +#: AperoDeDenis.py:7231 +msgid "- Possibilité de supprimer UN seul point GPS sur une photo" +msgstr "- Ability to delete a single GPS point on a photo" + +#: AperoDeDenis.py:7232 +msgid "Version 3.30 :" +msgstr "Version 3.30 :" + +#: AperoDeDenis.py:7233 +#, fuzzy +#| msgid "- Ajout de tarama : création d'une mosaïque aprés Tapas." +msgid "- Ajout de tarama : création d'une mosaïque après Tapas." +msgstr "- Added tarama: creation of a mosaic after Tapas." + +#: AperoDeDenis.py:7234 +msgid "- le mode Ortho de Malt utilise la mosaïque tarama, avec masque" +msgstr "- Malt's Ortho mode uses the mosaic tarama, with mask" + +#: AperoDeDenis.py:7235 +msgid "- drapage du nuage densifié par l'ortho mosaïque obtenue par Tawny" +msgstr "- draping of the densified cloud by the ortho mosaic obtained by Tawny" + +#: AperoDeDenis.py:7236 +msgid "- Possibilité d'inverser les masques 2D" +msgstr "- Possibility of reversing 2D masks" + +#: AperoDeDenis.py:7237 +msgid "- Ouverture des mosaïques Tarama et Tawny par menu" +msgstr "- Opening Tarama and Tawny mosaics by menu" + +#: AperoDeDenis.py:7238 +msgid "- Ajout d'un menu 'expert' permettant de saisir une ligne de commande." +msgstr "- Added an 'expert' menu to enter a command line." + +#: AperoDeDenis.py:7239 +msgid "Version 3.31 :" +msgstr "Version 3.31 :" + +#: AperoDeDenis.py:7239 +msgid "février 2017" +msgstr "February 2017" + +#: AperoDeDenis.py:7240 +msgid "" +"- Ajout d'un item du menu 'expert' : recopie les points GPS d'un chantier à " +"un autre." +msgstr "" +"- Added an item from the 'Expert' menu: Copies GPS points from one job site " +"to another." + +#: AperoDeDenis.py:7241 +#, fuzzy +#| msgid "Version 3.30 :" +msgid "Version 3.34 :" +msgstr "Version 3.30 :" + +#: AperoDeDenis.py:7241 AperoDeDenis.py:7246 +#, fuzzy +#| msgid "janvier 2017" +msgid "Janvier 2018" +msgstr "January 2017" + +#: AperoDeDenis.py:7242 +msgid "" +"- Du ménage! permet de conserver les résultats OU de supprimer tout le " +"chantier." +msgstr "" + +#: AperoDeDenis.py:7243 +#, fuzzy +#| msgid "Affichage de la surface interpolée" +msgid "- Affichage de la taille du dossier." +msgstr "Display the interpolated area" + +#: AperoDeDenis.py:7244 +msgid "- Correction de régressions de la V 3.20." +msgstr "" + +#: AperoDeDenis.py:7245 +msgid "" +"Remarque : la version 4.11 de décembre 2017 ajoute un item métier de calcul " +"d'indice surfacique," +msgstr "" + +#: AperoDeDenis.py:7246 +#, fuzzy +#| msgid "Version 2.20 :" +msgid "Version 5.0 :" +msgstr "Version 2.20:" + +#: AperoDeDenis.py:7247 +msgid "la version suivante 5.0 supprime l'item 'indices surfaciques'." +msgstr "" + +#: AperoDeDenis.py:7248 +#, fuzzy +#| msgid "Version 3.10 :" +msgid "Version 5.1 :" +msgstr "Version 3.10:" + +#: AperoDeDenis.py:7248 +msgid "décembre 2018" +msgstr "" + +#: AperoDeDenis.py:7249 +msgid "" +"- permet d'oublier les photos ayant servies à la calibration de l'appareil " +"pour l'exécution de Tapas." +msgstr "" + +#: AperoDeDenis.py:7250 +msgid "" +"- insertion d'un fichier texte de points GPS par le menu expert (séparateur " +"espace : nom,x,y,z,dx,dy,dz." +msgstr "" + +#: AperoDeDenis.py:7251 +#, fuzzy +#| msgid "fournit les dimensions de tous les appareils photos." +msgid "" +"- affichage des dimensions des photos dans le menu outils/nom de l'appareil " +"photo" +msgstr "Provides dimensions of all cameras." + +#: AperoDeDenis.py:7252 +msgid "" +"- Amélioration de libellés de boites de dialogue, suppression du polysème " +"'calibration'" +msgstr "" + +#: AperoDeDenis.py:7253 +#, fuzzy +#| msgid "Version 2.20 :" +msgid "Version 5.2 :" +msgstr "Version 2.20:" + +#: AperoDeDenis.py:7253 +#, fuzzy +#| msgid "janvier 2017" +msgid "janvier 2019" +msgstr "January 2017" + +#: AperoDeDenis.py:7254 +msgid "" +"- ajout du modulé CAMPARI après chaque géolocalisation par points GPS " +"(améliore les valeurs des Z)." +msgstr "" + +#: AperoDeDenis.py:7255 +msgid "" +"- répartition des photos provenant de plusieurs appareils par modification " +"du 'model' dans l'exif (menu expert)" +msgstr "" + +#: AperoDeDenis.py:7256 +msgid "" +"- affichage des noms des appareils photos présents dans le chantier (menu " +"expert)" +msgstr "" + +#: AperoDeDenis.py:7257 +msgid "" +"- affichage du log des traitement MicMac : mm3d-logFile.txt (menu expert)" +msgstr "" + +#: AperoDeDenis.py:7258 +msgid "" +"- amélioration de la fonction console système (Expert/Exécuter une commande)" +msgstr "" + +#: AperoDeDenis.py:7259 +#, fuzzy +#| msgid "Version 2.20 :" +msgid "Version 5.21 :" +msgstr "Version 2.20:" + +#: AperoDeDenis.py:7259 +#, fuzzy +#| msgid "février 2017" +msgid "février 2019" +msgstr "February 2017" + +#: AperoDeDenis.py:7260 +msgid "- Argument de Tapas aprés calibration : Figee (au lieu de Autocal)" +msgstr "" + +#: AperoDeDenis.py:7261 +msgid "- Ajout dans le menu expert d'un console python" +msgstr "" + +#: AperoDeDenis.py:7262 +#, fuzzy +#| msgid "Version 2.20 :" +msgid "Version 5.22 :" +msgstr "Version 2.20:" + +#: AperoDeDenis.py:7262 +#, fuzzy +#| msgid "février 2017" +msgid "11 février 2019" +msgstr "February 2017" + +#: AperoDeDenis.py:7263 +msgid "- fix 2 issues remontées sur github, numéro de version inchangée : 5.21" +msgstr "" + +#: AperoDeDenis.py:7264 +#, fuzzy +#| msgid "Version 3.30 :" +msgid "Version 5.30 :" +msgstr "Version 3.30 :" + +#: AperoDeDenis.py:7264 +#, fuzzy +#| msgid "février 2017" +msgid "21 février 2019" +msgstr "February 2017" + +#: AperoDeDenis.py:7265 +msgid "" +"- dans les items 'Outils/Qualité des photos' ajout des photos 'isolées', en " +"disjontion de toutes les autres." +msgstr "" + +#: AperoDeDenis.py:7266 +msgid " Ces photos font 'planter' la recherche de l'orientation." +msgstr "" + +#: AperoDeDenis.py:7267 +msgid "" +"- Suite à la recherche des points homologues vérification de l'unicité de la " +"scène photographiée." +msgstr "" + +#: AperoDeDenis.py:7268 +msgid "" +" Plusieurs scènes sans point homologue commun font planter la recherche " +"d'une orientation." +msgstr "" + +#: AperoDeDenis.py:7269 +msgid " Cette fonction est ajoutée à l'item 'Outils/Qualité des photos'." +msgstr "" + +#: AperoDeDenis.py:7270 +msgid "" +"- Lorsque le message MAXLINELENGTH est émis par Tapioca il est affiché et " +"expliqué dans la trace synthétique." +msgstr "" + +#: AperoDeDenis.py:7271 +msgid "" +"- prise en compte de l'issue concernant la fonction filedialog sous Mac-Os " +"lors des recherche de programmes (exiftool...)." +msgstr "" + +#: AperoDeDenis.py:7272 +msgid "" +"- Ajout d'un item dans paramètrage : recherche d'une nouvelle version GitHub." +msgstr "" + +#: AperoDeDenis.py:7283 +#, fuzzy +#| msgid "Réalisation Denis Jouin 2015-2016" +msgid "Réalisation Denis Jouin 2015-2019" +msgstr "Created by Denis Jouin 2015 - 2016" + +#: AperoDeDenis.py:7283 +msgid "Laboratoire Régional de Rouen" +msgstr "Laboratoire Régional de Rouen" + +#: AperoDeDenis.py:7284 +msgid "CEREMA Normandie Centre" +msgstr "" + +#: AperoDeDenis.py:7300 +msgid "erreur canvas logo cerema : " +msgstr "Canvas error 'logo cerema':" + +#: AperoDeDenis.py:7388 +msgid "erreur sauveParamChantier : " +msgstr "error sauveParamChantier:" + +#: AperoDeDenis.py:7416 +msgid "erreur sauveParamMicMac : " +msgstr "error sauveParamMicMac:" + +#: AperoDeDenis.py:7417 +msgid "" +"L'interface doit être installée dans un répertoire ou vous avez les droits " +"d'écriture." +msgstr "" +"The Graphical User Interface must be installed in a directory on which you " +"have write permissions." + +#: AperoDeDenis.py:7418 +msgid "" +"Installer l'interface AperoDeDenis à un emplacement ou vous avez ce droit." +msgstr "Install AperoDeDenis in a directory which on you have this permission." + +#: AperoDeDenis.py:7419 +msgid "Répertoire actuel : " +msgstr "Current directory:" + +#: AperoDeDenis.py:7420 +msgid "Erreur rencontrée : " +msgstr "Encountered error: " + +#: AperoDeDenis.py:7421 +msgid "Problème d'installation" +msgstr "Installation problem: " + +#: AperoDeDenis.py:7458 +msgid "Erreur restauration param généraux : " +msgstr "Error loading general settings: " + +#: AperoDeDenis.py:7550 +msgid "Erreur restauration param chantier : " +msgstr "Error loading project settings:" + +#: AperoDeDenis.py:7560 +msgid "erreur définir fichier trace, est normale lors d'une importation." +msgstr "Error define log trace. Normal when importing." + +#: AperoDeDenis.py:7735 +msgid "Fermer les options." +msgstr "Close options." + +#: AperoDeDenis.py:7735 +msgid "" +"La boîte de dialogue 'options' est ouverte et va être fermée.\n" +"Voulez-vous enregistrer les options saisies ?" +msgstr "" + +#: AperoDeDenis.py:7735 AperoDeDenis.py:7748 AperoDeDenis.py:7760 +msgid "enregistrer" +msgstr "save" + +#: AperoDeDenis.py:7735 AperoDeDenis.py:7748 AperoDeDenis.py:7760 +msgid "abandon" +msgstr "abort" + +#: AperoDeDenis.py:7748 +msgid "Fermer les options vidéo." +msgstr "Close video options." + +#: AperoDeDenis.py:7748 +msgid "Enregistrer les options vidéos saisies ?" +msgstr "Save these video options values?" + +#: AperoDeDenis.py:7760 +msgid "Fermer la modification des exifs." +msgstr "Close exif edit." + +#: AperoDeDenis.py:7760 +msgid "Enregistrer les valeurs saisies ?" +msgstr "Save choosen values ?" + +#: AperoDeDenis.py:7789 +msgid "Nouvelle version de l'interface AperoDeDenis" +msgstr "New version of the AperoDeDenis interface" + +#: AperoDeDenis.py:7790 +msgid "Nouvelle version disponible sur Internet : " +msgstr "New version available on the Internet:" + +#: AperoDeDenis.py:7792 +msgid "Téléchargement à l'adresse : " +msgstr "Download at:" + +#: AperoDeDenis.py:7794 AperoDeDenis.py:8143 AperoDeDenis.py:9666 +msgid "OK" +msgstr "OK" + +#: AperoDeDenis.py:7795 +msgid "Accéder au site" +msgstr "Access the site" + +#: AperoDeDenis.py:7796 +msgid "Ne plus me le rappeler" +msgstr "Do not remind me anymore" + +#: AperoDeDenis.py:7804 +msgid "Recherche sur internet en cours, patience..." +msgstr "" + +#: AperoDeDenis.py:7810 +#, fuzzy +#| msgid "erreur connexion internet : " +msgid "Erreur lors de la tentative de connexion à internet : " +msgstr "Internet connection error:" + +#: AperoDeDenis.py:7820 +#, fuzzy +#| msgid "Valider et mettre à jour" +msgid "Version actuelle à jour" +msgstr "Confirm and update" + +#: AperoDeDenis.py:7830 +msgid "Tous les chantiers sont déjà supprimés." +msgstr "All projects have already been deleted." + +#: AperoDeDenis.py:7844 +#, fuzzy +#| msgid "Chantiers à supprimer" +msgid "Chantiers à nettoyer ou supprimer" +msgstr "Project to delete" + +#: AperoDeDenis.py:7848 AperoDeDenis.py:8232 +msgid "repertoires" +msgstr "directories" + +#: AperoDeDenis.py:7857 AperoDeDenis.py:7866 +#, fuzzy +#| msgid "Suppression des répertoires de travail superflus" +msgid "Suppression ou nettoyage des répertoires de travail superflus" +msgstr "Deleting useless working directories..." + +#: AperoDeDenis.py:7858 +#, fuzzy +#| msgid "Le répertoire suivant va être supprimé, sans mise en corbeille :" +msgid "Le chantier suivant va être supprimé ou nettoyé :" +msgstr "Following directory will be deleted for good:" + +#: AperoDeDenis.py:7859 +#, fuzzy +#| msgid "Supprimer tous les points" +msgid "Supprimer totalement le chantier" +msgstr "Remove all points" + +#: AperoDeDenis.py:7860 +#, fuzzy +#| msgid "Débloquer le chantier - garder les résultats" +msgid "Nettoyer le chantier, conserver les résultats" +msgstr "Unblock project - keep the results." + +#: AperoDeDenis.py:7864 +#, fuzzy +#| msgid "ATTENTION : le chantier en cours va être supprimé." +msgid "ATTENTION : le chantier en cours va être nettoyéé." +msgstr "Warning: current project will be deleted." + +#: AperoDeDenis.py:7867 +#, fuzzy +#| msgid "Ces chantiers ne peuvent être ouverts mais peuvent être supprimés :" +msgid "Les chantiers suivant vont être supprimés ou nettoyés :" +msgstr "These projects can't be opened but can be deleted: " + +#: AperoDeDenis.py:7868 +#, fuzzy +#| msgid "Supprimer tous les points" +msgid "Supprimer totalement les chantiers" +msgstr "Remove all points" + +#: AperoDeDenis.py:7869 +#, fuzzy +#| msgid "Débloquer le chantier - garder les résultats" +msgid "Nettoyer les chantier, conserver les résultats" +msgstr "Unblock project - keep the results." + +#: AperoDeDenis.py:7876 +msgid "Suppression en cours...." +msgstr "Deleting..." + +#: AperoDeDenis.py:7882 +#, fuzzy, python-format +#| msgid "ATTENTION : le chantier en cours va être supprimé." +msgid "Le chantier en cours %s est supprimé." +msgstr "Warning: current project will be deleted." + +#: AperoDeDenis.py:7898 AperoDeDenis.py:7900 +msgid "Compte rendu de la suppression :" +msgstr "Suppression's log:" + +#: AperoDeDenis.py:7898 +msgid "Repertoires supprimés :" +msgstr "Deleted directories:" + +#: AperoDeDenis.py:7900 +msgid "Aucun répertoire supprimé." +msgstr "No deleted directory:" + +#: AperoDeDenis.py:7903 +msgid "Tous les chantiers demandés sont supprimés." +msgstr "All projects asked where deleted." + +#: AperoDeDenis.py:7905 +msgid "Il reste un chantier impossible à supprimer maintenant : " +msgstr "A project can't be deleted now:" + +#: AperoDeDenis.py:7907 +msgid "Il reste des chantiers impossibles à supprimer maintenant : " +msgstr "Some projects can't be deleted now:" + +#: AperoDeDenis.py:7908 AperoDeDenis.py:7927 +msgid "Espace disque récupéré : " +msgstr "" + +#: AperoDeDenis.py:7916 +#, fuzzy +#| msgid "Suppression des répertoires de travail superflus" +msgid "Suppression des sous-répertoires en cours...." +msgstr "Deleting useless working directories..." + +#: AperoDeDenis.py:7934 +msgid "Choisir" +msgstr "Choose" + +#: AperoDeDenis.py:7934 +msgid "Choisir : " +msgstr "Choose:" + +#: AperoDeDenis.py:8004 +msgid " : lancement de " +msgstr " : launching" + +#: AperoDeDenis.py:8013 +msgid "erreur lors de l'éxécution de la commande :" +msgstr "Error executing command:" + +#: AperoDeDenis.py:8014 AperoDeDenis.py:8022 AperoDeDenis.py:8044 +msgid " : fin de " +msgstr " : ending " + +#: AperoDeDenis.py:8021 +msgid "erreur lors de l'éxécution de la commande." +msgstr "Error executing command:" + +#: AperoDeDenis.py:8037 +msgid "erreur lecture output : " +msgstr "Error reading output:" + +#: AperoDeDenis.py:8059 +msgid "Trace complète" +msgstr "Complete log" + +#: AperoDeDenis.py:8060 +msgid "Trace synthétique" +msgstr "Synthetic log" + +#: AperoDeDenis.py:8063 +msgid "Choix des photos :" +msgstr "Pictures choice:" + +#: AperoDeDenis.py:8064 +msgid "répertoire du chantier :" +msgstr "Project directory:" + +#: AperoDeDenis.py:8065 +msgid "Version MicMac : " +msgstr "MicMac version: " + +#: AperoDeDenis.py:8123 +msgid "erreur ecritureTraceMicMac : " +msgstr "ecritureTraceMicMac error:" + +#: AperoDeDenis.py:8140 +msgid "Choisir une photo" +msgstr "Choose a picture" + +#: AperoDeDenis.py:8141 +msgid "Cliquer pour choisir une ou plusieurs photos : " +msgstr "Click to select one or several pictures" + +#: AperoDeDenis.py:8149 +msgid "Pas de photos pour cette demande." +msgstr "No pictures for this request." + +#: AperoDeDenis.py:8161 +msgid "Les fichiers suivants sont absents du disque :" +msgstr "Following files are not found:" + +#: AperoDeDenis.py:8161 +msgid "Dossier corrompu. Traitement interrompu." +msgstr "Corrupted directory. Aborted." + +#: AperoDeDenis.py:8260 +msgid "Options GoPro modifiées" +msgstr "GoPro options edited." + +#: AperoDeDenis.py:8272 +msgid "Abandon : options GoPro inchangées." +msgstr "Aborted: GoPro option unchanged." + +#: AperoDeDenis.py:8290 +msgid "" +"L'outil ffmpeg n'est pas installé sur votre ordinateur. Traitement des vidéo " +"GoPro impossible." +msgstr "ffmpeg tool not installet on computer. GoPro video process impossible." + +#: AperoDeDenis.py:8297 +#, python-format +msgid "" +"Choisir la video issue d'un appareil %(GoProMaker)s %(GoProName)s (sinon " +"modifier les options)" +msgstr "" +"Select a video from a %(GoProMaker)s %(GoProName)s camera (or else edit " +"options)" + +#: AperoDeDenis.py:8299 +msgid "Video" +msgstr "Video" + +#: AperoDeDenis.py:8303 +msgid "" +"Abandon, aucune sélection,\n" +" le chantier reste inchangé." +msgstr "Aborting, no selection, project unchanged." + +#: AperoDeDenis.py:8307 +#, python-format +msgid "" +"La version actuelle ne traite que les videos au format MP4, or le format des " +"photos est %s. Désolé." +msgstr "" +"Current version can only be used with video in .MP4 format. This format is " +"%s. " + +#: AperoDeDenis.py:8326 +msgid "Décompacte la vidéo" +msgstr "Unpack the video" + +#: AperoDeDenis.py:8331 +msgid "L'outil ffmpeg est absent." +msgstr "The ffmpeg tool is missing." + +#: AperoDeDenis.py:8331 +msgid "Il convient de l'associer." +msgstr "It should be associated." + +#: AperoDeDenis.py:8338 +msgid "Aucune image décompactée : consulter la trace." +msgstr "No picture unpacked: see log for more details." + +#: AperoDeDenis.py:8365 +msgid "Les images de la video sont décompactées sous le répertoire :" +msgstr "Video's pictures were unpacked in the following directory:" + +#: AperoDeDenis.py:8366 +#, python-format +msgid "Il y a %s images décompactées." +msgstr "%s pictures unpacked." + +#: AperoDeDenis.py:8367 +#, python-format +msgid "" +"Lancer 'Sélection des images' pour sélectionner %s images par seconde de " +"film." +msgstr "Launch 'Pictures select' to select %s pictures per second of video." + +#: AperoDeDenis.py:8368 +msgid "La sélection choisira les 'meilleures' images" +msgstr "The selection will choose the best pictures." + +#: AperoDeDenis.py:8369 +msgid "" +"Les options Tapioca et Tapas ont été positionnées pour des images GoPro : " +"modifier si besoin" +msgstr "Tapas and Tapioca options are for GoPro pictures: edit if necessary." + +#: AperoDeDenis.py:8379 +msgid "met à jour l'exif des JPG décompactés :" +msgstr "Update exif from uncompressed JPG:" + +#: AperoDeDenis.py:8413 +msgid "Cette sélection de photos est réservé aux chantiers vidéos" +msgstr "This pictures selection is for video projects only." + +#: AperoDeDenis.py:8422 AperoDeDenis.py:8460 +msgid "Sélection d'un sous ensemble des images GoPro décompactées." +msgstr "Selecting an unpacked pictures subset." + +#: AperoDeDenis.py:8434 AperoDeDenis.py:8473 +msgid " a supprimer : " +msgstr "to delete:" + +#: AperoDeDenis.py:8442 +msgid "" +"Aucune sélection effectuée. La version de micmac ne propose peut-être pas " +"cette fonction." +msgstr "No selection made. The micmac version may not offer this feature." + +#: AperoDeDenis.py:8442 AperoDeDenis.py:8481 AperoDeDenis.py:8816 +#: AperoDeDenis.py:8982 AperoDeDenis.py:9000 +msgid "Consulter la trace." +msgstr "Read the log." + +#: AperoDeDenis.py:8442 +msgid "Vous pouvez utiliser le menu 'outils/qualité des photos line'" +msgstr "Use 'Quality of the 'line' pictures' in the Tools menu " + +#: AperoDeDenis.py:8442 +msgid "puis effectuer une sélection manuelle." +msgstr "then execute a manual selection. " + +#: AperoDeDenis.py:8444 AperoDeDenis.py:8483 +msgid "Images sélectionnées." +msgstr "Selected pictures." + +#: AperoDeDenis.py:8444 AperoDeDenis.py:8483 +msgid "Vous pouvez lancer Micmac." +msgstr "You can launch MicMac." + +#: AperoDeDenis.py:8451 +msgid "Cette sélection de photos est réservé aux chantiers photos" +msgstr "This picture selection is for picture projects only." + +#: AperoDeDenis.py:8481 +msgid "Aucune sélection effectuée." +msgstr "No selection made." + +#: AperoDeDenis.py:8481 +msgid "" +"Vous pouvez utiliser le menu 'outils/qualité des photos line'\n" +"puis effectuer une sélection manuelle." +msgstr "" +"Use 'Quality of the 'line' pictures' in the Tools menu \n" +"then execute a manual selection. " + +#: AperoDeDenis.py:8521 +msgid "Trouvé : " +msgstr "Found:" + +#: AperoDeDenis.py:8523 +msgid "Non trouvé : " +msgstr "Not found:" + +#: AperoDeDenis.py:8543 +msgid " Pas de fichier pour " +msgstr "No file for" + +#: AperoDeDenis.py:8562 +msgid "erreur infobulle : " +msgstr "Tooltip error:" + +#: AperoDeDenis.py:8609 +msgid "Aucun point placé sur cette photo" +msgstr "No point placed on this picture." + +#: AperoDeDenis.py:8611 +msgid "Un point placé sur cette photo" +msgstr "One point placed on this picture." + +#: AperoDeDenis.py:8613 +msgid " points placés sur cette photo" +msgstr "points placed on this picture." + +#: AperoDeDenis.py:8679 +msgid "Aucun chantier mémorisé." +msgstr "No stored project." + +#: AperoDeDenis.py:8687 +msgid "Choisir le chantier à ouvrir :" +msgstr "Select a project to open:" + +#: AperoDeDenis.py:8689 +msgid "vertical" +msgstr "vertical" + +#: AperoDeDenis.py:8690 +msgid "horizontal" +msgstr "horizontal" + +#: AperoDeDenis.py:8710 +msgid "Ouvrir" +msgstr "Open" + +#: AperoDeDenis.py:8715 +msgid "Il y a des chantiers incomplets," +msgstr "Some projects are incomplete," + +#: AperoDeDenis.py:8715 +#, python-format +msgid " le fichier %s est absent." +msgstr "file %s not found." + +#: AperoDeDenis.py:8716 +msgid "Ces chantiers ne peuvent être ouverts mais peuvent être supprimés :" +msgstr "These projects can't be opened but can be deleted: " + +#: AperoDeDenis.py:8741 +msgid "Abandon utilisateur." +msgstr "User abort." + +#: AperoDeDenis.py:8766 AperoDeDenis.py:8783 +msgid "HomolTemporaire" +msgstr "HomolTemp" + +#: AperoDeDenis.py:8768 +msgid "erreur renommage Homol en HomolTemporaire : " +msgstr "Error renaming Homol into HomolTemp" + +#: AperoDeDenis.py:8773 +#, python-format +msgid "erreur renommage %s en Homol : " +msgstr "Error renaming %s into Homol: " + +#: AperoDeDenis.py:8781 +#, python-format +msgid "erreur renommage Homol en : %s : " +msgstr "Error renaming Homol into %s:" + +#: AperoDeDenis.py:8785 +msgid "erreur renommage HomolTemporaire en Homol : " +msgstr "Error renaming HomolTemp into Homol:" + +#: AperoDeDenis.py:8795 +msgid "ATTENTION : Les photos définissent plusieurs scènes disjointes" +msgstr "" + +#: AperoDeDenis.py:8805 +msgid "dernier traitement : " +msgstr "Last processing: " + +#: AperoDeDenis.py:8813 +msgid "Lancer MicMac avant de pouvoir évaluer la qualité des photos." +msgstr "Launch MicMac in order to evalutate the quality of the pictures." + +#: AperoDeDenis.py:8816 +msgid "Le traitement n'a donné aucun point homologue." +msgstr "No tie-point found by processing. " + +#: AperoDeDenis.py:8854 +msgid "Photo" +msgstr "Picture" + +#: AperoDeDenis.py:8854 +msgid "score" +msgstr "score" + +#: AperoDeDenis.py:8854 +msgid "nb photos en correspondance" +msgstr "Number of matching pictures" + +#: AperoDeDenis.py:8862 +msgid " : fin de la recherche sur la qualité des photos." +msgstr " : end of the pictures quality search." + +#: AperoDeDenis.py:8908 +msgid "Lancer d'abord Tapioca/Tapas" +msgstr "Launch Tapioca/Tapas in order to go further" + +#: AperoDeDenis.py:8936 AperoDeDenis.py:8953 +msgid "Aucun nuage de points dans ce chantier." +msgstr "There is no point cloud in this project." + +#: AperoDeDenis.py:8939 +msgid "Liste des nuages de points du chantier" +msgstr "Project's point clouds list" + +#: AperoDeDenis.py:8940 +msgid "les nuages (fichiers ply) :" +msgstr "Clouds (ply files)" + +#: AperoDeDenis.py:8941 +msgid "Visualiser" +msgstr "Display" + +#: AperoDeDenis.py:8956 +msgid "Fusion de nuages" +msgstr "Point clouds merge" + +#: AperoDeDenis.py:8957 +msgid "Choisir les fichiers à fusionner :" +msgstr "Choose files to merge" + +#: AperoDeDenis.py:8958 +msgid "Fusionner et visualiser" +msgstr "Merge and display" + +#: AperoDeDenis.py:8964 AperoDeDenis.py:8979 +msgid "Choisir au moins 2 nuages pour la fusion." +msgstr "Select at least two point clouds to merge." + +#: AperoDeDenis.py:8982 +msgid "Les ply attendus n'ont pas été créé." +msgstr "The expected ply have not been created." + +#: AperoDeDenis.py:8997 +msgid "Nuage fusionné :" +msgstr "Point clouds merged: " + +#: AperoDeDenis.py:8997 +msgid "ajouté à la liste des nuages." +msgstr "Added to point cloud list." + +#: AperoDeDenis.py:8997 +msgid "résultat de la fusion de :" +msgstr "Merged result from:" + +#: AperoDeDenis.py:9000 +msgid "La fusion n'a pu se réaliser." +msgstr "The merger could not take place." + +#: AperoDeDenis.py:9010 AperoDeDenis.py:9030 AperoDeDenis.py:9069 +#: AperoDeDenis.py:9083 AperoDeDenis.py:9117 +msgid "Saisir une valeur numérique" +msgstr "Enter a digital value" + +#: AperoDeDenis.py:9016 AperoDeDenis.py:9036 AperoDeDenis.py:9089 +msgid "Passage en coordonnées xyz" +msgstr "Passing into xyz coordinates." + +#: AperoDeDenis.py:9018 AperoDeDenis.py:9021 AperoDeDenis.py:9038 +#: AperoDeDenis.py:9091 +msgid "Création de la grille ..." +msgstr "Creating the grid..." + +#: AperoDeDenis.py:9046 AperoDeDenis.py:9096 +msgid "Le calcul peut durer quelques minutes ..." +msgstr "Calculation can take some minutes..." + +#: AperoDeDenis.py:9052 +msgid "Rugosité moyenne quadratique : " +msgstr "Medium quadratic roughness:" + +#: AperoDeDenis.py:9053 +msgid "Tortuosité moyenne : " +msgstr "average tortuosity:" + +#: AperoDeDenis.py:9054 AperoDeDenis.py:9102 +msgid "nombre de profils utilisés : " +msgstr "Number of profiles used: " + +#: AperoDeDenis.py:9055 AperoDeDenis.py:9064 AperoDeDenis.py:9071 +#: AperoDeDenis.py:9103 AperoDeDenis.py:9112 AperoDeDenis.py:9119 +msgid "id profil entre : " +msgstr "Id of the entered profile: " + +#: AperoDeDenis.py:9063 AperoDeDenis.py:9111 +msgid "Choisir une valeur valide " +msgstr "Choose a valid value" + +#: AperoDeDenis.py:9100 +msgid "Profondeur moyenne de profil (moyenne) : " +msgstr "average depth profile :" + +#: AperoDeDenis.py:9101 +msgid "Profondeur de texture équivalente : " +msgstr "Equivalent depth of texture :" + +#: AperoDeDenis.py:9129 +msgid "Le programme de conversion n'est pas présent." +msgstr "The conversion program is not present." + +#: AperoDeDenis.py:9155 +msgid "Paramètres mis à jour" +msgstr "Settings updated" + +#: AperoDeDenis.py:9156 +msgid "Méthode = " +msgstr "Method = " + +#: AperoDeDenis.py:9157 +msgid "Pas du maillage = " +msgstr "Mesh range = " + +#: AperoDeDenis.py:9206 +msgid "Exifs mis à jour" +msgstr "Exifs updated" + +#: AperoDeDenis.py:9207 +msgid "Fabricant = " +msgstr "Manufacturer =" + +#: AperoDeDenis.py:9208 +msgid "Modèle = " +msgstr "Model =" + +#: AperoDeDenis.py:9209 +msgid "Focale = " +msgstr "Focal length =" + +#: AperoDeDenis.py:9210 +msgid "Focale eq 35mm = " +msgstr "Focal length eq 35mm =" + +#: AperoDeDenis.py:9217 +msgid "Abandon de la mise à jour des exifs" +msgstr "Exif update aborted." + +#: AperoDeDenis.py:9227 +msgid "Aucune photo à mettre à jour." +msgstr "No picture to update." + +#: AperoDeDenis.py:9230 +msgid "" +"La liste des fichiers comporte plusieurs extensions différentes : abandon." +msgstr "These files include several different extensions: aborting." + +#: AperoDeDenis.py:9235 +#, python-format +msgid "" +"La version actuelle ne traite que les exif des photos au format JPG, or le " +"format des photos est %s. Désolé, abandon." +msgstr "" +"Current version can only process exif in JPG format, these pictures format " +"is %s. Aborting." + +#: AperoDeDenis.py:9241 +#, python-format +msgid "Le fichier %s n'existe pas. Abandon" +msgstr "%s file doesn't exists. Abort." + +#: AperoDeDenis.py:9245 +msgid "met à jour l'exif de " +msgstr "Update exif of" + +#: AperoDeDenis.py:9271 +msgid "Choisir des photos au préalable." +msgstr "Choose pictures beforehand." + +#: AperoDeDenis.py:9275 +#, fuzzy +#| msgid "Attention les photos suivantes sont absentes sur disque : " +msgid "Attention les photos suivantes sont absentes sur disque : " +msgstr "Warning, some pictures are missing on the disk:" + +#: AperoDeDenis.py:9275 +#, fuzzy +#| msgid "Elles sont supprimées." +msgid "Elles sont supprimées du chantier." +msgstr "They've been deleted." + +#: AperoDeDenis.py:9280 +msgid "Problème de fichiers" +msgstr "Files problem" + +#: AperoDeDenis.py:9284 +msgid "Bonjour !" +msgstr "Hello !" + +#: AperoDeDenis.py:9284 +msgid "Commencer par indiquer où se trouve MicMac :" +msgstr "Start by selecting the MicMac's directory:" + +#: AperoDeDenis.py:9285 +msgid " - menu Paramétrage/Associer le répertoire bin de MicMac" +msgstr "- Settings menu/link the MicMac\\bin directory." + +#: AperoDeDenis.py:9286 +msgid "Ensuite consulter l'aide, item 'pour commencer'." +msgstr "Next, read \"Get started\" in the Help menu." + +#: AperoDeDenis.py:9287 +msgid "Si besoin :" +msgstr "if necessary:" + +#: AperoDeDenis.py:9288 +msgid "" +" - Associer convert et exiftool s'ils ne sont pas trouvés automatiquement " +"sous micmac/binaire-aux" +msgstr "" +"- Link the convert and exiftool directories if they're not in micmac/binaire-" +"aux directory." + +#: AperoDeDenis.py:9289 +msgid "" +" - Associer un outil (CloudCompare ou Meshlab) pour afficher les nuages de " +"points 3D" +msgstr "- Link a tool (CloudCompare or Meslab) to display 3D point clouds." + +#: AperoDeDenis.py:9290 +msgid " - Consulter la notice d'installation et de prise en main" +msgstr "- Read installation and grip instructions" + +#: AperoDeDenis.py:9296 +msgid "Désigner le fichier exiftool (menu paramétrage)." +msgstr "Select the exiftool file (settings menu)" + +#: AperoDeDenis.py:9301 +msgid "Désigner le fichier convert, ou avconv, d'image Magick" +msgstr "Designate the convert or avconv file from ImageMagick " + +#: AperoDeDenis.py:9301 +msgid "en principe sous micmac\\binaire-aux (menu paramétrage)." +msgstr "usually in micmac\\binaire-aux (Settings menu)." + +#: AperoDeDenis.py:9306 +msgid "" +"Désigner le fichier ffmpeg (possible sous micmac\\binaire-aux (menu " +"paramétrage)." +msgstr "Designate the file ffmpeg." + +#: AperoDeDenis.py:9335 +msgid "Revenir aux options par défaut d'AperoDeDenis" +msgstr "Return to default AperoDeDenis's options." + +#: AperoDeDenis.py:9336 AperoDeDenis.py:9354 +msgid "Utiliser les options du chantier en cours" +msgstr "Use current project's options." + +#: AperoDeDenis.py:9337 AperoDeDenis.py:9355 +msgid "Ne rien changer" +msgstr "Don't change anything." + +#: AperoDeDenis.py:9340 +msgid "Options par défaut réinitialisées" +msgstr "Default options reset." + +#: AperoDeDenis.py:9344 AperoDeDenis.py:9359 +msgid "Les options par défaut seront désormais celles du chantier en cours" +msgstr "Default options are now current project's options." + +#: AperoDeDenis.py:9353 +msgid "" +"Les options par défaut actuelles sont les options par défaut d'AperoDeDenis" +msgstr "Current default options are AperoDeDenis's default options." + +#: AperoDeDenis.py:9368 +msgid "" +"Options par défaut non sauvegardées car les options du chantier en cours " +"sont invalides :" +msgstr "Project options not valid, default options remain unchanged:" + +#: AperoDeDenis.py:9396 +msgid "erreur sauveOptions : " +msgstr "Error sauveOptions:" + +#: AperoDeDenis.py:9397 +msgid "Erreur rencontrée lors de la sauvegarde des options : " +msgstr "Encountered error when saving options:" + +#: AperoDeDenis.py:9428 +msgid "erreur restauration options : " +msgstr "Error loading options:" + +#: AperoDeDenis.py:9467 +msgid "fin normale d'aperodedenis." +msgstr "Normal end of AperoDeDenis" + +#: AperoDeDenis.py:9485 +msgid "fonction" +msgstr "function" + +#: AperoDeDenis.py:9486 +msgid "valeur en retour : " +msgstr "Return value:" + +#: AperoDeDenis.py:9489 +msgid "variable" +msgstr "variable" + +#: AperoDeDenis.py:9490 +msgid "valeur : " +msgstr "valor:" + +#: AperoDeDenis.py:9491 +#, python-format +msgid "Détail de la %(typeVar)s : %(nomVar)s" +msgstr "%(typeVar)s détails: %(nomVar)s" + +#: AperoDeDenis.py:9492 +msgid "Identifiant : " +msgstr "Identifier:" + +#: AperoDeDenis.py:9493 +msgid "Type : " +msgstr "Type:" + +#: AperoDeDenis.py:9494 +msgid "class = " +msgstr "class =" + +#: AperoDeDenis.py:9495 +msgid "Les attributs : " +msgstr "Attributes:" + +#: AperoDeDenis.py:9503 +msgid "Erreur suppression fichier :" +msgstr "Error deleting file:" + +#: AperoDeDenis.py:9526 +msgid "erreur ajout : " +msgstr "Add error:" + +#: AperoDeDenis.py:9541 +msgid "erreur remove = " +msgstr "Remove error:" + +#: AperoDeDenis.py:9567 +msgid "erreur zip = " +msgstr "Zip error:" + +#: AperoDeDenis.py:9599 +#, python-format +msgid "erreur mercurial : %(e)s pour mm3D=%(mm3D)s" +msgstr "Mercurial error: %(e)s for mm3d=%(mm3D)s" + +#: AperoDeDenis.py:9600 +msgid "pas de version identifiée de MicMac" +msgstr "Not know MicMac's version" + +#: AperoDeDenis.py:9654 +msgid "Nouveau nom pour le chantier : " +msgstr "New project's name:" + +#: AperoDeDenis.py:9690 +msgid "Console" +msgstr "Console" + +#: AperoDeDenis.py:9807 +msgid "Question" +msgstr "Question" + +#~ msgid "Ply à lire" +#~ msgstr "Ply to read" + +#~ msgid "Fichier à lire : " +#~ msgstr "File to read: " + +#~ msgid "Il ne s'agit pas d'un fichier ply issu de MicMac !" +#~ msgstr "This ply file is not from MicMac !" + +#~ msgid "Fichier à écrire : " +#~ msgstr "File to write:" + +#~ msgid "nombre de points : " +#~ msgstr "Number of points: " + +#~ msgid " le format attendu est : fffBBB" +#~ msgstr "The awaited format is: fffBBB" + +#~ msgid "" +#~ "Le format des données indique qu'il ne s'agit pas d'un ply généré par " +#~ "MicMac. Le format trouvé est : " +#~ msgstr "" +#~ "The format of the datas shows that it's not a ply generated from MicMac. " +#~ "The found format is: " + +#~ msgid "Longueur du fichier : " +#~ msgstr "File length: " + +#~ msgid "format du fichier > = big_endian, < = little_endian :" +#~ msgstr "File format > = big_endian, < = little_endian:" + +#~ msgid " longueur : " +#~ msgstr " length: " + +#~ msgid "Format des données : " +#~ msgstr "Data format: " + +#~ msgid "patience : écriture du fichier xyz en cours" +#~ msgstr "Please wait: writing xyz file..." + +#~ msgid " fin = " +#~ msgstr " end = " + +#~ msgid " longueur = " +#~ msgstr " length = " + +#~ msgid "Plage des données : début = " +#~ msgstr "Data range: beginning= " + +#~ msgid "" +#~ "Erreur lors du décodage des données, le ply ne provient pas de micmac. " +#~ "Erreur : " +#~ msgstr "" +#~ "Error when decoding datas : the ply file was not provided from MicMac. " +#~ "Error : " + +#~ msgid "nom du fichier contenant les données : à déterminer" +#~ msgstr "Name of the file containing the datas: to be determined." + +#~ msgid " pas du maillaige : " +#~ msgstr " mesh range: " + +#~ msgid "profil n°" +#~ msgstr "profile n°" + +#~ msgid "(exemple : focales différentes)" +#~ msgstr "(example: differents focal lengths)" + +#~ msgid "éventuellement différente de la focale des autres photos." +#~ msgstr "but can have a different focal length than the other pictures." + +#~ msgid "Remarque : les masques sont communs à GeomImage et AperoDeDenis" +#~ msgstr "Note: masks are common to GeomImage and AperoDeDenis" + +#~ msgid "Tracer le masque 3D sur le nuage AperiCloud" +#~ msgstr "Draw 3D mask on the cloud of AperiCloud" + +#~ msgid "Dans l'outil : " +#~ msgstr "In the tool:" + +#~ msgid "C3DC a la priorité sur le masque 2D de Malt" +#~ msgstr "C3DC has priority over Malt's 2D mask" + +#~ msgid "Tout chemin relatif au chemin actuel est valide" +#~ msgstr "All relative path to actual path is valid." + +#~ msgid "Calibration présente" +#~ msgstr "Existing calibration." + +#~ msgid "Calibration annulée : distance=0" +#~ msgstr "Aborted calibration: distance = 0" + +#~ msgid "Calibration incomplète :" +#~ msgstr "Incomplete calibration:" + +#~ msgid "C3DC : Masque 3D" +#~ msgstr "C3DC: 3D mask" + +#~ msgid "les meilleures photos en correspondances seront choisies" +#~ msgstr "The best photos in matches will be chosen" + +#~ msgid "" +#~ "L'outil exiftool n'est pas localisé : controle des photos impossible." +#~ msgstr "Exiftool not found: controlling pictures is impossible." + +#~ msgid "erreur controle des photos : " +#~ msgstr "Error controlling pictures: " + +#~ msgid "Le chantier est interrompu suite à incident. " +#~ msgstr "The project has been interrupted following an incident." + +#~ msgid "" +#~ "Si besoin créer un nouveau chantier ou débloquer le chantier en lancant " +#~ "micmac." +#~ msgstr "If necessary, create or unblock a project by launching MicMac." + +#~ msgid "" +#~ " - Nettoyer le chantier pour modifier les options de Tapioca et Tapas" +#~ msgstr "- Clean project to edit Tapioca and Tapas options" + +#~ msgid "Suppression du masque 3D : la version de MicMac ne comporte pas C3DC" +#~ msgstr "Deleting 3D mask: this MicMac's version does not include C3DC" + +#~ msgid "lancer Micmac pour en constituer un." +#~ msgstr "launch MicMac to generate one." + +#~ msgid "La calibration par points GPS se fait aprés Tapas et avant Malt." +#~ msgstr "Calibration by GPS points must be done after Tapas and before Malt." + +#~ msgid "Elle est prioritaire sur la calibration par axe, plan et métrique." +#~ msgstr "It has priority over axis, plane and metric calibration." + +#~ msgid "Cependant vous pouvez essayer sans cela." +#~ msgstr "However you can try without it." + +#~ msgid " - lancer Malt, ou C3DC, pour obtenir un nuage dense" +#~ msgstr " - Launch Malt or C3DC to create a dense point cloud" + +#~ msgid "Lancer " +#~ msgstr "Launch" + +#~ msgid "Pas d'orientation trouvé par tapas." +#~ msgstr "No orientation found by Tapas." + +#~ msgid "Prises de vues non positionnées." +#~ msgstr "Shooting not placed." + +#~ msgid "Verifier la qualité des photos (item du menu outil)" +#~ msgstr "Check the quality of the pictures (item from the Tool menu)" + +#~ msgid "ou définir un masque 3D" +#~ msgstr "or define a 3D mask" + +#~ msgid "Pour cela utiliser l'item option/Malt ou option/C3DC du menu MicMac" +#~ msgstr "" +#~ "To do so, use the item option/Malt or option/C3DC from the MicMac menu." + +#~ msgid "Calibration intrinsèque lancée sur les photos : " +#~ msgstr "Intrinsic calibration launche on pictures:" + +#~ msgid "Recherche d'un point de convergence au centre de l'image." +#~ msgstr "Searching for a convergence points in the picture center." + +#~ msgid "Modification non prévue dans cette version de l'outil AperoDeDenis" +#~ msgstr "No changements planned in the current version of AperoDeDenis" + +#~ msgid "Dimensions du capteur mis à jour" +#~ msgstr "The dimensions of the sensors were updated." + +#~ msgid "Toutes les focales : " +#~ msgstr "All focal length:" + +#~ msgid "S'il n'y a pas de path sur mm3d entrer le chemin : " +#~ msgstr "If there is no path on mm3d enter the path:" + +#~ msgid "" +#~ " Cet item permet de supprimer les répertoires devenus inutiles." +#~ msgstr " This item allow to delete useless directories." + +#~ msgid " Remarque : " +#~ msgstr " Note:" + +#~ msgid "" +#~ " Typiquement sur les photos de plus grande " +#~ "focale si il y a 2 focales différentes." +#~ msgstr "" +#~ " Typically on pictures with a more large " +#~ "focal length in case of several different focal length." + +#~ msgid "" +#~ " Cette option est utilisée pour le nuage de " +#~ "point non densifié ET pour le nuage densifié." +#~ msgstr "" +#~ " This option can be used for densified and " +#~ "undensified point clouds." + +#~ msgid "" +#~ " Les 3 options suivantes concernent le calcul du nuage de points " +#~ "densifié :" +#~ msgstr "" +#~ " Three following options are related with densified point cloud " +#~ "calculation:" + +#~ msgid "" +#~ " - GPS : définir les points de calage GPS qui " +#~ "permettent de géolocaliser la scène." +#~ msgstr "" +#~ " - GPS : define GPS points, which allow to geolocate " +#~ "the scene." + +#~ msgid "" +#~ " Pour être utilisé chaque point, minimum " +#~ "3, doit être placé sur au moins 2 photos." +#~ msgstr "" +#~ " To be used, each point, with a minimum of " +#~ "3, must be placed on at least two pictures." + +#~ msgid "" +#~ " le fichier modele3D.ply est conservé sous un " +#~ "autre nom." +#~ msgstr "" +#~ " The modele3D.ply file in stored with another " +#~ "name." + +#~ msgid "" +#~ " - Tapioca : si le sujet est central conserver les " +#~ "paramètres par défaut." +#~ msgstr "" +#~ " -Tapioca : if the target is in the center, keep the " +#~ "default settings." + +#~ msgid "" +#~ " si les photos ont 2 focales alors choisir toutes " +#~ "celles qui ont la plus grande focale pour la calibration intrinsèque." +#~ msgstr "" +#~ " if the pictures have two diffrent focal length, " +#~ "choose those with a bigger focal length for the intrinsic calibration" + +#~ msgid "" +#~ " L'arrêt aprés Tapas est conseillé : la " +#~ "visualisation du nuage de points non densifié" +#~ msgstr "" +#~ " Stopping after Tapas is indicated: displaying " +#~ "undensified point cloud" + +#~ msgid " Tout d'abord : installer MicMac." +#~ msgstr " First : install MicMac" + +#~ msgid "" +#~ "2) Choisir quelques photos, par exemple du jeu d'essai gravillons, au " +#~ "moins 3 mais pas plus de 6 pour commencer (menu MicMac)." +#~ msgstr "" +#~ "2) Choose some pictures, at least three but no more than six for start " +#~ "(MicMac menu)." + +#~ msgid "" +#~ "4) Si tout va bien alors modifier les options pour la suite du traitement " +#~ "(Malt ou C3DC) (voir la doc)." +#~ msgstr "" +#~ "4) If everything works, edit options for next processing (Malt or C3DC) " +#~ "(see doc)." + +#~ msgid " Puis re lancer MicMac pour obtenir une vue 3D densifiée." +#~ msgstr " Then relaunch MicMac to generate a densified 3D view." + +#~ msgid "Direction Territoriale Normandie Centre" +#~ msgstr "Direction Territoriale Normandie Centre" + +#~ msgid "Enregistrer les options saisies ?" +#~ msgstr "Save changes?" + +#~ msgid "Confirmez" +#~ msgstr "Confirm" + +#~ msgid "" +#~ "Vont être supprimés les répertoires suivants, sans mise en corbeille :" +#~ msgstr "Following directories will be deleted for good:" + +#~ msgid "Confimez" +#~ msgstr "Confirm" + +#~ msgid "Le précédent chantier %s est en cours de suppression." +#~ msgstr "Previous project %s is being deleted." + +#~ msgid "Nouvelle version : " +#~ msgstr "New version: " + +#~ msgid "Ortho pour orthophotos" +#~ msgstr "Ortho for orthophotos" + +#~ msgid "Liste des images maîtresses et des masques" +#~ msgstr "Master pictures and masks list" + +#~ msgid "Photo utile pour malt AperoDeDenis : " +#~ msgstr "Photo useful for malt AperoDeDenis:" + +#~ msgid "Nombre de photos utiles en + et en - autour de l'image maitresse :" +#~ msgstr "Number of useful pictures in more or less around master picture" + +#~ msgid "2 fois %s photos utiles autour de la maîtresse" +#~ msgstr "2 times %s useful pictures around master picture." + +#~ msgid "Attention : chaque points doit être sur 2 photos au moins." +#~ msgstr "Warning: each points must be placed on at least two pictures." + +#~ msgid "Il est mis à 1." +#~ msgstr "It was put to 1." + +#~ msgid "Nombre de photos autour de la maîtresse : " +#~ msgstr "Number of pictures around the master picture:" + +#~ msgid " photos traitées par Malt :" +#~ msgstr " pictures processed by Malt: " + +#~ msgid "Erreur lors de la recherche des photos proches de la maitresse %s." +#~ msgstr "Error searching pictures like master picture %s. " + +#~ msgid "Toutes les photos sont conservées." +#~ msgstr "All pictures are preserved." + +#~ msgid "erreur verifier si executable : " +#~ msgstr "Error, check executable:" + +#~ msgid "" +#~ "Chantier modifé depuis la dernière sauvegarde. Voulez-vous l'enregistrer ?" +#~ msgstr "" +#~ "The project has been edited since last save. Do you want to save it?" + +#~ msgid "ATTENTION : FERMER la fenêtre 3D pour continuer" +#~ msgstr "Warning: close 3D window ton continue" + +#~ msgid "Sélectionnez la langue à utiliser. L'application sera redémarée." +#~ msgstr "Select the language. The application wil be relaunched." + +#~ msgid "avant" +#~ msgstr "before" + +#~ msgid "aprés =" +#~ msgstr "after =" + +#~ msgid "Nombre de photos retenues : " +#~ msgstr "Number of choosen pictures" + +#~ msgid "" +#~ " les photos ayant un mauvais score (voir le menu Outils/" +#~ "Qualité des photos 'All') doivent être supprimées du chantier : elle " +#~ "peuvent faire échouer le traitement." +#~ msgstr "" +#~ " Pictures with a bad score (see : Tools/Pictures quality " +#~ "'All' menu) must be deleted from the project : they can make the process " +#~ "fail." + +#~ msgid "Il convient de l'ajouter." +#~ msgstr "You should add it." + +#~ msgid "L'outil ffmpeg est absent du répertoire %s." +#~ msgstr "ffmpeg tool absent from %s" + +#~ msgid "" +#~ "Désigner le fichier ffmpeg en principe sous micmac\\binaire-aux (menu " +#~ "paramétrage)." +#~ msgstr "" +#~ "Designate the ffmpeg file, normally in micmac\\binaire-aux (Settings " +#~ "menu)." + +#~ msgid "Points GPS vérifiés par controlePoints : non conformes. Vérifiez." +#~ msgstr "GPS pointes checkec by controlePoints: improper. Check." + +#~ msgid "Points GPS non conformes. Vérifiez." +#~ msgstr "GPS points improper. Check." + +#~ msgid "le %(jour)s/%(mois)s/%(annee)s à %(heure)s:%(minutes)s:%(secondes)s" +#~ msgstr "" +#~ "On %(jour)s/%(mois)s/%(annee)s at %(heure)s:%(minutes)s:%(secondes)s" + +#~ msgid "AperoDeDenis est déjà lancé dans la fenêtre :" +#~ msgstr "AperoDeDenis is already launched in: " + +#~ msgid "" +#~ "La version actuelle d'AperoDeDenis n'autorise qu'une seule instance du " +#~ "programme." +#~ msgstr "" +#~ "This version of AperoDeDenis allow only one instance of the program." + +#~ msgid "Valider pour quitter." +#~ msgstr "Confirm to exit" + +#~ msgid "AperoDeDenis : avertissement" +#~ msgstr "AperoDeDenis : warning" + +#~ msgid "test bilingue new" +#~ msgstr "traduction bidon" + +#~ msgid "" +#~ "Erreur lors du décodage des données, le ply ne proviient pas de micmac. " +#~ "Erreur : " +#~ msgstr "" +#~ "Error when decoding the datas, the ply file is not from MicMac. Error: " + +#~ msgid " : Une interface graphique pour MicMac..." +#~ msgstr ": a MicMac's graphic user interface..." + +#~ msgid "Nouveau chantier : Choisir une video GoPro, ou autre" +#~ msgstr "New project: select a goPro video, or else" + +#~ msgid "Nom de la camera GoPRo : " +#~ msgstr "Name of the camera:" + +#~ msgid "Info : Format des photos" +#~ msgstr "Info: pictures format" + +#~ msgid "" +#~ "ATTENTION : Des points GPS ont été précedemment placés sur des photos non " +#~ "choisies pour ce chantier." +#~ msgstr "" +#~ "Warning: some pictures on which GPS points were previously placed were " +#~ "not choosen for the project." + +#~ msgid "" +#~ "Attention : Il faut au moins 3 points pour qu'ils soient pris en compte." +#~ msgstr "Warning: at least three points needed to take them into account." + +#~ msgid "Attention : Des points portent le même nom : corriger !" +#~ msgstr "Warning: some points have the same name : correct it !" + +#~ msgid "" +#~ "ATTENTION : Des Metadonnées nécessaires sont absentes des photos. " +#~ "Vérifier l'exif." +#~ msgstr "" +#~ "Warning: required metadatas are absent from pictures. Check the exif." + +#~ msgid " : Voir la trace complète." +#~ msgstr ": see complete log." + +#~ msgid "" +#~ " - Du ménage ! : Supprimer les chantiers : Chaque chantier crée une " +#~ "arborescence de travail." +#~ msgstr "" +#~ " - Let's clean !: delete projects: each project create a work tree." + +#~ msgid "" +#~ " - Tapas : Choix d'un mode de calcul, possibilité " +#~ "d'arrêter le traitement après tapas." +#~ msgstr "" +#~ " - Tapas: choice of a calculation mode, allow to stop " +#~ "processing after Tapas." + +#~ msgid "" +#~ " - GPS : Définir les points de calage GPS qui " +#~ "permettent de géolocaliser la scène." +#~ msgstr "" +#~ " -GPS: define GPS points allowing to geolocate the " +#~ "scene." + +#~ msgid "" +#~ " - GPS : Définir les points de calage GPS qui " +#~ "permettent de géolocaliser la scène." +#~ msgstr "" +#~ " - GPS: define GPS points that allows to geo-locate " +#~ "the scene." + +#~ msgid "" +#~ " - Lancer MicMac : Enregistre le chantier et lance le traitement " +#~ "avec les options par défaut ou choisies par l'item 'options'." +#~ msgstr "" +#~ "- Launch MicMac: save project and start processing with current options." + +#~ msgid "" +#~ " Attention : Cette étape n'est pas effective pour toutes les " +#~ "versions de MicMac. La version mercurial 5508 fonctionne." +#~ msgstr "" +#~ " Warning: this step does not work in all versions of MicMac. The " +#~ "mercurial 5508 version works." + +#~ msgid "" +#~ " les photos ayant un mauvais score doivent être " +#~ "supprimées du chantier : elle peuvent faire échouer le traitement." +#~ msgstr "" +#~ " Pictures with bad scores (See the Tools/Check quality " +#~ "of the pictures menu) must be deleted: these can make the process fails." + +#~ msgid "" +#~ " - Tapioca : Si le sujet est central conserver les " +#~ "paramètres par défaut." +#~ msgstr "" +#~ " - Tapioca: if the subject is in the center, keep the " +#~ "default settings." + +#~ msgid "" +#~ " - Tapas : Si l'appareil photo est un compact ou un " +#~ "smartphone choisir RadialBasic, " +#~ msgstr "" +#~ " - Tapas: if the camera is compact or a smartphone, choose " +#~ "RadialBasic," + +#~ msgid "" +#~ " Si l'appareil photo est de moyenne gamme choisir " +#~ "RadialStd" +#~ msgstr "" +#~ " If it's an average line camera, choose RadialStd" + +#~ msgid "" +#~ " Si les photos ont 2 focales alors choisir toutes " +#~ "celles qui ont la plus grande focale pour la calibration intrinsèque." +#~ msgstr "" +#~ " If pictures have two focal length, choose those " +#~ "which have a bigger focal length for intrinsic calibration." + +#~ msgid " Tout d'abord : Installer MicMac." +#~ msgstr " First of all: install MicMac" + +#~ msgid "" +#~ " Puis : Installer Meshlab ou CloudCompare (pour afficher les nuages de " +#~ "points)" +#~ msgstr " Then: install MeshLab or CloudCompare (to display point clouds)" + +#~ msgid "" +#~ "Version 1.55 : Sous Windows le fichier paramètre est placé sous le " +#~ "répertoire APPDATA de l'utilisateur," +#~ msgstr "Version 1.55:" + +#~ msgid "Version 1.60 : Ajout des fonctions :" +#~ msgstr "Version 1.60: functions added" + +#~ msgid "Version 2.00 : Ajout des fonctions :" +#~ msgstr "Version 2.00: functions added:" + +#~ msgid " : Lancement de " +#~ msgstr ": launching" + +#~ msgid " : Fin de " +#~ msgstr ": ending" + +#~ msgid " : Fin de la recherche sur la qualité des photos." +#~ msgstr ": search about picture quality has ended." + +#~ msgid "AperoDeDenis : Avertissement" +#~ msgstr "AperoDeDenis: warning" + +#~ msgid "photos" +#~ msgstr "pictures" + +#~ msgid "initial" +#~ msgstr "initial" + +#~ msgid "original" +#~ msgstr "original" + +#~ msgid "renommé" +#~ msgstr "renamed" + +#~ msgid "importé" +#~ msgstr "imported" + +#~ msgid "vidéo" +#~ msgstr "video" + +#~ msgid "le nuage est en cours de calibration." +#~ msgstr "Calibrating cloud..." + +#~ msgid "" +#~ " N'utiliser ces photos que pour la calibration\n" +#~ " (exemple : focales différentes)" +#~ msgstr "" +#~ "Use these picture for the calibration only \n" +#~ "(example : différents focal lenghts)" + +#~ msgid "" +#~ "Toutes ces photos doivent avoir la même focale,\n" +#~ "éventuellement différente de la focale des autres photos." +#~ msgstr "" +#~ "Every of theses pictures must have the same focal lenght,\n" +#~ "but can have a different focal lenght than the other pictures." + +#~ msgid "" +#~ "Attention : Le masque 3D de C3DC a la priorité sur Malt\n" +#~ "Pour supprimer un masque : supprimer la maitresse" +#~ msgstr "" +#~ "Warning : 3D mask from C3DC has priority over Malt.\n" +#~ "To delete a mask, delete the master picture." + +#~ msgid "" +#~ "Modification des Exif\n" +#~ "\n" +#~ "Marque de l'appareil : " +#~ msgstr "" +#~ "Exif edit\n" +#~ "\n" +#~ "Brand of the camera :" + +#~ msgid "" +#~ "Le renommage du chantier ne peut se faire actuellement,\n" +#~ "soit le nom fourni est incorrect," +#~ msgstr "" +#~ "Can't rename project now,\n" +#~ "either the name is incorrect," + +#~ msgid "" +#~ "%(heure)s\n" +#~ "Chantier :\n" +#~ "%(ancien)s\n" +#~ "renommé en :\n" +#~ "%(chantier)s\n" +#~ "Répertoire : %(rep)s" +#~ msgstr "" +#~ "%(heure)\n" +#~ " Project : \n" +#~ "%(ancien)s \n" +#~ "renamed into : \n" +#~ "%(chantier)s \n" +#~ "Directory : %(rep)s" + +#~ msgid "" +#~ "Archive \n" +#~ "%(nomChantier)s.exp\n" +#~ " créée sous \n" +#~ "%(rep)s\n" +#~ "\n" +#~ " Taille = %(str)s KO." +#~ msgstr "" +#~ "Archive \n" +#~ "%(nomChantier)s.exp \n" +#~ "created in \n" +#~ "%(rep)s \n" +#~ "\n" +#~ "Size = %(str)s Ko." + +#~ msgid "" +#~ "Recopie en cours dans\n" +#~ "%s\n" +#~ "Patience !" +#~ msgstr "" +#~ "Copying in \n" +#~ "%s. \n" +#~ "Please wait." + +#~ msgid "" +#~ "Le répertoire destination\n" +#~ "%s\n" +#~ "existe déjà. Abandon" +#~ msgstr "Destination directory %s already exist. Aborting." + +#~ msgid "" +#~ "Erreur lors de la copie du fichier paramètre chantier \n" +#~ "%(param)s\n" +#~ " vers \n" +#~ "%(rep)s\n" +#~ " erreur :" +#~ msgstr "" +#~ "Error when copying project settings file : \n" +#~ "%(param)s \n" +#~ "to \n" +#~ "%(rep)s \n" +#~ "error :" + +#~ msgid "" +#~ "%(entete)s\n" +#~ "Répertoire de la vidéo : \n" +#~ "%(chem)s" +#~ msgstr "" +#~ "%(entete)s \n" +#~ "Video directory : \n" +#~ "%(chem)s" + +#~ msgid "" +#~ " photos sélectionnées\n" +#~ "(sans calibration si tapas executé) : " +#~ msgstr "" +#~ "pictures selected\n" +#~ "(without calibration if Tapas executed)" + +#~ msgid "" +#~ "Les caractéristiques du chantier précédent \n" +#~ "%s\n" +#~ " n'ont pas pu être lues correctement." +#~ msgstr "" +#~ "Characteristics from last project \n" +#~ "%s \n" +#~ "couldn't be read properly." + +#~ msgid "" +#~ "Abandon, pas de changement.\n" +#~ "Répertoire bin de Micmac :" +#~ msgstr "" +#~ "Abort, no change. \n" +#~ "Directory of MicMac\\bin :" + +#~ msgid "" +#~ "Abandon, pas de changement.\n" +#~ "Fichier exiftool inchangé :" +#~ msgstr "" +#~ "Aborting, no change. \n" +#~ "Exiftool file unchanged." + +#~ msgid "" +#~ "Abandon, pas de changement.\n" +#~ "Fichier convert inchangé :" +#~ msgstr "" +#~ "Aborting, no change. \n" +#~ "Convert file unchanged." + +#~ msgid "" +#~ "Abandon, pas de changement.\n" +#~ "Fichier Meshlab ou cloud compare :" +#~ msgstr "" +#~ "Aborting, no change. \n" +#~ "Meshlab or CloudCompare file :" + +#~ msgid "" +#~ "Abandon, pas de changement.\n" +#~ "Fichier ffmpeg inchangé :" +#~ msgstr "" +#~ "Aborting, no change. \n" +#~ "ffmpeg file unchanged." + +#~ msgid "" +#~ "Abandon, aucune sélection de fichier image,\n" +#~ " le répertoire et les photos restent inchangés." +#~ msgstr "" +#~ "Aborting, no picture file selected, \n" +#~ "directory and pictures unchanged." + +#~ msgid "" +#~ "La version actuelle ne traite que les photos au format JPG,\n" +#~ "\n" +#~ " or le format des photos est : " +#~ msgstr "" +#~ "The current version can only process JPG files,\n" +#~ "\n" +#~ "but these pictures format is :" + +#~ msgid "" +#~ "Désigner l'outil de conversation 'convert' d'ImageMagick\n" +#~ "(Menu Paramétrage)" +#~ msgstr "" +#~ "Designate the ImageMagick's convert conversation tool. \n" +#~ "(Settings menu)" + +#~ msgid "" +#~ "Impossible de créer le répertoire de travail.\n" +#~ "Vérifier les droits en écriture sous le répertoire des photos" +#~ msgstr "" +#~ "Impossible to create working directory. \n" +#~ "Please check write permission on the pictures directory." + +#~ msgid "" +#~ "Aucun JPG, PNG, BMP, TIF, ou GIF sélectionné,\n" +#~ "le répertoire et les photos restent inchangés." +#~ msgstr "" +#~ "No JPG, PNG, BMP, TIF or GIF selected, \n" +#~ "pictures and directories unchanged." + +#~ msgid "" +#~ "L'outil exiftool n'est pas localisé : controle des photos impossible.\n" +#~ "Désigner le fichier exiftool (menu paramétrage)." +#~ msgstr "" +#~ "Exiftool not found : controlling pictures is impossible. \n" +#~ "Please show exiftool file (Settings menu)" + +#~ msgid "" +#~ "Les focales sont absentes des exif.\n" +#~ "Mettez à jour les exifs avant de lancer MicMac." +#~ msgstr "" +#~ "Focal lenght absent from exif. \n" +#~ "Please update exifs before launching MicMac." + +#~ msgid "" +#~ "erreur lors de la copie du fichier\n" +#~ "%(x)s\n" +#~ " dans le répertoire \n" +#~ "%(y)s\n" +#~ "libellé de l'erreur : \n" +#~ "%(z)s\n" +#~ "Causes possibles : manque d'espace disque ou droits insuffisants." +#~ msgstr "" +#~ "Error when copying \n" +#~ "%(x)s file\n" +#~ "in the \n" +#~ "%(y)s directory.\n" +#~ "Error :\n" +#~ "%(z)s \n" +#~ "Possibles causes : no enough space or you don't have permissions." + +#~ msgid "" +#~ "pas de fichier AperiCloud.ply pour construire le masque :\n" +#~ "lancer Micmac pour en constituer un." +#~ msgstr "" +#~ "No AperiCloud.ply file to build the mask : \n" +#~ "launch MicMac to generate one." + +#~ msgid "" +#~ "L'échelle 2 de MulScale pour tapioca\n" +#~ "%(x)s\n" +#~ " plus petite que l'échelle 1 : \n" +#~ "%(y)s" +#~ msgstr "" +#~ "Scale 2 of Tapioca's MulScale \n" +#~ "%(x)s \n" +#~ "is smaller than scale 1 : \n" +#~ "%(y)s" + +#~ msgid "" +#~ "La valeur de delta pour le mode Line de Tapioca est invalide,\n" +#~ " une valeur par défaut, %s, est affectée." +#~ msgstr "" +#~ "Delta value from Tapioca's Line is invalid, \n" +#~ "a default value, %s, is affected. " + +#~ msgid "" +#~ "L'échelle pour le mode All de tapioca = %(x)s\n" +#~ ", est plus grande que la dimension maxi de la photo : " +#~ msgstr "" +#~ "Scale for Tapioca's All mode = %(x)s, \n" +#~ "is bigger than pictures maximum dimension." + +#~ msgid "" +#~ "L'échelle 2 pour le mode MulScale de tapioca= %(x)s\n" +#~ " est plus grande que la dimension maxi de la photo :" +#~ msgstr "" +#~ "Scale 2 Tapioca's MulScale mode = %(x)s, \n" +#~ "is bigger than pictures maximum dimension." + +#~ msgid "" +#~ "L'échelle pour le mode Line de tapioca = %(x)s\n" +#~ " est plus grande que la dimension maxi de la photo :" +#~ msgstr "" +#~ "Scale for Tapioca's Line mode = %(x)s, \n" +#~ "is bigger than pictures maximum dimension." + +#~ msgid "" +#~ "Quelques photos, convergentes, d'angles écartés\n" +#~ "en jaune la calibration actuelle" +#~ msgstr "" +#~ "Some pictures, convergent, apart from angles\n" +#~ "in yellow, the current calibration." + +#~ msgid "" +#~ "Choisir une ou plusieurs image(s) maîtresse(s)\n" +#~ "en jaune : les maitresses actuelles\n" +#~ "Une info bulle informe de la présence d'un masque" +#~ msgstr "" +#~ "Select one or several master pictures. \n" +#~ "Current master pictures are in yellow.\n" +#~ "A tooltip informs of the presence of a mask. " + +#~ msgid "" +#~ "Appliquer au \n" +#~ "nuage non densifié" +#~ msgstr "" +#~ "Aplly on\n" +#~ "not densified point cloud" + +#~ msgid "" +#~ "Agrandissez la fenêtre avant d'ajouter un point GPS !\n" +#~ "(ou si impossible : supprimer un point)" +#~ msgstr "" +#~ "Extend the window before adding a GPS point !\n" +#~ "(or if impossible : remove a point)" + +#~ msgid "" +#~ "Lancer d'abord tapioca/tapas\n" +#~ "pour obtenir un nuage non densifié." +#~ msgstr "" +#~ "Launch Tapioca/Tapas first\n" +#~ "to obtain a not densified point cloud." + +#~ msgid "" +#~ "Avec 2 photos MicMac construira difficilement un nuage de point dense.\n" +#~ "Utiliser l'échelle -1 dans Tapioca pour obtenir un nuage optimal." +#~ msgstr "" +#~ "With two pictures, MicMac will build a densified point cloud with " +#~ "difficulty.\n" +#~ "Use scale -1 in Tapioca to obtain an optimal cloud." + +#~ msgid "" +#~ "Le chantier est interrompu.\n" +#~ "Vous pouvez le débloquer," +#~ msgstr "" +#~ "Project interrupted. \n" +#~ "You can unblock it," + +#~ msgid "" +#~ "Consulter l'aide (quelques conseils),\n" +#~ "consulter la trace." +#~ msgstr "" +#~ "See Help (advices), \n" +#~ "see the log." + +#~ msgid "" +#~ "Calibration intrinsèque, pour trouver les réglages de l'appareil photo " +#~ "sur quelques photos\n" +#~ "Recherche d'un point de convergence au centre de l'image." +#~ msgstr "" +#~ "Intrinsic calibration, to find camera settings on some pictures.\n" +#~ "Searching for a convergence points in the picture center." + +#~ msgid "" +#~ "Calibration, pour trouver les réglages intrinsèques de l'appareil photo\n" +#~ "Recherche l'orientation des prises de vue." +#~ msgstr "" +#~ "Calibration, to find intrinsic settings of the camera\n" +#~ "Searching for shooting orientation." + +#~ msgid "" +#~ "Erreur lors de la recherche des photos proches de la maitresse %s.\n" +#~ "Toutes les photos sont conservées." +#~ msgstr "" +#~ "Error searching pictures like master picture %s. \n" +#~ "All pictures are preserved." + +#~ msgid "" +#~ "Le résultat sera inscrit dans le fichier trace synthétique\n" +#~ "\n" +#~ "Patience..." +#~ msgstr "" +#~ "The result will be written in the synthetic log file. \n" +#~ "\n" +#~ "Please wait..." + +#~ msgid "" +#~ "Il y a des chantiers incomplets,\n" +#~ " le fichier %s est absent." +#~ msgstr "" +#~ "Some projects are incomplete,\n" +#~ "file %s not found." + +#~ msgid "" +#~ "Le traitement n'a donné aucun point homologue.\n" +#~ "\n" +#~ "Consulter la trace." +#~ msgstr "" +#~ "No homologous point found by processing. \n" +#~ "\n" +#~ "Please read the log." + +#~ msgid "" +#~ "Désigner le fichier ffmpeg en principe sous micmac\\010inaire-aux (menu " +#~ "paramétrage)." +#~ msgstr "" +#~ "Select the ffmpeg file, probably in micmac\\binaire-aux (settings menu)." + +#~ msgid "" +#~ "%(entete)s\n" +#~ "Répertoire des photos : \n" +#~ "%(chem)s" +#~ msgstr "" +#~ "%(entete)s \n" +#~ "Pictures directory : \n" +#~ "%(chem)s" + +#~ msgid "" +#~ "Désigner le fichier convert, ou avconv, d'image Magick\n" +#~ "en principe sous micmac\\010inaire-aux (menu paramétrage)." +#~ msgstr "" +#~ "Select the convert file, or avconv, of Image Magick\n" +#~ "probably in micmac\\binaire-aux (settings menu)" + +#~ msgid "essai" +#~ msgstr "try" diff --git a/InterfaceCEREMA/locale/fr/LC_MESSAGES/AperoDeDenis.mo b/InterfaceCEREMA/locale/fr/LC_MESSAGES/AperoDeDenis.mo new file mode 100644 index 0000000..3f816c3 Binary files /dev/null and b/InterfaceCEREMA/locale/fr/LC_MESSAGES/AperoDeDenis.mo differ diff --git a/InterfaceCEREMA/locale/fr/LC_MESSAGES/AperoDeDenis.po b/InterfaceCEREMA/locale/fr/LC_MESSAGES/AperoDeDenis.po new file mode 100644 index 0000000..9ce912b --- /dev/null +++ b/InterfaceCEREMA/locale/fr/LC_MESSAGES/AperoDeDenis.po @@ -0,0 +1,6528 @@ +# SOME DESCRIPTIVE TITLE. +# Copyright (C) YEAR ORGANIZATION +# FIRST AUTHOR , YEAR. +# +msgid "" +msgstr "" +"Project-Id-Version: \n" +"POT-Creation-Date: 2019-02-21 15:35+0100\n" +"PO-Revision-Date: 2019-02-21 16:09+0100\n" +"Last-Translator: \n" +"Language-Team: \n" +"Language: fr\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Generated-By: pygettext.py 1.5\n" +"X-Generator: Poedit 2.1.1\n" +"Plural-Forms: nplurals=2; plural=(n > 1);\n" + +#: AperoDeDenis.py:303 +msgid " lancement d'aperodedenis" +msgstr "" + +#: AperoDeDenis.py:312 +msgid "Tracer le masque" +msgstr "" + +#: AperoDeDenis.py:314 +msgid "Saisie sur la photo : " +msgstr "" + +#: AperoDeDenis.py:363 +msgid "Inverser" +msgstr "" + +#: AperoDeDenis.py:364 AperoDeDenis.py:676 +msgid "Valider" +msgstr "" + +#: AperoDeDenis.py:365 AperoDeDenis.py:679 AperoDeDenis.py:3347 +#: AperoDeDenis.py:3590 AperoDeDenis.py:4987 AperoDeDenis.py:5036 +#: AperoDeDenis.py:5056 AperoDeDenis.py:5066 AperoDeDenis.py:5076 +#: AperoDeDenis.py:5092 AperoDeDenis.py:5107 AperoDeDenis.py:5129 +#: AperoDeDenis.py:6297 AperoDeDenis.py:8667 AperoDeDenis.py:9711 +msgid "Abandon" +msgstr "" + +#: AperoDeDenis.py:368 +msgid "molette de la souris = zoom," +msgstr "" + +#: AperoDeDenis.py:369 +msgid "utilisable avant ET pendant le tracé" +msgstr "" + +#: AperoDeDenis.py:370 +msgid "glisser-déposer actif avant le tracé=" +msgstr "" + +#: AperoDeDenis.py:371 +msgid "Tracer :" +msgstr "" + +#: AperoDeDenis.py:372 +msgid "" +"Clic gauche : ajouter un point;\n" +" double clic gauche : fermer le polygone," +msgstr "" + +#: AperoDeDenis.py:373 +msgid "Touche Del pour supprimer un point ou le polygone," +msgstr "" + +#: AperoDeDenis.py:450 +msgid "Il faut au moins 2 points dans le polygone." +msgstr "" + +#: AperoDeDenis.py:480 AperoDeDenis.py:768 +msgid "Zoom maximum atteint" +msgstr "" + +#: AperoDeDenis.py:566 +msgid "Erreur suppression d'info bulle : " +msgstr "" + +#: AperoDeDenis.py:628 +msgid "Calibration GPS " +msgstr "" + +#: AperoDeDenis.py:629 +msgid "Position des points sur la photo : " +msgstr "" + +#: AperoDeDenis.py:678 +msgid "Supprimer un ou plusieurs points" +msgstr "" + +#: AperoDeDenis.py:686 +msgid "Changer la couleur des libellés" +msgstr "" + +#: AperoDeDenis.py:693 +msgid "Utiliser la molette pour zoomer/dezoomer pendant la saisie." +msgstr "" + +#: AperoDeDenis.py:710 +msgid "Placer le point " +msgstr "" + +#: AperoDeDenis.py:713 +msgid "Point " +msgstr "" + +#: AperoDeDenis.py:921 AperoDeDenis.py:922 +msgid " : une interface graphique pour MicMac..." +msgstr "" + +#: AperoDeDenis.py:926 +msgid "Fermeture inatendue de la fenêtre." +msgstr "" + +#: AperoDeDenis.py:929 +msgid "Erreur initialisation de la fenêtre principale : " +msgstr "" + +#: AperoDeDenis.py:949 AperoDeDenis.py:6266 +msgid "Nouveau chantier" +msgstr "" + +#: AperoDeDenis.py:950 +msgid "Ouvrir un chantier" +msgstr "" + +#: AperoDeDenis.py:952 +msgid "Enregistrer le chantier en cours" +msgstr "" + +#: AperoDeDenis.py:953 +msgid "Renommer ou déplacer le chantier en cours" +msgstr "" + +#: AperoDeDenis.py:955 +msgid "Exporter le chantier en cours" +msgstr "" + +#: AperoDeDenis.py:956 +msgid "Importer un chantier" +msgstr "" + +#: AperoDeDenis.py:958 +msgid "Ajouter un chantier à partir d'un répertoire" +msgstr "" + +#: AperoDeDenis.py:960 +msgid "Du ménage !" +msgstr "" + +#: AperoDeDenis.py:962 +msgid "Quitter" +msgstr "" + +#: AperoDeDenis.py:967 +msgid "Afficher l'état du chantier" +msgstr "" + +#: AperoDeDenis.py:969 +msgid "Visualiser toutes les photos sélectionnées" +msgstr "" + +#: AperoDeDenis.py:970 +msgid "Visualiser les photos pour la calibration intrinsèque" +msgstr "" + +#: AperoDeDenis.py:971 +msgid "Visualiser les maîtresses et les masques" +msgstr "" + +#: AperoDeDenis.py:972 +msgid "Visualiser le masque sur mosaique Tarama" +msgstr "" + +#: AperoDeDenis.py:973 +msgid "Visualiser le masque 3D" +msgstr "" + +#: AperoDeDenis.py:974 +msgid "Visualiser les points GPS" +msgstr "" + +#: AperoDeDenis.py:976 +msgid "Visualiser la ligne horizontale/verticale" +msgstr "" + +#: AperoDeDenis.py:977 +msgid "Visualiser la zone plane" +msgstr "" + +#: AperoDeDenis.py:978 +msgid "Visualiser la distance" +msgstr "" + +#: AperoDeDenis.py:980 +msgid "Afficher la trace complète du chantier" +msgstr "" + +#: AperoDeDenis.py:981 +msgid "Afficher la trace synthétique du chantier" +msgstr "" + +#: AperoDeDenis.py:983 +msgid "Afficher la mosaïque Tarama" +msgstr "" + +#: AperoDeDenis.py:984 +msgid "Afficher l'ortho mosaïque Tawny" +msgstr "" + +#: AperoDeDenis.py:986 +msgid "Afficher l'image 3D non densifiée" +msgstr "" + +#: AperoDeDenis.py:987 +msgid "Afficher l'image 3D densifiée" +msgstr "" + +#: AperoDeDenis.py:989 +msgid "Lister-Visualiser les images 3D" +msgstr "" + +#: AperoDeDenis.py:990 +msgid "Fusionner des images 3D" +msgstr "" + +#: AperoDeDenis.py:997 AperoDeDenis.py:3357 +msgid "Choisir des photos" +msgstr "" + +#: AperoDeDenis.py:998 +msgid "Options" +msgstr "" + +#: AperoDeDenis.py:1000 +msgid "Lancer MicMac" +msgstr "" + +#: AperoDeDenis.py:1005 +msgid "Options (GoPro par défaut)" +msgstr "" + +#: AperoDeDenis.py:1007 +msgid "Nouveau chantier : choisir une vidéo GoPro, ou autre" +msgstr "" + +#: AperoDeDenis.py:1008 +msgid "Sélection des meilleures images" +msgstr "" + +#: AperoDeDenis.py:1014 +msgid "Nom et focale de l'appareil photo, dimension des photos" +msgstr "" + +#: AperoDeDenis.py:1015 +msgid "Toutes les focales et les noms des appareils photos" +msgstr "" + +#: AperoDeDenis.py:1016 +msgid "Mettre à jour DicoCamera.xml" +msgstr "" + +#: AperoDeDenis.py:1018 +msgid "Qualité des photos du dernier traitement" +msgstr "" + +#: AperoDeDenis.py:1019 +msgid "Sélectionner les N meilleures photos" +msgstr "" + +#: AperoDeDenis.py:1021 +msgid "Qualité des photos 'line'" +msgstr "" + +#: AperoDeDenis.py:1022 +msgid "Qualité des photos 'All' " +msgstr "" + +#: AperoDeDenis.py:1024 +msgid "Modifier l'exif des photos" +msgstr "" + +#: AperoDeDenis.py:1026 AperoDeDenis.py:9333 AperoDeDenis.py:9351 +msgid "Modifier les options par défaut" +msgstr "" + +#: AperoDeDenis.py:1031 +msgid "Exécuter une ligne de commande système" +msgstr "" + +#: AperoDeDenis.py:1032 +msgid "Exécuter une commande python" +msgstr "" + +#: AperoDeDenis.py:1034 +msgid "Ajouter les points GPS à partir d'un fichier" +msgstr "" + +#: AperoDeDenis.py:1035 +msgid "Ajouter les points GPS d'un autre chantier" +msgstr "" + +#: AperoDeDenis.py:1037 +msgid "Définir plusieurs appareils photos" +msgstr "" + +#: AperoDeDenis.py:1038 +msgid "Liste des appareils photos" +msgstr "" + +#: AperoDeDenis.py:1040 +msgid "Consulter le fichier mm3d-LogFile.txt" +msgstr "" + +#: AperoDeDenis.py:1046 +msgid "Désactiver le 'tacky' message de lancement" +msgstr "" + +#: AperoDeDenis.py:1048 +msgid "Activer le 'tacky' message de lancement" +msgstr "" + +#: AperoDeDenis.py:1051 +msgid "Afficher les paramètres" +msgstr "" + +#: AperoDeDenis.py:1053 +msgid "Associer le répertoire bin de MicMac" +msgstr "" + +#: AperoDeDenis.py:1054 +msgid "Associer 'exiftool'" +msgstr "" + +#: AperoDeDenis.py:1055 +msgid "Associer 'convert' d'ImageMagick" +msgstr "" + +#: AperoDeDenis.py:1056 +msgid "Associer 'ffmpeg (décompacte les vidéos)" +msgstr "" + +#: AperoDeDenis.py:1057 +msgid "Associer 'Meshlab' ou 'CloudCompare'" +msgstr "" + +#: AperoDeDenis.py:1059 +msgid "Changer la langue" +msgstr "" + +#: AperoDeDenis.py:1061 +msgid "Désactive/Active le tacky message de lancement..." +msgstr "" + +#: AperoDeDenis.py:1063 +msgid "Vérifie la présence d'une nouvelle version sur GitHub" +msgstr "" + +#: AperoDeDenis.py:1068 +msgid "Affichage de la surface interpolée" +msgstr "" + +#: AperoDeDenis.py:1069 +msgid "Calcul des indices" +msgstr "" + +#: AperoDeDenis.py:1070 +msgid "Calcul de la PMP" +msgstr "" + +#: AperoDeDenis.py:1075 +msgid "Pour commencer..." +msgstr "" + +#: AperoDeDenis.py:1076 +msgid "Aide sur les menus" +msgstr "" + +#: AperoDeDenis.py:1077 +msgid "Quelques conseils" +msgstr "" + +#: AperoDeDenis.py:1078 +msgid "Historique" +msgstr "" + +#: AperoDeDenis.py:1079 +msgid "A Propos" +msgstr "" + +#: AperoDeDenis.py:1083 +msgid "Fichier" +msgstr "" + +#: AperoDeDenis.py:1084 +msgid "Edition" +msgstr "" + +#: AperoDeDenis.py:1086 +msgid "Vidéo" +msgstr "" + +#: AperoDeDenis.py:1087 +msgid "Outils" +msgstr "" + +#: AperoDeDenis.py:1088 +msgid "Expert" +msgstr "" + +#: AperoDeDenis.py:1089 +msgid "Paramétrage" +msgstr "" + +#: AperoDeDenis.py:1091 +msgid "Aide" +msgstr "" + +#: AperoDeDenis.py:1124 +msgid "Pas de répertoire désigné pour MicMac\\bin" +msgstr "" + +#: AperoDeDenis.py:1125 +msgid "Pas de fichier désigné pour ouvrir les .PLY" +msgstr "" + +#: AperoDeDenis.py:1126 +msgid "Pas de chemin pour ExifTool" +msgstr "" + +#: AperoDeDenis.py:1127 +msgid "Pas de fichier pour mm3d" +msgstr "" + +#: AperoDeDenis.py:1128 +msgid "Pas de fichier pour ffmpeg" +msgstr "" + +#: AperoDeDenis.py:1129 +msgid "Pas de version MicMac" +msgstr "" + +#: AperoDeDenis.py:1131 +msgid "Pas de version Image Magick" +msgstr "" + +#: AperoDeDenis.py:1251 +msgid "" +"Tapioca recherche les points homologues entre photos : indiquer l'échelle ou " +"les échelles utilisées" +msgstr "" + +#: AperoDeDenis.py:1266 AperoDeDenis.py:1286 +msgid "Echelle image (-1 pour l'image entière) :" +msgstr "" + +#: AperoDeDenis.py:1274 +msgid "Echelle image réduite : " +msgstr "" + +#: AperoDeDenis.py:1278 +msgid "Seconde Echelle (-1 pour l'image entière) :" +msgstr "" + +#: AperoDeDenis.py:1288 +msgid "Delta (nombre d'images se recouvrant, avant et après) : " +msgstr "" + +#: AperoDeDenis.py:1299 +msgid "" +"Tapas positionne les appareils photos sur le nuage de points homologues. " +"Préciser le type d'appareil." +msgstr "" + +#: AperoDeDenis.py:1300 +msgid "" +"Quelques photos avec une grande profondeur d'image aident à calibrer " +"l'optique des appareils photos." +msgstr "" + +#: AperoDeDenis.py:1321 +msgid "Choisir quelques photos pour la calibration intrinsèques" +msgstr "" + +#: AperoDeDenis.py:1324 +msgid " N'utiliser ces photos que pour la calibration" +msgstr "" + +#: AperoDeDenis.py:1325 +msgid "Toutes ces photos doivent avoir la même focale." +msgstr "" + +#: AperoDeDenis.py:1327 +msgid "" +"lancer Tarama après TAPAS : mosaique pouvant définir un masque pour Malt/" +"ortho)" +msgstr "" + +#: AperoDeDenis.py:1330 +msgid "Arrêter le traitement après TAPAS" +msgstr "" + +#: AperoDeDenis.py:1345 +msgid "" +"Définition d'un référentiel et d'une métrique sur le nuage de points " +"homologues." +msgstr "" + +#: AperoDeDenis.py:1346 +msgid "Une ligne, un plan et la distance entre 2 points sont nécessaires." +msgstr "" + +#: AperoDeDenis.py:1358 AperoDeDenis.py:1393 +msgid "Choisir entre :" +msgstr "" + +#: AperoDeDenis.py:1361 +msgid "Ligne horizontale" +msgstr "" + +#: AperoDeDenis.py:1365 AperoDeDenis.py:1400 +msgid "ou" +msgstr "" + +#: AperoDeDenis.py:1368 +msgid "Ligne verticale" +msgstr "" + +#: AperoDeDenis.py:1381 AperoDeDenis.py:1415 +msgid "ET :" +msgstr "" + +#: AperoDeDenis.py:1396 +msgid "Zone plane horizontale" +msgstr "" + +#: AperoDeDenis.py:1403 +msgid "Zone plane verticale" +msgstr "" + +#: AperoDeDenis.py:1426 +msgid "Distance entre les 2 points :" +msgstr "" + +#: AperoDeDenis.py:1431 +msgid "Placer 2 points identiques sur 2 photos" +msgstr "" + +#: AperoDeDenis.py:1441 +msgid "Pour annuler la calibration mettre la distance = 0" +msgstr "" + +#: AperoDeDenis.py:1448 +msgid "Utiliser C3DC" +msgstr "" + +#: AperoDeDenis.py:1449 +msgid "Utiliser MALT" +msgstr "" + +#: AperoDeDenis.py:1458 +msgid "Option de Malt :" +msgstr "" + +#: AperoDeDenis.py:1461 +msgid "UrbanMNE pour photos urbaines" +msgstr "" + +#: AperoDeDenis.py:1462 +msgid "GeomImage pour photos du sol ou d'objets" +msgstr "" + +#: AperoDeDenis.py:1463 +msgid "Ortho pour orthophotos de terrain naturel [f(x,y)=z)]" +msgstr "" + +#: AperoDeDenis.py:1464 +msgid "AperoDeDenis choisit pour vous les options de GeomImage" +msgstr "" + +#: AperoDeDenis.py:1485 AperoDeDenis.py:4229 +msgid "Choisir les maîtresses" +msgstr "" + +#: AperoDeDenis.py:1487 AperoDeDenis.py:1521 +msgid "Tracer les masques" +msgstr "" + +#: AperoDeDenis.py:1488 +msgid "Attention : Le masque 3D de C3DC a la priorité sur Malt" +msgstr "" + +#: AperoDeDenis.py:1488 +msgid "Pour supprimer un masque : supprimer la maitresse" +msgstr "" + +#: AperoDeDenis.py:1490 +msgid "Nombre de photos à retenir autour de l'image maitresse (-1 = toutes) :" +msgstr "" + +#: AperoDeDenis.py:1497 +msgid "Zoom final : 8, 4, 2 ou 1 (8=le plus rapide, 1=le plus précis)" +msgstr "" + +#: AperoDeDenis.py:1504 +msgid "Lancer tawny après MALT" +msgstr "" + +#: AperoDeDenis.py:1505 +msgid "Tawny génère une ortho mosaïque qui sera drapée sur le nuage densifié." +msgstr "" + +#: AperoDeDenis.py:1506 +msgid "Saisir si besoin les paramètres facultatifs, exemple :" +msgstr "" + +#: AperoDeDenis.py:1509 +msgid "Liste des paramètres facultatifs nommés :" +msgstr "" + +#: AperoDeDenis.py:1513 +msgid "Tracer un masque sur la mosaïque Tarama" +msgstr "" + +#: AperoDeDenis.py:1519 +msgid "La saisie des masques n'est active qu'après Tapas." +msgstr "" + +#: AperoDeDenis.py:1520 AperoDeDenis.py:2712 AperoDeDenis.py:4282 +#: AperoDeDenis.py:4283 +msgid "Pas de masque." +msgstr "" + +#: AperoDeDenis.py:1522 +msgid "" +"Pour supprimer un masque : supprimer la maitresse dans l'option GeomImage" +msgstr "" + +#: AperoDeDenis.py:1523 +msgid "Consulter la documentation." +msgstr "" + +#: AperoDeDenis.py:1549 +msgid "Option de C3DC :" +msgstr "" + +#: AperoDeDenis.py:1550 +msgid "Forest - avec drapage, rapide" +msgstr "" + +#: AperoDeDenis.py:1551 +msgid "Statue - avec drapage" +msgstr "" + +#: AperoDeDenis.py:1552 +msgid "QuickMac - rapide, sans drapage" +msgstr "" + +#: AperoDeDenis.py:1553 +msgid "MicMac - sans drapage" +msgstr "" + +#: AperoDeDenis.py:1554 +msgid "BigMac - précis, sans drapage" +msgstr "" + +#: AperoDeDenis.py:1561 +msgid "Tracer un masque 3D" +msgstr "" + +#: AperoDeDenis.py:1563 +msgid "Supprimer le masque 3D" +msgstr "" + +#: AperoDeDenis.py:1566 +msgid "Dans la boîte de dialogue pour tracer le masque : " +msgstr "" + +#: AperoDeDenis.py:1567 +msgid "Définir le masque : F9 " +msgstr "" + +#: AperoDeDenis.py:1568 +msgid "Ajouter un point : clic gauche" +msgstr "" + +#: AperoDeDenis.py:1569 +msgid "Fermer le polygone : clic droit" +msgstr "" + +#: AperoDeDenis.py:1570 +msgid "Sélectionner : touche espace" +msgstr "" + +#: AperoDeDenis.py:1571 +msgid "Sauver le masque : Ctrl S." +msgstr "" + +#: AperoDeDenis.py:1572 +msgid "Quitter : Ctrl Q." +msgstr "" + +#: AperoDeDenis.py:1573 +msgid "Agrandir les points : Maj +" +msgstr "" + +#: AperoDeDenis.py:1574 +msgid "Saisie simultanée de plusieurs masques disjoints possible" +msgstr "" + +#: AperoDeDenis.py:1593 +msgid " Valider les options" +msgstr "" + +#: AperoDeDenis.py:1596 AperoDeDenis.py:1618 AperoDeDenis.py:1676 +#: AperoDeDenis.py:1723 AperoDeDenis.py:1797 AperoDeDenis.py:1824 +msgid " Annuler" +msgstr "" + +#: AperoDeDenis.py:1609 +msgid "Indiquer les dimensions du capteur, en mm." +msgstr "" + +#: AperoDeDenis.py:1610 +msgid "par exemple :" +msgstr "" + +#: AperoDeDenis.py:1611 +msgid "Le site :" +msgstr "" + +#: AperoDeDenis.py:1612 +msgid "fournit les dimensions de tous les appareils photos." +msgstr "" + +#: AperoDeDenis.py:1615 AperoDeDenis.py:1673 AperoDeDenis.py:1821 +msgid " Valider" +msgstr "" + +#: AperoDeDenis.py:1651 AperoDeDenis.py:1777 +msgid "Marque de l'appareil : " +msgstr "" + +#: AperoDeDenis.py:1655 +msgid "Nom de la camera : " +msgstr "" + +#: AperoDeDenis.py:1659 AperoDeDenis.py:1785 +msgid "Focale en mm:" +msgstr "" + +#: AperoDeDenis.py:1663 AperoDeDenis.py:1789 +msgid "Focale équivalente 35mm :" +msgstr "" + +#: AperoDeDenis.py:1667 +msgid "Nombre d'images à conserver par seconde :" +msgstr "" + +#: AperoDeDenis.py:1709 AperoDeDenis.py:1732 +msgid "linéaire" +msgstr "" + +#: AperoDeDenis.py:1710 +msgid "cubique" +msgstr "" + +#: AperoDeDenis.py:1713 +msgid " Choisir la méthode d'interpolation " +msgstr "" + +#: AperoDeDenis.py:1715 +msgid " Choisir le pas du maillage " +msgstr "" + +#: AperoDeDenis.py:1720 AperoDeDenis.py:1753 +msgid "Valider " +msgstr "" + +#: AperoDeDenis.py:1749 +msgid "Choisir profil à afficher " +msgstr "" + +#: AperoDeDenis.py:1756 +msgid "Annuler " +msgstr "" + +#: AperoDeDenis.py:1777 +msgid "Modification des Exif" +msgstr "" + +#: AperoDeDenis.py:1781 +msgid "Modèle de l'appareil: " +msgstr "" + +#: AperoDeDenis.py:1794 +msgid "Valider et mettre à jour" +msgstr "" + +#: AperoDeDenis.py:1816 +msgid "Indiquer le nombre de photos à retenir." +msgstr "" + +#: AperoDeDenis.py:1817 +msgid "" +"Un nouveau chantier sera créé avec les photos ayant, par paire, le plus de " +"points homologues" +msgstr "" + +#: AperoDeDenis.py:1818 +msgid "Ce choix est différent du nombre moyen de points homologues par photo." +msgstr "" + +#: AperoDeDenis.py:1839 +msgid "" +"MicMac est une réalisation de\n" +" Marc Pierrot-Deseilligny, IGN" +msgstr "" + +#: AperoDeDenis.py:2126 +msgid "Quelles options par défaut utiliser pour les nouveaux chantiers ?" +msgstr "" + +#: AperoDeDenis.py:2127 +msgid "Les options par défaut concernent :" +msgstr "" + +#: AperoDeDenis.py:2128 +msgid "Points homologues : All, MulScale, line ,les échelles et delta" +msgstr "" + +#: AperoDeDenis.py:2129 +msgid "" +"Orientation : RadialExtended,RadialStandard, Radialbasic, arrêt après Tapas" +msgstr "" + +#: AperoDeDenis.py:2130 +msgid "Points GPS : options de CAMPARI" +msgstr "" + +#: AperoDeDenis.py:2131 +msgid "" +"Densification Malt : mode, zoom final, nombre de photos autour de la " +"maîtresse" +msgstr "" + +#: AperoDeDenis.py:2132 +msgid "Densification Malt Ortho : Tawny et ses options en saisie libre" +msgstr "" + +#: AperoDeDenis.py:2133 +msgid "Densification C3DC : mode (Statue ou QuickMac)" +msgstr "" + +#: AperoDeDenis.py:2176 +msgid "Pas de répertoire pour les photos" +msgstr "" + +#: AperoDeDenis.py:2282 AperoDeDenis.py:2304 +msgid "Enregistrer le chantier ?" +msgstr "" + +#: AperoDeDenis.py:2283 AperoDeDenis.py:2305 +msgid "Chantier non encore enregistré. Voulez-vous l'enregistrer ?" +msgstr "" + +#: AperoDeDenis.py:2284 AperoDeDenis.py:2292 AperoDeDenis.py:2306 +#: AperoDeDenis.py:2313 AperoDeDenis.py:9464 +msgid "Enregistrer" +msgstr "" + +#: AperoDeDenis.py:2285 AperoDeDenis.py:2293 AperoDeDenis.py:2307 +#: AperoDeDenis.py:2314 AperoDeDenis.py:9464 +msgid "Ne pas enregistrer." +msgstr "" + +#: AperoDeDenis.py:2287 AperoDeDenis.py:2295 AperoDeDenis.py:2309 +#: AperoDeDenis.py:2316 AperoDeDenis.py:9466 +#, python-format +msgid "Chantier précédent enregistré : %s" +msgstr "" + +#: AperoDeDenis.py:2290 AperoDeDenis.py:2311 AperoDeDenis.py:9462 +#, python-format +msgid "Enregistrer le chantier %s ?" +msgstr "" + +#: AperoDeDenis.py:2291 AperoDeDenis.py:2312 AperoDeDenis.py:9463 +msgid "" +"Chantier modifié depuis la dernière sauvegarde. Voulez-vous l'enregistrer ?" +msgstr "" + +#: AperoDeDenis.py:2317 +msgid "Choisir un chantier." +msgstr "" + +#: AperoDeDenis.py:2319 AperoDeDenis.py:6698 +msgid "Aucun chantier choisi." +msgstr "" + +#: AperoDeDenis.py:2327 AperoDeDenis.py:6717 AperoDeDenis.py:6721 +#, python-format +msgid "Chantier choisi %s corrompu. Abandon." +msgstr "" + +#: AperoDeDenis.py:2331 +msgid "Chantier enregistré" +msgstr "" + +#: AperoDeDenis.py:2336 +msgid "Indiquer les photos à traiter avant d'enregistrer le chantier." +msgstr "" + +#: AperoDeDenis.py:2346 +msgid "Le chantier est en cours de définition." +msgstr "" + +#: AperoDeDenis.py:2346 +msgid "Il n'a pas encore de nom, il ne peut être renommé." +msgstr "" + +#: AperoDeDenis.py:2346 +msgid "Commencer par choisir les photos" +msgstr "" + +#: AperoDeDenis.py:2348 +#, python-format +msgid "Nouveau nom ou nouveau chemin pour le chantier %s :" +msgstr "" + +#: AperoDeDenis.py:2349 +msgid "Donner le nouveau nom du chantier" +msgstr "" + +#: AperoDeDenis.py:2350 +msgid "" +"Un chemin absolu sur la même unité disque ou relatif au répertoire pére est " +"valide" +msgstr "" + +#: AperoDeDenis.py:2351 +msgid "Aucun fichier de l'arborescence du chantier ne doit être ouvert." +msgstr "" + +#: AperoDeDenis.py:2352 +msgid "Chemin actuel : " +msgstr "" + +#: AperoDeDenis.py:2361 +msgid "Nouveau nom = ancien nom ; Abandon" +msgstr "" + +#: AperoDeDenis.py:2365 +#, python-format +msgid "Le nom du nouveau chantier %s est déjà un chantier. Abandon." +msgstr "" + +#: AperoDeDenis.py:2368 +msgid "Le nouveau répertoire " +msgstr "" + +#: AperoDeDenis.py:2368 +msgid "implique un changement de disque." +msgstr "" + +#: AperoDeDenis.py:2368 +msgid "Utiliser l'Export-Import." +msgstr "" + +#: AperoDeDenis.py:2371 AperoDeDenis.py:2374 +msgid "Le répertoire" +msgstr "" + +#: AperoDeDenis.py:2371 +msgid "pour le chantier est déjà utilisé." +msgstr "" + +#: AperoDeDenis.py:2371 AperoDeDenis.py:2374 +msgid "Choisissez un autre nom." +msgstr "" + +#: AperoDeDenis.py:2374 +msgid "désigne un sous-répertoire du chantier en cours." +msgstr "" + +#: AperoDeDenis.py:2386 +msgid "Le renommage du chantier ne peut se faire actuellement," +msgstr "" + +#: AperoDeDenis.py:2386 +msgid "soit le nom fourni est incorrect," +msgstr "" + +#: AperoDeDenis.py:2387 +msgid "soit un fichier du chantier est ouvert par une autre application." +msgstr "" + +#: AperoDeDenis.py:2388 +msgid "soit l'explorateur explore l'arborescence." +msgstr "" + +#: AperoDeDenis.py:2388 +msgid "erreur : " +msgstr "" + +#: AperoDeDenis.py:2404 +msgid "Chantier :" +msgstr "" + +#: AperoDeDenis.py:2404 +msgid "renommé en :" +msgstr "" + +#: AperoDeDenis.py:2404 +msgid "Répertoire : " +msgstr "" + +#: AperoDeDenis.py:2471 +msgid "Pas de chantier en cours" +msgstr "" + +#: AperoDeDenis.py:2473 +msgid "Patience : chantier en cours d'archivage..." +msgstr "" + +#: AperoDeDenis.py:2475 +msgid "Archive " +msgstr "" + +#: AperoDeDenis.py:2475 +msgid "créée sous " +msgstr "" + +#: AperoDeDenis.py:2475 +msgid "Taille =" +msgstr "" + +#: AperoDeDenis.py:2480 +msgid "Choisir le nom de l'archive à importer." +msgstr "" + +#: AperoDeDenis.py:2482 +msgid "Export" +msgstr "" + +#: AperoDeDenis.py:2482 AperoDeDenis.py:3203 AperoDeDenis.py:3226 +#: AperoDeDenis.py:3248 AperoDeDenis.py:3271 AperoDeDenis.py:3359 +#: AperoDeDenis.py:6772 AperoDeDenis.py:8299 +msgid "Tous" +msgstr "" + +#: AperoDeDenis.py:2484 +msgid "Chantier à importer" +msgstr "" + +#: AperoDeDenis.py:2486 +msgid "Importation abandonnée." +msgstr "" + +#: AperoDeDenis.py:2489 +msgid " n'est pas un fichier d'export valide" +msgstr "" + +#: AperoDeDenis.py:2490 +msgid "ou alors, sous ubuntu,il lui manque le droit d'exécution." +msgstr "" + +#: AperoDeDenis.py:2494 +msgid "Choisir le répertoire dans lequel recopier le chantier." +msgstr "" + +#: AperoDeDenis.py:2498 +msgid " n'est pas un répertoire valide." +msgstr "" + +#: AperoDeDenis.py:2501 +msgid "Recopie en cours dans" +msgstr "" + +#: AperoDeDenis.py:2501 +msgid "Patience !" +msgstr "" + +#: AperoDeDenis.py:2509 +msgid "Le répertoire destination" +msgstr "" + +#: AperoDeDenis.py:2509 +msgid "existe déjà. Abandon" +msgstr "" + +#: AperoDeDenis.py:2520 AperoDeDenis.py:2529 +msgid "Erreur copie lors d'un import : " +msgstr "" + +#: AperoDeDenis.py:2521 AperoDeDenis.py:2530 +msgid "L'importation a échouée. Erreur : " +msgstr "" + +#: AperoDeDenis.py:2545 +msgid " absent" +msgstr "" + +#: AperoDeDenis.py:2561 +msgid "Chantier importé :" +msgstr "" + +#: AperoDeDenis.py:2561 +msgid "Répertoire :" +msgstr "" + +#: AperoDeDenis.py:2561 +msgid "Vous pouvez le renommer si besoin." +msgstr "" + +#: AperoDeDenis.py:2564 +#, python-format +msgid "Version de MicMac avant l'import : %s" +msgstr "" + +#: AperoDeDenis.py:2565 +#, python-format +msgid "Version de MicMac : %s" +msgstr "" + +#: AperoDeDenis.py:2568 +msgid "erreur affichage version lors de l'import d'un chantier : " +msgstr "" + +#: AperoDeDenis.py:2570 +msgid "Anomalie lors de l'importation : " +msgstr "" + +#: AperoDeDenis.py:2581 +#, python-format +msgid "" +"Le répertoire du nouveau chantier \n" +" %s \n" +" est déjà un chantier.\n" +" Abandon." +msgstr "" + +#: AperoDeDenis.py:2583 +msgid "Répertoire correct. Patience..." +msgstr "" + +#: AperoDeDenis.py:2595 +msgid "Le répertoire ne contient pas le fichier :\n" +msgstr "" + +#: AperoDeDenis.py:2595 +msgid "" +"\n" +"Ce n'est pas un chantier.\n" +"Abandon." +msgstr "" + +#: AperoDeDenis.py:2603 +#, python-format +msgid "erreur copie fichier param chantier : %(param)s vers %(rep)s erreur=" +msgstr "" + +#: AperoDeDenis.py:2606 +msgid "Erreur lors de la copie du fichier paramètre chantier" +msgstr "" + +#: AperoDeDenis.py:2606 +msgid "vers" +msgstr "" + +#: AperoDeDenis.py:2606 +msgid "erreur :" +msgstr "" + +#: AperoDeDenis.py:2627 +msgid "Répertoire des photos :" +msgstr "" + +#: AperoDeDenis.py:2629 +msgid "Répertoire de la vidéo :" +msgstr "" + +#: AperoDeDenis.py:2631 +msgid "Aucune photo sélectionnée." +msgstr "" + +#: AperoDeDenis.py:2634 +msgid " photos sélectionnées" +msgstr "" + +#: AperoDeDenis.py:2634 +msgid "(sans calibration si tapas executé) : " +msgstr "" + +#: AperoDeDenis.py:2636 +msgid " photos sélectionnées : " +msgstr "" + +#: AperoDeDenis.py:2639 +msgid "ATTENTION : plusieurs extensions différentes dans les photos choisies !" +msgstr "" + +#: AperoDeDenis.py:2639 +msgid "Le traitement ne se fera que sur un type de fichier." +msgstr "" + +#: AperoDeDenis.py:2644 AperoDeDenis.py:2658 AperoDeDenis.py:2701 +msgid "Mode : " +msgstr "" + +#: AperoDeDenis.py:2646 AperoDeDenis.py:2648 +msgid "Echelle 1 : " +msgstr "" + +#: AperoDeDenis.py:2649 +msgid "Echelle 2 : " +msgstr "" + +#: AperoDeDenis.py:2651 +msgid "Echelle : " +msgstr "" + +#: AperoDeDenis.py:2652 +msgid "Delta : " +msgstr "" + +#: AperoDeDenis.py:2660 +msgid "Nombre de photos pour calibration intrinsèque : " +msgstr "" + +#: AperoDeDenis.py:2662 +msgid "Ces photos servent uniquement à la calibration." +msgstr "" + +#: AperoDeDenis.py:2664 +msgid "Tarama demandé après Tapas" +msgstr "" + +#: AperoDeDenis.py:2666 +msgid "Arrêt demandé après Tapas" +msgstr "" + +#: AperoDeDenis.py:2671 +msgid "Mise à l'échelle présente" +msgstr "" + +#: AperoDeDenis.py:2674 +msgid "Mise à l'échelle invalide : distance=0" +msgstr "" + +#: AperoDeDenis.py:2676 +msgid "Mise à l'échelle incomplète :" +msgstr "" + +#: AperoDeDenis.py:2681 +msgid "Points GPS : Saisie complète, les points seront pris en compte" +msgstr "" + +#: AperoDeDenis.py:2683 +msgid "Points GPS : Saisie incomplète, les points ne seront pas pris en compte" +msgstr "" + +#: AperoDeDenis.py:2688 +msgid "La version installée de Micmac n'autorise pas les masques en 3D" +msgstr "" + +#: AperoDeDenis.py:2694 +msgid "Densification : C3DC avec masque 3D" +msgstr "" + +#: AperoDeDenis.py:2696 +msgid "Densification : C3DC sans Masque" +msgstr "" + +#: AperoDeDenis.py:2704 +msgid "Pas d'image maîtresse\n" +msgstr "" + +#: AperoDeDenis.py:2706 AperoDeDenis.py:2724 +msgid "Image maîtresse : " +msgstr "" + +#: AperoDeDenis.py:2708 AperoDeDenis.py:2726 AperoDeDenis.py:4276 +#: AperoDeDenis.py:4279 +msgid " images maîtresses" +msgstr "" + +#: AperoDeDenis.py:2710 +msgid "1 masque" +msgstr "" + +#: AperoDeDenis.py:2714 AperoDeDenis.py:4290 AperoDeDenis.py:4291 +msgid " masques" +msgstr "" + +#: AperoDeDenis.py:2716 +#, python-format +msgid "%s photos utiles autour de la maîtresse" +msgstr "" + +#: AperoDeDenis.py:2720 +msgid "Tawny lancé après Malt" +msgstr "" + +#: AperoDeDenis.py:2728 +msgid "arrêt au zoom : " +msgstr "" + +#: AperoDeDenis.py:2733 +msgid "Chantier en cours de définition." +msgstr "" + +#: AperoDeDenis.py:2751 +msgid "Chantier nettoyé." +msgstr "" + +#: AperoDeDenis.py:2758 +msgid "Chantier : " +msgstr "" + +#: AperoDeDenis.py:2764 +msgid "Chemin du chantier :" +msgstr "" + +#: AperoDeDenis.py:2766 +msgid "Chantier en attente d'enregistrement." +msgstr "" + +#: AperoDeDenis.py:2768 +msgid "Chantier enregistré." +msgstr "" + +#: AperoDeDenis.py:2770 +msgid "Options du chantier modifiables." +msgstr "" + +#: AperoDeDenis.py:2772 +msgid "Chantier interrompu suite à erreur." +msgstr "" + +#: AperoDeDenis.py:2772 +msgid "Relancer micmac." +msgstr "" + +#: AperoDeDenis.py:2774 +msgid "Options de Malt/C3DC modifiables." +msgstr "" + +#: AperoDeDenis.py:2776 +msgid "Chantier terminé." +msgstr "" + +#: AperoDeDenis.py:2778 +msgid "Chantier exécuté puis débloqué." +msgstr "" + +#: AperoDeDenis.py:2780 +msgid "La densification a echoué : pas de nuage dense généré." +msgstr "" + +#: AperoDeDenis.py:2785 +msgid "Nuage de point non densifié généré après Tapas." +msgstr "" + +#: AperoDeDenis.py:2789 +msgid "Nuage de point densifié généré." +msgstr "" + +#: AperoDeDenis.py:2792 +msgid "Aucun nuage de point généré." +msgstr "" + +#: AperoDeDenis.py:2801 +msgid "Les caractéristiques du chantier précédent" +msgstr "" + +#: AperoDeDenis.py:2801 +msgid "n'ont pas pu être lues correctement." +msgstr "" + +#: AperoDeDenis.py:2802 +msgid "" +"Le fichier des paramètres est probablement incorrect ou vous avez changé la " +"version de l'interface." +msgstr "" + +#: AperoDeDenis.py:2803 +msgid "Certaines fonctions seront peut_être défaillantes." +msgstr "" + +#: AperoDeDenis.py:2804 +msgid "Désolé pour l'incident." +msgstr "" + +#: AperoDeDenis.py:2805 +msgid "Erreur : " +msgstr "" + +#: AperoDeDenis.py:2833 AperoDeDenis.py:2834 AperoDeDenis.py:2837 +msgid "Toutes les photos" +msgstr "" + +#: AperoDeDenis.py:2836 +msgid "Toutes les photos utiles" +msgstr "" + +#: AperoDeDenis.py:2837 +#, python-format +msgid "sans les %s photos pour calibration intrinseque" +msgstr "" + +#: AperoDeDenis.py:2843 AperoDeDenis.py:2854 AperoDeDenis.py:2865 +#: AperoDeDenis.py:2877 AperoDeDenis.py:2892 AperoDeDenis.py:2915 +#: AperoDeDenis.py:2939 AperoDeDenis.py:2956 AperoDeDenis.py:2967 +#: AperoDeDenis.py:2985 AperoDeDenis.py:3003 AperoDeDenis.py:8942 +#: AperoDeDenis.py:8959 +msgid "Fermer" +msgstr "" + +#: AperoDeDenis.py:2848 +msgid "Aucun point GPS saisi." +msgstr "" + +#: AperoDeDenis.py:2851 +msgid "Affichage des photos avec points GPS" +msgstr "" + +#: AperoDeDenis.py:2853 +msgid "seules les photos avec points sont montrées." +msgstr "" + +#: AperoDeDenis.py:2862 +msgid "Liste des images maîtresses et des masques " +msgstr "" + +#: AperoDeDenis.py:2862 +msgid "communs à GeomImage et AperoDedenis" +msgstr "" + +#: AperoDeDenis.py:2864 +msgid "Images maîtresses et masques" +msgstr "" + +#: AperoDeDenis.py:2868 +msgid "Pas de maîtresses définies pour ce chantier" +msgstr "" + +#: AperoDeDenis.py:2874 +msgid "Mosaique Tarama et masque " +msgstr "" + +#: AperoDeDenis.py:2874 +msgid "Option Ortho de Malt" +msgstr "" + +#: AperoDeDenis.py:2876 +msgid "Image maîtresse et masque" +msgstr "" + +#: AperoDeDenis.py:2883 +msgid "Pas de masque 3D pour ce chantier." +msgstr "" + +#: AperoDeDenis.py:2890 +msgid "Visaliser le masque 3D" +msgstr "" + +#: AperoDeDenis.py:2894 +msgid "Affichage du masque 3D :" +msgstr "" + +#: AperoDeDenis.py:2895 +msgid "Les points blancs du nuage sont dans le masque" +msgstr "" + +#: AperoDeDenis.py:2896 +msgid "Ce masque C3DC a la priorité sur le masque 2D de Malt" +msgstr "" + +#: AperoDeDenis.py:2897 +msgid "ATTENTION : pour continuer FERMER la fenêtre 3D" +msgstr "" + +#: AperoDeDenis.py:2898 +msgid "puis cliquer si besoin sur le bouton FERMER ci-dessus." +msgstr "" + +#: AperoDeDenis.py:2908 +msgid "horizontale" +msgstr "" + +#: AperoDeDenis.py:2910 +msgid "verticale" +msgstr "" + +#: AperoDeDenis.py:2912 +msgid "Visualiser l'image maîtresse et le plan horizontal ou vertical" +msgstr "" + +#: AperoDeDenis.py:2914 +msgid "Zone plane " +msgstr "" + +#: AperoDeDenis.py:2920 +msgid "Pas de plan horizontal ou vertical défini pour ce chantier" +msgstr "" + +#: AperoDeDenis.py:2930 +msgid "HORIZONTALE" +msgstr "" + +#: AperoDeDenis.py:2933 +msgid "VERTICALE" +msgstr "" + +#: AperoDeDenis.py:2936 +msgid "Affichage des photos avec ligne horizontale ou verticale" +msgstr "" + +#: AperoDeDenis.py:2938 +msgid "ligne " +msgstr "" + +#: AperoDeDenis.py:2942 +msgid "Pas de ligne horizontale ou verticale définie pour ce chantier" +msgstr "" + +#: AperoDeDenis.py:2948 +msgid "Pas de distance correcte définie pour ce chantier." +msgstr "" + +#: AperoDeDenis.py:2953 +msgid "Visualiser les photos avec distance" +msgstr "" + +#: AperoDeDenis.py:2955 +msgid "Valeur de la distance : " +msgstr "" + +#: AperoDeDenis.py:2961 +msgid "Pas de photos pour la calibration intrinsèque par Tapas." +msgstr "" + +#: AperoDeDenis.py:2964 +msgid "Les photos pour calibration intrinsèque (Tapas)" +msgstr "" + +#: AperoDeDenis.py:2966 +msgid "Calibration intrinsèque" +msgstr "" + +#: AperoDeDenis.py:2972 +msgid "Pas de mosaique. Choisir l'option Tarama de tapas." +msgstr "" + +#: AperoDeDenis.py:2978 +msgid "Echec de la conversion mosaique en JPG." +msgstr "" + +#: AperoDeDenis.py:2982 +msgid "Mosaique créée par Tarama" +msgstr "" + +#: AperoDeDenis.py:2990 +msgid "Pas d' ortho mosaique par Tawny. Choisir l'option Tawny de Malt." +msgstr "" + +#: AperoDeDenis.py:2996 +msgid "Echec de la conversion de la mosaïque TIF en JPG." +msgstr "" + +#: AperoDeDenis.py:3000 +msgid "Ortho mosaique créée par Tawny" +msgstr "" + +#: AperoDeDenis.py:3027 +msgid "Pas de trace de la trace !" +msgstr "" + +#: AperoDeDenis.py:3038 +msgid "Pas de nuage de points non densifié." +msgstr "" + +#: AperoDeDenis.py:3040 +msgid "Programme pour ouvrir les .PLY non trouvéé." +msgstr "" + +#: AperoDeDenis.py:3045 +msgid "Pas de nuage de points densifié." +msgstr "" + +#: AperoDeDenis.py:3047 AperoDeDenis.py:5357 +msgid "Programme pour ouvrir les .PLY non trouvé." +msgstr "" + +#: AperoDeDenis.py:3053 +msgid "Répertoire bin de MicMac : " +msgstr "" + +#: AperoDeDenis.py:3055 +msgid "Version MicMac :" +msgstr "" + +#: AperoDeDenis.py:3057 +msgid "Outil exiftool :" +msgstr "" + +#: AperoDeDenis.py:3059 +msgid "Outil convert d'ImageMagick :" +msgstr "" + +#: AperoDeDenis.py:3061 +msgid "Outil pour afficher les .ply :" +msgstr "" + +#: AperoDeDenis.py:3063 +msgid "Outil pour décompacter les vidéos (ffmpeg):" +msgstr "" + +#: AperoDeDenis.py:3065 +msgid "Répertoire d'AperoDeDenis :" +msgstr "" + +#: AperoDeDenis.py:3067 +msgid "Répertoire des paramètres :" +msgstr "" + +#: AperoDeDenis.py:3077 +msgid "Répertoire bin sous MICMAC : " +msgstr "" + +#: AperoDeDenis.py:3086 +msgid "Désigner le répertoire bin sous Micmac " +msgstr "" + +#: AperoDeDenis.py:3088 AperoDeDenis.py:3095 AperoDeDenis.py:3209 +#: AperoDeDenis.py:3232 AperoDeDenis.py:3254 AperoDeDenis.py:3277 +msgid "Abandon, pas de changement." +msgstr "" + +#: AperoDeDenis.py:3088 AperoDeDenis.py:3095 +msgid "Répertoire bin de Micmac :" +msgstr "" + +#: AperoDeDenis.py:3093 +msgid "" +"Le chemin du répertoire bin de micmac ne doit pas comporter le caractère " +"'espace'." +msgstr "" + +#: AperoDeDenis.py:3094 +msgid "Renommer le répertoire de MicMac." +msgstr "" + +#: AperoDeDenis.py:3109 +#, python-format +msgid "Le répertoire %s ne contient pas le fichier mm3d.exe. Abandon" +msgstr "" + +#: AperoDeDenis.py:3155 +#, python-format +msgid "Le répertoire %s ne contient pas le fichier mm3d. Abandon" +msgstr "" + +#: AperoDeDenis.py:3168 +msgid "Nouveau répertoire de Micmac :" +msgstr "" + +#: AperoDeDenis.py:3173 +msgid "Le programme mm3d est présent mais ne peut s'exécuter." +msgstr "" + +#: AperoDeDenis.py:3173 +msgid "Vérifier si la version est compatible avec le système. :" +msgstr "" + +#: AperoDeDenis.py:3175 +msgid "Le programme mm3d est absent du répertoire choisi :" +msgstr "" + +#: AperoDeDenis.py:3175 +msgid "Répertoire bin sous MicMac incorrect." +msgstr "" + +#: AperoDeDenis.py:3175 +msgid "Abandon." +msgstr "" + +#: AperoDeDenis.py:3180 +msgid "Chemin de exiftool :" +msgstr "" + +#: AperoDeDenis.py:3182 +msgid "Chemin de convert d'image Magick :" +msgstr "" + +#: AperoDeDenis.py:3184 +msgid "Chemin de ffmpeg :" +msgstr "" + +#: AperoDeDenis.py:3189 +msgid "Pas de version identifiée de MicMac" +msgstr "" + +#: AperoDeDenis.py:3190 +msgid "Nouvelle version de MicMac : " +msgstr "" + +#: AperoDeDenis.py:3197 +msgid "Pas de chemin pour le programme exiftool" +msgstr "" + +#: AperoDeDenis.py:3199 AperoDeDenis.py:3214 +msgid "Programme exiftool :" +msgstr "" + +#: AperoDeDenis.py:3207 +msgid "Recherche exiftool" +msgstr "" + +#: AperoDeDenis.py:3209 +msgid "Fichier exiftool inchangé :" +msgstr "" + +#: AperoDeDenis.py:3220 +msgid "Pas de chemin pour le programme convert d'ImageMagick" +msgstr "" + +#: AperoDeDenis.py:3222 AperoDeDenis.py:3237 +msgid "Programme convert :" +msgstr "" + +#: AperoDeDenis.py:3230 +msgid "Recherche convert" +msgstr "" + +#: AperoDeDenis.py:3232 +msgid "Fichier convert inchangé :" +msgstr "" + +#: AperoDeDenis.py:3243 +msgid "Pas de chemin pour le programme ouvrant les .PLY" +msgstr "" + +#: AperoDeDenis.py:3245 AperoDeDenis.py:3259 +msgid "Programme ouvrant les .PLY :" +msgstr "" + +#: AperoDeDenis.py:3248 +msgid "meshlab ou CloudCompare" +msgstr "" + +#: AperoDeDenis.py:3252 +msgid "Recherche fichier Meshlab sous VCG, ou CloudCompare" +msgstr "" + +#: AperoDeDenis.py:3254 +msgid "Fichier Meshlab ou cloud compare :" +msgstr "" + +#: AperoDeDenis.py:3265 +msgid "Pas de chemin pour le programme Ffmpeg" +msgstr "" + +#: AperoDeDenis.py:3267 AperoDeDenis.py:3282 +msgid "Programme ffmpeg :" +msgstr "" + +#: AperoDeDenis.py:3275 +msgid "Recherche ffmpeg" +msgstr "" + +#: AperoDeDenis.py:3277 +msgid "Fichier ffmpeg inchangé :" +msgstr "" + +#: AperoDeDenis.py:3288 +msgid "Tacky message au lancement activé" +msgstr "" + +#: AperoDeDenis.py:3290 +msgid "Tacky message au lancement désactivé" +msgstr "" + +#: AperoDeDenis.py:3294 +msgid "Sélectionnez la langue à utiliser. L'application sera redémarrée." +msgstr "" + +#: AperoDeDenis.py:3302 +msgid "Appliquer" +msgstr "" + +#: AperoDeDenis.py:3305 AperoDeDenis.py:3311 +msgid "Français" +msgstr "" + +#: AperoDeDenis.py:3306 +msgid "Anglais" +msgstr "" + +#: AperoDeDenis.py:3331 +msgid "" +"Avant de choisir les photos associer le répertoire bin de micmac (Menu " +"Paramétrage\\associer le répertoire bin de MicMac)." +msgstr "" + +#: AperoDeDenis.py:3335 +msgid "" +"Avant de choisir les photos associer le chemin du programme exiftool (Menu " +"trage\\Associer exiftool)." +msgstr "" + +#: AperoDeDenis.py:3343 +msgid "Nouvelles photos pour le meme chantier" +msgstr "" + +#: AperoDeDenis.py:3344 +msgid "Choisir de nouvelles photos réinitialisera le chantier." +msgstr "" + +#: AperoDeDenis.py:3345 +msgid "Les traces et l'arborescence des calculs seront effacées." +msgstr "" + +#: AperoDeDenis.py:3346 +msgid "Les options compatibles avec les nouvelles photos seront conservées." +msgstr "" + +#: AperoDeDenis.py:3348 +msgid "Réinitialiser le chantier" +msgstr "" + +#: AperoDeDenis.py:3349 AperoDeDenis.py:6816 +msgid "Abandon, le chantier n'est pas modifié." +msgstr "" + +#: AperoDeDenis.py:3359 +msgid "Photos" +msgstr "" + +#: AperoDeDenis.py:3363 +msgid "Abandon, aucune sélection de fichier image," +msgstr "" + +#: AperoDeDenis.py:3363 AperoDeDenis.py:3427 AperoDeDenis.py:6282 +msgid "le répertoire et les photos restent inchangés." +msgstr "" + +#: AperoDeDenis.py:3367 AperoDeDenis.py:3390 +msgid "Aucune extension acceptable pour des images. Abandon." +msgstr "" + +#: AperoDeDenis.py:3371 +msgid "Plusieurs extensions différentes :" +msgstr "" + +#: AperoDeDenis.py:3371 +msgid "Impossible dans cette version. Abandon." +msgstr "" + +#: AperoDeDenis.py:3376 +msgid "Info : format des photos" +msgstr "" + +#: AperoDeDenis.py:3376 +msgid "La version actuelle ne traite que les photos au format JPG," +msgstr "" + +#: AperoDeDenis.py:3376 +msgid "or le format des photos est : " +msgstr "" + +#: AperoDeDenis.py:3377 +msgid "les photos vont être converties au format JPG." +msgstr "" + +#: AperoDeDenis.py:3378 +msgid "Convertir en JPG" +msgstr "" + +#: AperoDeDenis.py:3379 AperoDeDenis.py:3407 +msgid "Abandonner" +msgstr "" + +#: AperoDeDenis.py:3382 +msgid "Désigner l'outil de conversation 'convert' d'ImageMagick" +msgstr "" + +#: AperoDeDenis.py:3382 +msgid "(Menu Paramétrage)" +msgstr "" + +#: AperoDeDenis.py:3404 +msgid "ATTENTION !" +msgstr "" + +#: AperoDeDenis.py:3404 +msgid "" +"ATTENTION : des points GPS ont été précedemment placés sur des photos non " +"choisies pour ce chantier." +msgstr "" + +#: AperoDeDenis.py:3405 +msgid "" +"Les emplacements de ces points vont être supprimés si vous validez cette " +"sélection de photos." +msgstr "" + +#: AperoDeDenis.py:3406 +msgid "Valider la sélection de photos" +msgstr "" + +#: AperoDeDenis.py:3415 +msgid "Copie des photos en cours... Patience" +msgstr "" + +#: AperoDeDenis.py:3424 AperoDeDenis.py:6279 +msgid "Impossible de créer le répertoire de travail." +msgstr "" + +#: AperoDeDenis.py:3424 AperoDeDenis.py:6279 +msgid "Vérifier les droits en écriture sous le répertoire des photos" +msgstr "" + +#: AperoDeDenis.py:3427 AperoDeDenis.py:6282 +msgid "Aucun JPG, PNG, BMP, TIF, ou GIF sélectionné," +msgstr "" + +#: AperoDeDenis.py:3438 +msgid "Les focales sont absentes des exif." +msgstr "" + +#: AperoDeDenis.py:3438 +msgid "Mettez à jour les exifs avant de lancer MicMac." +msgstr "" + +#: AperoDeDenis.py:3439 +msgid "Utiliser le menu Outils/Modifier l'exif des photos." +msgstr "" + +#: AperoDeDenis.py:3441 +msgid "Attention : Les focales des photos ou ne sont pas toutes identiques." +msgstr "" + +#: AperoDeDenis.py:3443 +msgid "Attention : les dimensions des photos ne sont pas toutes identiques." +msgstr "" + +#: AperoDeDenis.py:3444 +msgid "Le traitement par MicMac ne sera peut-être pas possible." +msgstr "" + +#: AperoDeDenis.py:3455 +msgid "De nouvelles photos ont été sélectionnés sur un chantier pré-existant." +msgstr "" + +#: AperoDeDenis.py:3456 +msgid "" +"Les anciennes options compatibles avec les nouvelles photos ont été " +"conservées." +msgstr "" + +#: AperoDeDenis.py:3507 +msgid "erreur lors de la copie du fichier" +msgstr "" + +#: AperoDeDenis.py:3507 +msgid "dans le répertoire " +msgstr "" + +#: AperoDeDenis.py:3507 +msgid "libellé de l'erreur :" +msgstr "" + +#: AperoDeDenis.py:3507 +msgid "Causes possibles : manque d'espace disque ou droits insuffisants." +msgstr "" + +#: AperoDeDenis.py:3573 +msgid "Impossible de créer le répertoire de travail : erreur = " +msgstr "" + +#: AperoDeDenis.py:3587 +#, python-format +msgid "Le chantier %s a été interrompu en cours d'exécution." +msgstr "" + +#: AperoDeDenis.py:3588 AperoDeDenis.py:5090 +msgid "Le chantier est interrompu." +msgstr "" + +#: AperoDeDenis.py:3588 AperoDeDenis.py:5090 AperoDeDenis.py:5105 +msgid "Vous pouvez le débloquer," +msgstr "" + +#: AperoDeDenis.py:3589 AperoDeDenis.py:5091 +msgid "ce qui permettra de modifier les options et de le relancer." +msgstr "" + +#: AperoDeDenis.py:3590 AperoDeDenis.py:5092 AperoDeDenis.py:5107 +msgid "Débloquer le chantier" +msgstr "" + +#: AperoDeDenis.py:3596 AperoDeDenis.py:5098 AperoDeDenis.py:5113 +#: AperoDeDenis.py:5141 +#, python-format +msgid "Chantier %s de nouveau modifiable, paramètrable et exécutable." +msgstr "" + +#: AperoDeDenis.py:3606 +#, python-format +msgid "Le chantier %(x)s est terminé." +msgstr "" + +#: AperoDeDenis.py:3607 +msgid "Le chantier est terminé après " +msgstr "" + +#: AperoDeDenis.py:3608 +msgid "Vous pouvez :" +msgstr "" + +#: AperoDeDenis.py:3609 +msgid " - Modifier les options de Tapioca et Tapas" +msgstr "" + +#: AperoDeDenis.py:3610 +msgid "" +" - Conserver les traitements de Tapioca/Tapas pour relancer la densification" +msgstr "" + +#: AperoDeDenis.py:3611 +msgid " - Ne rien faire." +msgstr "" + +#: AperoDeDenis.py:3612 +msgid "Modifier les options de Tapioca et Tapas" +msgstr "" + +#: AperoDeDenis.py:3613 +msgid "Modifier les options de la densification" +msgstr "" + +#: AperoDeDenis.py:3614 AperoDeDenis.py:6814 +msgid "Ne rien faire" +msgstr "" + +#: AperoDeDenis.py:3643 AperoDeDenis.py:4182 +msgid "Nombre de photos choisies : " +msgstr "" + +#: AperoDeDenis.py:3667 +msgid "" +"La version de Micmac installée ne propose pas le module C3DC. Choisir MALT." +msgstr "" + +#: AperoDeDenis.py:3671 +msgid "Pas de nuage Apericloud : pour construire un masque" +msgstr "" + +#: AperoDeDenis.py:3671 +msgid "lancer Tapioca/tapas." +msgstr "" + +#: AperoDeDenis.py:3676 AperoDeDenis.py:4464 +msgid "Masque 3D créé" +msgstr "" + +#: AperoDeDenis.py:3678 +msgid "Pas de masque 3D" +msgstr "" + +#: AperoDeDenis.py:3713 AperoDeDenis.py:5461 +msgid "Option incorrecte :" +msgstr "" + +#: AperoDeDenis.py:3726 +msgid "Points GPS non conformes. Nom est absent ou en double. Vérifiez." +msgstr "" + +#: AperoDeDenis.py:3733 AperoDeDenis.py:6568 +msgid "Nom" +msgstr "" + +#: AperoDeDenis.py:3752 +msgid "NomPhoto" +msgstr "" + +#: AperoDeDenis.py:3754 AperoDeDenis.py:3760 +msgid "NomPoint" +msgstr "" + +#: AperoDeDenis.py:3783 +msgid "Pas de points GPS." +msgstr "" + +#: AperoDeDenis.py:3788 +#, python-format +msgid "%s points GPS placés" +msgstr "" + +#: AperoDeDenis.py:3789 +#, python-format +msgid "pour %s points GPS définis" +msgstr "" + +#: AperoDeDenis.py:3791 +msgid "" +"Attention : il faut au moins 3 points pour qu'ils soient pris en compte." +msgstr "" + +#: AperoDeDenis.py:3810 +msgid "" +"Il n'y a pas 3 points placés sur 2 photos : les points GPS seront ignorés." +msgstr "" + +#: AperoDeDenis.py:3813 +msgid "" +"Anomalie : les points suivants ne sont placés que sur une seule photo : " +msgstr "" + +#: AperoDeDenis.py:3816 +msgid "Anomalie : le point suivant n'est placé que sur une seule photo : " +msgstr "" + +#: AperoDeDenis.py:3823 +msgid "Attention : plusieurs points GPS ont les mêmes coordonnées." +msgstr "" + +#: AperoDeDenis.py:3826 +msgid "Saisie incomplète : les points GPS ne seront pas pris en compte" +msgstr "" + +#: AperoDeDenis.py:3841 +msgid "La ligne horizontale ou verticale ne comporte pas 2 points" +msgstr "" + +#: AperoDeDenis.py:3844 +msgid "Pas de maitre plan horizontal ou vertical" +msgstr "" + +#: AperoDeDenis.py:3848 +msgid "Pas de plan horizontal ou vertical" +msgstr "" + +#: AperoDeDenis.py:3853 +#, python-format +msgid "%(x)s Distance %(y)s invalide." +msgstr "" + +#: AperoDeDenis.py:3855 +msgid "Calibration annulée." +msgstr "" + +#: AperoDeDenis.py:3857 +#, python-format +msgid "%s Pas de distance." +msgstr "" + +#: AperoDeDenis.py:3863 +msgid "La distance n'est pas mesurée par 2 points repérés sur 2 photos." +msgstr "" + +#: AperoDeDenis.py:3866 AperoDeDenis.py:3869 +#, python-format +msgid "La photo avec distance %s est absente." +msgstr "" + +#: AperoDeDenis.py:3871 +msgid "Pas de distance pour la calibration." +msgstr "" + +#: AperoDeDenis.py:3888 +msgid "Fichiers" +msgstr "" + +#: AperoDeDenis.py:3979 +#, python-format +msgid "" +"L'échelle pour le mode All de Tapioca est invalide, une valeur par défaut, " +"%s, est affectée." +msgstr "" + +#: AperoDeDenis.py:3983 +msgid "Echelle pour le mode All de Tapioca trop petite :" +msgstr "" + +#: AperoDeDenis.py:3983 AperoDeDenis.py:4022 +msgid "Minimum = 50" +msgstr "" + +#: AperoDeDenis.py:3995 +#, python-format +msgid "" +"L'échelle 1 pour MulScale de Tapioca est invalide, une valeur par défaut, " +"%s, est affectée." +msgstr "" + +#: AperoDeDenis.py:3999 +msgid "L'échelle 1 de MulScale ne doit pas être -1." +msgstr "" + +#: AperoDeDenis.py:3999 +msgid "Elle est mise à 300." +msgstr "" + +#: AperoDeDenis.py:4006 +msgid "L'échelle 1 pour le mode MulScale de Tapioca est trop petite : " +msgstr "" + +#: AperoDeDenis.py:4006 +msgid "Minimum = 50, maximum conseillé : 300" +msgstr "" + +#: AperoDeDenis.py:4018 +#, python-format +msgid "" +"L'échelle 2 pour le mode MulScale de Tapioca est invalide, une valeur par " +"défaut, %s, est affectée." +msgstr "" + +#: AperoDeDenis.py:4022 +msgid "L'échelle 2 pour le mode MulScale de Tapioca est trop petite :" +msgstr "" + +#: AperoDeDenis.py:4030 +msgid "L'échelle 2 de MulScale pour tapioca" +msgstr "" + +#: AperoDeDenis.py:4030 +msgid "plus petite que l'échelle 1 :" +msgstr "" + +#: AperoDeDenis.py:4042 +#, python-format +msgid "" +"L'échelle pour le mode Line de tapioca est invalide, une valeur par défaut, " +"%s, est affectée." +msgstr "" + +#: AperoDeDenis.py:4046 +msgid "Echelle pour le mode Line de tapioca trop petite : " +msgstr "" + +#: AperoDeDenis.py:4058 +msgid "La valeur de delta pour le mode Line de Tapioca est invalide," +msgstr "" + +#: AperoDeDenis.py:4058 +#, python-format +msgid "une valeur par défaut, %s, est affectée." +msgstr "" + +#: AperoDeDenis.py:4062 +msgid "Delta trop petit :" +msgstr "" + +#: AperoDeDenis.py:4062 +msgid "Minimum = 1" +msgstr "" + +#: AperoDeDenis.py:4069 +#, python-format +msgid "Le zoom final pour MALT n'est pas 1,2,4 ou 8 : %s" +msgstr "" + +#: AperoDeDenis.py:4083 AperoDeDenis.py:4085 +msgid "Malt mode Geomimage :" +msgstr "" + +#: AperoDeDenis.py:4083 +#, python-format +msgid "" +"Le nombre de photos utiles autour de l'image maîtresse est trop petit : %s" +msgstr "" + +#: AperoDeDenis.py:4085 +msgid "" +"Le nombre de photos utiles autour de l'image centrale n'est pas numérique : " +msgstr "" + +#: AperoDeDenis.py:4085 +msgid "Il est mis à 5." +msgstr "" + +#: AperoDeDenis.py:4093 +#, python-format +msgid "La photo %s n'existe plus." +msgstr "" + +#: AperoDeDenis.py:4098 +msgid "Inutile et ralenti le traitement. Modifier." +msgstr "" + +#: AperoDeDenis.py:4102 +msgid "L'échelle pour le mode All de tapioca = " +msgstr "" + +#: AperoDeDenis.py:4102 +msgid ", est plus grande que la dimension maxi de la photo : " +msgstr "" + +#: AperoDeDenis.py:4106 +msgid "L'échelle 2 pour le mode MulScale de tapioca= " +msgstr "" + +#: AperoDeDenis.py:4106 AperoDeDenis.py:4110 +msgid "est plus grande que la dimension maxi de la photo :" +msgstr "" + +#: AperoDeDenis.py:4110 +msgid "L'échelle pour le mode Line de tapioca = " +msgstr "" + +#: AperoDeDenis.py:4166 AperoDeDenis.py:4307 AperoDeDenis.py:4340 +#: AperoDeDenis.py:4690 AperoDeDenis.py:4774 AperoDeDenis.py:4816 +#: AperoDeDenis.py:4857 AperoDeDenis.py:4888 AperoDeDenis.py:4919 +msgid "Choisir d'abord les photos du chantier." +msgstr "" + +#: AperoDeDenis.py:4170 +msgid "Pour calibrer l'appareil photo" +msgstr "" + +#: AperoDeDenis.py:4171 +msgid "Quelques photos, convergentes, d'angles écartés" +msgstr "" + +#: AperoDeDenis.py:4171 +msgid "en jaune la calibration actuelle" +msgstr "" + +#: AperoDeDenis.py:4172 +msgid "Supprimer" +msgstr "" + +#: AperoDeDenis.py:4175 +msgid "Pas de photos de calibration intrinseque." +msgstr "" + +#: AperoDeDenis.py:4179 +msgid "Choix inchangé." +msgstr "" + +#: AperoDeDenis.py:4215 +msgid "Image maitresse avec masque" +msgstr "" + +#: AperoDeDenis.py:4230 +msgid "Choisir une ou plusieurs image(s) maîtresse(s)" +msgstr "" + +#: AperoDeDenis.py:4230 +msgid "en jaune : les maitresses actuelles" +msgstr "" + +#: AperoDeDenis.py:4230 +msgid "Une info bulle informe de la présence d'un masque" +msgstr "" + +#: AperoDeDenis.py:4231 +msgid "Supprimer les images maîtresses" +msgstr "" + +#: AperoDeDenis.py:4242 +msgid "Abandon. Choix inchangé." +msgstr "" + +#: AperoDeDenis.py:4261 +msgid "Image maitresse obligatoire pour GeomImage." +msgstr "" + +#: AperoDeDenis.py:4263 +msgid "Exécuter Tapioca/Tapas pour saisir des masques avec cette option." +msgstr "" + +#: AperoDeDenis.py:4269 AperoDeDenis.py:4272 +msgid "image maîtresse = " +msgstr "" + +#: AperoDeDenis.py:4286 AperoDeDenis.py:4287 +msgid "un seul masque : " +msgstr "" + +#: AperoDeDenis.py:4294 +msgid "Pas de mosaique Tarama : pas de masque." +msgstr "" + +#: AperoDeDenis.py:4297 +msgid "Tracer un nouveau masque sur la mosaique Tarama" +msgstr "" + +#: AperoDeDenis.py:4300 +msgid "Tracer un masque sur la mosaique Tarama" +msgstr "" + +#: AperoDeDenis.py:4303 +msgid "erreur dans miseAJour701_703 : " +msgstr "" + +#: AperoDeDenis.py:4312 AperoDeDenis.py:4379 +msgid "Il faut au moins une image maîtresse pour définir un masque." +msgstr "" + +#: AperoDeDenis.py:4319 AperoDeDenis.py:4355 +msgid "Un masque existe déjà" +msgstr "" + +#: AperoDeDenis.py:4321 AperoDeDenis.py:4357 AperoDeDenis.py:4389 +msgid "Choisir l'image pour le masque" +msgstr "" + +#: AperoDeDenis.py:4322 AperoDeDenis.py:4358 +msgid "" +"Choisir une image maîtresse pour le masque\n" +"en jaune = un masque existe" +msgstr "" + +#: AperoDeDenis.py:4343 +msgid "Exécuter d'abord Tapioca/Tapas." +msgstr "" + +#: AperoDeDenis.py:4347 +msgid "Pas d'image maîtresse. Bizarre." +msgstr "" + +#: AperoDeDenis.py:4390 +msgid "Choisir une image maîtresse pour le masque" +msgstr "" + +#: AperoDeDenis.py:4408 +msgid "pas de masque" +msgstr "" + +#: AperoDeDenis.py:4410 +msgid "Il faut une image maîtresse pour définir un masque." +msgstr "" + +#: AperoDeDenis.py:4467 +msgid "Abandon : pas de masque créé." +msgstr "" + +#: AperoDeDenis.py:4475 +msgid "Masque 3D supprimé." +msgstr "" + +#: AperoDeDenis.py:4495 +msgid "3 points doivent être placés sur au moins 2 photos" +msgstr "" + +#: AperoDeDenis.py:4496 +msgid "Les points GPS sont prioritaires sur la mise à l'échelle.\n" +msgstr "" + +#: AperoDeDenis.py:4504 +msgid "CAMPARI : incertitude cible GPS :" +msgstr "" + +#: AperoDeDenis.py:4506 +msgid "incertitude pixel image :" +msgstr "" + +#: AperoDeDenis.py:4520 +msgid "Incertitude sur X,Y,Z" +msgstr "" + +#: AperoDeDenis.py:4525 +msgid "Ajouter un point" +msgstr "" + +#: AperoDeDenis.py:4526 +msgid "Supprimer des points" +msgstr "" + +#: AperoDeDenis.py:4527 +msgid "Placer les points" +msgstr "" + +#: AperoDeDenis.py:4528 +msgid "Appliquer au " +msgstr "" + +#: AperoDeDenis.py:4528 +msgid "nuage non densifié" +msgstr "" + +#: AperoDeDenis.py:4591 +msgid "Agrandissez la fenêtre avant d'ajouter un point GPS !" +msgstr "" + +#: AperoDeDenis.py:4591 +msgid "(ou si impossible : supprimer un point)" +msgstr "" + +#: AperoDeDenis.py:4595 +msgid "Soyez raisonnable : pas plus de 30 points GPS !" +msgstr "" + +#: AperoDeDenis.py:4608 +msgid "Aucun point à supprimer !" +msgstr "" + +#: AperoDeDenis.py:4616 +msgid "Points à supprimer" +msgstr "" + +#: AperoDeDenis.py:4618 AperoDeDenis.py:7846 +msgid "Multiselection possible." +msgstr "" + +#: AperoDeDenis.py:4620 AperoDeDenis.py:7847 AperoDeDenis.py:7861 +#: AperoDeDenis.py:7870 AperoDeDenis.py:8712 AperoDeDenis.py:9668 +msgid "Annuler" +msgstr "" + +#: AperoDeDenis.py:4702 +msgid "Choisir une photo pour placer les points GPS : " +msgstr "" + +#: AperoDeDenis.py:4730 +msgid "Impossible : des points portent le même nom : modifier ou supprimer !" +msgstr "" + +#: AperoDeDenis.py:4732 +msgid "Attention : un point n'a pas de nom. " +msgstr "" + +#: AperoDeDenis.py:4734 +msgid "controle points : " +msgstr "" + +#: AperoDeDenis.py:4745 +msgid "Lancer d'abord tapioca/tapas" +msgstr "" + +#: AperoDeDenis.py:4745 +msgid "pour obtenir un nuage non densifié." +msgstr "" + +#: AperoDeDenis.py:4752 AperoDeDenis.py:4756 +msgid "Points GPS non conformes :" +msgstr "" + +#: AperoDeDenis.py:4759 +msgid "Patienter :" +msgstr "" + +#: AperoDeDenis.py:4759 +msgid "le nuage est en cours de calibration" +msgstr "" + +#: AperoDeDenis.py:4776 +msgid "Origine Ox" +msgstr "" + +#: AperoDeDenis.py:4776 +msgid "Extrémité Ox" +msgstr "" + +#: AperoDeDenis.py:4783 +msgid "Placer une ligne horizontale sur une seule photo : " +msgstr "" + +#: AperoDeDenis.py:4808 +msgid "il faut placer les 2 points." +msgstr "" + +#: AperoDeDenis.py:4824 +msgid "Placer une ligne verticale sur une seule photo : : " +msgstr "" + +#: AperoDeDenis.py:4835 +msgid "Origine Oy" +msgstr "" + +#: AperoDeDenis.py:4835 +msgid "Extrémité Oy" +msgstr "" + +#: AperoDeDenis.py:4849 +msgid "il faut placer exactement 2 points." +msgstr "" + +#: AperoDeDenis.py:4861 AperoDeDenis.py:4892 +msgid "Plan vertical" +msgstr "" + +#: AperoDeDenis.py:4863 AperoDeDenis.py:4894 +msgid "Plan horizontal" +msgstr "" + +#: AperoDeDenis.py:4866 +msgid "Une photo pour placer le plan vertical : " +msgstr "" + +#: AperoDeDenis.py:4884 +msgid "Délimiter un plan vertical" +msgstr "" + +#: AperoDeDenis.py:4897 +msgid "Une photo pour placer le plan horizontal : " +msgstr "" + +#: AperoDeDenis.py:4915 +msgid "Délimiter un plan horizontal" +msgstr "" + +#: AperoDeDenis.py:4925 +msgid "Choisir deux fois une photo pour placer les 2 points : " +msgstr "" + +#: AperoDeDenis.py:4941 +msgid "" +"Il y a dèjà 2 images avec des points 'distance'. Supprimer les points sur " +"une des 2 images." +msgstr "" + +#: AperoDeDenis.py:4958 +#, python-format +msgid "Le chantier %(chant)s est terminé après %(densif)s" +msgstr "" + +#: AperoDeDenis.py:4959 +msgid "Vous pouvez modifier les options puis relancer MicMac." +msgstr "" + +#: AperoDeDenis.py:4978 +msgid "Options incorrectes : corriger" +msgstr "" + +#: AperoDeDenis.py:4984 +msgid "Avec 2 photos MicMac construira difficilement un nuage de point dense." +msgstr "" + +#: AperoDeDenis.py:4984 +msgid "Utiliser l'échelle -1 dans Tapioca pour obtenir un nuage optimal." +msgstr "" + +#: AperoDeDenis.py:4985 +msgid "Avertissement : 2 photos seulement" +msgstr "" + +#: AperoDeDenis.py:4987 AperoDeDenis.py:5036 AperoDeDenis.py:5056 +#: AperoDeDenis.py:5066 AperoDeDenis.py:5076 +msgid "Continuer" +msgstr "" + +#: AperoDeDenis.py:4997 +msgid "" +"Nombre de photos insuffisant après retrait des photos pour la calibration : " +msgstr "" + +#: AperoDeDenis.py:5004 +msgid "" +"Une seule photo pour la calibration intrinsèque de l'appareil photo. C'est " +"insuffisant.\n" +msgstr "" + +#: AperoDeDenis.py:5005 +msgid "Modifier la liste des photos pour calibration." +msgstr "" + +#: AperoDeDenis.py:5022 +msgid "Une seule photo pour la calibration de l'appareil " +msgstr "" + +#: AperoDeDenis.py:5022 AperoDeDenis.py:5024 +msgid " c'est insuffisant.\n" +msgstr "" + +#: AperoDeDenis.py:5024 +msgid "Aucune photo pour la calibration de l'appareil " +msgstr "" + +#: AperoDeDenis.py:5026 +msgid "" +"\n" +"\n" +" Modifier la liste des photos pour calibration." +msgstr "" + +#: AperoDeDenis.py:5027 +msgid "" +"\n" +"\n" +" Le menu 'expert/liste des appareils' fournit le nom de l'appareil pour " +"chaque photo." +msgstr "" + +#: AperoDeDenis.py:5032 +msgid "Aucune photo pour la calibration intrinsèque des " +msgstr "" + +#: AperoDeDenis.py:5032 +msgid " appareils photos." +msgstr "" + +#: AperoDeDenis.py:5033 +msgid "" +"\n" +"Cela peut rendre difficile les traitements." +msgstr "" + +#: AperoDeDenis.py:5034 +msgid "" +"\n" +"\n" +"Conseil : prendre 2 photos pour la calibration de chaque appareil." +msgstr "" + +#: AperoDeDenis.py:5036 AperoDeDenis.py:5056 AperoDeDenis.py:5076 +msgid "Avertissement" +msgstr "" + +#: AperoDeDenis.py:5048 +msgid "" +"Controle des photos en cours....\n" +"Patienter jusqu'à la fin du controle." +msgstr "" + +#: AperoDeDenis.py:5053 +msgid "Les dimensions des photos ne sont pas toutes identiques." +msgstr "" + +#: AperoDeDenis.py:5054 +msgid "Le traitement par MicMac est incertain." +msgstr "" + +#: AperoDeDenis.py:5062 +msgid "Absence de focales" +msgstr "" + +#: AperoDeDenis.py:5063 +msgid "Certaines photos n'ont pas de focales." +msgstr "" + +#: AperoDeDenis.py:5064 +msgid "Le traitement echouera probablement." +msgstr "" + +#: AperoDeDenis.py:5065 +msgid "Mettre à jour les exifs (menu Outils)" +msgstr "" + +#: AperoDeDenis.py:5074 +msgid "Les focales des photos ne sont pas toutes identiques." +msgstr "" + +#: AperoDeDenis.py:5075 +msgid "" +"Le traitement par MicMac est préférable en utilisant une focale pour la " +"calibration intrinsèque." +msgstr "" + +#: AperoDeDenis.py:5082 +msgid "Pas assez de photos pour le traitement : il en faut au moins 2." +msgstr "" + +#: AperoDeDenis.py:5089 +#, python-format +msgid "Le chantier %s a été interrompu lors de Tapioca/Tapas." +msgstr "" + +#: AperoDeDenis.py:5104 +#, python-format +msgid "Le chantier %s a été interrompu en cours densification." +msgstr "" + +#: AperoDeDenis.py:5105 +msgid "Le chantier est interrompu en cours de densification." +msgstr "" + +#: AperoDeDenis.py:5106 +msgid "" +"ce qui permettra de modifier les options et de le relancer la densification." +msgstr "" + +#: AperoDeDenis.py:5122 +#, python-format +msgid "Continuer le chantier %s après tapas ?" +msgstr "" + +#: AperoDeDenis.py:5123 +msgid "Le chantier est arrêté après tapas. Vous pouvez :" +msgstr "" + +#: AperoDeDenis.py:5124 +msgid " - lancer la densification" +msgstr "" + +#: AperoDeDenis.py:5125 +msgid " - débloquer le chantier pour modifier les paramètres de Tapioca/tapas" +msgstr "" + +#: AperoDeDenis.py:5126 +msgid " - ne rien faire" +msgstr "" + +#: AperoDeDenis.py:5127 +msgid "Lancer la densification " +msgstr "" + +#: AperoDeDenis.py:5128 +msgid "Débloquer le chantier - garder les résultats" +msgstr "" + +#: AperoDeDenis.py:5131 +msgid "abandon de Malt" +msgstr "" + +#: AperoDeDenis.py:5135 +#, python-format +msgid "" +" Reprise du chantier %s arrêté après TAPAS - La trace depuis l'origine sera " +"disponible dans le menu édition." +msgstr "" + +#: AperoDeDenis.py:5204 AperoDeDenis.py:5213 AperoDeDenis.py:5227 +msgid "Pourquoi MicMac s'arrête : " +msgstr "" + +#: AperoDeDenis.py:5213 +msgid "Aucun point en correspondance sur 2 images n'a été trouvé par Tapioca." +msgstr "" + +#: AperoDeDenis.py:5214 +msgid "Parmi les raisons de cet échec il peut y avoir :" +msgstr "" + +#: AperoDeDenis.py:5215 +msgid "" +"soit l'exif des photos ne comporte pas la focale ou plusieurs focales sont " +"présentes" +msgstr "" + +#: AperoDeDenis.py:5216 +msgid "Soit l'appareil photo est inconnu de Micmac" +msgstr "" + +#: AperoDeDenis.py:5217 +msgid "soit la qualité des photos est en cause." +msgstr "" + +#: AperoDeDenis.py:5218 +msgid "" +"soit la trace compléte contient : 'Error: -- Input line too long, increase " +"MAXLINELENGTH' ." +msgstr "" + +#: AperoDeDenis.py:5219 +msgid "" +"alors tenter, sans certitude, de modifier le fichier /binaire-aux/windows/" +"startup/local.mk" +msgstr "" + +#: AperoDeDenis.py:5220 +msgid "Utiliser les items du menu 'outils' pour vérifier ces points." +msgstr "" + +#: AperoDeDenis.py:5227 +msgid "Les photos définissent plusieurs scènes disjointes" +msgstr "" + +#: AperoDeDenis.py:5228 AperoDeDenis.py:8796 +msgid "" +"MicMac ne peut travailler que sur une seule scène : toutes les photos " +"doivent former une seule scéne." +msgstr "" + +#: AperoDeDenis.py:5229 AperoDeDenis.py:8797 +msgid "Les photos se répartissent en :" +msgstr "" + +#: AperoDeDenis.py:5229 AperoDeDenis.py:8797 +msgid " groupes distincts (consulter la trace) : " +msgstr "" + +#: AperoDeDenis.py:5232 AperoDeDenis.py:8799 +msgid "Les groupes de photos séparés : " +msgstr "" + +#: AperoDeDenis.py:5243 +msgid "Pourquoi MicMac s'arrête :" +msgstr "" + +#: AperoDeDenis.py:5243 +msgid "consulter la trace." +msgstr "" + +#: AperoDeDenis.py:5257 +msgid "Calibration incomplète : " +msgstr "" + +#: AperoDeDenis.py:5287 +msgid "Arrêt après Tapas " +msgstr "" + +#: AperoDeDenis.py:5287 +msgid ". Lancer MicMac pour reprendre le traitement." +msgstr "" + +#: AperoDeDenis.py:5288 +msgid "Arrêt après Tapas sur demande utilisateur" +msgstr "" + +#: AperoDeDenis.py:5301 +msgid "Tapas n'a pas généré de nuage de points." +msgstr "" + +#: AperoDeDenis.py:5302 AperoDeDenis.py:5311 +msgid "Le traitement ne peut se poursuivre." +msgstr "" + +#: AperoDeDenis.py:5303 +msgid "Consulter l'aide/quelques conseils." +msgstr "" + +#: AperoDeDenis.py:5304 +msgid "" +"Vérifier la qualité des photos, modifier les paramètres et relancer tapioca-" +"tapas" +msgstr "" + +#: AperoDeDenis.py:5310 +msgid "Pas d'image maîtresse pour Malt option geoimage." +msgstr "" + +#: AperoDeDenis.py:5312 +msgid "Définir une image maîtresse" +msgstr "" + +#: AperoDeDenis.py:5313 +msgid "ou Changer le mode 'GeomImage' qui impose une image maîtresse" +msgstr "" + +#: AperoDeDenis.py:5333 +msgid "Le fichier modele3D.ply précédent est renommé en " +msgstr "" + +#: AperoDeDenis.py:5335 +msgid "erreur renommage ancien modele_3d en " +msgstr "" + +#: AperoDeDenis.py:5336 +msgid "" +"Le fichier Modele3D.ply précédent n'a pu être renommé. Il sera remplacé." +msgstr "" + +#: AperoDeDenis.py:5352 +msgid "Pas de nuage de points après Malt ou C3DC." +msgstr "" + +#: AperoDeDenis.py:5358 +msgid "Fin du traitement MicMac " +msgstr "" + +#: AperoDeDenis.py:5369 +msgid "Tapas non effectué, lancer Micmac depuis le menu. Etat du chantier = " +msgstr "" + +#: AperoDeDenis.py:5375 +msgid "Pourquoi MicMac est arrêté :" +msgstr "" + +#: AperoDeDenis.py:5376 +msgid "Pas d'image maîtresse." +msgstr "" + +#: AperoDeDenis.py:5377 +msgid "Celle-ci est nécessaire pour l'option choisie geomImage de Malt." +msgstr "" + +#: AperoDeDenis.py:5378 +msgid "" +"Pour corriger modifier les options de Malt ou choississez un masque 3D avec " +"C3DC." +msgstr "" + +#: AperoDeDenis.py:5379 +msgid "Corriger." +msgstr "" + +#: AperoDeDenis.py:5394 +msgid "Erreur copie modele3D.ply" +msgstr "" + +#: AperoDeDenis.py:5415 +msgid "erreur malt GeomImage copy de nuage en modele3D : " +msgstr "" + +#: AperoDeDenis.py:5415 AperoDeDenis.py:5418 AperoDeDenis.py:5437 +#: AperoDeDenis.py:5440 +msgid " pour : " +msgstr "" + +#: AperoDeDenis.py:5418 +msgid "erreur malt GeomImage fusion des nuages en modele3D : " +msgstr "" + +#: AperoDeDenis.py:5437 +msgid "erreur malt AperoDeDenis copy de nuage en modele3D : " +msgstr "" + +#: AperoDeDenis.py:5440 +msgid "erreur malt AperoDeDenis fusion des nuages en modele3D : " +msgstr "" + +#: AperoDeDenis.py:5453 +msgid "Aucune photo choisie. Abandon." +msgstr "" + +#: AperoDeDenis.py:5457 +msgid "Une seule photo choisie. Abandon." +msgstr "" + +#: AperoDeDenis.py:5463 +msgid "TRACE DETAILLEE" +msgstr "" + +#: AperoDeDenis.py:5464 +msgid "TRACE SYNTHETIQUE" +msgstr "" + +#: AperoDeDenis.py:5466 +msgid "DEBUT DU TRAITEMENT MICMAC à " +msgstr "" + +#: AperoDeDenis.py:5469 +msgid "Photos choisies :" +msgstr "" + +#: AperoDeDenis.py:5470 +msgid "Ces photos sont recopiées dans le répertoire du chantier :" +msgstr "" + +#: AperoDeDenis.py:5526 AperoDeDenis.py:5532 +#, python-format +msgid "" +"Recherche des points remarquables et des correspondances sur une image de " +"taille %s pixels." +msgstr "" + +#: AperoDeDenis.py:5530 +msgid "" +"Recherche des points remarquables et des correspondances sur l'image entière." +msgstr "" + +#: AperoDeDenis.py:5535 +msgid "Trop de photos pour Windows. Une idée : Utiliser Linux." +msgstr "" + +#: AperoDeDenis.py:5544 +msgid "" +"Une seule photo pour un appareil pour la calibration intrinsèque : " +"insuffisant." +msgstr "" + +#: AperoDeDenis.py:5561 +msgid "" +"Calibration intrinsèque, pour trouver les réglages de l'appareil photo sur " +"quelques photos" +msgstr "" + +#: AperoDeDenis.py:5562 +msgid "Recherche des paramètres optiques des appareils sur les photos :\n" +msgstr "" + +#: AperoDeDenis.py:5571 +msgid "La calibration intrinsèque n'a pas permis de trouver une orientation." +msgstr "" + +#: AperoDeDenis.py:5573 +msgid "Calibration intrinsèque effectuée mais pas d'orientation trouvée." +msgstr "" + +#: AperoDeDenis.py:5577 +msgid "" +"Moins de 2 photos pour Tapas (sans les photos de calibration) : insuffisant." +msgstr "" + +#: AperoDeDenis.py:5581 +msgid "Calibration intrinsèque effectuée." +msgstr "" + +#: AperoDeDenis.py:5594 +msgid "Photos retenues pour calibrer les appareils :" +msgstr "" + +#: AperoDeDenis.py:5609 +msgid "Recherche l'orientation des prises de vues" +msgstr "" + +#: AperoDeDenis.py:5624 +msgid "Calibration, pour trouver les réglages intrinsèques de l'appareil photo" +msgstr "" + +#: AperoDeDenis.py:5624 +msgid "Recherche l'orientation des prises de vue." +msgstr "" + +#: AperoDeDenis.py:5627 +msgid "Tapas n'a pu trouver d'orientation pour les prises de vue." +msgstr "" + +#: AperoDeDenis.py:5653 +msgid "" +"Fixe l'orientation (axe,plan et métrique) suivant les options de " +"'calibration'" +msgstr "" + +#: AperoDeDenis.py:5672 +msgid "Positionne les appareils photos autour du sujet." +msgstr "" + +#: AperoDeDenis.py:5672 +msgid "Création d'un nuage de points grossier." +msgstr "" + +#: AperoDeDenis.py:5678 +msgid "ligne avec meta : " +msgstr "" + +#: AperoDeDenis.py:5679 +msgid "" +"ATTENTION : des metadonnées nécessaires sont absentes des photos. Vérifier " +"l'exif." +msgstr "" + +#: AperoDeDenis.py:5690 +msgid "Ouverture du nuage de points après Apericloud" +msgstr "" + +#: AperoDeDenis.py:5693 +msgid "Pas de fichier AperiCloud.ply généré." +msgstr "" + +#: AperoDeDenis.py:5695 +msgid "" +"Consulter l'aide (quelques conseils),\n" +"Consulter la trace." +msgstr "" + +#: AperoDeDenis.py:5701 +msgid "Tarama : mosaïque des photos d'après les tie points" +msgstr "" + +#: AperoDeDenis.py:5712 +msgid "" +"Prise en compte des points GPS : nécessite au minimum 3 points, chacun sur 2 " +"photos" +msgstr "" + +#: AperoDeDenis.py:5714 +msgid "" +"Le nombre minimum de points placés sur les photos n'est pas atteint. Abandon." +msgstr "" + +#: AperoDeDenis.py:5742 +msgid "Campari non lancé : paramètres incorrects : " +msgstr "" + +#: AperoDeDenis.py:5748 +msgid "Campari non lancé : pas d'orientation 'bascul'" +msgstr "" + +#: AperoDeDenis.py:5751 +msgid "Campari : correction points GPS" +msgstr "" + +#: AperoDeDenis.py:5772 +msgid "Préparation du lancement de Malt" +msgstr "" + +#: AperoDeDenis.py:5780 +msgid "Photos utiles pour malt GeomImage : " +msgstr "" + +#: AperoDeDenis.py:5782 +msgid "Malt sur toutes les photos" +msgstr "" + +#: AperoDeDenis.py:5794 +msgid "Photos utiles pour malt AperoDeDenis : " +msgstr "" + +#: AperoDeDenis.py:5805 +msgid "Mosaique et masque: " +msgstr "" + +#: AperoDeDenis.py:5807 +msgid "Mosaique seule : " +msgstr "" + +#: AperoDeDenis.py:5828 AperoDeDenis.py:5991 AperoDeDenis.py:8499 +msgid "ATTENTION : cette procédure est longue : patience !" +msgstr "" + +#: AperoDeDenis.py:5959 +msgid "lance Tawny" +msgstr "" + +#: AperoDeDenis.py:5965 +msgid " : voir la trace complète." +msgstr "" + +#: AperoDeDenis.py:6095 +#, python-format +msgid "Pas de fichier %s généré." +msgstr "" + +#: AperoDeDenis.py:6095 +msgid "Echec du traitement MICMAC" +msgstr "" + +#: AperoDeDenis.py:6103 +#, python-format +msgid "Nuage de points %s généré." +msgstr "" + +#: AperoDeDenis.py:6133 +msgid "Détermine un indice de qualité des photos en mode 'line'" +msgstr "" + +#: AperoDeDenis.py:6134 AperoDeDenis.py:6165 +msgid "Le résultat sera inscrit dans le fichier trace synthétique" +msgstr "" + +#: AperoDeDenis.py:6134 AperoDeDenis.py:6165 AperoDeDenis.py:6241 +#: AperoDeDenis.py:6354 AperoDeDenis.py:6600 +msgid "Patience..." +msgstr "" + +#: AperoDeDenis.py:6136 +msgid "Debut de la recherche sur la qualité des photos mode 'Line'." +msgstr "" + +#: AperoDeDenis.py:6164 +msgid "Détermine un indice de qualité des photos en mode 'All' ou 'MulScale'" +msgstr "" + +#: AperoDeDenis.py:6167 +msgid "" +"Debut de la recherche sur la qualité des photos, mode 'All' ou 'MulScale'." +msgstr "" + +#: AperoDeDenis.py:6215 AperoDeDenis.py:8853 +msgid "Classement des photos par nombre de points homologues :" +msgstr "" + +#: AperoDeDenis.py:6217 +msgid "photo " +msgstr "" + +#: AperoDeDenis.py:6217 +msgid " score = " +msgstr "" + +#: AperoDeDenis.py:6220 AperoDeDenis.py:8860 +msgid "Aucune photo n'a de point analogue avec une autre." +msgstr "" + +#: AperoDeDenis.py:6224 +msgid "Qualité des photos suite au traitement : " +msgstr "" + +#: AperoDeDenis.py:6225 AperoDeDenis.py:8766 AperoDeDenis.py:8771 +#: AperoDeDenis.py:8779 +msgid "Homol" +msgstr "" + +#: AperoDeDenis.py:6237 +msgid "Fin d'examen de qualité des photos." +msgstr "" + +#: AperoDeDenis.py:6241 +msgid "Copie des photos dans un répertoire de test." +msgstr "" + +#: AperoDeDenis.py:6266 +msgid "Créer un nouveau chantier avec les photos : " +msgstr "" + +#: AperoDeDenis.py:6267 +msgid "Les paramètres de Tapioca/Malt seront optimisés." +msgstr "" + +#: AperoDeDenis.py:6358 +msgid "Caractéristiques de l'appareil photo : " +msgstr "" + +#: AperoDeDenis.py:6361 +msgid "fabricant : " +msgstr "" + +#: AperoDeDenis.py:6365 +msgid "Nom de l'appareil photo inacessible." +msgstr "" + +#: AperoDeDenis.py:6367 +msgid "Nom de l'appareil photo : " +msgstr "" + +#: AperoDeDenis.py:6371 +msgid "Numéro de série de l'appareil photo : " +msgstr "" + +#: AperoDeDenis.py:6377 +msgid "Pas de focale dans l'exif." +msgstr "" + +#: AperoDeDenis.py:6379 +msgid "Focale : " +msgstr "" + +#: AperoDeDenis.py:6382 +msgid "Pas de focale équivalente 35 mm dans l'exif :" +msgstr "" + +#: AperoDeDenis.py:6382 +msgid "Présence de la taille du capteur dans DicoCamera nécesssaire." +msgstr "" + +#: AperoDeDenis.py:6385 +msgid "Focale équivalente 35 mm absente de l'exif" +msgstr "" + +#: AperoDeDenis.py:6387 +msgid "Focale équivalente 35 mm : " +msgstr "" + +#: AperoDeDenis.py:6390 AperoDeDenis.py:6507 +msgid "" +"DicoCamera.xml non trouvé : paramètrer au préalable le chemin de MicMac\\bin." +msgstr "" + +#: AperoDeDenis.py:6394 +msgid "L'appareil est inconnu dans DicoCamera.XML." +msgstr "" + +#: AperoDeDenis.py:6396 +msgid "L'appareil est connu dans DicoCamera.XML." +msgstr "" + +#: AperoDeDenis.py:6397 +msgid "Taille du capteur en mm : " +msgstr "" + +#: AperoDeDenis.py:6410 +msgid "Appareil photo :" +msgstr "" + +#: AperoDeDenis.py:6417 +msgid "" +"Attention : les photos proviennent de plusieurs appareils différents.\n" +" Voir l'item 'toutes les focales...' et le menu expert." +msgstr "" + +#: AperoDeDenis.py:6440 +msgid "Erreur dans exiftool : " +msgstr "" + +#: AperoDeDenis.py:6442 +msgid "erreur tagExif : " +msgstr "" + +#: AperoDeDenis.py:6517 +msgid "\\Pas de nom d'appareil photo dans l'exif" +msgstr "" + +#: AperoDeDenis.py:6521 AperoDeDenis.py:6564 +msgid "" +"\n" +"Le fichier DicoCamera.xml contient déjà la taille du capteur pour " +"l'appareil :" +msgstr "" + +#: AperoDeDenis.py:6522 AperoDeDenis.py:6565 +msgid "taille = " +msgstr "" + +#: AperoDeDenis.py:6522 AperoDeDenis.py:6565 +msgid "Pas de modification possible." +msgstr "" + +#: AperoDeDenis.py:6527 +msgid "Pour l'appareil " +msgstr "" + +#: AperoDeDenis.py:6533 +msgid "Choisir le ou les appareils à mettre à jour" +msgstr "" + +#: AperoDeDenis.py:6534 +msgid "Liste des appareils du chantier : \n" +msgstr "" + +#: AperoDeDenis.py:6540 +msgid "Pour les appareils choisis :\n" +msgstr "" + +#: AperoDeDenis.py:6548 +msgid "Paramètrer au préalable le chemin de MicMac\\bin." +msgstr "" + +#: AperoDeDenis.py:6567 +msgid "NomCourt" +msgstr "" + +#: AperoDeDenis.py:6569 +msgid "tailleEnMM" +msgstr "" + +#: AperoDeDenis.py:6576 +msgid "Fichier DicoCamera.xml invalide : balise de fin manquante : " +msgstr "" + +#: AperoDeDenis.py:6587 +msgid "Erreur lors de l'écriture de DicoCamera.xml" +msgstr "" + +#: AperoDeDenis.py:6587 +msgid "Une sauvegarde a été créée : DicoCamera.xml.sav" +msgstr "" + +#: AperoDeDenis.py:6590 AperoDeDenis.py:6597 +msgid "Dimensions du capteur non mis à jour" +msgstr "" + +#: AperoDeDenis.py:6593 +msgid "Mise à jour de dicocamera.xml : " +msgstr "" + +#: AperoDeDenis.py:6603 +msgid "" +"Les focales, les focales équivalentes en 35mm et le nom des appareils " +"photos :" +msgstr "" + +#: AperoDeDenis.py:6618 +msgid "" +"Ceci est une console système : Saisir une ou plusieurs ligne(s) de commande" +msgstr "" + +#: AperoDeDenis.py:6620 AperoDeDenis.py:6650 +msgid "Attention : Le chantier n'existe pas." +msgstr "" + +#: AperoDeDenis.py:6623 +msgid "" +"Entrer soit une commande MicMac, par exemple : mm3d GCPBascule .*.JPG " +"Arbitrary" +msgstr "" + +#: AperoDeDenis.py:6624 +msgid "" +"soit une commande du système, par exemple sous windows : del /S /Q Tmp-MM-Dir" +msgstr "" + +#: AperoDeDenis.py:6625 +msgid "ou une commande mm3d interactive comme : mm3d vC3DC" +msgstr "" + +#: AperoDeDenis.py:6626 +msgid "Possibilité de copier une commande du fichier mm3d-LogFile.txt." +msgstr "" + +#: AperoDeDenis.py:6627 AperoDeDenis.py:6656 +msgid "Le tout sous votre responsabilité" +msgstr "" + +#: AperoDeDenis.py:6648 +msgid "" +"Ceci est une console python : Saisir une ou plusieurs ligne(s) de script " +"python" +msgstr "" + +#: AperoDeDenis.py:6653 +msgid "Entrer soit une commande python, par exemple : locals()" +msgstr "" + +#: AperoDeDenis.py:6654 +msgid "" +"la commande sera éxécutée puis évaluée et les résultats affichés dans une " +"fenetre" +msgstr "" + +#: AperoDeDenis.py:6655 +msgid "et aussi dans la trace synthétique." +msgstr "" + +#: AperoDeDenis.py:6663 +msgid "résultat de la commande python : " +msgstr "" + +#: AperoDeDenis.py:6670 +msgid "commande : " +msgstr "" + +#: AperoDeDenis.py:6677 +msgid "" +"\n" +"L'exécution de la commande python retourne la valeur : " +msgstr "" + +#: AperoDeDenis.py:6680 +msgid "" +"\n" +"L'éxécution de la commande python ne retourne pas de valeur" +msgstr "" + +#: AperoDeDenis.py:6683 +msgid "" +"\n" +"L'évaluation de la commande python retourne la valeur : " +msgstr "" + +#: AperoDeDenis.py:6686 +msgid "" +"\n" +"L'évaluation de la commande python ne retourne pas de valeur" +msgstr "" + +#: AperoDeDenis.py:6696 +msgid "Choisir le chantier pour ajouter les points gps." +msgstr "" + +#: AperoDeDenis.py:6718 +msgid "Erreur restauration points GPS : " +msgstr "" + +#: AperoDeDenis.py:6760 AperoDeDenis.py:6799 +msgid " points GPS ajoutés." +msgstr "" + +#: AperoDeDenis.py:6771 +msgid "" +"Liste de points GPS : Nom, X,Y,Z, dx,dy,dz (fichier texte séparteur " +"espace) : " +msgstr "" + +#: AperoDeDenis.py:6772 +msgid "Texte" +msgstr "" + +#: AperoDeDenis.py:6801 +msgid "" +" points GPS ajoutés : c'est beaucoup, sans doute trop (pb affichage options " +"GPS)" +msgstr "" + +#: AperoDeDenis.py:6806 +msgid "Plusieurs appareils photos" +msgstr "" + +#: AperoDeDenis.py:6807 +msgid "Lorque les photos choisies proviennent de plusieurs appareils photos" +msgstr "" + +#: AperoDeDenis.py:6808 +msgid "les TAGS 'model' doivent être différenciés dans l'exif des photos." +msgstr "" + +#: AperoDeDenis.py:6809 +msgid "La calibration s'effectue alors pour chaque appareil." +msgstr "" + +#: AperoDeDenis.py:6810 +msgid "AperoDeDenis propose de modifier ces tags soit : " +msgstr "" + +#: AperoDeDenis.py:6811 +msgid "" +" - en y ajoutant le numéro de série de l'appareil (parfois présent dans " +"l'exif" +msgstr "" + +#: AperoDeDenis.py:6812 +msgid " - en y ajoutant le préfixe du nom du fichier de la photo" +msgstr "" + +#: AperoDeDenis.py:6813 +msgid " le préfixe = les 3 premiers caractères du nom de fichier." +msgstr "" + +#: AperoDeDenis.py:6815 +msgid "Modifier les tags 'model'" +msgstr "" + +#: AperoDeDenis.py:6819 +msgid "" +"La prise en compte de plusieurs appareils photos doit se faire après la " +"selection des photos" +msgstr "" + +#: AperoDeDenis.py:6820 +msgid "" +"et AVANT tout traitement.\n" +"Choisir des photos ou créer un nouveau chantier." +msgstr "" + +#: AperoDeDenis.py:6822 +msgid "" +"Recherche des modifications possibles du modèle d'appareil photo. Patience !." +msgstr "" + +#: AperoDeDenis.py:6826 +msgid "Les photos proviennent déjà de plusieurs appareils différents." +msgstr "" + +#: AperoDeDenis.py:6829 +msgid "Pas de modification du chantier" +msgstr "" + +#: AperoDeDenis.py:6827 +msgid "Liste des appareils :\n" +msgstr "" + +#: AperoDeDenis.py:6836 +msgid "" +"Modification du modèle de l'appareil photo en cours : ajout du numéro de " +"série." +msgstr "" + +#: AperoDeDenis.py:6837 AperoDeDenis.py:6845 +msgid "Attention : procédure longue si beaucoup de photos." +msgstr "" + +#: AperoDeDenis.py:6841 +msgid "" +"Fin :\n" +"Modéle de l'appareil photo modifié par ajout du numéro de série." +msgstr "" + +#: AperoDeDenis.py:6844 +msgid "" +"Modification du modèle de l'appareil photo en cours : ajout du préfixe du " +"nom de fichier." +msgstr "" + +#: AperoDeDenis.py:6849 +msgid "" +"Fin : \n" +"Modéle de l'appareil photo modifié : ajout du préfixe du nom de fichier sur " +"3 caractères." +msgstr "" + +#: AperoDeDenis.py:6851 +msgid "Modéle de l'appareil photo non modifiable :" +msgstr "" + +#: AperoDeDenis.py:6851 +msgid "pas de numéro de série multiple pour les appareils photos," +msgstr "" + +#: AperoDeDenis.py:6852 +msgid "pas de préfixe multiple pour les noms de fichiers." +msgstr "" + +#: AperoDeDenis.py:6857 +msgid "Recherche des noms d'appareil photos. Patience !." +msgstr "" + +#: AperoDeDenis.py:6859 +msgid "Les photos proviennent de " +msgstr "" + +#: AperoDeDenis.py:6859 +msgid " appareils photos différents : " +msgstr "" + +#: AperoDeDenis.py:6860 +msgid "Les photos proviennent d'un seul appareil : " +msgstr "" + +#: AperoDeDenis.py:6861 +msgid "L'exif des photos ne contient pas le nom de l'appareil photo." +msgstr "" + +#: AperoDeDenis.py:6881 +msgid "Pas de trace du log !" +msgstr "" + +#: AperoDeDenis.py:6890 +msgid "Interface graphique du CEREMA pour lancer les modules de MICMAC." +msgstr "" + +#: AperoDeDenis.py:6891 +msgid "Utilisable sous Linux, Windows, Mac OS." +msgstr "" + +#: AperoDeDenis.py:6892 +msgid "Logiciel libre et open source diffusé sous licence CeCILL-B." +msgstr "" + +#: AperoDeDenis.py:6894 +msgid "" +"La barre de titre présente le nom du chantier et la version de l'outil. Une " +"* indique que le chantier est à sauvegarder." +msgstr "" + +#: AperoDeDenis.py:6895 +msgid "Menu Fichier :" +msgstr "" + +#: AperoDeDenis.py:6896 +msgid "" +" - Nouveau chantier : constitution d'un 'chantier' comportant les " +"photos, les options d'exécution de Micmac et" +msgstr "" + +#: AperoDeDenis.py:6897 +msgid " les résultats des traitements." +msgstr "" + +#: AperoDeDenis.py:6898 +msgid " Les paramètres du chantier sont conservés dans le fichier " +msgstr "" + +#: AperoDeDenis.py:6899 +msgid "" +" Enregistrer le chantier crée une arborescence dont la racine est le " +"répertoire des photos et le nom du chantier." +msgstr "" + +#: AperoDeDenis.py:6900 +msgid "" +" - Ouvrir un chantier : revenir sur un ancien chantier pour le " +"poursuivre ou consulter les résultats." +msgstr "" + +#: AperoDeDenis.py:6901 +msgid "" +" - Enregistrer le chantier : enregistre le chantier en cours sans " +"l'exécuter." +msgstr "" + +#: AperoDeDenis.py:6902 +msgid "" +" Une * dans la barre de titre indique que le chantier a été modifié." +msgstr "" + +#: AperoDeDenis.py:6903 +msgid "" +" Le chantier en cours, même non enregistré, est conservé lors de la " +"fermeture de l'application." +msgstr "" + +#: AperoDeDenis.py:6904 +msgid " - Renommer le chantier : personnalise le nom du chantier." +msgstr "" + +#: AperoDeDenis.py:6905 +msgid "" +" Le chantier est déplacé dans l'arborescence en indiquant un chemin " +"absolu ou relatif." +msgstr "" + +#: AperoDeDenis.py:6906 +msgid "" +" Par exemple : 'D:\\MonPremierChantier' nomme 'MonPremierChantier' " +"sous la racine du disque D." +msgstr "" + +#: AperoDeDenis.py:6907 +msgid "" +" Attention : le changement de disque n'est pas possible dans cette " +"version de l'outil." +msgstr "" + +#: AperoDeDenis.py:6908 +msgid "" +" - Exporter le chantier en cours : création d'une archive du chantier, " +"qui permet :" +msgstr "" + +#: AperoDeDenis.py:6909 +msgid " - de conserver le chantier en l'état, pour y revenir." +msgstr "" + +#: AperoDeDenis.py:6910 +msgid "" +" - de l'importer sous un autre répertoire, un autre disque, un " +"autre ordinateur, un autre système d'exploitation" +msgstr "" + +#: AperoDeDenis.py:6911 +msgid " - Importer un chantier :" +msgstr "" + +#: AperoDeDenis.py:6912 +msgid "" +" - copie le chantier sauvegardé dans un nouvel environnement " +"(ordinateur, système d'exploitation)" +msgstr "" + +#: AperoDeDenis.py:6913 +msgid "" +" - un exemple d'intérêt : copier un chantier après tapas, lancer " +"malt avec des options variées sans perdre l'original." +msgstr "" + +#: AperoDeDenis.py:6914 +msgid " - Ajouter le répertoire d'un chantier :" +msgstr "" + +#: AperoDeDenis.py:6915 +msgid "" +" - ajoute le chantier présent sous le répertoire indiqué. " +"Alternative moins robuste à l'export/import)" +msgstr "" + +#: AperoDeDenis.py:6916 +msgid "" +" - Du ménage ! : nettoyer ou supprimer les chantiers : chaque chantier " +"crée une arborescence de travail assez lourde." +msgstr "" + +#: AperoDeDenis.py:6917 +msgid "" +" Le nettoyage ne garde que les photos, les modèles 3D résultats, les " +"traces, les paramètres : gain de place assuré !." +msgstr "" + +#: AperoDeDenis.py:6918 +msgid " La suppression supprime tout le chantier." +msgstr "" + +#: AperoDeDenis.py:6919 +msgid "" +" Un message demande confirmation avant la suppression définitive, " +"sans récupération possible :" +msgstr "" + +#: AperoDeDenis.py:6920 +msgid "" +" Toute l'arborescence est supprimée, même les archives exportées." +msgstr "" + +#: AperoDeDenis.py:6921 +msgid "" +" - Quitter : quitte l'application, le chantier en cours est conservé " +"et sera ouvert lors du prochain lancement." +msgstr "" + +#: AperoDeDenis.py:6922 +msgid "Menu Edition :" +msgstr "" + +#: AperoDeDenis.py:6923 +msgid "" +" - Afficher l'état du chantier : affiche les paramètres du chantier et " +"son état d'exécution." +msgstr "" + +#: AperoDeDenis.py:6924 +msgid "" +" Par défaut l'état du chantier est affiché lors du lancement de " +"l'application." +msgstr "" + +#: AperoDeDenis.py:6925 +msgid "" +" Cet item est utile après un message ou l'affichage d'une trace." +msgstr "" + +#: AperoDeDenis.py:6926 +msgid "" +" - Plusieurs items permettent de consulter les photos, les traces et " +"les vues 3D du chantier en cours." +msgstr "" + +#: AperoDeDenis.py:6927 +msgid "" +" Visualiser toutes les photos sélectionnées : visualise les photos" +msgstr "" + +#: AperoDeDenis.py:6928 +msgid " Visualiser les photos pour la calibration intrinsèque" +msgstr "" + +#: AperoDeDenis.py:6929 +msgid "" +" Visualiser les maitresses et les masques : visualise les " +"masques 2D pour la densification Malt/géoimage." +msgstr "" + +#: AperoDeDenis.py:6930 +msgid "" +" Visualiser le masque sur mosaïque TARAMA : visualise le masque " +"défini sur la mosaïque TARAMA." +msgstr "" + +#: AperoDeDenis.py:6931 +msgid "" +" Visualiser le masque 3D : visualise le masque " +"3D pour la densification C3DC" +msgstr "" + +#: AperoDeDenis.py:6932 +msgid "" +" Visualiser les points GPS : visu des seules " +"photos avec points GPS." +msgstr "" + +#: AperoDeDenis.py:6934 +msgid "" +" Visualiser la ligne horizontale/verticale : visualise le repère " +"Ox ou Oy pour la mise à l'échelle." +msgstr "" + +#: AperoDeDenis.py:6935 +msgid "" +" Visualiser la zone plane : visualise la zone " +"plane" +msgstr "" + +#: AperoDeDenis.py:6936 +msgid "" +" Visualiser la distance : visualise de la " +"distance et les points associés." +msgstr "" + +#: AperoDeDenis.py:6938 +msgid "" +" Afficher la trace complete du chantier : visualise la trace " +"complète, standard micmac" +msgstr "" + +#: AperoDeDenis.py:6939 +msgid "" +" Afficher la trace synthétique du chantier : visualise la trace " +"filtrée par aperoDeDenis, moins bavarde" +msgstr "" + +#: AperoDeDenis.py:6941 +msgid "" +" Afficher la mosaïque Tarama : si la mosaïque " +"tarama est demandée dans l'onglet 'orientation'" +msgstr "" + +#: AperoDeDenis.py:6942 +msgid "" +" Afficher l'ortho mosaïque Tawny : l'ortho mosaïque " +"tawny est demandée dans l'onglet Densifisation/Malt/Ortho" +msgstr "" + +#: AperoDeDenis.py:6944 +msgid "" +" Afficher l'image 3D non densifiée : lance l'outil pour " +"ouvrir les .PLY sur l'image 3D produite par Tapas" +msgstr "" + +#: AperoDeDenis.py:6945 +msgid "" +" Afficher l'image 3D densifiée : lance l'outil pour " +"ouvrir les .PLY sur l'image 3D produite par Malt ou C3DC" +msgstr "" + +#: AperoDeDenis.py:6947 +msgid "" +" Lister Visualiser les images 3D : liste la pyramide " +"des images 3D, créées à chaque étape de Malt" +msgstr "" + +#: AperoDeDenis.py:6948 +msgid "" +" Fusionner des images 3D : permet de fusionner " +"plusieurs PLY en un seul" +msgstr "" + +#: AperoDeDenis.py:6949 +msgid "Menu MicMac :" +msgstr "" + +#: AperoDeDenis.py:6950 +msgid "" +" - Choisir les photos : permet choisir les photos JPG, GIF, TIF ou BMP " +"pour le traitement." +msgstr "" + +#: AperoDeDenis.py:6951 +msgid "" +" Les photos GIF et BMP seront converties en JPG (nécessite la " +"présence de l'outil convert)." +msgstr "" + +#: AperoDeDenis.py:6952 +msgid "" +" Un EXIF avec la focale utilisée pour la prise de vue est " +"nécessaire : si besoin l'ajouter (menu Outil/ajout exif)." +msgstr "" + +#: AperoDeDenis.py:6953 +msgid "" +" Remarques : 1) Si l'exif ne comporte pas la focale équivalente en " +"35 mm alors " +msgstr "" + +#: AperoDeDenis.py:6954 +msgid "" +" le fichier DicoCamera.xml doit comporter la taille du " +"capteur de l'appareil (voir menu Outils)" +msgstr "" + +#: AperoDeDenis.py:6955 +msgid "" +" 2) Si les photos proviennent de plusieurs appareils " +"alors les tags 'model' des exif doivent" +msgstr "" + +#: AperoDeDenis.py:6956 +msgid " être différenciés (voir menu Expert)" +msgstr "" + +#: AperoDeDenis.py:6957 +msgid "" +" - Options : choisir les options des modules Tapioca, Tapas, GPS " +"(nuage non densifié) puis de densification : " +msgstr "" + +#: AperoDeDenis.py:6958 +msgid "" +" Consulter le wiki MicMac pour obtenir de l'info sur les " +"options, par exemple : https://micmac.ensg.eu/index.php/Tapas" +msgstr "" + +#: AperoDeDenis.py:6959 +msgid "" +" Les options suivantes concernent le calcul du nuage de points NON " +"densifié :" +msgstr "" + +#: AperoDeDenis.py:6960 +msgid "" +" - Points homologues : Tapioca : options et sous options " +"associées (échelles, fichier xml)" +msgstr "" + +#: AperoDeDenis.py:6961 +msgid "" +" Voir la documentation MicMac sur Tapioca." +msgstr "" + +#: AperoDeDenis.py:6962 +msgid "" +" - Orientation : Tapas : choix d'un type d'appareil " +"photo , possibilité d'arrêter le traitement après tapas." +msgstr "" + +#: AperoDeDenis.py:6963 +msgid "" +" Le type d'appareil photo détermine le nombre " +"de paramètres décrivant l'optique et le capteur." +msgstr "" + +#: AperoDeDenis.py:6964 +msgid "" +" Si plusieurs appareils photos alors il faut " +"les distinguer, voir menu expert." +msgstr "" + +#: AperoDeDenis.py:6965 +msgid "" +" La calibration intrinsèque permet de " +"déterminer les caractéristiques de l'appareil sur des photos spécifiques :" +msgstr "" + +#: AperoDeDenis.py:6966 +msgid "" +" Par exemple photos d'un angle de batiment " +"avec une grande longueur de mur." +msgstr "" + +#: AperoDeDenis.py:6967 +msgid "" +" Ces photos ne servent pas nécessairement " +"pour la suite du chantier." +msgstr "" + +#: AperoDeDenis.py:6968 +msgid "" +" L'arrêt après Tapas est nécessaire pour " +"décrire le masque 2D ou 3D." +msgstr "" + +#: AperoDeDenis.py:6969 +msgid "" +" Produit une image 3D non densifiée avec " +"position des appareils photos." +msgstr "" + +#: AperoDeDenis.py:6970 +msgid "" +" - Mise à l'échelle : définir un axe, une zone plane, une " +"distance pour définir le repère du chantier." +msgstr "" + +#: AperoDeDenis.py:6971 +msgid "" +" cette mise à l'échelle s'effectue sur le " +"nuage de points homologues" +msgstr "" + +#: AperoDeDenis.py:6972 +msgid "" +" - GPS : définir les points de calage (coordonnées GPS ou " +"repère local) qui permettent de (géo)localiser la scène." +msgstr "" + +#: AperoDeDenis.py:6973 +msgid "" +" Une première ligne permet de définir les options " +"du module CAMPARI qui améliore la précision des calculs." +msgstr "" + +#: AperoDeDenis.py:6974 +msgid "" +" Il faut indiquer la précision des cibles GPS (en " +"unité du GPS) et la précision des points images (en pixels)." +msgstr "" + +#: AperoDeDenis.py:6975 +msgid "" +" CAMPARI ne sera lancé que si les points GPS sont " +"corrects ainsi que les 2 paramètres ci-dessus." +msgstr "" + +#: AperoDeDenis.py:6976 +msgid "" +" Pour être utilisé chaque point GPS, au minimum " +"3, doit être placé sur au moins 2 photos." +msgstr "" + +#: AperoDeDenis.py:6977 +msgid "" +" Le bouton 'appliquer' permet de calibrer le " +"modèle non densifié immédiatement sur le nuage de points homologues." +msgstr "" + +#: AperoDeDenis.py:6978 +msgid "" +" - Densification : choix du module de densification : " +"C3DC (récent) ou Malt (ancien)." +msgstr "" + +#: AperoDeDenis.py:6979 +msgid " - Malt : Si le mode est GeomImage : " +msgstr "" + +#: AperoDeDenis.py:6980 +msgid "" +" désigner une ou plusieurs images maîtresses" +msgstr "" + +#: AperoDeDenis.py:6981 +msgid "" +" dessiner si besoin le ou les masques " +"associés." +msgstr "" + +#: AperoDeDenis.py:6982 +msgid "" +" Seuls les points visibles sur les images " +"maitres seront sur l'image 3D finale." +msgstr "" + +#: AperoDeDenis.py:6983 +msgid "" +" Le masque limite la zone utile de l'image " +"3D finale." +msgstr "" + +#: AperoDeDenis.py:6984 +msgid "" +" La molette permet de zoomer et le clic " +"droit maintenu de déplacer l'image." +msgstr "" + +#: AperoDeDenis.py:6985 +msgid "" +" Supprimer une image maîtresse de la liste " +"réinitialise le masque." +msgstr "" + +#: AperoDeDenis.py:6986 +msgid "" +" Nombre de photos utiles autour de l'image " +"maîtresse :" +msgstr "" + +#: AperoDeDenis.py:6987 +msgid "" +" Permet de limiter les recherches aux " +"images entourant chaque image maîtresse." +msgstr "" + +#: AperoDeDenis.py:6988 +msgid "" +" Choix du niveau de densification final : " +"8,4,2 ou 1." +msgstr "" + +#: AperoDeDenis.py:6989 +msgid " Le niveau 1 est le plus dense. " +msgstr "" + +#: AperoDeDenis.py:6990 +msgid "" +" La géométrie est revue à chaque niveau et " +"de plus en plus précise : " +msgstr "" + +#: AperoDeDenis.py:6991 +msgid "" +" la densification s'accroît, et la " +"géométrie s'affine aussi." +msgstr "" + +#: AperoDeDenis.py:6992 +msgid " - C3DC : choix par défaut." +msgstr "" + +#: AperoDeDenis.py:6993 +msgid "" +" Possibilité de dessiner un masque 3D sur le " +"nuage de points non dense." +msgstr "" + +#: AperoDeDenis.py:6994 +msgid "" +" Les touches fonctions à utiliser sont " +"décrites dans l'onglet." +msgstr "" + +#: AperoDeDenis.py:6995 +msgid "" +" Le masque limite la zone en 3 dimensions de " +"l'image finale." +msgstr "" + +#: AperoDeDenis.py:6996 +msgid " L'outil de saisie est issu de micmac." +msgstr "" + +#: AperoDeDenis.py:6997 +msgid "" +" - Lancer MicMac : enregistre le chantier et lance le traitement avec " +"les options par défaut ou choisies par l'item 'options'." +msgstr "" + +#: AperoDeDenis.py:6998 +msgid "" +" Relance micmac si l'arrêt a été demandé après tapas." +msgstr "" + +#: AperoDeDenis.py:6999 +msgid "" +" Lancer micmac bloque les photos et les options du " +"chantier." +msgstr "" + +#: AperoDeDenis.py:7000 +msgid "" +" Pour débloquer le chantier il faut lancer micmac à " +"nouveau et choisir le débloquage." +msgstr "" + +#: AperoDeDenis.py:7001 +msgid "" +" Le débloquage permet de relancer Malt sans relancer " +"tapioca/tapas tout en conservant le modèle densifié, renommé." +msgstr "" + +#: AperoDeDenis.py:7002 +msgid "menu Vidéo :" +msgstr "" + +#: AperoDeDenis.py:7003 +msgid "" +" - Options : indiquer le nom de la camera (GoPro, smartphone...), sa " +"focale, sa focale equivalente 35mm" +msgstr "" + +#: AperoDeDenis.py:7004 +msgid " et le nombre d'images à conserver par seconde de film" +msgstr "" + +#: AperoDeDenis.py:7005 +msgid "" +" Le nom permet de faire le lien avec DicoCamera.xml qui contient la " +"taille du capteur." +msgstr "" + +#: AperoDeDenis.py:7006 +msgid " Les focales seront recopiées dans l'exif des images." +msgstr "" + +#: AperoDeDenis.py:7007 +msgid "" +" Le nombre d'images par seconde sera utilisé pour la sélection des " +"meilleures images." +msgstr "" + +#: AperoDeDenis.py:7008 +msgid " Remarque :" +msgstr "" + +#: AperoDeDenis.py:7009 +msgid "" +" Il faut indiquer dans DicoCamera la taille du capteur " +"effectivement utilisée par la fonction camera," +msgstr "" + +#: AperoDeDenis.py:7010 +msgid "" +" taille qui peut être inférieure à la taille du capteur utilisée " +"pour les photos." +msgstr "" + +#: AperoDeDenis.py:7011 +msgid " Voir par exemple pour une camera Gopro :" +msgstr "" + +#: AperoDeDenis.py:7013 +msgid "" +" - Nouveau chantier : choisir une video : choisir un fichier video " +"issu d'une camera ou d'une GoPro." +msgstr "" + +#: AperoDeDenis.py:7014 +msgid "" +" La vidéo sera décompactée en images, l'exif sera créé avec les " +"informations en options." +msgstr "" + +#: AperoDeDenis.py:7015 +msgid "" +" Cette étape nécessite la présence de l'outil ffmpeg sous le " +"répertoire bin de MicMac (dépend de la version de MicMac)." +msgstr "" + +#: AperoDeDenis.py:7016 +msgid "" +" Un nouveau chantier est créé avec les options suivante : Line pour " +"Tapioca et FishEyeBasic pour Tapas." +msgstr "" + +#: AperoDeDenis.py:7017 +msgid "" +" - Sélection des images : il est raisonnable de ne garder que quelques " +"images par seconde de film." +msgstr "" + +#: AperoDeDenis.py:7018 +msgid "" +" Le nombre d'images conservées par seconde est indiqué dans les " +"options." +msgstr "" + +#: AperoDeDenis.py:7019 +msgid "" +" Chaque seconde de film les 'meilleures' images seront retenues, les " +"autres effacées." +msgstr "" + +#: AperoDeDenis.py:7020 +msgid "" +" Attention : cette étape n'est pas effective pour toutes les " +"versions de MicMac. La version mercurial 5508 fonctionne." +msgstr "" + +#: AperoDeDenis.py:7021 +msgid "" +" Une fois les images sélectionnées le chantier est créé : utiliser " +"le menu MicMac comme pour un chantier normal." +msgstr "" + +#: AperoDeDenis.py:7022 +msgid "menu Outils :" +msgstr "" + +#: AperoDeDenis.py:7023 +msgid "" +" - Info extraites de l'exif : fabricant, modèle, focale et dimensions " +"en pixels de la première photo." +msgstr "" + +#: AperoDeDenis.py:7024 +msgid "" +" Il y a 2 types de focales : focale effective et focale équivalente " +"35 mm." +msgstr "" + +#: AperoDeDenis.py:7025 +msgid "" +" Indique si l'appareil photo est connu dans '/XML MicMac/DicoCamera." +"xml'." +msgstr "" + +#: AperoDeDenis.py:7026 +msgid "" +" - Afficher toutes les focales des photos : focales et focales " +"equivalentes en 35mm." +msgstr "" + +#: AperoDeDenis.py:7027 +msgid "" +" Si les focales ne sont pas identiques pour toutes les photos : " +"utiliser la calibration intrinséque de tapas." +msgstr "" + +#: AperoDeDenis.py:7028 +msgid " Affiche aussi le nom de l'appareil photo pour chaque photo." +msgstr "" + +#: AperoDeDenis.py:7029 +msgid "" +" - Mettre à jour DicoCamera.xml : ajouter la taille du capteur dans '/" +"XML MicMac/DicoCamera.xml'." +msgstr "" + +#: AperoDeDenis.py:7030 +msgid "" +" La taille du capteur dans DicoCamera.xml est requise si la focale " +"équivalente 35mm est absente de l'exif." +msgstr "" + +#: AperoDeDenis.py:7031 +msgid "" +" La taille du capteur facilite les calculs et améliore les résultats." +msgstr "" + +#: AperoDeDenis.py:7032 +msgid "" +" La taille du capteur se trouve sur le site du fabricant ou sur " +"http://www.dpreview.com." +msgstr "" + +#: AperoDeDenis.py:7033 +msgid "" +" - Qualité des photos du dernier traitement : calcule le nombre moyen " +"de points homologues par photo." +msgstr "" + +#: AperoDeDenis.py:7034 +msgid "" +" Si des photos présentent des moyennes très faibles elles peuvent " +"faire échouer le traitement." +msgstr "" + +#: AperoDeDenis.py:7035 +msgid "" +" - Qualité des photos 'Line' : calcule le nombre moyen de points " +"homologues par photo en mode 'Line', taille 1000." +msgstr "" + +#: AperoDeDenis.py:7036 +msgid "" +" - Qualité des photos 'MulScale ou All' : calcule le nombre moyen de " +"points homologues par photo, taille 1000.'." +msgstr "" + +#: AperoDeDenis.py:7037 +msgid "" +" Ce nombre informe sur la qualité relative des photos au sein du " +"chantier." +msgstr "" + +#: AperoDeDenis.py:7038 +msgid "" +" La présence de photos avec peu de points homologues peut faire " +"échouer le traitement." +msgstr "" + +#: AperoDeDenis.py:7039 +msgid "" +" Il est parfois préférable de traiter peu de photos mais de bonne " +"qualité." +msgstr "" + +#: AperoDeDenis.py:7040 +msgid "" +" - Modifier l'exif des photos : permet la création et la modification " +"des exifs des photos du chantier." +msgstr "" + +#: AperoDeDenis.py:7041 +msgid "" +" - Modifier les options par défauts : les valeurs par défaut de " +"certains paramètres sont modifiables." +msgstr "" + +#: AperoDeDenis.py:7042 +msgid "" +" Les paramètres concernés sont ceux des onglets du menu MicMac/" +"options : 'Points homologues',... : ." +msgstr "" + +#: AperoDeDenis.py:7043 +msgid "menu Expert :" +msgstr "" + +#: AperoDeDenis.py:7044 +msgid "" +" - Ouvrir une console permettant de passer des commandes système et " +"MicMac (mm3d)." +msgstr "" + +#: AperoDeDenis.py:7045 +msgid "" +" - Ouvrir une console permettant de passer des commandes Python (ex. : " +"afficher une variable." +msgstr "" + +#: AperoDeDenis.py:7046 +msgid "" +" - Insérer de points GPS à partir d'un fichier texte, séparateur " +"espace, format : X Y Z dx dy dz " +msgstr "" + +#: AperoDeDenis.py:7047 +msgid " Le caractère # en début de ligne signale un commentaire." +msgstr "" + +#: AperoDeDenis.py:7048 +msgid " - Recopier des points GPS à partir d'un autre chantier." +msgstr "" + +#: AperoDeDenis.py:7049 +msgid " - Définir plusieurs appareils photos." +msgstr "" + +#: AperoDeDenis.py:7050 +msgid "" +" Si le lot de photos provient de plusieurs appareils de même type il " +"faut informer MicMac de cette situation." +msgstr "" + +#: AperoDeDenis.py:7051 +msgid " Plusieurs solutions existent dans MicMac." +msgstr "" + +#: AperoDeDenis.py:7052 +msgid "" +" AperoDeDenis propose de modifier le tag 'model' de l'exif des " +"photos :" +msgstr "" + +#: AperoDeDenis.py:7053 +msgid "" +" - en utilisant le numéro de série de l'appareil présent dans " +"l'exif" +msgstr "" + +#: AperoDeDenis.py:7054 +msgid "" +" - à défaut en utilisant 3 caractères du préfixe des noms de " +"fichiers, que l'utilisateur a préparé de telle sorte" +msgstr "" + +#: AperoDeDenis.py:7055 +msgid "" +" que chaque préfixe corresponde à un appareil. Certains appareil " +"proposent de modifier qyqtématiquement ce préfixe." +msgstr "" + +#: AperoDeDenis.py:7056 +msgid " - Lister les appareils photos présents dans le lot de photos." +msgstr "" + +#: AperoDeDenis.py:7057 +msgid " - Consulter le fichier de logging MicMac : mm3d-logFile.txt." +msgstr "" + +#: AperoDeDenis.py:7058 +msgid "menu Paramétrage :" +msgstr "" + +#: AperoDeDenis.py:7059 +msgid "" +" - Afficher les paramètres : visualise les chemins de micmac\\bin, " +"d'exiftool, du fichier pour visualiser les .ply (Meshlab ou Cloud Compare)," +msgstr "" + +#: AperoDeDenis.py:7060 +msgid "" +" ainsi que le répertoire où se trouve les fichiers paramètres de " +"l'interface." +msgstr "" + +#: AperoDeDenis.py:7061 +msgid "" +" Ces paramètres sont sauvegardés de façon permanente dans le " +"fichier :" +msgstr "" + +#: AperoDeDenis.py:7063 +msgid "" +" - Désigner le répertoire MicMac\\bin : répertoire où se trouvent les " +"modules de MicMac " +msgstr "" + +#: AperoDeDenis.py:7064 +msgid "" +" Si plusieurs versions sont installées cet item permet de changer " +"facilement la version de MicMac utilisée." +msgstr "" + +#: AperoDeDenis.py:7065 +msgid "" +" - Désigner l'application exiftool, utile pour modifier les exif (elle " +"se trouve sous micMac\\binaire-aux)." +msgstr "" + +#: AperoDeDenis.py:7066 +msgid "" +" - Désigner l'application convert d'ImageMagick, utile pour convertir " +"les gif, tif et bmp en jpg (elle se trouve sous micMac\\binaire-aux)." +msgstr "" + +#: AperoDeDenis.py:7067 +msgid "" +" - Désigner l'application ouvrant les fichiers .PLY. Ce peut être " +"Meshlab, CloudCompare ou autre." +msgstr "" + +#: AperoDeDenis.py:7068 +msgid " Sous Windows Meshlab se trouve sous un répertoire nommé VCG." +msgstr "" + +#: AperoDeDenis.py:7069 +msgid " - Activer/désactiver le 'tacky' message de lancement" +msgstr "" + +#: AperoDeDenis.py:7070 +msgid "menu Aide :" +msgstr "" + +#: AperoDeDenis.py:7071 +msgid "" +" - Pour commencer : à lire lors de la prise en main de l'interface." +msgstr "" + +#: AperoDeDenis.py:7072 +msgid " - Aide : le détail des items de menu." +msgstr "" + +#: AperoDeDenis.py:7073 +msgid " - Quelques conseils : sur la prise de vue et les options." +msgstr "" + +#: AperoDeDenis.py:7074 +msgid " - Historique : les nouveautés de chaque version." +msgstr "" + +#: AperoDeDenis.py:7075 +msgid " - A propos" +msgstr "" + +#: AperoDeDenis.py:7076 +msgid " Quelques précisions :" +msgstr "" + +#: AperoDeDenis.py:7077 +msgid "" +" Cette version a été développée sous Windows XP et Seven avec micmac rev " +"5508 d'avril 2015." +msgstr "" + +#: AperoDeDenis.py:7078 +msgid "" +" L'utilisation d'autres versions de Micmac a été testée, jusqu'à la version " +"6219." +msgstr "" + +#: AperoDeDenis.py:7079 +msgid " Le fonctionnement sous Ubuntu Trusty a été vérifié." +msgstr "" + +#: AperoDeDenis.py:7080 +msgid " Consulter la documentation de MicMac, outil réalisé par l'IGN." +msgstr "" + +#: AperoDeDenis.py:7081 +msgid " Consulter le guide d'installation et de prise en main d'AperoDeDenis." +msgstr "" + +#: AperoDeDenis.py:7091 +msgid "" +"Interface graphique pour lancer les modules de MICMAC : quelques conseils." +msgstr "" + +#: AperoDeDenis.py:7092 +msgid "Prises de vue :" +msgstr "" + +#: AperoDeDenis.py:7093 +msgid "" +" - Le sujet doit être immobile durant toutes la séance de " +"prise de vue." +msgstr "" + +#: AperoDeDenis.py:7094 +msgid " - Le sujet doit être unique et d'un seul tenant" +msgstr "" + +#: AperoDeDenis.py:7095 +msgid "" +" - Le sujet doit être bien éclairé, la prise de vue en plein " +"jour doit être recherchée." +msgstr "" + +#: AperoDeDenis.py:7096 +msgid "" +" - Les photos doivent être nettes, attention à la profondeur " +"de champ :" +msgstr "" + +#: AperoDeDenis.py:7097 +msgid "" +" utiliser la plus petite ouverture possible (nombre F le " +"plus grand, par exemple 22)." +msgstr "" + +#: AperoDeDenis.py:7098 +msgid "" +" - Utiliser la calibration intrinsèque des appareils photos " +"(item MicMac/Options/Orientation )." +msgstr "" + +#: AperoDeDenis.py:7099 +msgid "" +" - Les photos de personnes ou d'objet en mouvement sont " +"déconseillées" +msgstr "" + +#: AperoDeDenis.py:7100 +msgid "" +" - Les surfaces lisses ou réfléchissantes sont défavorables." +msgstr "" + +#: AperoDeDenis.py:7101 +msgid "" +" - Si le sujet est central prendre une photo tous les 20°, " +"soit 9 photos pour un 'demi-tour', 18 pour un tour complet." +msgstr "" + +#: AperoDeDenis.py:7102 +msgid "" +" - Si le sujet est en 'ligne' le recouvrement entre photos " +"doit être des 2/3." +msgstr "" + +#: AperoDeDenis.py:7103 +msgid "" +" - Tester la 'qualité' des photos au sein du chantier (voir " +"les items du menu Outils)." +msgstr "" + +#: AperoDeDenis.py:7104 +msgid "" +" les photos ayant un mauvais score (voir le menu Outils/" +"Qualité des photos 'All') doivent être supprimées du chantier : " +msgstr "" + +#: AperoDeDenis.py:7105 +msgid "" +" une seule mauvaise photo peut faire échouer le traitement." +msgstr "" + +#: AperoDeDenis.py:7106 +msgid "" +" - La présence des dimensions du capteur de l'appareil dans " +"DicoCamera.xml améliore le traitement." +msgstr "" + +#: AperoDeDenis.py:7107 +msgid "" +" Cette présence est obligatoire si l'exif ne présente pas " +"la focale équivalente 35mm." +msgstr "" + +#: AperoDeDenis.py:7108 +msgid "" +" Pour ajouter la taille du capteur utiliser le menu " +"'Outils//mettre à jour DicoCamera'." +msgstr "" + +#: AperoDeDenis.py:7109 +msgid " Précautions : " +msgstr "" + +#: AperoDeDenis.py:7110 +msgid "" +" Ne pas utiliser la fonction autofocus. Deux focales " +"différentes maximum pour un même chantier." +msgstr "" + +#: AperoDeDenis.py:7111 +msgid "" +" Eviter aussi la fonction 'anti tremblement' qui agit en " +"modfiant la position du capteur." +msgstr "" + +#: AperoDeDenis.py:7112 +msgid "Options :" +msgstr "" + +#: AperoDeDenis.py:7113 +msgid " - Points homologues : " +msgstr "" + +#: AperoDeDenis.py:7114 +msgid "" +" L'échelle est la taille en pixels de l'image (ou " +"-1 pour l'image entière) pour la recherche des points homologues." +msgstr "" + +#: AperoDeDenis.py:7115 +msgid "" +" Si le sujet est en ligne choisir 'line' dans les " +"options de Tapioca, " +msgstr "" + +#: AperoDeDenis.py:7116 +msgid "" +" puis delta = 1, si les " +"photos se recouvrent à moitiè, " +msgstr "" + +#: AperoDeDenis.py:7117 +msgid "" +" ou delta = 2 voire +, " +"si le recouvrement est plus important." +msgstr "" + +#: AperoDeDenis.py:7118 +msgid "" +" L'option ALl recherche les points homologues sur " +"toutes les paires de photos (ce qui peut faire beaucoup !)" +msgstr "" + +#: AperoDeDenis.py:7119 +msgid "" +" L'option MulScale recherche les points homologues " +"en 2 temps :" +msgstr "" + +#: AperoDeDenis.py:7120 +msgid "" +" 1) sur toutes les paires avec une taille de " +"photo réduite (typiquement 300)" +msgstr "" + +#: AperoDeDenis.py:7121 +msgid "" +" 2) Seules les paires de photos ayant eu au " +"moins 2 points homologues à cette échelle seront" +msgstr "" + +#: AperoDeDenis.py:7122 +msgid "" +" retenues pour rechercher les points " +"homologues à la seconde échelle. Gain de temps important possible." +msgstr "" + +#: AperoDeDenis.py:7123 +msgid "" +" - Orientation : si l'appareil photo est un compact ou un " +"smartphone choisir RadialBasic, " +msgstr "" + +#: AperoDeDenis.py:7124 +msgid "" +" si l'appareil photo est un reflex haut de gamme " +"choisir RadialExtended " +msgstr "" + +#: AperoDeDenis.py:7125 +msgid "" +" si l'appareil photo est de moyenne gamme choisir " +"RadialStd" +msgstr "" + +#: AperoDeDenis.py:7126 +msgid "" +" Ces conseils ne sont pas toujours vérifiés : " +"modifeir votre choix s'il échoue. " +msgstr "" + +#: AperoDeDenis.py:7127 +msgid "" +" L'arrêt après l'orientation permet de définir un " +"masque 3D, pour la densification par C3DC." +msgstr "" + +#: AperoDeDenis.py:7128 +msgid "" +" - Mise à l'échelle : permet de définir un repère et une " +"métrique (axe, plan et distance, tous obligatoires)." +msgstr "" + +#: AperoDeDenis.py:7129 +msgid "" +" - Points GPS: définir au moins 3 points cotés et les placer " +"sur 2 photos. L'état du chantier indique s'ils sont pris en compte" +msgstr "" + +#: AperoDeDenis.py:7130 +msgid "" +" - Densification par Malt : pour le mode GeomImage indiquer " +"une ou plusieurs images maîtresses." +msgstr "" + +#: AperoDeDenis.py:7131 +msgid "" +" Seuls les points visibles sur ces images seront " +"conservés dans le nuage de points." +msgstr "" + +#: AperoDeDenis.py:7132 +msgid "" +" Sur ces images maîtresses tracer les masque " +"délimitant la partie 'utile' de la photo." +msgstr "" + +#: AperoDeDenis.py:7133 +msgid "" +" Le résultat sera mis en couleur suivant les images " +"maitresses." +msgstr "" + +#: AperoDeDenis.py:7134 +msgid "" +" (éviter trop de recouvrement entre les maîtresses !)." +msgstr "" + +#: AperoDeDenis.py:7135 +msgid "" +" Le traitement avec masque sera accéléré et le " +"résultat plus 'propre'." +msgstr "" + +#: AperoDeDenis.py:7136 +msgid "" +" - Densification par C3DC : propose de définir un masque en 3D " +"qui conservera tout le volume concerné." +msgstr "" + +#: AperoDeDenis.py:7137 +msgid "" +" Alternative à Malt, le traitement est parfois plus " +"rapide. Nécessite une version récente de MicMac." +msgstr "" + +#: AperoDeDenis.py:7138 +msgid "Si MicMac ne trouve pas d'orientation ou pas de nuage de points :" +msgstr "" + +#: AperoDeDenis.py:7139 +msgid "" +" - Examiner la trace et la qualité des photos (utiliser le " +"menu outils/Qualité des photos): ." +msgstr "" + +#: AperoDeDenis.py:7140 +msgid " 0) Prenez un pastis" +msgstr "" + +#: AperoDeDenis.py:7141 +msgid "" +" 1) si erreur dans la trace : 'Radiale distorsion " +"abnormaly high' :" +msgstr "" + +#: AperoDeDenis.py:7142 +msgid "" +" modifier le type d'appareil pour l'orientation " +"(radialstd ou radialbasic ou RadialExtended ou...)" +msgstr "" + +#: AperoDeDenis.py:7143 +msgid "" +" 2) Eliminer les photos ayant les plus mauvais " +"scores, les photos ou groupe de photos 'isolées" +msgstr "" + +#: AperoDeDenis.py:7144 +msgid "" +" 3) si ce n'est pas suffisant ne garder que les " +"meilleures photos (typiquement : moins de 10)" +msgstr "" + +#: AperoDeDenis.py:7145 +msgid "" +" Penser que des photos floues ou avec un sujet " +"brillant, lisse, mobile, transparent, vivant sont défavorables." +msgstr "" + +#: AperoDeDenis.py:7146 +msgid "" +" 4) Augmenter l'échelle des photos pour tapioca, " +"mettre -1 au lieu de la valeur par défaut." +msgstr "" + +#: AperoDeDenis.py:7147 +msgid "" +" 5) Utiliser la calibration intrinsèque sur des " +"photos adaptées" +msgstr "" + +#: AperoDeDenis.py:7148 +msgid "" +" 6) Si plusieurs appareils photos sont utilisés il " +"faut les distinguer dans l'exif (voir menu expert)" +msgstr "" + +#: AperoDeDenis.py:7149 +msgid "" +" et prendre des photos spécifiques pour la " +"calibration intrinsèque de chaque appareil." +msgstr "" + +#: AperoDeDenis.py:7150 +msgid "" +" 7) vérifier la taille du capteur dans dicocamera, " +"nécessaire si la focale equivalente 35 mm est absente de l'exif" +msgstr "" + +#: AperoDeDenis.py:7151 +msgid "" +" 8) examiner la trace synthétique et la trace " +"complète : MicMac donne quelques informations" +msgstr "" + +#: AperoDeDenis.py:7152 +msgid "" +" si la trace compléte contient : 'Error: -- Input " +"line too long, increase MAXLINELENGTH'" +msgstr "" + +#: AperoDeDenis.py:7153 +msgid "" +" alors tenter, sans certitude, de modifier le " +"fichier /binaire-aux/windows/startup/local.mk" +msgstr "" + +#: AperoDeDenis.py:7154 +msgid "" +" 9) consulter le wiki micmac (https://micmac.ensg.eu/" +"index.php)" +msgstr "" + +#: AperoDeDenis.py:7155 +msgid "" +" 10) consulter le forum micmac (http://forum-micmac." +"forumprod.com)" +msgstr "" + +#: AperoDeDenis.py:7156 +msgid "" +" 11) faites appel à l'assistance de l'interface (voir " +"adresse dans l'a-propos)" +msgstr "" + +#: AperoDeDenis.py:7166 +msgid " Pour commencer avec l'interface graphique MicMac :" +msgstr "" + +#: AperoDeDenis.py:7167 +msgid "" +" Tout d'abord : installer MicMac. Consulter le wiki MicMac : https://" +"micmac.ensg.eu/index.php" +msgstr "" + +#: AperoDeDenis.py:7168 +msgid "" +" Puis : installer CloudCompare (ou Meshlab) (pour afficher les nuages de " +"points)" +msgstr "" + +#: AperoDeDenis.py:7169 +msgid " Ensuite, dans cette interface graphique :" +msgstr "" + +#: AperoDeDenis.py:7170 +msgid "" +"1) Paramètrer l'interface : indiquer ou se trouvent le répertoire bin de " +"MicMac et l'éxécutable CloudCompare (ou Meshlab)." +msgstr "" + +#: AperoDeDenis.py:7171 +msgid "" +" Indiquer éventuellement ou se trouvent exiftool et convert d'ImageMagick " +"(en principe sous MicMac\\binaire-aux)." +msgstr "" + +#: AperoDeDenis.py:7172 +msgid " Vérifier en affichant les paramètres (menu paramètrage)." +msgstr "" + +#: AperoDeDenis.py:7173 +msgid "" +"2) Choisir quelques photos (4 à 6) pour commencer (menu MicMac/choisir des " +"photos)." +msgstr "" + +#: AperoDeDenis.py:7174 +msgid "" +"3) Lancer MicMac en laissant les paramètres par défaut (menu MicMac/lancer " +"Micmac)." +msgstr "" + +#: AperoDeDenis.py:7175 +msgid "" +" Si tout va bien une vue en 3D non densifiée doit s'afficher, puis une vue " +"3D densifiée. Patience : cela peut être long." +msgstr "" + +#: AperoDeDenis.py:7176 +msgid "4) Si tout ne va pas bien prendre un pastis puis :" +msgstr "" + +#: AperoDeDenis.py:7177 +msgid " Lire 'quelques conseils' (menu Aide)." +msgstr "" + +#: AperoDeDenis.py:7178 +msgid " Tester la qualité des photos (menu Outils)." +msgstr "" + +#: AperoDeDenis.py:7179 +msgid " Examiner les traces (menu Edition)," +msgstr "" + +#: AperoDeDenis.py:7180 +msgid " Consulter l'aide (menu Aide)," +msgstr "" + +#: AperoDeDenis.py:7181 +msgid "" +" Consulter le guide d'installation et de prise en main de l'interface." +msgstr "" + +#: AperoDeDenis.py:7182 +msgid " Consulter le forum MicMac sur le net, consulter la doc MicMac." +msgstr "" + +#: AperoDeDenis.py:7183 +msgid "" +"5) Si une solution apparaît : modifier les options (menu MicMac/options)." +msgstr "" + +#: AperoDeDenis.py:7184 +msgid " puis relancer le traitement." +msgstr "" + +#: AperoDeDenis.py:7185 +msgid "" +"6) Si le problème persiste faire appel à l'assistance de l'interface " +"(adresse mail dans Aide/A-propos)" +msgstr "" + +#: AperoDeDenis.py:7190 +msgid "Historique des versions diffusées sur le site de l'IGN" +msgstr "" + +#: AperoDeDenis.py:7192 +msgid "" +"Version 1.5 : première version diffusée sur le site de l'IGN le 23/11/2015." +msgstr "" + +#: AperoDeDenis.py:7193 +msgid "" +"Version 1.55 : sous Windows le fichier paramètre est placé sous le " +"répertoire APPDATA de l'utilisateur," +msgstr "" + +#: AperoDeDenis.py:7194 +msgid "" +"ce qui règle les questions relatives aux droits d'accès en écriture. Mise en " +"ligne le 04/12/2015." +msgstr "" + +#: AperoDeDenis.py:7195 +msgid "Version 1.60 : ajout des fonctions :" +msgstr "" + +#: AperoDeDenis.py:7196 +msgid "- Qualité des photos lors du dernier traitement" +msgstr "" + +#: AperoDeDenis.py:7197 +msgid "- Exporter le chantier en cours" +msgstr "" + +#: AperoDeDenis.py:7198 +msgid "" +"- Importer un chantier (permet de recopier le chantier sur un autre " +"répertoire, disque, ordinateur, système d'exploitation)" +msgstr "" + +#: AperoDeDenis.py:7199 +msgid "- Les fichiers 'trace' sont enregistrés au format utf-8." +msgstr "" + +#: AperoDeDenis.py:7200 +msgid "Version 2.00 : ajout des fonctions :" +msgstr "" + +#: AperoDeDenis.py:7201 +msgid "- Choix de photos pour la calibration intrinsèque par Tapas." +msgstr "" + +#: AperoDeDenis.py:7202 +msgid "" +"- Possibilité de relancer Malt sans relancer Tapioca/Tapas tout en " +"conservant les images 3D générées." +msgstr "" + +#: AperoDeDenis.py:7203 +msgid "" +"- Conservation de plusieurs fichiers modele3D.ply après Malt pour un même " +"chantier." +msgstr "" + +#: AperoDeDenis.py:7204 +msgid "" +"- Choix du niveau de zoom d'arrêt de la procédure Malt : de 1 (par défaut) à " +"8." +msgstr "" + +#: AperoDeDenis.py:7205 +msgid "" +"- Création de tous les fichiers .ply correspondants à tous les niveaux de " +"zoom calculés." +msgstr "" + +#: AperoDeDenis.py:7206 +msgid "" +"- Ajout d'un item du menu édition listant et visualisant toutes les images " +"3D générées." +msgstr "" + +#: AperoDeDenis.py:7207 +msgid "" +"- Choix du nombre de photos à retenir autour de l'image maître pour Malt." +msgstr "" + +#: AperoDeDenis.py:7208 +msgid "" +"- Traitement des vidéos (par exemple GoPro) : décompactage, sélection, mise " +"à jour de l'exif" +msgstr "" + +#: AperoDeDenis.py:7209 +msgid "" +"- Ajout de deux contrôles sur le lot des photos : mêmes dimensions, même " +"focale." +msgstr "" + +#: AperoDeDenis.py:7210 +msgid "- Ajout d'un item 'historique' dans le menu Aide." +msgstr "" + +#: AperoDeDenis.py:7211 +msgid "Version 2.10" +msgstr "" + +#: AperoDeDenis.py:7211 +msgid "- Ajout d'un item du menu édition fusionnant les images 3D." +msgstr "" + +#: AperoDeDenis.py:7212 +msgid "- Plusieurs images maîtresses, plusieurs masques." +msgstr "" + +#: AperoDeDenis.py:7213 +msgid "- Conversion automatique des fichiers PNG, BMP, GIF, TIF en JPG" +msgstr "" + +#: AperoDeDenis.py:7214 +msgid "" +"- Ajout d'un item du menu Outils permettant de modifier les exifs. Diffusion " +"restreinte à la DTer NC le 16/02/2016" +msgstr "" + +#: AperoDeDenis.py:7215 +msgid "Version 2.20 :" +msgstr "" + +#: AperoDeDenis.py:7215 +msgid "" +"- Maintien des options compatibles lors du choix de nouvelles photos. " +"Février 2016" +msgstr "" + +#: AperoDeDenis.py:7216 +msgid "Version 2.30 : " +msgstr "" + +#: AperoDeDenis.py:7217 +msgid "- Modification des options par défaut dans le menu outils." +msgstr "" + +#: AperoDeDenis.py:7218 +msgid "Version 2.40 :" +msgstr "" + +#: AperoDeDenis.py:7218 +msgid "- Choix de l'option (Statue ou QuickMac) pour C3DC. Avril 2016" +msgstr "" + +#: AperoDeDenis.py:7219 +msgid "Version 2.45 :" +msgstr "" + +#: AperoDeDenis.py:7219 +msgid "" +"- Référentiel GPS calculé après Tapas (et toujours avant Malt). La virgule " +"est un séparateur décimal accepté." +msgstr "" + +#: AperoDeDenis.py:7220 +msgid "" +"- Possiblité d'appliquer la calibration GPS sans relancer malt. Mai 2016" +msgstr "" + +#: AperoDeDenis.py:7221 +msgid "Version 2.50 :" +msgstr "" + +#: AperoDeDenis.py:7221 +msgid "" +"- Ajout de Tawny après Malt en mode Ortho, désactivation du message de " +"lancement. Juin 2016" +msgstr "" + +#: AperoDeDenis.py:7222 +msgid "Version 3.00 :" +msgstr "" + +#: AperoDeDenis.py:7222 +msgid "- Version bilingue Français/Anglais. Octobre 2016" +msgstr "" + +#: AperoDeDenis.py:7223 +msgid "Version 3.10 :" +msgstr "" + +#: AperoDeDenis.py:7223 +msgid "- Choix des N meilleures photos pour un nouveau dossier. Novembre 2016" +msgstr "" + +#: AperoDeDenis.py:7224 +msgid "Version 3.20 :" +msgstr "" + +#: AperoDeDenis.py:7224 AperoDeDenis.py:7232 +msgid "janvier 2017" +msgstr "" + +#: AperoDeDenis.py:7225 +msgid "" +"- Ajout d'un choix pour Malt : AperoDeDenis, l'interface recherche pour vous " +"les maîtresses et les photos correspondantes" +msgstr "" + +#: AperoDeDenis.py:7226 +msgid "" +"- Item de sélection des meilleures images pour créer un nouveau chantier. " +"janvier 2017" +msgstr "" + +#: AperoDeDenis.py:7227 +msgid "- Possibilité de saisir une unité avec la distance." +msgstr "" + +#: AperoDeDenis.py:7228 +msgid "- Lancement de Tapas accéléré : suppression du controle des photos" +msgstr "" + +#: AperoDeDenis.py:7229 +msgid "" +"- Les photos autour de la maîtresse pour Malt sont choisies parmi les " +"meilleures en correspondances" +msgstr "" + +#: AperoDeDenis.py:7230 +msgid "- Controle affiné des points GPS, message informatif détaillé" +msgstr "" + +#: AperoDeDenis.py:7231 +msgid "- Possibilité de supprimer UN seul point GPS sur une photo" +msgstr "" + +#: AperoDeDenis.py:7232 +msgid "Version 3.30 :" +msgstr "" + +#: AperoDeDenis.py:7233 +msgid "- Ajout de tarama : création d'une mosaïque après Tapas." +msgstr "" + +#: AperoDeDenis.py:7234 +msgid "- le mode Ortho de Malt utilise la mosaïque tarama, avec masque" +msgstr "" + +#: AperoDeDenis.py:7235 +msgid "- drapage du nuage densifié par l'ortho mosaïque obtenue par Tawny" +msgstr "" + +#: AperoDeDenis.py:7236 +msgid "- Possibilité d'inverser les masques 2D" +msgstr "" + +#: AperoDeDenis.py:7237 +msgid "- Ouverture des mosaïques Tarama et Tawny par menu" +msgstr "" + +#: AperoDeDenis.py:7238 +msgid "- Ajout d'un menu 'expert' permettant de saisir une ligne de commande." +msgstr "" + +#: AperoDeDenis.py:7239 +msgid "Version 3.31 :" +msgstr "" + +#: AperoDeDenis.py:7239 +msgid "février 2017" +msgstr "" + +#: AperoDeDenis.py:7240 +msgid "" +"- Ajout d'un item du menu 'expert' : recopie les points GPS d'un chantier à " +"un autre." +msgstr "" + +#: AperoDeDenis.py:7241 +msgid "Version 3.34 :" +msgstr "" + +#: AperoDeDenis.py:7241 AperoDeDenis.py:7246 +msgid "Janvier 2018" +msgstr "" + +#: AperoDeDenis.py:7242 +msgid "" +"- Du ménage! permet de conserver les résultats OU de supprimer tout le " +"chantier." +msgstr "" + +#: AperoDeDenis.py:7243 +msgid "- Affichage de la taille du dossier." +msgstr "" + +#: AperoDeDenis.py:7244 +msgid "- Correction de régressions de la V 3.20." +msgstr "" + +#: AperoDeDenis.py:7245 +msgid "" +"Remarque : la version 4.11 de décembre 2017 ajoute un item métier de calcul " +"d'indice surfacique," +msgstr "" + +#: AperoDeDenis.py:7246 +msgid "Version 5.0 :" +msgstr "" + +#: AperoDeDenis.py:7247 +msgid "la version suivante 5.0 supprime l'item 'indices surfaciques'." +msgstr "" + +#: AperoDeDenis.py:7248 +msgid "Version 5.1 :" +msgstr "" + +#: AperoDeDenis.py:7248 +msgid "décembre 2018" +msgstr "" + +#: AperoDeDenis.py:7249 +msgid "" +"- permet d'oublier les photos ayant servies à la calibration de l'appareil " +"pour l'exécution de Tapas." +msgstr "" + +#: AperoDeDenis.py:7250 +msgid "" +"- insertion d'un fichier texte de points GPS par le menu expert (séparateur " +"espace : nom,x,y,z,dx,dy,dz." +msgstr "" + +#: AperoDeDenis.py:7251 +msgid "" +"- affichage des dimensions des photos dans le menu outils/nom de l'appareil " +"photo" +msgstr "" + +#: AperoDeDenis.py:7252 +msgid "" +"- Amélioration de libellés de boites de dialogue, suppression du polysème " +"'calibration'" +msgstr "" + +#: AperoDeDenis.py:7253 +msgid "Version 5.2 :" +msgstr "" + +#: AperoDeDenis.py:7253 +msgid "janvier 2019" +msgstr "" + +#: AperoDeDenis.py:7254 +msgid "" +"- ajout du modulé CAMPARI après chaque géolocalisation par points GPS " +"(améliore les valeurs des Z)." +msgstr "" + +#: AperoDeDenis.py:7255 +msgid "" +"- répartition des photos provenant de plusieurs appareils par modification " +"du 'model' dans l'exif (menu expert)" +msgstr "" + +#: AperoDeDenis.py:7256 +msgid "" +"- affichage des noms des appareils photos présents dans le chantier (menu " +"expert)" +msgstr "" + +#: AperoDeDenis.py:7257 +msgid "" +"- affichage du log des traitement MicMac : mm3d-logFile.txt (menu expert)" +msgstr "" + +#: AperoDeDenis.py:7258 +msgid "" +"- amélioration de la fonction console système (Expert/Exécuter une commande)" +msgstr "" + +#: AperoDeDenis.py:7259 +msgid "Version 5.21 :" +msgstr "" + +#: AperoDeDenis.py:7259 +msgid "février 2019" +msgstr "" + +#: AperoDeDenis.py:7260 +msgid "- Argument de Tapas aprés calibration : Figee (au lieu de Autocal)" +msgstr "" + +#: AperoDeDenis.py:7261 +msgid "- Ajout dans le menu expert d'un console python" +msgstr "" + +#: AperoDeDenis.py:7262 +msgid "Version 5.22 :" +msgstr "" + +#: AperoDeDenis.py:7262 +msgid "11 février 2019" +msgstr "" + +#: AperoDeDenis.py:7263 +msgid "- fix 2 issues remontées sur github, numéro de version inchangée : 5.21" +msgstr "" + +#: AperoDeDenis.py:7264 +msgid "Version 5.30 :" +msgstr "" + +#: AperoDeDenis.py:7264 +msgid "21 février 2019" +msgstr "" + +#: AperoDeDenis.py:7265 +msgid "" +"- dans les items 'Outils/Qualité des photos' ajout des photos 'isolées', en " +"disjontion de toutes les autres." +msgstr "" + +#: AperoDeDenis.py:7266 +msgid " Ces photos font 'planter' la recherche de l'orientation." +msgstr "" + +#: AperoDeDenis.py:7267 +msgid "" +"- Suite à la recherche des points homologues vérification de l'unicité de la " +"scène photographiée." +msgstr "" + +#: AperoDeDenis.py:7268 +msgid "" +" Plusieurs scènes sans point homologue commun font planter la recherche " +"d'une orientation." +msgstr "" + +#: AperoDeDenis.py:7269 +msgid " Cette fonction est ajoutée à l'item 'Outils/Qualité des photos'." +msgstr "" + +#: AperoDeDenis.py:7270 +msgid "" +"- Lorsque le message MAXLINELENGTH est émis par Tapioca il est affiché et " +"expliqué dans la trace synthétique." +msgstr "" + +#: AperoDeDenis.py:7271 +msgid "" +"- prise en compte de l'issue concernant la fonction filedialog sous Mac-Os " +"lors des recherche de programmes (exiftool...)." +msgstr "" + +#: AperoDeDenis.py:7272 +msgid "" +"- Ajout d'un item dans paramètrage : recherche d'une nouvelle version GitHub." +msgstr "" + +#: AperoDeDenis.py:7283 +msgid "Réalisation Denis Jouin 2015-2019" +msgstr "" + +#: AperoDeDenis.py:7283 +msgid "Laboratoire Régional de Rouen" +msgstr "" + +#: AperoDeDenis.py:7284 +msgid "CEREMA Normandie Centre" +msgstr "" + +#: AperoDeDenis.py:7300 +msgid "erreur canvas logo cerema : " +msgstr "" + +#: AperoDeDenis.py:7388 +msgid "erreur sauveParamChantier : " +msgstr "" + +#: AperoDeDenis.py:7416 +msgid "erreur sauveParamMicMac : " +msgstr "" + +#: AperoDeDenis.py:7417 +msgid "" +"L'interface doit être installée dans un répertoire ou vous avez les droits " +"d'écriture." +msgstr "" + +#: AperoDeDenis.py:7418 +msgid "" +"Installer l'interface AperoDeDenis à un emplacement ou vous avez ce droit." +msgstr "" + +#: AperoDeDenis.py:7419 +msgid "Répertoire actuel : " +msgstr "" + +#: AperoDeDenis.py:7420 +msgid "Erreur rencontrée : " +msgstr "" + +#: AperoDeDenis.py:7421 +msgid "Problème d'installation" +msgstr "" + +#: AperoDeDenis.py:7458 +msgid "Erreur restauration param généraux : " +msgstr "" + +#: AperoDeDenis.py:7550 +msgid "Erreur restauration param chantier : " +msgstr "" + +#: AperoDeDenis.py:7560 +msgid "erreur définir fichier trace, est normale lors d'une importation." +msgstr "" + +#: AperoDeDenis.py:7735 +msgid "Fermer les options." +msgstr "" + +#: AperoDeDenis.py:7735 +msgid "" +"La boîte de dialogue 'options' est ouverte et va être fermée.\n" +"Voulez-vous enregistrer les options saisies ?" +msgstr "" + +#: AperoDeDenis.py:7735 AperoDeDenis.py:7748 AperoDeDenis.py:7760 +msgid "enregistrer" +msgstr "" + +#: AperoDeDenis.py:7735 AperoDeDenis.py:7748 AperoDeDenis.py:7760 +msgid "abandon" +msgstr "" + +#: AperoDeDenis.py:7748 +msgid "Fermer les options vidéo." +msgstr "" + +#: AperoDeDenis.py:7748 +msgid "Enregistrer les options vidéos saisies ?" +msgstr "" + +#: AperoDeDenis.py:7760 +msgid "Fermer la modification des exifs." +msgstr "" + +#: AperoDeDenis.py:7760 +msgid "Enregistrer les valeurs saisies ?" +msgstr "" + +#: AperoDeDenis.py:7789 +msgid "Nouvelle version de l'interface AperoDeDenis" +msgstr "" + +#: AperoDeDenis.py:7790 +msgid "Nouvelle version disponible sur Internet : " +msgstr "" + +#: AperoDeDenis.py:7792 +msgid "Téléchargement à l'adresse : " +msgstr "" + +#: AperoDeDenis.py:7794 AperoDeDenis.py:8143 AperoDeDenis.py:9666 +msgid "OK" +msgstr "" + +#: AperoDeDenis.py:7795 +msgid "Accéder au site" +msgstr "" + +#: AperoDeDenis.py:7796 +msgid "Ne plus me le rappeler" +msgstr "" + +#: AperoDeDenis.py:7804 +msgid "Recherche sur internet en cours, patience..." +msgstr "" + +#: AperoDeDenis.py:7810 +msgid "Erreur lors de la tentative de connexion à internet : " +msgstr "" + +#: AperoDeDenis.py:7820 +msgid "Version actuelle à jour" +msgstr "" + +#: AperoDeDenis.py:7830 +msgid "Tous les chantiers sont déjà supprimés." +msgstr "" + +#: AperoDeDenis.py:7844 +msgid "Chantiers à nettoyer ou supprimer" +msgstr "" + +#: AperoDeDenis.py:7848 AperoDeDenis.py:8232 +msgid "repertoires" +msgstr "" + +#: AperoDeDenis.py:7857 AperoDeDenis.py:7866 +msgid "Suppression ou nettoyage des répertoires de travail superflus" +msgstr "" + +#: AperoDeDenis.py:7858 +msgid "Le chantier suivant va être supprimé ou nettoyé :" +msgstr "" + +#: AperoDeDenis.py:7859 +msgid "Supprimer totalement le chantier" +msgstr "" + +#: AperoDeDenis.py:7860 +msgid "Nettoyer le chantier, conserver les résultats" +msgstr "" + +#: AperoDeDenis.py:7864 +msgid "ATTENTION : le chantier en cours va être nettoyéé." +msgstr "" + +#: AperoDeDenis.py:7867 +msgid "Les chantiers suivant vont être supprimés ou nettoyés :" +msgstr "" + +#: AperoDeDenis.py:7868 +msgid "Supprimer totalement les chantiers" +msgstr "" + +#: AperoDeDenis.py:7869 +msgid "Nettoyer les chantier, conserver les résultats" +msgstr "" + +#: AperoDeDenis.py:7876 +msgid "Suppression en cours...." +msgstr "" + +#: AperoDeDenis.py:7882 +#, python-format +msgid "Le chantier en cours %s est supprimé." +msgstr "" + +#: AperoDeDenis.py:7898 AperoDeDenis.py:7900 +msgid "Compte rendu de la suppression :" +msgstr "" + +#: AperoDeDenis.py:7898 +msgid "Repertoires supprimés :" +msgstr "" + +#: AperoDeDenis.py:7900 +msgid "Aucun répertoire supprimé." +msgstr "" + +#: AperoDeDenis.py:7903 +msgid "Tous les chantiers demandés sont supprimés." +msgstr "" + +#: AperoDeDenis.py:7905 +msgid "Il reste un chantier impossible à supprimer maintenant : " +msgstr "" + +#: AperoDeDenis.py:7907 +msgid "Il reste des chantiers impossibles à supprimer maintenant : " +msgstr "" + +#: AperoDeDenis.py:7908 AperoDeDenis.py:7927 +msgid "Espace disque récupéré : " +msgstr "" + +#: AperoDeDenis.py:7916 +msgid "Suppression des sous-répertoires en cours...." +msgstr "" + +#: AperoDeDenis.py:7934 +msgid "Choisir" +msgstr "" + +#: AperoDeDenis.py:7934 +msgid "Choisir : " +msgstr "" + +#: AperoDeDenis.py:8004 +msgid " : lancement de " +msgstr "" + +#: AperoDeDenis.py:8013 +msgid "erreur lors de l'éxécution de la commande :" +msgstr "" + +#: AperoDeDenis.py:8014 AperoDeDenis.py:8022 AperoDeDenis.py:8044 +msgid " : fin de " +msgstr "" + +#: AperoDeDenis.py:8021 +msgid "erreur lors de l'éxécution de la commande." +msgstr "" + +#: AperoDeDenis.py:8037 +msgid "erreur lecture output : " +msgstr "" + +#: AperoDeDenis.py:8059 +msgid "Trace complète" +msgstr "" + +#: AperoDeDenis.py:8060 +msgid "Trace synthétique" +msgstr "" + +#: AperoDeDenis.py:8063 +msgid "Choix des photos :" +msgstr "" + +#: AperoDeDenis.py:8064 +msgid "répertoire du chantier :" +msgstr "" + +#: AperoDeDenis.py:8065 +msgid "Version MicMac : " +msgstr "" + +#: AperoDeDenis.py:8123 +msgid "erreur ecritureTraceMicMac : " +msgstr "" + +#: AperoDeDenis.py:8140 +msgid "Choisir une photo" +msgstr "" + +#: AperoDeDenis.py:8141 +msgid "Cliquer pour choisir une ou plusieurs photos : " +msgstr "" + +#: AperoDeDenis.py:8149 +msgid "Pas de photos pour cette demande." +msgstr "" + +#: AperoDeDenis.py:8161 +msgid "Les fichiers suivants sont absents du disque :" +msgstr "" + +#: AperoDeDenis.py:8161 +msgid "Dossier corrompu. Traitement interrompu." +msgstr "" + +#: AperoDeDenis.py:8260 +msgid "Options GoPro modifiées" +msgstr "" + +#: AperoDeDenis.py:8272 +msgid "Abandon : options GoPro inchangées." +msgstr "" + +#: AperoDeDenis.py:8290 +msgid "" +"L'outil ffmpeg n'est pas installé sur votre ordinateur. Traitement des vidéo " +"GoPro impossible." +msgstr "" + +#: AperoDeDenis.py:8297 +#, python-format +msgid "" +"Choisir la video issue d'un appareil %(GoProMaker)s %(GoProName)s (sinon " +"modifier les options)" +msgstr "" + +#: AperoDeDenis.py:8299 +msgid "Video" +msgstr "" + +#: AperoDeDenis.py:8303 +msgid "" +"Abandon, aucune sélection,\n" +" le chantier reste inchangé." +msgstr "" + +#: AperoDeDenis.py:8307 +#, python-format +msgid "" +"La version actuelle ne traite que les videos au format MP4, or le format des " +"photos est %s. Désolé." +msgstr "" + +#: AperoDeDenis.py:8326 +msgid "Décompacte la vidéo" +msgstr "" + +#: AperoDeDenis.py:8331 +msgid "L'outil ffmpeg est absent." +msgstr "" + +#: AperoDeDenis.py:8331 +msgid "Il convient de l'associer." +msgstr "" + +#: AperoDeDenis.py:8338 +msgid "Aucune image décompactée : consulter la trace." +msgstr "" + +#: AperoDeDenis.py:8365 +msgid "Les images de la video sont décompactées sous le répertoire :" +msgstr "" + +#: AperoDeDenis.py:8366 +#, python-format +msgid "Il y a %s images décompactées." +msgstr "" + +#: AperoDeDenis.py:8367 +#, python-format +msgid "" +"Lancer 'Sélection des images' pour sélectionner %s images par seconde de " +"film." +msgstr "" + +#: AperoDeDenis.py:8368 +msgid "La sélection choisira les 'meilleures' images" +msgstr "" + +#: AperoDeDenis.py:8369 +msgid "" +"Les options Tapioca et Tapas ont été positionnées pour des images GoPro : " +"modifier si besoin" +msgstr "" + +#: AperoDeDenis.py:8379 +msgid "met à jour l'exif des JPG décompactés :" +msgstr "" + +#: AperoDeDenis.py:8413 +msgid "Cette sélection de photos est réservé aux chantiers vidéos" +msgstr "" + +#: AperoDeDenis.py:8422 AperoDeDenis.py:8460 +msgid "Sélection d'un sous ensemble des images GoPro décompactées." +msgstr "" + +#: AperoDeDenis.py:8434 AperoDeDenis.py:8473 +msgid " a supprimer : " +msgstr "" + +#: AperoDeDenis.py:8442 +msgid "" +"Aucune sélection effectuée. La version de micmac ne propose peut-être pas " +"cette fonction." +msgstr "" + +#: AperoDeDenis.py:8442 AperoDeDenis.py:8481 AperoDeDenis.py:8816 +#: AperoDeDenis.py:8982 AperoDeDenis.py:9000 +msgid "Consulter la trace." +msgstr "" + +#: AperoDeDenis.py:8442 +msgid "Vous pouvez utiliser le menu 'outils/qualité des photos line'" +msgstr "" + +#: AperoDeDenis.py:8442 +msgid "puis effectuer une sélection manuelle." +msgstr "" + +#: AperoDeDenis.py:8444 AperoDeDenis.py:8483 +msgid "Images sélectionnées." +msgstr "" + +#: AperoDeDenis.py:8444 AperoDeDenis.py:8483 +msgid "Vous pouvez lancer Micmac." +msgstr "" + +#: AperoDeDenis.py:8451 +msgid "Cette sélection de photos est réservé aux chantiers photos" +msgstr "" + +#: AperoDeDenis.py:8481 +msgid "Aucune sélection effectuée." +msgstr "" + +#: AperoDeDenis.py:8481 +msgid "" +"Vous pouvez utiliser le menu 'outils/qualité des photos line'\n" +"puis effectuer une sélection manuelle." +msgstr "" + +#: AperoDeDenis.py:8521 +msgid "Trouvé : " +msgstr "" + +#: AperoDeDenis.py:8523 +msgid "Non trouvé : " +msgstr "" + +#: AperoDeDenis.py:8543 +msgid " Pas de fichier pour " +msgstr "" + +#: AperoDeDenis.py:8562 +msgid "erreur infobulle : " +msgstr "" + +#: AperoDeDenis.py:8609 +msgid "Aucun point placé sur cette photo" +msgstr "" + +#: AperoDeDenis.py:8611 +msgid "Un point placé sur cette photo" +msgstr "" + +#: AperoDeDenis.py:8613 +msgid " points placés sur cette photo" +msgstr "" + +#: AperoDeDenis.py:8679 +msgid "Aucun chantier mémorisé." +msgstr "" + +#: AperoDeDenis.py:8687 +msgid "Choisir le chantier à ouvrir :" +msgstr "" + +#: AperoDeDenis.py:8689 +msgid "vertical" +msgstr "" + +#: AperoDeDenis.py:8690 +msgid "horizontal" +msgstr "" + +#: AperoDeDenis.py:8710 +msgid "Ouvrir" +msgstr "" + +#: AperoDeDenis.py:8715 +msgid "Il y a des chantiers incomplets," +msgstr "" + +#: AperoDeDenis.py:8715 +#, python-format +msgid " le fichier %s est absent." +msgstr "" + +#: AperoDeDenis.py:8716 +msgid "Ces chantiers ne peuvent être ouverts mais peuvent être supprimés :" +msgstr "" + +#: AperoDeDenis.py:8741 +msgid "Abandon utilisateur." +msgstr "" + +#: AperoDeDenis.py:8766 AperoDeDenis.py:8783 +msgid "HomolTemporaire" +msgstr "" + +#: AperoDeDenis.py:8768 +msgid "erreur renommage Homol en HomolTemporaire : " +msgstr "" + +#: AperoDeDenis.py:8773 +#, python-format +msgid "erreur renommage %s en Homol : " +msgstr "" + +#: AperoDeDenis.py:8781 +#, python-format +msgid "erreur renommage Homol en : %s : " +msgstr "" + +#: AperoDeDenis.py:8785 +msgid "erreur renommage HomolTemporaire en Homol : " +msgstr "" + +#: AperoDeDenis.py:8795 +msgid "ATTENTION : Les photos définissent plusieurs scènes disjointes" +msgstr "" + +#: AperoDeDenis.py:8805 +msgid "dernier traitement : " +msgstr "" + +#: AperoDeDenis.py:8813 +msgid "Lancer MicMac avant de pouvoir évaluer la qualité des photos." +msgstr "" + +#: AperoDeDenis.py:8816 +msgid "Le traitement n'a donné aucun point homologue." +msgstr "" + +#: AperoDeDenis.py:8854 +msgid "Photo" +msgstr "" + +#: AperoDeDenis.py:8854 +msgid "score" +msgstr "" + +#: AperoDeDenis.py:8854 +msgid "nb photos en correspondance" +msgstr "" + +#: AperoDeDenis.py:8862 +msgid " : fin de la recherche sur la qualité des photos." +msgstr "" + +#: AperoDeDenis.py:8908 +msgid "Lancer d'abord Tapioca/Tapas" +msgstr "" + +#: AperoDeDenis.py:8936 AperoDeDenis.py:8953 +msgid "Aucun nuage de points dans ce chantier." +msgstr "" + +#: AperoDeDenis.py:8939 +msgid "Liste des nuages de points du chantier" +msgstr "" + +#: AperoDeDenis.py:8940 +msgid "les nuages (fichiers ply) :" +msgstr "" + +#: AperoDeDenis.py:8941 +msgid "Visualiser" +msgstr "" + +#: AperoDeDenis.py:8956 +msgid "Fusion de nuages" +msgstr "" + +#: AperoDeDenis.py:8957 +msgid "Choisir les fichiers à fusionner :" +msgstr "" + +#: AperoDeDenis.py:8958 +msgid "Fusionner et visualiser" +msgstr "" + +#: AperoDeDenis.py:8964 AperoDeDenis.py:8979 +msgid "Choisir au moins 2 nuages pour la fusion." +msgstr "" + +#: AperoDeDenis.py:8982 +msgid "Les ply attendus n'ont pas été créé." +msgstr "" + +#: AperoDeDenis.py:8997 +msgid "Nuage fusionné :" +msgstr "" + +#: AperoDeDenis.py:8997 +msgid "ajouté à la liste des nuages." +msgstr "" + +#: AperoDeDenis.py:8997 +msgid "résultat de la fusion de :" +msgstr "" + +#: AperoDeDenis.py:9000 +msgid "La fusion n'a pu se réaliser." +msgstr "" + +#: AperoDeDenis.py:9010 AperoDeDenis.py:9030 AperoDeDenis.py:9069 +#: AperoDeDenis.py:9083 AperoDeDenis.py:9117 +msgid "Saisir une valeur numérique" +msgstr "" + +#: AperoDeDenis.py:9016 AperoDeDenis.py:9036 AperoDeDenis.py:9089 +msgid "Passage en coordonnées xyz" +msgstr "" + +#: AperoDeDenis.py:9018 AperoDeDenis.py:9021 AperoDeDenis.py:9038 +#: AperoDeDenis.py:9091 +msgid "Création de la grille ..." +msgstr "" + +#: AperoDeDenis.py:9046 AperoDeDenis.py:9096 +msgid "Le calcul peut durer quelques minutes ..." +msgstr "" + +#: AperoDeDenis.py:9052 +msgid "Rugosité moyenne quadratique : " +msgstr "" + +#: AperoDeDenis.py:9053 +msgid "Tortuosité moyenne : " +msgstr "" + +#: AperoDeDenis.py:9054 AperoDeDenis.py:9102 +msgid "nombre de profils utilisés : " +msgstr "" + +#: AperoDeDenis.py:9055 AperoDeDenis.py:9064 AperoDeDenis.py:9071 +#: AperoDeDenis.py:9103 AperoDeDenis.py:9112 AperoDeDenis.py:9119 +msgid "id profil entre : " +msgstr "" + +#: AperoDeDenis.py:9063 AperoDeDenis.py:9111 +msgid "Choisir une valeur valide " +msgstr "" + +#: AperoDeDenis.py:9100 +msgid "Profondeur moyenne de profil (moyenne) : " +msgstr "" + +#: AperoDeDenis.py:9101 +msgid "Profondeur de texture équivalente : " +msgstr "" + +#: AperoDeDenis.py:9129 +msgid "Le programme de conversion n'est pas présent." +msgstr "" + +#: AperoDeDenis.py:9155 +msgid "Paramètres mis à jour" +msgstr "" + +#: AperoDeDenis.py:9156 +msgid "Méthode = " +msgstr "" + +#: AperoDeDenis.py:9157 +msgid "Pas du maillage = " +msgstr "" + +#: AperoDeDenis.py:9206 +msgid "Exifs mis à jour" +msgstr "" + +#: AperoDeDenis.py:9207 +msgid "Fabricant = " +msgstr "" + +#: AperoDeDenis.py:9208 +msgid "Modèle = " +msgstr "" + +#: AperoDeDenis.py:9209 +msgid "Focale = " +msgstr "" + +#: AperoDeDenis.py:9210 +msgid "Focale eq 35mm = " +msgstr "" + +#: AperoDeDenis.py:9217 +msgid "Abandon de la mise à jour des exifs" +msgstr "" + +#: AperoDeDenis.py:9227 +msgid "Aucune photo à mettre à jour." +msgstr "" + +#: AperoDeDenis.py:9230 +msgid "" +"La liste des fichiers comporte plusieurs extensions différentes : abandon." +msgstr "" + +#: AperoDeDenis.py:9235 +#, python-format +msgid "" +"La version actuelle ne traite que les exif des photos au format JPG, or le " +"format des photos est %s. Désolé, abandon." +msgstr "" + +#: AperoDeDenis.py:9241 +#, python-format +msgid "Le fichier %s n'existe pas. Abandon" +msgstr "" + +#: AperoDeDenis.py:9245 +msgid "met à jour l'exif de " +msgstr "" + +#: AperoDeDenis.py:9271 +msgid "Choisir des photos au préalable." +msgstr "" + +#: AperoDeDenis.py:9275 +msgid "Attention les photos suivantes sont absentes sur disque : " +msgstr "" + +#: AperoDeDenis.py:9275 +msgid "Elles sont supprimées du chantier." +msgstr "" + +#: AperoDeDenis.py:9280 +msgid "Problème de fichiers" +msgstr "" + +#: AperoDeDenis.py:9284 +msgid "Bonjour !" +msgstr "" + +#: AperoDeDenis.py:9284 +msgid "Commencer par indiquer où se trouve MicMac :" +msgstr "" + +#: AperoDeDenis.py:9285 +msgid " - menu Paramétrage/Associer le répertoire bin de MicMac" +msgstr "" + +#: AperoDeDenis.py:9286 +msgid "Ensuite consulter l'aide, item 'pour commencer'." +msgstr "" + +#: AperoDeDenis.py:9287 +msgid "Si besoin :" +msgstr "" + +#: AperoDeDenis.py:9288 +msgid "" +" - Associer convert et exiftool s'ils ne sont pas trouvés automatiquement " +"sous micmac/binaire-aux" +msgstr "" + +#: AperoDeDenis.py:9289 +msgid "" +" - Associer un outil (CloudCompare ou Meshlab) pour afficher les nuages de " +"points 3D" +msgstr "" + +#: AperoDeDenis.py:9290 +msgid " - Consulter la notice d'installation et de prise en main" +msgstr "" + +#: AperoDeDenis.py:9296 +msgid "Désigner le fichier exiftool (menu paramétrage)." +msgstr "" + +#: AperoDeDenis.py:9301 +msgid "Désigner le fichier convert, ou avconv, d'image Magick" +msgstr "" + +#: AperoDeDenis.py:9301 +msgid "en principe sous micmac\\binaire-aux (menu paramétrage)." +msgstr "" + +#: AperoDeDenis.py:9306 +msgid "" +"Désigner le fichier ffmpeg (possible sous micmac\\binaire-aux (menu " +"paramétrage)." +msgstr "" + +#: AperoDeDenis.py:9335 +msgid "Revenir aux options par défaut d'AperoDeDenis" +msgstr "" + +#: AperoDeDenis.py:9336 AperoDeDenis.py:9354 +msgid "Utiliser les options du chantier en cours" +msgstr "" + +#: AperoDeDenis.py:9337 AperoDeDenis.py:9355 +msgid "Ne rien changer" +msgstr "" + +#: AperoDeDenis.py:9340 +msgid "Options par défaut réinitialisées" +msgstr "" + +#: AperoDeDenis.py:9344 AperoDeDenis.py:9359 +msgid "Les options par défaut seront désormais celles du chantier en cours" +msgstr "" + +#: AperoDeDenis.py:9353 +msgid "" +"Les options par défaut actuelles sont les options par défaut d'AperoDeDenis" +msgstr "" + +#: AperoDeDenis.py:9368 +msgid "" +"Options par défaut non sauvegardées car les options du chantier en cours " +"sont invalides :" +msgstr "" + +#: AperoDeDenis.py:9396 +msgid "erreur sauveOptions : " +msgstr "" + +#: AperoDeDenis.py:9397 +msgid "Erreur rencontrée lors de la sauvegarde des options : " +msgstr "" + +#: AperoDeDenis.py:9428 +msgid "erreur restauration options : " +msgstr "" + +#: AperoDeDenis.py:9467 +msgid "fin normale d'aperodedenis." +msgstr "" + +#: AperoDeDenis.py:9485 +msgid "fonction" +msgstr "" + +#: AperoDeDenis.py:9486 +msgid "valeur en retour : " +msgstr "" + +#: AperoDeDenis.py:9489 +msgid "variable" +msgstr "" + +#: AperoDeDenis.py:9490 +msgid "valeur : " +msgstr "" + +#: AperoDeDenis.py:9491 +#, python-format +msgid "Détail de la %(typeVar)s : %(nomVar)s" +msgstr "" + +#: AperoDeDenis.py:9492 +msgid "Identifiant : " +msgstr "" + +#: AperoDeDenis.py:9493 +msgid "Type : " +msgstr "" + +#: AperoDeDenis.py:9494 +msgid "class = " +msgstr "" + +#: AperoDeDenis.py:9495 +msgid "Les attributs : " +msgstr "" + +#: AperoDeDenis.py:9503 +msgid "Erreur suppression fichier :" +msgstr "" + +#: AperoDeDenis.py:9526 +msgid "erreur ajout : " +msgstr "" + +#: AperoDeDenis.py:9541 +msgid "erreur remove = " +msgstr "" + +#: AperoDeDenis.py:9567 +msgid "erreur zip = " +msgstr "" + +#: AperoDeDenis.py:9599 +#, python-format +msgid "erreur mercurial : %(e)s pour mm3D=%(mm3D)s" +msgstr "" + +#: AperoDeDenis.py:9600 +msgid "pas de version identifiée de MicMac" +msgstr "" + +#: AperoDeDenis.py:9654 +msgid "Nouveau nom pour le chantier : " +msgstr "" + +#: AperoDeDenis.py:9690 +msgid "Console" +msgstr "" + +#: AperoDeDenis.py:9807 +msgid "Question" +msgstr ""