IGNF / myria3d

Myria3D: Aerial Lidar HD Semantic Segmentation with Deep Learning
https://ignf.github.io/myria3d/
BSD 3-Clause "New" or "Revised" License
148 stars 19 forks source link

Classification des toits plats #72

Closed KlatbahII closed 11 months ago

KlatbahII commented 1 year ago

Bonjour, Félicitation pour ce framework qui fonctionne très bien et permet d'obtenir une bonne classification du LiDAR.

Nous avons réussi à prédire des dalles de notre LiDAR avec Myria3D.
Les résultats sont très bons, mais il y a un problème qui revient assez fréquemment :
des points qui font partie d'un bâtiment avec un toit plat sont classifiés comme "SOL". Il s'agit souvent d'une forme ronde ou ovale au milieu du toit.

J'avais vu une issue #58 où tu parlais de la possibilité d'augmenter la taille des "tiles" de 50mètres à 100mètres.
Je voulais donc savoir s'il est possible de modifier des paramètres lorsque l'on prédit avec Myria3D afin d'essayer de régler ce problème.

Voici un apercu des problèmes rencontrés: 2 3

J'ai également installé lidar-prod afin d'essayer de régler ce problème. Est-ce que lidar-prod peut régler ce problème de classification des toits plats ? En effet, il est indiqué qu'il permet d'améliorer les résultats de la classification obtenus avec myria3d.
Je n'ai pas réussi à accéder à la BD UNI via les paramètres de connexion que tu indiques. Ne vaudrait-il pas mieux que tu indiques un accès à la BD TOPO car la BD UNI n'est pas censée être publique ?

Notre LiDAR a une résolution de 20pts par m², est-ce que cela peut être la cause de la mauvaise classification des toits plats? Faut il entraîner un nouveau modèle ?

Merci pour ton travail qui est très intéressant et nous a permis de classifier efficacement notre LiDAR

CharlesGaydon commented 1 year ago

Bonjour @KlatbahII, Cette confusion "sol - larges toits plats" est un problème récurrent en segmentation sémantique de lidar aérien. On rencontre le problème sur le Lidar HD IGN (à 10 impulsions / m²) également.

J'avais vu une https://github.com/IGNF/myria3d/issues/58 où tu parlais de la possibilité d'augmenter la taille des "tiles" de 50mètres à 100mètres.

Ca me semble être la bonne première approche. Surtout si ton intérêt est sur le bâti et pas sur les plus petits objets - en effet mon intuition est qu'augmenter la taille de la donnée réduira (très) légèrement la séparation des objets suite aux aléas des samplings dans RandLaNet. J'avais fait de tests qui montrait une (très) légère dégradation des IoU sur certaines classes, maius je n'étais pas allé à l'époque regarder les large bâtiments visuellement. Mais ça pourrait augmenter le champs réceptif et le contexte. Si cela fonctionne, on pourra envisager de documenter cette configuration dans myria3d. Car ça nous intéressera aussi à l'IGN. 🧁

Concernant lidar-prod : l'outil peut servir à valider/réfuter les erreurs d'une première classification "rule based". Ca peut permettre d'identifier pour correction humaine les cas où les probas du modèle ne sont pas claires, mais il faut au préalable avoir trouvé ces bâtiments avec un autre algo donc... Pas évident.

Sur les changements à faire dans lidar-prod (BDUni/BDTopo), est-ce que tu peux ouvrir une issue sur le repo lidar-prod directement, en linkant notre discussion ? Je passe progressivement la main sur la maintenance applicative, donc ce ne sera pas moi qui prendrai cette décision. Lidar-prod est un outil vraiment orienté vers la production IGN, mais la question se pose effectivement. (CC @leavauchier et @gliegard)

KlatbahII commented 1 year ago

Bonjour, merci de ta réponse.
J'avais également observé ce problème avec d'autres framework de classification de LiDAR aérien(KPConv).
Pour notre classification, les 2 classes qui nous intéressent le plus sont:

Du coup j'espère vraiment pouvoir réussir à régler ce problème de toits plats.

Par rapport à la partie "technique" pour la modification des paramètres,
dans l'issue que j'ai lié tu parlais de reconstruire l'image Docker, dans mon cas de figure j'utilise un environnement conda.
J'imagine que je peux donc modifier le fichier de config :

Voici le fichier auquel je fais référence pour les lignes : proto151_V2.0_epoch_100_Myria3DV3.1.0_predict_config_V3.3.0.yaml

#ligne 112
subtile_width: 50
# Modifier à 100 pour avoir des "tuiles" de 100 mètres et essayer de diminuer le problème des toits plats

Voici ce que tu disais dans l'issue ou modifier la taille des tuiles était indiquée

Additionnaly, you will need to increase the aforementionned "point budget" to 4 * 40000 points to have a comparable density.
I think the most convenient way to change those parameters for you would be to use a configuration file (i.e. edit the default config) and 
either rebuild the docker image, or pass the config to the image with keywords --config-path=XXX and config-name=XXX (hydra style).

Dans le fichier config, j'ai trouvé plusieurs mention de cette valeur de 40000

# datamodule:
#   transforms:
#     preparations:
# train:
# ligne 44
        MaximumNumNodes:
          _target_: myria3d.pctl.transforms.transforms.MaximumNumNodes
          _args_:
          - 40000

# datamodule:
#   transforms:
#     preparations:
# eval:
# Ligne 67
        MaximumNumNodes:
          _target_: myria3d.pctl.transforms.transforms.MaximumNumNodes
          _args_:
          - 40000

# datamodule:
#   transforms:
#     preparations:
# predict:
# ligne 91
        MaximumNumNodes:
          _target_: myria3d.pctl.transforms.transforms.MaximumNumNodes
          _args_:
          - 40000

Donc j'imagine qu'il faut modifier la partie predict.
Quelle valeur dois-je rentrer à la place de 40 000 ? 160 000(4 * 40 000)

Par rapport à lidar-prod, pour l'instant j'ai réussi à faire la première étape apply_on_building, et le résultat observé était la création de groupe parmi les points de bâtiments.
Je voulais donc savoir si les autres tâches peuvent modifier la classification des bâtiments.
Et pas de souci pour la création des issues sur le repo lidar-prod.

Merci beaucoup de ta réponse rapide, et les résultats que l'on a obtenu avec Myria3D sont très satisfaisants

CharlesGaydon commented 1 year ago

C'est exactement ça ! La valeur 40000 est là pour des questions de mémoire, car on veut contrôler la taille total d'un batch de données pour éviter un crash. 160000 est la valeur cohérente car on multiplie par quatre la surface. Tu peux également mettre une valeur très haute pour garder tous les points en inférence.

Pour lidar-prod : les groupes créés correspondent au résultat de la partie Building Identification. Les autres tâches peuvent modifier une classification déjà existante du bâti. On appelle ça les "candidats bâti" (le code de classification est paramétrable dans la config ici) Typiquement une classification basée sur des règles qui aurait détecté les surfaces planes, etc. Et qu'on veut améliorer/corriger avec le modèle d'IA.

Merci beaucoup de ta réponse rapide, et les résultats que l'on a obtenu avec Myria3D sont très satisfaisants

Cheers !

KlatbahII commented 1 year ago

Merci pour ta réponse, j'ai pu tester en modifiant les variables dont on avait parlé :

# subtile_width: 50
subtile_width: 100

# predict:
# ligne 91
MaximumNumNodes:
  _target_: myria3d.pctl.transforms.transforms.MaximumNumNodes
  _args_:
  # - 40000
  - 160000

En mettant ces paramètres, et en lancant la prédiction sur 2 sous-dalles, les zones de SOL dans les toits plats a diminué pour les très grand bâtiments, mais cela a impacté la classification précédente.

C'est sur cette dalle que les résultats sont le plus visible selon moi.
La première image correspond à la dalle prédite avec les paramètres de base.
1_base
La deuxième image correspond à la même dalle avec une taille de tuile de 100 mètres et une valeur de 160 000. 1_160

Il y a une amélioration même si le problème persiste avec des fausses valeurs de SOL dans les bâtiments à toit plats.

Voici la 2ème sous-dalle que j'ai classifié.
La 1ère image est avec les réglages de base, et la 2ème avec une taille de tuile de 100 mètres et une valeur de 160 000. 2_base
2_160

Dans la deuxième la taille des toits plats et plus petit et j'ai l'impression que cela impacte plus l'ancienne classification(avec les réglages de base).Il y a une amélioration, mais il y a toujours des problèmes.

Par rapport à lidar-prod, est ce que des dalles LiDAR "brutes" prédites avec myria3D peuvent être envoyé dans lidar-prod afin d'en améliorer la classification ? Et si oui quelle est l'ordre des étapes à suivre ?

Quand tu dis

Typiquement une classification basée sur des règles qui aurait détecté les surfaces planes, etc. Et qu'on veut 
améliorer/corriger avec le modèle d'IA

Est ce que cela veut dire qu'il faudrait rajouter de nouveaux Scalar Fields(dimensions) avec ce type d'information ? Parce que dans mes recherches précédentes, j'avais trouvé un algorithme qui permettait assez facilement et rapidement de détecter des surfaces planes. Si on l'utilise sur une sortie de myria3d en excluant la végétation(par exemple), je pense qu'il serait possible d'obtenir les surfaces planes(telles qu'on peut les obtenir avec un algorithme RANSAC par exemple).

Pour résumer, j'espère qu'avec une dalle prédite avec myria3d il est possible d'aller jusqu'au bout du process de lidar-prod afin de voir les résultats que l'on peut obtenir, si cela est possible bien entendu.

Merci encore

CharlesGaydon commented 1 year ago

Très intéressant, merci pour ces retours d'expérience. Dans le premier cas l'amélioration est nette. Dans la deuxième sous-dalle on voit des amélioration mais aussi une régression (bâtiment au milieu à droite). Mais dans l'ensemble on place en bâti plus de points, ce qui est positif. Tu mentionnes :

mais cela a impacté la classification précédente.

Est-ce tu peux élaborer ?


Typiquement une classification basée sur des règles qui aurait détecté les surfaces planes, etc. 
Et qu'on veut améliorer/corriger avec le modèle d'IA

En effet : Myria3D+lidar-prod ne sont pas conçu pour fonctionner à deux seulement. Il manque une troisième brique, qui doit avoir une bonne "régularité géométrique" (i.e. pas de trous dans les plans). Un algo de détection de large plans peut être une bonne option pour identifier les toits. Et ensuite Myria3D fournit des probas de bâti. Et enfin lidar-prod, pour chaque plan / composante connexe de points "candidats bâtis", va valider ou réfuter (ou dire qu'il ne sait pas) en utilisant les probas bâti de myria3d et la BDUni(/BDOrtho). Lidar-prod attend un code "candidats bati" (dans ton cas : qui correspondrait aux grands plans de grands bâtiments) dans le canal Classification. Ce code est 202 par défaut, cf. la configuration par défaut.

image

CharlesGaydon commented 1 year ago

@KlatbahII : dans l'issue que tu mentionnes, j'avais en fait oublié qu'un paramètre important est également à modifier. Désolé du contre-temps.

Cela peut avoir un impact sur la qualité générale des résultats, pour les grands bâtiments et pour les autres objets. Je te laisse regarder le commentaire en question : https://github.com/IGNF/myria3d/issues/58#issuecomment-1543573629

KlatbahII commented 1 year ago

Merci pour tes 2 réponses,

Quand je disais

mais cela a impacté la classification précédente

Je parlais de la classification obtenue avant de modifier les paramètres subtile_width et myria3d.pctl.transforms.transforms.MaximumNumNodes de 40 000 à 160 000.

Test NormalizePos.subtile_width=50

J'ai pu tester le paramètre que tu mentionnes dans ta dernière réponse: datamodule.transforms.normalizations.NormalizePos.subtile_width=50.
Afin de voir les différences j'ai utilisé 3 configurations différentes: La configuration de base

La configuration avec des sous-tuiles avec une largeur de 100 et 160 000 points

La configuration précédente avec le nouveau paramètre que tu as mentionné

Et malgré ces configurations différentes, il y a n'a pas de configuration qui améliore les résultats.
En effet, dans les essais avec une taille de tuile de 100 mètres, les grands toits plats sont mieux classifiés, mais c'est la classification des bâtiments plus petits qui est "dégradée" par rapport à des essais avec une taille de tuile de 50 mètres(réglagles de base).
Le paramètre que tu mentionnais dans l'autre issue n'a pas arrangé les résultats.

Recherche création "Troisième brique"

Pour la "3ème brique" dont tu parlais

une troisième brique, qui doit avoir une bonne "régularité géométrique" (i.e. pas de trous dans les plans). Un algo de détection de large plans peut être une bonne option pour identifier les toits

J'ai commencé à chercher des solutions de mon côté, et il y a une dimension du LiDAR qui est au coeur des 2 pistes les plus prometteuses: HeightAboveGround.

Création Dimension HeightAbove Ground

Dans mon cas de figure, le LiDAR que j'utilise a une classification de base très sommaire:

Cela me permet de générer un raster MNT(Modèle Numérique de Terrain) en utilisant uniquement les points du sol(2), et en interpolant les zones vides(sans points) avec PDAL.
La fonctionnalité PDAL filters.hag_dem permet d'obtenir la dimension HeightAboveGround en utilisant le raster MNT.
Il est également possible d'utiliser seulement le LiDAR pour générer HeightAboveGround avec la fonctionnalité PDAL filters.hag_nn.Il faut cependant avoir des points avec une valeur de 2 dans la dimension Classification.
Dans le cas du LiDAR HD, ou il me semble qu'il n'y a pas de classification SOL-SURSOL, il y a des outils permettant de réaliser cette classification:

1ère piste : Détection de larges plans

Voici les résultats de l'algorithme dont je te parlais qui permet de détecter les plans des toits. Dans ces exemples, j'ai isolé des bâtiments afin que le rendu soit plus visible.

toits_plats
J'ai également testé avec des bâtiments avec de grands toits plats, et les plans sont bien déterminés

Je pense que cette détection des plans pourrait faire office de 3ème brique.
J'ai pensé à une implémentation possible:

Je n'ai pas encore testé cette possibilité, mais il me semble que cela pourrait être intéressant.
De plus, cet algorithme n'a pas de problèmes pour les bâtiments de grande tailles avec un toit plat.

2ème piste : Détection des points de sol avec une valeur élevée dans le Dimension HeightAboveGound

Malgré le fait qu'elle soit très simple,c'est cette piste qui m'a permis d'obtenir les meilleurs résultats et d'identifier assez facilement tout les points de bâtiments à toit plats classifiés en SOL.
Je modifie les valeurs de la dimension UserData afin d'isoler les points dont la classification pose problème(toits plats).
L'idée ici est d'assigner une valeur de 6 pour les points qui ont une valeur de 2 dans la dimension confidence et une valeur de HeightAboveGround supérieure à 3mètres Voici les différentes étapes réalisées:

L'idée ici est de modifier la valeur d'UserData en 6.
Cela me permet ensuite de modifier la dimension confidence, afin de reclasser ces points en bâti.(cette étape est pour mon process vu que je n'ai pas réussi à faire fonctionner lidar-prod).

Voici les 4 dimensions utilisées dans ce process:

4_dimensions
confidence, HeightAboveGround, UserData, Classification(avec la valeur 202 )

J'ai ensuite essayé de lancer lidar-prod avec les candidats bâti à 202 et cela ne permet pas de régler les problèmes de toits plats.
J'avais obtenu les mêmes résultats que précédemment, ou les toits plats ne sont pas "complétés" par lidar-prod.
Du coup on va utiliser cette 2ème piste qui nous permet de régler ce problème.
Si cela t'intéresse je pourrais te passer les JSON PDAL que j'utilise.

Merci encore pour myria3d qui nous a permis d'obtenir de très bons résultats.

CharlesGaydon commented 1 year ago

Merci @KlatbahII d'avoir pris le temps de faire ce partage d'expérience détaillé. Ca a une valeur immense pour nous. D'une part ton évaluation illustrée de l'effet du changement de champs réceptif nous conforte dans le choix du processus d'inférence actuel à 50mx50m. D'autre part le processus que tu propose semble robuste et simple à mettre en place. J'en ferai part à nos équipes. Je suis preneur des json PDAL (tu peux les attacher directement dans cette issue), merci. :)

Je suis ravi que Myria3D vous permettent d'obtenir des résultats satisfaisants ! 😃 Est-ce que tu pourrais m'en dire un peu plus sur ton cas d'usage / l'organisme auquel tu te rattache ? J'essaye de me rendre compte des contributeurs pour valoriser Myria3D en interne et s'assurer de la pérennisation de sa maintenance applicative :). On compte également améliorer les modèles dans les mois à venir.

CharlesGaydon commented 1 year ago

Je vais essayer de faire une synthèse dans ce message, que je peux mettre à jour en fonction de tes retours :

Champs réceptif à 100mx100m

Correction ciblée des toit larges détectés en sol par Myria3D

CharlesGaydon commented 1 year ago

Sur une dernière note :

J'ai ensuite essayé de lancer lidar-prod avec les candidats bâti à 202 et cela ne permet pas de régler les problèmes de toits plats. J'avais obtenu les mêmes résultats que précédemment, ou les toits plats ne sont pas "complétés" par lidar-prod.

Si les points "candidats bati" incluent l'ensemble des points des bâtiments larges, alors lidar-prod devrait être capable de les valider, ou a minima de les classer en "incertain". lidar-prod ne gère pas forcément parfaitement les "trous dans le bâti", mais on s'attend en tout cas à ce que les points candidats appartenant à la même composante connexe soient traités ensemble, donc ça me surprend que tu mentionnes des toits "non complétés".

KlatbahII commented 1 year ago

Bonjour, merci de tes réponses. Par rapport à ton message de synthèse, j'ai quelques informations supplémentaires par rapport au process que l'on emploie Post-myria3d.

Voici l'ensemble du JSON pipeline que j'utilise.
Les PATH ne correspondent à rien, et sont juste la pour indiquer le type de fichier utilisés.
Je mets des commentaires dans le JSON afin d'expliquer le process

[
    // Chargement du .laz
    {
        "type":"readers.las",
        "filename":"../../dalle_predite_myria3d.laz",
        "override_srs":"EPSG:3943",
        "nosrs":"true"
    },
    // Ajout Dimension HeightAboveGround
    {
        "type":"filters.hag_dem",
        "raster":"../../raster_mnt.tif"
    },
    // Création d'une nouvelle dimension "Voirie"(elle ne contient que des 0)
    {
        "type":"filters.ferry",
        "dimensions":"UserData => Voirie"
    },
    // Les routes du Shapefile ont un champ CLS avec une valeur de 1
    // même principe que ton champ PRESENCE pour la couche issue de la BD UNI
    // On définit une valeur de 1 dans la dimension Voirie pour les points qui intersectent les entités du Shapefile
    {
        "type":"filters.overlay",
        "column": "CLS",
        "datasource":"../../routes_zone_etude.shp",
        "dimension":"Voirie"
    },
    // On modifie les valeurs des points à re-classer dans la dimension UserData

    // 1(NonAttribué): confidence sol ou bâti et HeightAboveGround > 3 && Voirie = 1
    //      Il s'agit des points "fantômes" mal classifiés sur des bus/camions   

    // 6(Bâtiment): confidence sol et HeightAboveGround > 0 && Voirie = 0
    //      Il s'agit des points des toits plats classifiés en sol
    {
        "type":"filters.assign",
        "value": 
        [
            "UserData = 1 where (confidence == 6 || confidence == 2) && HeightAboveGround > 3 && Voirie == 1",
            "UserData = 6 where confidence == 2 && HeightAboveGround > 3 && Voirie == 0 "
        ]
    },
    // On enregistre la dalle avec toutes ces modifications
    {
        "type": "writers.las",
        "a_srs":"EPSG:3943",
        "compression": "true",
        "minor_version": "4",
        "extra_dims":"all",
        "filename":"../../dalle_post_myria3d.laz"
    }
]

Je te joins également ce fichier JSON dans la discussion(au format .txt).
process.txt

Problèmes points "fantômes" voirie : Bus/Camion

Il y a des étapes supplémentaires qui sont dues à un problème que l'on a constaté et qui est selon moi dû à la colorisation du LiDAR.
Il s'agit de points "fantômes", principalement des bus ou des camions qui ont la couleur de la route.
Sur l'image ci-dessous, dans la première figure(le LiDAR RGB), le camion blanc au milieu de la route ne correspond qu'à des points du sol(il n'y a pas de camion à cet endroit).

affichage_fantomes
LiDAR RGB, confidence, UserData, shapefiles dans QGIS

Dans la 2ème figure confidence les zones dans les rectangles jaunes correspondent à ces bus/camions qui ont mal été classifiés(sol ou bâti).
C'est ces zones la qu'il faut "reclassifier".
Et dans la 3ème figure UserData, les zones de couleur violet correspondent à ces points que l'on réussit à isoler.
Le rouge correspond aux points de bâtiments mal classifiés en sol(toits plats).
La 4ème figure est une vue de la zone d'étude dans QGIS(on génére des rasters du LiDAR que l'on polygonize afin de pouvoir vérifier rapidement d'éventuels problèmes de classification dans QGIS).

Utilisation couche Voirie

Afin de pouvoir identifier ces points fantômes, situés sur la voirie, on utilise un shapefile qui contient les routes de notre zone d'étude.
Les routes ne correspondent pas parfaitement à la réalité du terrain, mais cela nous permet d'en régler une grosse quantité.

shapefile_voirie
Affichage du shapefile des routes dans QGIS, il s'agit d'une autre dalle LiDAR

Cette couche va nous permettre de repérer ces points fantômes ainsi que de confirmer les points dans les toits plats.

Modification des valeurs de Classification : 202 pour les candidats bâtis

J'ai ensuite filtré les points qui ont une valeur de 6(Bâtiment) dans les dimensions UserData ou confidence(Cela permet d'obtenir des faux positifs comme tu disais précédemment) et avec FME je leur donne une valeur de 202

classification_202
Tout les points "candidats bâti" ont une valeur de 202 dans la dimension Classification

Test de lidar-prod

Avec ce LiDAR ayant une valeur de 202 dans le canal Classification pour les "candidats bâti", je lance lidar-prod depuis l'image docker, en utilisant un shapefile issu de la BDTopo correspondant à l'emprise de la dalle LiDAR.

qgis_bati_shp
Affichage des bâtis issu de la BD Topo dans QGIS

Dans la ligne de commande le paramètre building_validation.application.shp_path permet de chercher le shapefile qui se trouve dans le dossier inputs du container Voici la ligne de commande utilisée pour lancer lidar-prod.

sudo docker run \
    -v /home/smig/Documents/lidar/myria/documentation/Classification_202_lidar-prod/Classification_202/laz_hag/conditions:/inputs/ \
    -v /home/smig/Documents/lidar/myria/documentation/Classification_202_lidar-prod/Classification_202/laz_hag/conditions/output:/outputs/ \
    lidar_prod \
    python lidar_prod/run.py \
    paths.src_las=/inputs \
    building_validation.application.shp_path=/inputs/ \
    paths.output_dir=/outputs

Et voici le résultat obtenu

(base) smig@krakenito:~/Bureau$ sudo docker run     -v /home/smig/Documents/lidar/myria/documentation/Classification_202_lidar-prod/Classification_202/laz_hag/conditions:/inputs/     -v /home/smig/Documents/lidar/myria/documentation/Classification_202_lidar-prod/Classification_202/laz_hag/conditions/output:/outputs/     lidar_prod     python lidar_prod/run.py     paths.src_las=/inputs     building_validation.application.shp_path=/inputs/     paths.output_dir=/outputs
[2023-05-12 08:14:08,206][matplotlib.font_manager][INFO] - generated new fontManager
[2023-05-12 08:14:08,414][__main__][INFO] - Starting applying the default process
[2023-05-12 08:14:08,415][lidar_prod.application][INFO] - Processing /inputs/1562000_2267500_hag_modif_sol_202_conditions.laz
[2023-05-12 08:14:39,445][lidar_prod.tasks.cleaning][INFO] - Saved to /tmp/tmp64f5hphb/1562000_2267500_hag_modif_sol_202_conditions.laz
[2023-05-12 08:14:48,482][lidar_prod.tasks.building_validation][INFO] - Preparation : Clustering of candidates buildings & Import vectors
[2023-05-12 08:14:48,483][lidar_prod.tasks.building_validation][INFO] - Applying Building Validation to file 
/tmp/tmp64f5hphb/1562000_2267500_hag_modif_sol_202_conditions.laz
[2023-05-12 08:15:07,590][lidar_prod.tasks.building_validation][INFO] - Read shapefile
 /inputs/
[2023-05-12 08:15:27,476][lidar_prod.tasks.building_validation][INFO] - Using AI and Databases to update cloud Classification
Update cluster classification: 0clusters [00:00, ?clusters/s]
[2023-05-12 08:15:30,240][lidar_prod.tasks.building_completion][INFO] - Completion of building with relatively distant points that have high enough probability
Complete buildings with isolated points: 100%|██████████| 503/503 [00:00<00:00, 9711.63grp/s]
[2023-05-12 08:15:41,933][lidar_prod.tasks.building_identification][INFO] - Clustering of points with high building proba.
[2023-05-12 08:16:32,918][lidar_prod.tasks.cleaning][INFO] - Saved to /outputs/1562000_2267500_hag_modif_sol_202_conditions.laz
[2023-05-12 08:16:32,965][lidar_prod.commons.commons][INFO] - Processing time of apply_building_module: 144.55s
[2023-05-12 08:16:32,965][lidar_prod.commons.commons][INFO] - Processing time of apply: 144.55s

J'ai testé avec 2 versions différentes dans la dimension Classification. Le formes blanches affichées sont les entités du Shapefile issu de la BdTOPO.

1er essai

cc_conditions
Je n'ai mis en 202 que les points mal classifié dans les toits plats

2ème essai

cc_myria_conditions
J'ai mis en 202 tout les points liés au bâti

Résultat

Avec ces couches bien que différentes dans les points ayant une valeur de 202, j'obtiens les mêmes résultats en sortie de lidar-prod pour ces 2 lidar.

cc_output_group
L'affichage de la dimension Group

Est ce que cela est du aux valeurs présentes dans la dimension building ?

building
Il y a des valeurs très faible dans la dimension building pour les toits plats

Merci encore

CharlesGaydon commented 1 year ago

A nouveau, merci @KlatbahII pour ton travail de formalisation et de partage. Tes expérimentations sont très claires, et j'ai actualisé mon message de synthèse en conséquence. :)

L'approche me paraît bonne pour gérer les cas des bus/camions.

Usage de lidar-prod

Donc en conclusion : je m'attends à ce que le canal Classification du deuxième essai soit en fait pas mal du tout ! Mais pas de miracle non plus sur les grands batis : le mieux qu'on peut espérer considérant les probas faibles c'est qu'ils finissent en "bâti incertain" grâce à la BDTopo :)

CharlesGaydon commented 1 year ago

(Pour info: je regarde généralement les issues de Myria3D qui sont de mon ressort le jeudi matin.)

KlatbahII commented 1 year ago

Petit retour, en effet il fallait regarder dans la dimension Classification.
En regardant les 2 dalles différentes je vois qu'il y a une grande différence entre les 2.
Dans la dimension Classification, la valeur maximum est de 10 pour les 2 dalles.

Par rapport à ce que tu disais:

Donc en conclusion : je m'attends à ce que le canal Classification du deuxième essai soit en fait pas mal du tout ! Mais pas de miracle non plus sur les grands batis : le mieux qu'on peut espérer considérant les probas faibles c'est qu'ils finissent en "bâti incertain" grâce à la BDTopo :)

1er essai

Dans cette version ou je n'avais mis que les points des toits plats classifiés en sol, ils ont tous une valeur de 10 dans la dimension Classification

conditions
Affichage de la dimension Classification pour la dalle ou je n'ai mis que les points mal classifiés dans les toits plats

2ème essai

Comme tu l'avais annoncé, les résultats sont vraiment satisfaisants ici.

myria_conditions
Affichage de la dimension Classification pour la dalle qui contient tout les "candidats bâti"

Résumé

La version avec tout les candidats bâti a grandement amélioré les résultats.
Cependant, je ne comprends pas le sens de la valeur 10 dans la dimension Classification pour les points que j'ai placé dans les "candidats bâti"(j'ai cette valeur dans les 2 dalles).
A noter, il y a également des points avec des valeurs 1 et 2 dans la dimension Classification, qui semblent correspondre aux points NonClassifiés et du Sol

valeur_classification
Ici j'affiche la dalle avec tout les candidats bâti, dans l'autre dalle la valeur est également de 10

Le process de détection des toits plats avec ma pipeline PDAL et lidar-prod en suivant permet d'identifier quasiment tout les bâtiments.
Il suffit de comparer avec les images des messages précédents pour constater la différence.
Je pense que j'implémenterais donc lidar-prod dans mon process après les JSON pour corrections des points des toits plats et détection des fantômes.

Merci encore

CharlesGaydon commented 1 year ago

La classification du deuxième essai est vraiment bien, les toits sont parfait dans la dimension Classification avec une valeur de 10

Super nouvelle déjà ! Je ne vois pas forcément lesquelles images comparer dans les messages précédents, mais je te fais confiance sur cette observation. :)

Je suis aussi surpris que toi : le code 10 ne correspond à rien dans lidar-prod, ni dans myria3d.

C'est peut-être un soucis lié au format LAS lui-même : certaines valeurs de Classification sont parfois écretées suivant le format choisis...

Donc : lidar-prod est censé prendre les candidats batis (code 202) et les reclasser en bati 6 (confirmation) / pas-bâti 208 (réfutation) / incertain (208). Les codes sont listés dans la configuration par défaut.

Dans lidar-prod, le format de sortie du LAS est compatible avec des codes élevés, cf. la fonction d'écriture get_pdal_writer:

def get_pdal_writer(target_las_path: str, extra_dims: str = "all") -> pdal.Writer.las:
    """Standard LAS Writer which imposes LAS 1.4 specification and dataformat 8.

    Args:
        target_las_path (str): output LAS path to write.
        extra_dims (str): extra dimensions to keep, in the format expected by pdal.Writer.las.

    Returns:
        pdal.Writer.las: writer to use in a pipeline.

    """
    return pdal.Writer.las(
        filename=target_las_path,
        minor_version=4,
        dataformat_id=8,
        forward="all",
        extra_dims=extra_dims,
    )
CharlesGaydon commented 1 year ago

Tant qu'on est sur le sujet des lectures/écritures : je remarque au passage tes pipeline n'écrivent pas les fichiers en en Lambert93. Actuellement, l'EPSG:2154 est codé en dur dans lidar-prod. Je suppose que ça peut poser soucis pour le croisement avec les shapefiles de bâti BD Topo...

cf. dans lidar-prod la fonction de lecture : get_pdal_reader :

def get_pdal_reader(las_path: str) -> pdal.Reader.las:
    """Standard Reader which imposes Lamber 93 SRS.

    Args:
        las_path (str): input LAS path to read.

    Returns:
        pdal.Reader.las: reader to use in a pipeline.

    """
    return pdal.Reader.las(
        filename=las_path,
        nosrs=True,
        override_srs="EPSG:2154",
    )

Deux options ici je suppose :

CharlesGaydon commented 1 year ago

Petit update sur le sujet des codes de classification qui seraient écrétés : on rencontre ce type de soucis lors d'une lecture avec laspy d'un LAS non produit par l'IGN, pour lequel le canal Classification est lu en 5 bits (cf. le Header laspy du fichier, qui indique une valeur maximale de 31 pour ce canal).

On m'informe que la valeur 202 se code 11001010 et que 10 se code 1010. Là réside peut-être l'explication.

On regarde de notre côté. :)

KlatbahII commented 1 year ago

Par rapport au fichier .laz que l'on utilise, lorsque j'ai créé les points avec une valeur de 202 j'ai du le faire avec FME parce qu'avec PDAL cela ne fonctionnait pas.Il m'indiquait que la valeur était trop élevée et qu'il la modifiait en 1. Je pourrais retrouver le message d'erreur si cela t'intéresse.

Peut-être que ce problème à écrire ces valeurs élevées avec PDAL explique les problèmes d'écriture de 202 ou une valeur plus élevée(206 ou 208 dont tu parlais précédemment pas bâti/incertain).
Pour revenir sur les résultats que j'avais obtenu, tout les points de "candidats bâti" avaient une valeur de 10.

Je vais ré-essayer d'utiliser lidar-prod avec une dalle LiDAR en Lambert93(EPSG:2154).
J'utiliserais également un shapefile en Lambert93(EPSG:2154).

Par rapport aux options de gestions d'autres SRC, j'ai bien envie de voir la direction que vous allez prendre à ce sujet.

Quand tu dis

laspy d'un LAS non produit par l'IGN, pour lequel le canal Classification est lu en 5 bits (cf. le Header laspy du fichier, qui indique une valeur maximale de 31 pour ce canal).

Est ce que tu pourrais me mettre un petit bout de code, comment récupérer ces informations ? notamment le Header laspy. Afin de vérifier si le canal Classification de mon LiDAR a bien une valeur maximale de 31.

Je vais regarder de mon côté pour les valeurs de la dimension Classification, je pense que cela peut venir de la version du LiDAR. Je te tiens au courant

leavauchier commented 1 year ago

Bonjour, concernant le problème d'encodage des grandes valeurs de classification, j'ai trouvé une piste dans la spécification du las 1.4 (https://www.asprs.org/wp-content/uploads/2019/07/LAS_1_4_r15.pdf) Les valeurs que peut prendre la classification dépendent du Point Data Record Format (dataformat_id dans PDAL) :

Le writer LAS de PDAL écrit par défaut en las 1.2 et dans le record format 3, je pense que c'est pour ça que ça n'a pas fonctionné avec PDAL, mais je pense qu'en choisissant un record format >= 6 ça devrait fonctionner

Pour vérfier quelle valeur est utilisée, ceci devrait marcher : pdal info --metadata my_file.laz | grep dataformat_id

CharlesGaydon commented 1 year ago

Ok, merci pour toutes ces infos, j'ai l'impression qu'on commence à converger vers une résolution ! @KlatbahII :

CharlesGaydon commented 11 months ago

Je ferme. N'hésite pas à rouvrir l'issue si besoin.