TUTTO

SOMMAIRE


Objectif : Géoréférencer des photographies à partir d'une table de coordonnées CSV.


I. PRÉREQUIS & PRÉPARATION QGIS

Avant de lancer le script, assurez-vous d'avoir installé Visual Studio Code et Python.

1. Préparation des données sur QGIS

Pour faire le lien entre vos clichés et le terrain, suivez ces étapes :

  • Création de la couche : Créez une couche de points (GPKG ou Shapefile) avec les champs : fid, chemin, x, y.
  • Saisie des données : Pointez sur la carte l'emplacement exact de la prise de vue.
  • Champ Chemin : Renseignez le chemin complet du fichier (ex: C:\Photos\P1010.jpg). > Important : Ne pas mettre de guillemets dans les chemins.
  • Calculatrice de champ : Mettez à jour les champs x et y (en Lambert 93 - EPSG:2154).

2. Exportation

Exportez la table attributaire en CSV dans le même dossier que vos photos. * Format : UTF-8. * Séparateur : Point-virgule (;). * Géométrie : Choisissez "Pas de géométrie" lors de l'export.


II. CONFIGURATION DU SCRIPT PYTHON

Ouvrez Visual Studio Code, créez un nouveau fichier .py et collez-y le code ci-dessous.

!!! warning "Attention : Variables à modifier" Vous devez modifier les variables suivantes dans le script : * base_dir : Le dossier racine (ex: 06_prospection). * test_dir : Le sous-dossier contenant les images (ex: Fenioux). * csv_file : Le nom de votre fichier CSV (ex: fenioux.csv).

```python import os import pandas as pd from pyproj import Transformer import piexif from PIL import Image

---- 1. CONFIGURATION DES CHEMINS ----

base_dir = r"C:\photos\06_Prospection" test_dir = os.path.join(base_dir, "Fenioux") csv_file = os.path.join(test_dir, "fenioux.csv")

---- 2. CHARGEMENT ET NETTOYAGE ----

df = pd.read_csv(csv_file, sep=";", encoding="utf-8-sig") df = df.rename(columns=lambda c: c.strip())

---- 3. CONVERSION COORDONNÉES (Lambert93 -> WGS84) ----

transformer = Transformer.from_crs("EPSG:2154", "EPSG:4326", always_xy=True) df["lon"], df["lat"] = transformer.transform(df["x"].values, df["y"].values)

def deg_to_dms_rational(deg): d = int(abs(deg)) m = int((abs(deg) - d) * 60) s = round((abs(deg) - d - m/60) * 3600 * 100) return ((d, 1), (m, 1), (s, 100))

---- 4. TRAITEMENT DES IMAGES ----

output_dir = os.path.join(base_dir, "EXF") os.makedirs(output_dir, exist_ok=True)

for _, row in df.iterrows(): chemin = row["chemin"].strip().replace("\u202a", "") lat, lon = row["lat"], row["lon"]

lat_ref = "N" if lat >= 0 else "S"
lon_ref = "E" if lon >= 0 else "W"

gps_ifd = {
    piexif.GPSIFD.GPSLatitudeRef: lat_ref,
    piexif.GPSIFD.GPSLatitude: deg_to_dms_rational(lat),
    piexif.GPSIFD.GPSLongitudeRef: lon_ref,
    piexif.GPSIFD.GPSLongitude: deg_to_dms_rational(lon),
}

exif_dict = {"GPS": gps_ifd}
exif_bytes = piexif.dump(exif_dict)

try:
    im = Image.open(chemin)
    nom_fichier = os.path.basename(chemin)
    sortie = os.path.join(output_dir, nom_fichier)
    im.save(sortie, exif=exif_bytes)
    print(f"✅ Succès : {nom_fichier}")
except Exception as e:
    print(f"❌ Erreur pour {chemin} : {e}")