Aller au contenu

Contribution Mapillary et retour d'expérience#

📆 Date de publication initiale : 09 décembre 2022

Prérequis#

Matériel#

  • GoPro Max
  • Support ventouse

Application#

Intro#

Mapillary

Cet article s'inscrit dans la continuité de l'article que j'avais intitulé accéder aux données Mapillary et les intégrer dans son SIG. En effet, au moment où celui-ci avait été rédigé, je n'étais pas encore équipé pour réaliser des vues immersives. C'est maintenant chose faite et je vous propose un retour d'expérience qui je l'espère permettra d'alimenter discussions et réflexions sur le sujet.

Commenter cet article


Le matériel#

Le point de départ#

logo GoPro

J'interviens dans une petite Communauté de Communes et comme chacun le sait nos finances sont particulièrement contraintes. L'idée n'était donc pas de réinventer la poudre mais de s'appuyer sur des solutions éprouvées et mises en place dans différentes structures comme la CA du Grand Montauban ou l'Agglomération Val Parisis. Je suis donc parti sur :

  • une GoPro Max 360° livrée avec une batterie et une carte mémoire carte SD de 64 Go : environ 430 €
  • un support triple ventouse Ram Mount (ref. RAP-B-365-224-202AU) : environ 90€
  • un adpatateur GoPro à visser : environ 3€

Configuration initiale

Une erreur qui aurait pu me coûter une GoPro#

J'avais acheté un adapteur GoPro en plastique à 3€ pour limiter les coûts mais cette "chinoiserie" a bien failli me coûter la caméra !

En effet, le lendemain de ma première matinée de test, la caméra était posée sur le bureau quand sans action extérieure, elle s'est retrouvée sans prévenir sur le sol, gloups ! L'adapteur en plastique avait complètement explosé.

Configuration cassée

Un défaut de fabrication, la pièce trop serrée,... je ne sais pas mais toujours est-il que ça m'a bien refroidi !

Après avoir partagé ma mésaventure sur Twitter, Stéphane Péneau de Carto'Cité me conseille d'acheter un adaptateur Ram Mount (ref. RAP-B-202U-GOP1), certes plus cher mais aussi d'une tout autre qualité et 100% compatible avec le support triple ventouse du même fabriquant.

Configuration finale

Sécuriser le système#

Et pour sécuriser encore un peu plus un éventuel décrochement, j'ai ajouté deux éléments "basiques" pour assurer la caméra et me rassurer :

  1. une ficelle et un mousqueton que j'ai fixés au support triple ventouse et que je viens attacher à l'intérieur de l'habitacle (poignée ou pare soleil suivant les véhicules).
  2. un bas de ligne acier (normalement utilisé pour la pêche au carnassier) pour relier cette ficelle à la GoPro pour ne pas la perdre en cas de détachement éventuel ou de rupture de l'adaptateur.

L'autonomie#

Avec une batterie neuve, on arrive à faire une demi-journée de prises de vue. Si on veut aller plus loin, il faut faire l'acquisition de plusieurs batteries et d'un chargeur multiple.


Prises de vue#

Configuration#

La caméra installée et démarrée, j'utilise l'application GoPro Quik et la connexion bluetooth pour lancer ou stopper les prises de vue tout en étant dans la voiture.

GoPro Quik

A noter que pour bénéficier de l'aperçu en direct et la visualisation des médias, vous devrez basculer sur une connexion Wi-Fi entre la caméra et votre mobile.

Info

La connexion bluetooth consomme moins d'énergie que la connexion Wi-Fi.

L'intervalle#

La GoPro est paramétrée pour prendre des prises de vue 360° avec un intervalle de deux secondes (intervalle minimum avec cette caméra) ce qui représente pour vous donner un ordre d'idée, une distance de :

  • 17 mètres à 30km/h
  • 28 mètres à 50km/h

Dans les secteurs urbains assez denses, il est nécessaire de limiter sa vitesse pour obtenir une bonne densité d'images.

Une équipe de photographes#

Les prises de vue sont réalisées par :

  • notre équipe de gardes champêtres/ASVP qui sont en permanence sur le terrain et que j'oriente pour capter certaines "zones blanches",
  • moi-même lors de mes déplacements sur le territoire (réunions, formations, collectes,...).

Quelques chiffres#

La caméra a été réceptionnée début août et après la phase de test, nous avons réalisé des prises de vue de manière aléatoire en terme de durée et ce jusqu'à fin septembre. A ce jour, nous avons publié un peu plus de 14000 images et parcouru près de 160km.

Ce qui représente autour de 40Go en terme de stockage des fichiers bruts.

Voir nos prises de vue

Conditions#

A partir du mois d'octobre, le soleil étant plus bas et la luminosité plus faible, les images sont "moins nettes" et le soleil peut plus facilement éblouir le capteur. Nous avons donc décidé de stopper la campagne de prises de vue jusqu'au printemps privilégiant la qualité des prises de vue à la quantité.


Traitement des photos#

Processus global#

Le processus que je vous présente mélange du bash, de l'OGR, du SQL et du python.

flowchart TD;
    A[Photo 360]
    A --> |exiftool|R{Extraction de la<br>localisation des img}
    R --> |ogr/sql|B{Suppression des<br>images inutiles}
    B --> |nadir-patcher.py| C{Ajout du logo}
    C --> E(Mapillary Desktop)
    E --> |Publication| F(Mapillary)

Un environnement de travail : config.env#

Avant de se lancer, il est bon de paramétrer le fichier de configuration que vous devrez adapter à votre organisation et qui sera utilisé pour traiter les photos. On y définit le répertoire de travail et différentes variables nécessaires à la bonne éxécution du script.

Voici le fichier config.env à adapter :

Environnement de travail
1
2
3
4
5
6
7
8
# REPERTOIRE DE TRAVAIL
REPER='/mapillary_traitement_images'

# REPERTOIRE DE STOCKAGE DES LOGS
REPER_LOGS='logs'

# PARAMETRES OGR
ENCODAGE='UTF-8'

Consulter le fichier de configuration

Nettoyer les photos "inutiles"#

Après mes premiers tests, lorsque je chargeais mes photos dans l'application Mapillary Desktop Uploader, je me rendais compte que j'avais une redondance de photos "identiques" lorsque je marquais un point d'arrêt, notamment aux Stop. Cette redondance est peu pertinente pour l'utilisateur et d'un point de vue environnemental, elle vient inutilement charger les serveurs de Mapillary. Je vous explique ci-dessous quelle solution a été mise en place pour réaliser ce "nettoyage".

Accéder au script complet

Info

Si vous utilisez mapillary_tools, il existe la commande --duplicate_distance DUPLICATE_DISTANCEqui vous permet de faire sensiblement la même chose mais l'idée était bien d'être indépendant pour ne pas s'enfermer dans la solution Mapillary si le projet Panoramax aboutit. A noter, cette option n'est pas présente dans Mapillary Desktop Uploader. --duplicate_distance DUPLICATE_DISTANCE : The maximum distance that can be considered "too close" between two images. If both images also point in the same direction (see --duplicate_angle), the later image will be marked as duplicate and will not be upload. [default: 0.1]

Extraire la localisation des images#

Pour la première étape, j'ai utilisé exiftool pour lire chacune des images afin d'en extraire leur localisation ainsi que la date et l'heure de la prise de vue. En sortie, j'obtiens un fichier csv listant chacune des images ainsi que les paramètres demandés (latitude, longitude, date, nom du fichier, ...).

Extraction de la localisation des images
exiftool -filename -gpstimestamp -gpsdatestamp -gpslatitude -gpslongitude -n -csv -r $REPER'/tmp' > './list/'$DATE_YMD'_img.csv'

Créer un fichier SIG à partir de la localisation des images#

La deuxième étape est une étape intermédiaire qui permet de créer un fichier SIG à partir des informations extraites précédemment des images. En entrée, on a donc le fichier csv que l'on va transformer en une couche ponctuelle localisant les images et intégrant les informations extraites.

Création du fichier au format SIG
1
2
3
4
5
6
7
8
ogr2ogr \
  -f "SQLite" \ # FORMAT DE SORTIE
  -dsco SPATIALITE=YES \
  -lco LAUNDER=NO \
  -oo X_POSSIBLE_NAMES=gpslongitude \ # ON DEFINIT LE CHAMP X
  -oo Y_POSSIBLE_NAMES=gpslatitude \ # ON DEFINIT LE CHAMP Y
  ${csvfile%.*}.sqlite \ # NOM DU FICHIER EN SORTIE
  ${csvfile%.*}.csv # NOM DU FICHIER EN ENTREE

Identification des images#

Vous connaissez mon côté OGR centré ! Au départ, j'ai commencé par digérer la localisation des images dans OGR pour supprimer les points des photos dont la distance avec le suivant était inférieure à 2 mètres. C'était un bon début mais perfectible.

Identification des images à supprimer - version 1

Finalement après de nombreux échanges avec Michaël Galien, plutôt SQL centré, on est arrivé à une requête récursive sur PostgreSQL permettant de supprimer les photos qui se succèdent si leur écartement est inférieur à X mètres (dans le cas présent 3 mètres). Si on compare visuellement ces deux versions, cette solution permet de conserver une meilleure répartition des photos. C'est notamment lié à la récursivité qui permet d'avancer sur le point qui suit de manière progressive.

Identification des images à supprimer - version 2

Cette requête a ensuite été adaptée pour tourner avec ogr2ogr de manière autonome (OGR centré, je vous dis !).

Identification des images
ogr2ogr \
-f CSV \ # FORMAT DE SORTIE
-dialect sqlite \
-sql 'WITH RECURSIVE clean_sequence as (
  --PERMET DE RECUPERER LA PREMIERE PHOTO
  SELECT g.*,
  cast(null as geometry) as aproximite,
  cast(null as integer) as id_ref,
  cast(null as real) AS distance
  FROM (SELECT * FROM conf LIMIT 1) g
  UNION ALL
  --REGARDE SI LE POINT SUIVANT SE TROUVE A UNE DISTANCE XX
  SELECT T.*,
    CASE
    WHEN C.aproximite IS NULL AND PtDistWithin(T.geom, C.geom,3) THEN T.geom_prev
    WHEN not (C.aproximite IS NULL) AND PtDistWithin(T.geom, C.aproximite,3) THEN C.aproximite
    ELSE NULL
    END as aproximite,
    CASE
    WHEN C.aproximite IS NULL AND PtDistWithin(T.geom, C.geom,3) THEN t.prev_val
    WHEN not (C.aproximite IS NULL) AND PtDistWithin(T.geom, C.aproximite,3) THEN C.id_ref
    ELSE NULL
    END as id_ref,
    CASE
    WHEN C.aproximite IS NULL AND PtDistWithin(T.geom, C.geom,3) THEN ST_Distance(T.geom, C.geom)
    WHEN not (C.aproximite IS NULL) AND PtDistWithin(T.geom, C.aproximite,3) THEN ST_Distance(T.geom, C.aproximite)
    ELSE NULL
    END as distance
    FROM clean_sequence as C
    INNER JOIN (SELECT * FROM conf) as T
    ON T.id_photo = C.id_photo + 1),
  conf AS (SELECT
    sourcefile,
    filename,
    substr(filename,1,4) as sequence,
    cast(substr(filename,5,4) AS integer) as id_photo,
    CAST(gpslatitude AS REAL) AS gpslatitude,
    CAST(gpslongitude AS REAL) AS gpslongitude,
    ST_Transform(SetSRID(MakePoint(CAST(gpslongitude AS REAL), CAST(gpslatitude AS REAL)), 4326),2154)as geom,
    LEAD(ST_Transform(SetSRID(MakePoint(CAST(gpslongitude AS REAL), CAST(gpslatitude AS REAL)), 4326),2154)) over (order by filename) AS geom_next, --GEOMETRY DU POINT SUIVANT
    LAG(ST_Transform(SetSRID(MakePoint(CAST(gpslongitude AS REAL), CAST(gpslatitude AS REAL)), 4326),2154)) over (order by filename) AS geom_prev, --GEOMETRY DU POINT PRECEDENT
    LAG(cast(substr(filename,5,4) AS integer)) OVER (ORDER BY cast(substr(filename,5,4) AS integer)) AS prev_val, --NUMERO DU POINT PRECEDENT
    LEAD(cast(substr(filename,5,4) AS integer)) OVER (ORDER BY cast(substr(filename,5,4) AS integer)) AS next_val --NUMERO DU POINT SUIVANT
  FROM "'${csvfile%.*}'" ORDER BY filename)
  SELECT sourcefile
   FROM clean_sequence WHERE NOT (aproximite IS NULL)
  ' \
  ${csvfile%.*}"_a_sup.csv" \ # NOM DU FICHIER EN SORTIE
  ${csvfile%.*}".sqlite" # NOM DU FICHIER EN ENTREE

Suppression des images#

Une fois la liste des images à supprimer identifiée, il ne nous reste plus qu'à les effacer.

Suppression des images
1
2
3
4
5
6
# SUPPRESSION DES IMAGES INUTILES
for csvfile_sup in *.csv; # BOUCLE SUR LES FICHIERS CSV
do
    sed 1d ${csvfile_sup} | xargs rm -f | bash # SUPPRESSION DES IMAGES
    rm ${csvfile_sup} # SUPPRESSION DU FICHIER CSV A LA FIN
done

Autre piste à explorer#

En parallèle des échanges avec M. Galien, Vincent de Château-Thierry nous proposait une solution alternative ne s'appuyant pas sur le recursif et qu'il serait intéressant de creuser 👇.

Pour la partie intégration du logo, je suis reparti d'une solution proposée par Cécile Mahé et Christophe Munoz du SIG de l'Agglomération Val Parisis et partagée au sein du groupe de l'AITF SIG et topographie. Cette solution repose sur le projet et le script python Nadir Patcher de David G de Trek View.

Accéder au projet Nadir Patcher

Intégration du logo
# Exemple : permet d'intéger un logo couvrant 17% de l'image panoramique
python3 nadir-patcher.py $REPER'/tmp' $REPER'/logo.png' 17 $REPER'/out'

Intégration du logo


Publication des photos#

Pour la publication des photos, je ne passe pas par Mapillary Tools. Je préfère utiliser l'application bureautique car cela me permet de contrôler mon cheminement et éventuellement de supprimer certaines images manuellement avant publication.


Usages#

Le territoire n'étant pas intégralement couvert, il n'y a pas encore eu de campagne de promotion en interne. Toutefois, l'usage de la GoPro a éveillé la curiosité de certains collègues ayant l'habitude d'utiliser StreetView et à qui j'ai déjà présenté la démarche :

  • le service qui instruit les demandes d'urbanisme pour localiser et visualiser les projets,
  • le service déchet pour s'immerger sur site lors d'appels d'usagers,
  • les services techniques pour travailler sur des projets d'aménagement.

A terme, l'objectif est de présenter ce projet à l'ensemble des services de l'intercommunalité ainsi qu'aux agents des communes.

Concrètement dans notre WebSIG, l'utilisateur peut visualiser les voies couvertes et à l'aide d'un outil métier, il peut interroger la localisation d'une photo pour ensuite la visualiser dans Mapillary.

Rappel

Comme expliqué dans l'article précédent, les données relatives à la couvertures et aux images sont récupérées depuis Mapillary et régulièrement intégrées dans notre base de données.

Intégration WebSIG

En dehors de Mapillary, j'ai aussi travaillé avec mon service culture pour photographier une exposition de Street Art dans le but de prolonger l'évènement sous la forme d'une visite immersive en m'appuyant sur l'outil Pannellum. On sort clairement du cadre initial mais cela ouvre d'autres perspectives.

Exposition immersive


Conclusion#

Cet article vous illustre mon retour d'expérience matériel concernant la prise de vues immersives et vous détaille l'enchainement des étapes que je réalise entre la prise de vue et la publication sur Mapillary avec pour objectif d'automatiser au maximum de traitements tout en gardant une forme d'indépendance si nous devions changer de solution à l'avenir (ex. le Géocommun Panoramax). A noter, que j'ai récemment retravaillé sur une nouvelle version de mon script pour intègrer deux possibilités :

  • supprimer les images lorsque je suis passé récemment sur une voie,
  • créer des dossiers separés pour chacune des séquences d'images me permettant ainsi de choisir les séquences à publier pour améliorer le maillage sans introduire de redondance d'images.

Auteur#

Florian Boret#

Portrait Florian Boret

Géomaticien/cartographe, je suis arrivé dans le monde de la géomatique en suivant un cursus « professionnalisant » (BTS Géomètre-Topographe, Licence pro GGAT, Master SIGAT). J’ai ensuite travaillé dans un bureau d’études spécialisé dans la production de données d’occupation du sol et puis pour des raisons personnelles je me suis expatrié quelques années au Sénégal où je me suis lancé comme géomaticien indépendant (DATA\WAX).

Depuis mon retour en France, je suis en charge du SIG de la communauté de communes du Pays de Lunel.

En dehors de ces expériences, j'ai aussi régulièrement initié de petits projets personnels iGeo-Topo, GIS-Blog.fr, osm2igeo, osm2igeotopo. Aujourd'hui, c’est avec plaisir que j’interviens également comme contributeur de GeoTribu.

Licence #

Ce contenu est sous licence Creative Commons International 4.0 BY-NC-SA, avec attribution et partage dans les mêmes conditions, sauf dans le cadre d'une utilisation commerciale.
Les médias d'illustration sont potentiellement soumis à d'autres conditions d'utilisation.

Réutiliser, citer l'article

Vous êtes autorisé(e) à :

  • Partager : copier, distribuer et communiquer le matériel par tous moyens et sous tous formats
  • Adapter : remixer, transformer et créer à partir du matériel pour toute utilisation, exceptée commerciale.

Citer cet article :

"Contribution Mapillary et retour d'expérience" publié par Florian Boret sur Geotribu sous CC BY-NC-SA - Source : https://geotribu.fr/articles/2022/2022-12-09_mapillary_experience/

Commentaires

Afin de favoriser les échanges constructifs, merci de préférer le pseudonymat à l'anonymat. Pour rappel, l'adresse mail n'est pas exposée publiquement. Consulter la page sur la confidentialité et les données personnelles.
Une version minimale de la syntaxe markdown est acceptée pour la mise en forme des commentaires.
Propulsé par Isso.

Ce contenu est sous licence Creative Commons BY-NC-SA 4.0 International Pictogramme Creative Commons Pictogramme Creative Commons BY Pictogramme Creative Commons NC Pictogramme Creative Commons SA