Table des matières

IGN BdOrtho

Des versions de la BdOrtho sont accessibles en TMS via https://data.geopf.fr/tms/1.0.0/

Il y a aussi des version à télécharger sur https://geoservices.ign.fr/telechargement-api/BDORTHO

Indre-et-Loire (37)

Outils

P'tit script Python pour découper les JP2 en JPG 640 pixels pour Yolo:

"""
 
Installation:
pip install rasterio pillow numpy tqdm
 
"""
import rasterio
import os
import glob
import shutil
from rasterio.windows import Window
from PIL import Image
import numpy as np
from tqdm import tqdm
from concurrent.futures import ThreadPoolExecutor, as_completed
 
def decouper_fichier_jp2(fichier, dossier_sortie, taille=640):
    nom_base = os.path.splitext(os.path.basename(fichier))[0]
    sous_dossier = os.path.join(dossier_sortie, nom_base)
    os.makedirs(sous_dossier, exist_ok=True)
    # Copie du fichier .tab correspondant
    fichier_tab = fichier.replace('.jp2', '.tab')
    if os.path.exists(fichier_tab):
        shutil.copy(fichier_tab, os.path.join(sous_dossier, f"{nom_base}.tab"))
    # Découpe le fichier JP2 en tuiles JPG
    with rasterio.open(fichier) as src:
        h, w = src.shape
        nb_tuiles_h = h // taille
        nb_tuiles_w = w // taille
        total_tuiles = nb_tuiles_h * nb_tuiles_w
        # réserve un buffer pour limiter une allocation à chaque tuile.
        buffer = np.empty((src.count, taille, taille), dtype=np.uint8)
        with tqdm(total=total_tuiles, desc=f"Traitement de {nom_base}") as pbar:
            for y in range(0, h, taille):
                for x in range(0, w, taille):
                    window = Window(x, y, taille, taille)
                    if y + taille <= h and x + taille <= w:
                        tile = src.read(window=window, out=buffer)
                        tile_rgb = np.moveaxis(tile, 0, -1).astype(np.uint8)
                        img = Image.fromarray(tile_rgb)
                        img.save(f"{sous_dossier}/{nom_base}_x{x}_y{y}.jpg")
                        pbar.update(1)
 
def decouper_jp2_en_tuiles_parallele(dossier_entree, dossier_sortie, taille=640, nb_threads=4):
    os.makedirs(dossier_sortie, exist_ok=True)
    fichiers = glob.glob(os.path.join(dossier_entree, "*.jp2"))
    #fichiers = glob.glob(os.path.join(dossier_entree, "37-2025-0505-6715-LA93-0M20-E080.jp2"))
    with ThreadPoolExecutor(max_workers=nb_threads) as executor:
        futures = [executor.submit(decouper_fichier_jp2, fichier, dossier_sortie, taille) for fichier in fichiers]
        for future in as_completed(futures):
            future.result()  # Attend la fin de chaque tâche
 
if __name__ == "__main__":
 
    decouper_jp2_en_tuiles_parallele(
        "BDORTHO_2-0_RVB-0M20_JP2-E080_LAMB93_D003_2025-01-01/ORTHOHR/1_DONNEES_LIVRAISON_2026-01-00061/OHR_RVB_0M20_JP2-E080_LAMB93_D03-2025/",
        "BDORTHO_tuiles-640_03/",
        nb_threads=4,
    )