# Développement et mise en place d'un web service de calcul de la densité apparente des sols par photogrammétrie

Norman François

► To cite this version:

Norman François. Développement et mise en place d'un web service de calcul de la densité apparente des sols par photogrammétrie. Informatique [cs]. 2025. hal-05422912

HAL Id: hal-05422912

https://hal.inrae.fr/hal-05422912v1

Submitted on 18 Dec 2025

HAL is a multi-disciplinary open access
archive for the deposit and dissemination of sci-
entific research documents, whether they are pub-
lished or not. The documents may come from
teaching and research institutions in France or
abroad, or from public or private research centers.

L'archive ouverte pluridisciplinaire HAL, est
destinée au dépôt et à la diffusion de documents
scientifiques de niveau recherche, publiés ou non,
émanant des établissements d'enseignement et de
recherche français ou étrangers, des laboratoires
publics ou privés.

<figure><img src="image_1.png" /></figure>

Distributed under a Creative Commons Attribution 4.0 International License
# RAPPORT DE STAGE

Développement et mise en place d'un web
service de calcul de la densité apparente des
sols par photogrammétrie

Réalisé par :

Norman FRANÇOIS

Stage encadré par :

Denis FEURER

Marc JOANNIDES

Pour l'obtention du BUT Informatique

IUT Montpellier-Sète

2024-2025
Remerciements

Je tiens à remercier tous les membres du LISAH pour leur accueil chaleureux ainsi que mon intégration au sein du laboratoire au cours de mon stage.

Je remercie tout particulièrement mon tuteur, Denis FEURER, pour sa disponibilité et son accompagnement attentif durant ces mois de travail. Je souhaite également exprimer ma gratitude aux membres de l'équipe autour du projet Grounded pour leur bienveillance ainsi que pour leurs retours au cours du développement. Ainsi qu'à Armel THÖNI, qui, bien que ne faisant pas partie de l'équipe autour du projet Grounded, s'est investi pour aider mon tuteur à encadrer mon stage lors de moments clés.

Je remercie également Marc JOANIDES pour sa prévenance quant à la bonne transmission des informations ainsi que pour ses conseils quant à la rédaction de mon rapport de stage ainsi que pour la préparation de ma soutenance.

Enfin, j'adresse mes plus sincères remerciements à ma famille pour son soutien et ses encouragements constants, avec une pensée particulière pour mon grand-père Santiago ROVIRA et ma grand-mère Rosa ANGULO.
# Résumé

## Résumé en Français

L'objectif de ce stage est de concevoir et développer un service web modulaire permettant de piloter et d'encapsuler la chaîne de traitement automatisée de mesure de la densité apparente du sol par photogrammétrie : Grounded. Cette application vise à rendre ces fonctionnalités accessibles via une interface web intuitive et une API REST. L'objectif est de simplifier l'utilisation de la méthode pour des utilisateurs non experts, tout en garantissant la pérennité et la maintenabilité du système afin de faciliter son évolution future. Cette approche soutient la diffusion de la méthode au sein de la communauté scientifique en permettant son intégration dans des applications clientes, notamment mobiles.

Mots-clés : service web, API REST, photogrammétrie, densité apparente du sol, automatisation

## Abstract in English

The aim of this internship is to design and develop a modular web service to drive and encapsulate the Grounded automated processing chain for measuring soil bulk density using photogrammetry. This application aims to make these functionalities accessible via an intuitive web interface and a REST API. The aim is to simplify use of the method for non-expert users, while guaranteeing the system's durability and maintainability to facilitate future development. This approach supports the dissemination of the method within the scientific community by enabling its integration into client applications, particularly mobile ones.

Keywords : web service, REST API, photogrammetry, soil bulk density, automation
Table des matières

<table><tr><td>Résumé</td><td>III</td></tr><tr><td>Résumé en Français</td><td>III</td></tr><tr><td>Abstract in English</td><td>III</td></tr><tr><td>Glossaire</td><td>VII</td></tr><tr><td>I – Introduction</td><td>1</td></tr><tr><td>II – Contexte du stage</td><td>2</td></tr><tr><td>2.1 Organisation du laboratoire</td><td>2</td></tr><tr><td>2.2 – Enjeux du stage</td><td>3</td></tr><tr><td>III – Analyse</td><td>6</td></tr><tr><td>3.1 Analyse de l' existant</td><td>6</td></tr><tr><td>3.2 – Analyse du problème à résoudre</td><td>9</td></tr><tr><td>3.3 – Cahier des charges</td><td>10</td></tr><tr><td>3.3.1 – Introduction</td><td>10</td></tr><tr><td>3.3.2 – Objectif</td><td>10</td></tr><tr><td>3.3.3 – Spécification fonctionnelles</td><td>10</td></tr><tr><td>3.3.4 – Spécifications techniques</td><td>11</td></tr><tr><td>3.3.5 – Livrables attendus</td><td>11</td></tr><tr><td>IV – Rapport Technique</td><td>12</td></tr><tr><td>4.1 – Identification des besoins clients</td><td>12</td></tr><tr><td>4.2 – Architecture globale de l' application</td><td>13</td></tr><tr><td>4.2.1 – Base de données</td><td>13</td></tr><tr><td>4.2.2 – Stockage de fichiers</td><td>13</td></tr><tr><td>4.2.3 – Gestion des tâches asynchrones</td><td>14</td></tr><tr><td>4.3 – Virtualisation de Grounded cli</td><td>16</td></tr><tr><td>4.4 – Conception de l' API</td><td>17</td></tr><tr><td>4.4.1 – Présentation du framework Django</td><td>17</td></tr><tr><td>4.4.2 – Contexte et évolution de la structure de données</td><td>18</td></tr><tr><td>4.4.3 – Implémentation de la modularité</td><td>18</td></tr><tr><td>4.4.4 – Gestion des fichiers</td><td>22</td></tr><tr><td>4.4.5 – Tests unitaires</td><td>25</td></tr><tr><td>4.4.6 – Documentation</td><td>27</td></tr><tr><td>4.4.7 – Interface administrateur</td><td>28</td></tr><tr><td>4.5 – Conception du client web</td><td>31</td></tr><tr><td>4.5.1 – Présentation du framework Vue.js</td><td>31</td></tr><tr><td>4.5.2 – Gestion de la communication avec l' API</td><td>31</td></tr><tr><td>4.5.3 – Fonctionnalités principales</td><td>34</td></tr><tr><td>4.6 – Déploiement de l' application</td><td>36</td></tr><tr><td>4.6.1 – Environnement de développement</td><td>36</td></tr><tr><td>4.6.2 – Environnement d'intégration continue (CI)</td><td>36</td></tr><tr><td>4.6.3 – Environnement de production</td><td>37</td></tr><tr><td>4.6.4 – Gestion des configurations et variables d'environnement de l' API</td><td>38</td></tr><tr><td>4.6.5 – Avantages de cette approche</td><td>39</td></tr><tr><td>V – Méthodologie</td><td>40</td></tr><tr><td>5.1 – Organisation du travail en entreprise</td><td>40</td></tr><tr><td>5.2 – Gestion du code et du versionnement</td><td>40</td></tr><tr><td>5.3 – Approche personnelle et autonomie</td><td>41</td></tr></table>
<table><tr><td>Conclusion</td><td>44</td></tr><tr><td>Bibliographie</td><td>I</td></tr><tr><td>Annexes</td><td>II</td></tr></table>
Index des figures

<table><tr><td>Figure 1: Organigramme de l'UMR LISAH</td><td>3</td></tr><tr><td>Figure 2: Présentation des différentes méthodes de mesure de la densité apparente d'un sol</td><td>4</td></tr><tr><td>Figure 3: Configuration terrain lors de la prise d'un échantillon</td><td>6</td></tr><tr><td>Figure 4: Diagramme de flux simplifié représentant le processus d'analyse de Grounded</td><td>7</td></tr><tr><td>Figure 5: Présentation sommaire des différentes options de la ligne de commande</td><td>8</td></tr><tr><td>Figure 6: Sortie au format pdf de la chaîne de traitement automatisée</td><td>9</td></tr><tr><td>Figure 7: Diagramme de déploiement simplifié du Backend</td><td>15</td></tr><tr><td>Figure 8: Tableau de comparaison des patterns MVC et MTV</td><td>17</td></tr><tr><td>Figure 9: Classe abstraite Tool</td><td>19</td></tr><tr><td>Figure 10: Création du modèle du module MicMac dans l'API</td><td>20</td></tr><tr><td>Figure 11: Extrait simplifié du modèle Configuration</td><td>21</td></tr><tr><td>Figure 12: Exemple de la création duOME rizer d'un module</td><td>21</td></tr><tr><td>Figure 13: Exemple du contenu d'une requête de création d'une configuration</td><td>22</td></tr><tr><td>Figure 14: Protocole d'envoi d'un dataset</td><td>25</td></tr><tr><td>Figure 15: Exemple de la modification dynamique des paramètres lors des tests</td><td>26</td></tr><tr><td>Figure 16: Extrait d'une partie de la documentation de l'api</td><td>28</td></tr><tr><td>Figure 17: Exemple de la définition d'une page de l'interface administrateur</td><td>29</td></tr><tr><td>Figure 18: Intégration d'un module polymorphique dans l'interface d'administration</td><td>30</td></tr><tr><td>Figure 19: Configuration du client Axios</td><td>32</td></tr><tr><td>Figure 20: Exemple d'une fonction de l'apiStore</td><td>33</td></tr><tr><td>Figure 21: Exemple d'utilisation de l'apiStore dans un module</td><td>33</td></tr><tr><td>Figure 22: Contenu du fichier de configuration production_local.py</td><td>39</td></tr><tr><td>Figure 23: Mesure du volume des étalons par poussée d'Archimède</td><td>43</td></tr><tr><td>Figure 24: Configuration d'expérimentation</td><td>43</td></tr></table>
# Glossaire

**Photogrammétrie** : Technique de mesure qui consiste à déterminer la forme, les dimensions et la situation d'un objet dans l'espace à partir de prises de vues photographiques de cet objet.

**API** : Interface logicielle qui permet de « connecter » un logiciel ou un service à un autre logiciel ou service afin d'échanger des données et des fonctionnalités.

**Virtualisation** : Technique permettant de faire fonctionner plusieurs systèmes ou environnements isolés sur une même machine physique, en simulant des machines virtuelles partageant ses ressources.

**Mire** : Symbole possédant un identifiant unique utilisé en photogrammétrie pour ajouter des informations (ici les mires sont utilisées pour établir l'échelle du nuage de points).

**SFM (Structure From Motion)** : Technique photogrammétrique destinée à estimer la structure 3D d'une scène à partir d'images 2D

**Nuage de points** : Ensemble de points dans un espace 3D permettant la visualisation d'objets en 3 dimensions.

**Frontend** : Désigne les éléments d'un site ou d'une application que les utilisateurs voient à l'écran et avec lesquels ils vont interagir

**Framework** : Ensemble structuré de bibliothèques, d'outils et de conventions qui encadrent et accélèrent le développement d'applications.

**Architecture distribuée** : Un système informatique dans lequel les traitements et les données sont répartis sur plusieurs machines, interconnectées par un réseau, et communiquent entre elles par échange de requêtes.

**SGBDR (Système de Gestion de Base de Données Relationnelle)** : Système logiciel conçu pour stocker, organiser et gérer des données sous forme de tableaux (lignes et colonnes) reliés entre eux, en garantissant l'intégrité, la cohérence et la sécurité via des transactions, des contraintes et l'usage du langage SQL.

**ORM** : Ensemble de bibliothèques permettant de faire correspondre les structures de données orientées objet d'un langage de programmation avec les tables d'une base de données. L'objectif est de simplifier et d'abstraire les opérations de base de données pour le développeur, en permettant de manipuler les données comme s'il s'agissait d'objets dans le langage de programmation choisi.
**Backend**: Terme désignant une couche logicielle accédant à des données mais, à l'inverse du frontend, ne gère pas d'interface utilisateur.

**Courtier**: Composant logiciel qui sert d'intermédiaire pour transporter les messages entre les producteurs et les consommateurs de tâches asynchrones. Dans Celery, il gère la file d'attente des tâches à exécuter.

**Thread**: Unité de base à laquelle un système d'exploitation alloue du temps processeur.

**Type MIME**: Standard permettant d'indiquer la nature et le format d'un document.

**Responsive**: Design d'interface qui s'adapte automatiquement à la taille de l'écran, pour une utilisation optimale sur tous les appareils (ordinateur, tablette, mobile).

**Load balancer**: Dispositif physique ou virtuel chargé de répartir le trafic réseau et les charges de travail entre plusieurs serveurs.

**Backlog**: Liste hiérarchisée de tâches destinées à l'équipe de développement.
# I – Introduction

Dans un contexte où la puissance de calcul et les outils numériques offrent de nouvelles perspectives pour la recherche, les équipes scientifiques cherchent à automatiser et fiabiliser des méthodes autrefois longues ou peu pratiques. Parmi elles, la mesure de la densité apparente des sols par *photogrammétrie se développe comme une alternative prometteuse : elle consiste à reconstruire en 3D le volume laissé par un prélèvement de sol pour en déduire sa densité, en le rapportant à sa masse mesurée au laboratoire. Cette approche vise à obtenir des mesures plus rapides, reproductibles et exploitables sur le terrain, tout en réduisant les contraintes logistiques des méthodes traditionnelles, notamment sur les sols complexes.

Pour mettre en œuvre cette méthode, j'ai déjà, lors de mon précédent stage à l'UMR LISAH, développé une chaîne de traitement automatisée, baptisée Grounded. Cette chaîne combine plusieurs étapes de reconstruction 3D, de traitement et d'analyse des données. Toutefois, son utilisation restait jusqu'alors réservée à des utilisateurs avancés : l'utilisation se faisait en ligne de commande, l'installation nécessitait des dépendances lourdes, et le suivi des exécutions manquait d'ergonomie. Ces contraintes pourraient contribuer à limiter la diffusion de la méthode, freinant son appropriation par des utilisateurs non spécialistes.

C'est avant tout dans la perspective de l'intégration future d'une application mobile d'aide à la prise de vue, mais aussi pour répondre aux besoins d'accessibilité de la méthode, que l'équipe en charge du projet Grounded a décidé de développer un service web capable d'encapsuler et de piloter la chaîne de traitement. Mon stage a ainsi porté sur la conception et le développement de ce service, composé d'une *API modulaire et maintenable, ainsi que d'une interface web dédiée. Ce choix visait à simplifier l'accès aux fonctionnalités de Grounded en les exposant via des technologies web, tout en préparant leur réutilisation dans une application mobile. Les enjeux étaient multiples : améliorer l'expérience utilisateur, garantir la pérennité et la maintenabilité de la solution, et permettre son évolution au fil des besoins du laboratoire.

Après avoir présenté l'organisation de l'UMR LISAH ainsi que les enjeux spécifiques du projet Grounded, j'analyserai la chaîne de traitement déjà existante. La troisième partie sera dédiée à la description des étapes de conception et de développement du service web : des choix d'architecture jusqu'à la mise en œuvre de l'API et de l'interface web, en passant par la *virtualisation, la gestion des données et le déploiement. Enfin, je détaillerai la méthodologie de travail adoptée avant de conclure sur les apports du projet et les perspectives d'évolution permettant d'assurer la pérennité et l'adaptabilité de la solution au sein du laboratoire.
## II – Contexte du stage

### 2.1 Organisation du laboratoire

Le lieu de mon stage, l'UMR LISAH, est une unité mixte de recherche affiliée à l'INRAE, à l'IRD, à l'Institut Agro Montpellier et à AgroParisTech. Sa mission est de développer des connaissances et des outils numériques pour mieux comprendre et gérer les paysages cultivés en tenant compte des impacts du changement climatique et des activités humaines. L'accent est mis sur l'étude du fonctionnement des paysages cultivés, en mettant en lumière les interactions entre le sol, les cultures et les ressources naturelles sur les espaces concernés. Le campus de la Gaillarde à Montpellier abrite le laboratoire, qui mène également des activités secondaires en Tunisie sur les campus INAT et INRGREF de Tunis. Des travaux sont également menés en Inde ainsi qu'en Guadeloupe. Les membres du laboratoire sont répartis en plusieurs équipes.

Parmi ces équipes nous pouvons retrouver :

* L'équipe « Ressource en sol sous changement globaux » qui est également l'équipe à laquelle j'ai eu l'occasion d'être affecté.

* L'équipe « Ecohydrologie des paysages cultivés » qui étudie de l'eau dans les milieux agricoles, principalement les bassins versants.

* L'équipe « Contaminants des sols et des eaux » évalue le risque de contamination des sols et des eaux par les produits phytosanitaires et recherche des solutions pour en limiter la dispersion.

* L'équipe « OpenFLUID » où travaillent les personnes en charge du développement du logiciel du même nom et dont le développement a été lancé en 2006.

Il est possible de retrouver l'organigramme ci-dessous :
<figure><img src="image_2.png" /><figcaption>Figure 1: Organigramme de l'UMR LISAH</figcaption></figure>

## 2.2 - Enjeux du stage

Lorsqu'on souhaite analyser un sol, plusieurs mesures peuvent entrer en compte en fonction des caractéristiques que l'on souhaite identifier sur ce dernier, dont l'une des principales est notamment la densité apparente qui n'est autre que le rapport poids/volume d'un sol. Il existe de nombreuses méthodes de mesure de cette caractéristique.
<figure><img src="image_3.png" /><figcaption>Figure 2: Présentation des différentes méthodes de mesure de la densité apparente d'un sol</figcaption></figure>

La méthode aujourd'hui la plus utilisée pour obtenir la densité apparente est de prélever un échantillon de sol à l'aide d'un cylindre dont on connaît le volume, d'en extraire la terre prélevée, de la sécher puis d'appliquer le rapport poids/volume pour obtenir la densité apparente. Cette méthode pose des difficultés lorsque le sol est très caillouteux. Il est impossible de planter le cylindre s'il bute sur un caillou, forçant l'opérateur à cibler une zone avec moins de cailloux, ce qui peut introduire des biais. Si le taux de cailloux est trop élevé la méthode au cylindre peut même être impossible à mettre en œuvre.

C'est dans l'optique de trouver une méthode de mesure pouvant être universelle à tous les types de sols qu'une équipe au sein de l'UMR travaille depuis 2019 sur une méthode de mesure de la densité apparente des sol par photogrammétrie. En effet, la principale difficulté lors de l'évaluation de la densité apparente d'un sol est la mesure précise du volume qu'occupait initialement un échantillon lorsqu'il était en place. L'équipe propose une méthode permettant de calculer précisément le volume de sol prélevé entre deux séries de photos (photos avant excavation et photos après excavation).

Dans cette optique, lors d'un précédent stage, j'ai réalisé une chaîne d'automatisation modulaire visant à automatiser ce traitement de photos avant et après excavation. Cette chaîne repose sur différentes briques logicielles paramétrables et interchangeables afin de faciliter l'expérimentation sur la méthode. Cette chaîne d'automatisation apporte des résultats concluants mais reste complexe à utiliser en pratique car elle nécessite d'avoir une puissante configuration afin de réaliser l'analyse en un temps raisonnable. De plus, étant un outil en ligne de commande, ce dernier est difficilement accessible à des personnes n'étant pas à l'aise avec l'informatique.
L'un des objectifs majeurs de mon stage a été de développer un web service exposant une API REST, destinée à être réutilisée par une application mobile d'aide à la prise de vue, développée en parallèle par un prestataire externe. Dans ce cadre, j'ai activement participé aux réunions de coordination et échangé avec ce prestataire afin de garantir la compatibilité et la bonne intégration de l'API dans l'application. Ce travail de conception d'API s'inscrit dans une volonté de cohérence globale du projet Grounded, visant à accompagner l'utilisateur tout au long du processus, depuis l'acquisition des photos jusqu'à leur traitement.

En complément de cette API, j'ai également développé une interface graphique web permettant à un utilisateur non expert de lancer une analyse de manière autonome, sans passer par la ligne de commande. L'ensemble constitue un service ergonomique et accessible, réduisant les risques d'erreurs et facilitant l'appropriation de la méthode. Les utilisateurs finaux ciblés par le projet Grounded sont des chercheurs, des bureaux d'études des sols, ainsi que d'autres professionnels comme des agriculteurs ou des architectes.
# III – Analyse

## 3.1 Analyse de l'existant

La chaîne de traitement automatisée est, au début de mon stage, le seul maillon opérationnel du projet Grounded. Ce dernier traite un jeu de photos prisent sur le terrain lors d'un prélèvement de sol.

<figure><img src="image_4.png" /><figcaption>Figure 3: Configuration terrain lors de la prise d'un échantillon</figcaption></figure>

Dans la configuration terrain, nous pouvons identifier des *mires, ces dernières étant uniques, sont assignées à un identifiant et regroupés par paire dont on connaît la longueur (aussi appelé réglets), elles permettent de conserver un facteur d'échelle plus tard lors du traitement. Elles sont situées tout autour des zones d'excavation, ici entourées par des cercles rouges.

Ce jeu d'image est ensuite traité selon un protocole mis au point au sein du laboratoire, dont voici le diagramme de flux ci-dessous :
<figure><img src="image_5.png" /><figcaption>Figure 4: Diagramme de flux simplifié représentant le processus d'analyse de Grounded</figcaption></figure>
Le processus d'analyse des données représente une chaîne de blocs reprenant chacun les résultats des précédents pour effectuer leur traitement. Ces blocs font parfois appel à des modules regroupés sous 3 catégories :

* **Détecteur de mire** : permet de détecter les mires présentes sur une image.

* **\*SFM** : permet la génération de nuages de points à partir de photos.

* **Opérateur de \*nuage de points** : effectue des opérations et des modifications sur des nuages de points.

Dans son utilisation, le logiciel est donc hautement configurable. Il fonctionne à base d'un fichier de configuration au format yaml dont il est possible d'écraser et de remplacer les valeurs via la ligne de commande dont voici un exemple d'utilisation :

<figure><img src="image_6.png" /><figcaption>Figure 5: Présentation sommaire des différentes options de la ligne de commande</figcaption></figure>

À la suite de l'exécution de cette chaîne de traitement, la principale sortie générée est un fichier pdf montrant une représentation de la surface de sol excavée. Il est possible d'y observer les trous entourés ici en noir qui en leur centre contiennent leur volume en mètres cubes.
<figure><img src="image_7.png" /><figcaption>Figure 6: Sortie au format pdf de la chaîne de traitement automatisée</figcaption></figure>

## 3.2 - Analyse du problème à résoudre

Le but de mon stage est d'encapsuler l'application en ligne de commande préexistante « Grounded CLI » au sein d'un web service exposé via une API REST et accessible via un *frontend web. Ce projet comporte de nombreux problèmes à résoudre, en termes de virtualisation de l'application en ligne de commande préexistante mais également en termes d'infrastructure qui se doit d'être évolutive ce qui se traduit par la séparation des responsabilités en plusieurs services. Cependant je n'ai pas de contraintes légales ou spécifiques liées développement.
## 3.3 – Cahier des charges

Ce cahier des charges a été élaboré à l'issue d'une phase d'analyse des besoins des utilisateurs finaux, tout en veillant à assurer une cohérence globale avec l'ensemble du projet.
Il se révèle ainsi plus ambitieux que les demandes formulées initialement (voir annexe 1).

### 3.3.1 – Introduction

Grounded Web est une application web destinée à démocratiser l'analyse des images
prise pour l'estimation de la densité des sols par photogrammétrie, en s'appuyant sur un outil
en ligne de commande préexistant : Grounded CLI.

L'objectif est de rendre cette mesure de volume accessible à un public non technique via une interface intuitive, tout en déportant les calculs sur une machine distante. Une application mobile complémentaire d'aide à la prise de vue est également prévue, l'API REST devra être conçue pour être utilisable à la fois par le client web et à terme, par cette application mobile.

### 3.3.2 – Objectif

L'objectif de cette application composée de deux projets distincts (une API REST ainsi qu'un client web) est de rendre l'utilisation cette nouvelle méthode accessible aux utilisateurs novices, n'ayant ni de compétence particulière en informatique ni en photogrammétrie.

### 3.3.3 – Spécification fonctionnelles

#### Soumission d'analyses

* L'utilisateur peut envoyer un lot de photos à analyser.

* Pour un utilisateur débutant, une configuration d'exécution par défaut doit être fourni, cependant il doit être laissé la possibilité à un utilisateur avancé de configurer ses paramètres d'exécution.

#### Suivi d'état

* Consultation de l'état d'avancement des analyses (en attente, en cours, terminé, erreur).

* Historique des analyses précédentes.

* Envoi de notification (e-mail, webhooks) lors de la fin du traitement en y incluant les résultats.
### Traçabilité d'exécution

* Il doit être possible de retrouver pour chaque résultat d'analyses les jeux de donnée ainsi que la configuration d'exécution associée.

* L'application doit fournir des moyens de visualiser certains fichiers de résultat intermédiaire ainsi que les logs afin de faciliter le débogage.

* Les résultats, les fichiers intermédiaires ainsi que les jeux de données doivent être stockés et rendu facilement accessible à l'utilisateur et ce de façon sécurisée.

### 3.3.4 – Spécifications techniques

* Création de l'application sous la forme d'une API REST encapsulant l'outil grounded CLI ainsi que d'un client web permettant de l'interroger

* L'application devra être robuste, notamment dans sa gestion du traitement des analyses, en cas de coupure de courant par exemple.

* Les bonnes pratiques en matière de sécurité devront être appliquées afin de protéger les données utilisateurs

* En vue d'une probable mise en production, l'application devra pouvoir passer à l'échelle facilement, en permettant le déploiement sur plusieurs serveurs afin de répondre aux besoins de nombreux utilisateurs.

* L'application devra comporter des tests de non-régression afin de pérenniser les développements futurs.

* L'API doit comporter une documentation développeur OpenAPI complète afin de permettre le développement ultérieur d'outil basé sur cette dernière.

### 3.3.5 – Livrables attendus

* Une API REST documentée

* Un client web

* Un script de déploiement
# IV – Rapport Technique

## 4.1 – Identification des besoins clients

Afin de concevoir une application répondant de manière optimale aux besoins du projet, il a d'abord été nécessaire de réaliser un état de l'art en me renseignant sur les technologies envisageables ainsi que sur les bonnes pratiques liées au développement de ce type d'application. Parallèlement à ces recherches, j'ai pu échanger régulièrement avec mon tuteur de stage pour préciser les besoins spécifiques de l'application et affiner mes orientations au fur et à mesure de l'avancée de mes investigations.

Parmi les choix déterminants, la sélection des *frameworks de développement a été déterminante. Le laboratoire disposant de ressources de développement limitées, il était indispensable de choisir ces outils en fonction des fonctionnalités attendues, mais aussi des compétences déjà présentes au sein de l'équipe et plus largement au sein de l'UMR.

Au terme de la première semaine de stage, j'ai ainsi rédigé un rapport comparatif présentant les différentes technologies présélectionnées ainsi que leurs alternatives. En tenant compte des contraintes évoquées, le choix s'est porté sur le framework Django, et plus précisément sur Django Rest Framework, une surcouche facilitant le développement d'API. Ce choix s'explique notamment par l'usage du langage Python, déjà bien maîtrisé au sein du laboratoire, ainsi que par la familiarité de certains membres avec ce framework. Quant à la partie frontend, elle sera développée avec le framework Vue.js, pour des raisons similaires d'affinités de certains membres du laboratoire.

Concernant l'architecture globale de l'application, les échanges avec mon tuteur ont montré qu'une solution minimale était initialement envisagée, consistant en une application ne permettant pas nécessairement la mise à l'échelle du service et sans forcément de gestion des comptes utilisateurs. Toutefois, au regard des ambitions globales du projet, notamment la création d'une application d'aide à la prise de vue par un prestataire, il est apparu qu'une telle approche serait contre-productive. Bien qu'elle permette un développement rapide, cette base serait très difficile à faire évoluer. Or, le projet vise à terme à supporter un trafic important, ce qui implique la mise en place d'une *architecture distribuée, permettant une mise à l'échelle en fonction des besoins futurs.
## 4.2 – Architecture globale de l'application

Lors de cette première phase d'analyse, il a été nécessaire d'identifier et de caractériser les besoins externes essentiels de l'application, parmi lesquels :

* la base de données

* le stockage de fichiers

* la gestion des tâches asynchrones (notamment l'intégration avec Grounded CLI).

### 4.2.1 – Base de données

Au regard des spécifications fonctionnelles et des volumes de données prévus, l'utilisation d'une base de données relationnelle a été privilégiée plutôt qu'une solution NoSQL, moins adaptée à ce contexte. Ce choix s'explique par la nature principalement tabulaire des données, la nécessité d'assurer la cohérence transactionnelle et la simplicité de mise en œuvre qu'offre ce type de base.

Par ailleurs, une fois cette orientation technique décidée, le choix d'un *SGBDR particulier (PostgreSQL, MySQL, etc.) n'était pas déterminant : ces technologies étant largement interchangeables grâce aux couches d'abstraction fournies par les *ORM (ici Django ORM). Cette flexibilité permet de s'adapter facilement aux contraintes d'infrastructure du laboratoire ou de futurs déploiements.

### 4.2.2 – Stockage de fichiers

Concernant le stockage des fichiers, il s'agissait d'un domaine que je n'avais pas eu l'occasion d'aborder de manière concrète lors de mes projets précédents à l'IUT. J'ai donc mené des recherches sur les pratiques courantes et les standards associés.

Bien qu'une implémentation basée sur le système de fichiers local du serveur hébergeant l'API soit envisageable (et simple à mettre en place pour un prototype), cette approche présente des limites importantes en termes de mise à l'échelle et de robustesse.

En effet, pour un déploiement en production et afin de permettre une montée en charge horizontale (par exemple en déployant plusieurs instances de l'API derrière un *load
balancer), il est préférable de découpler le stockage des fichiers de l'application elle-même. Cela permet à toutes les instances de l'API d'accéder à un stockage partagé et persistant.

La solution la plus courante repose sur l'utilisation d'un service compatible avec l'API S3 (Simple Storage Service, popularisée par AWS). Cette norme offre une grande portabilité : on peut utiliser des services cloud commerciaux (AWS S3, Google Cloud Storage, Wasabi...) ou même des solutions locales (comme MinIO) hébergées en interne. Cette approche permet de déléguer la gestion du stockage à un service spécialisé.

### 4.2.3 – Gestion des tâches asynchrones

La gestion des tâches asynchrones représente un besoin central du projet, notamment pour l'exécution de traitements externes tels que l'utilisation de la chaîne de traitement Grounded, dont la durée peut varier de 15 minutes à plusieurs heures selon les configurations utilisées et les ressources de calcul.

Le choix de l'outil pour répondre à ce besoin a été fortement conditionné par la stack technique retenue pour l'API (Django et Django Rest Framework). Celery, un framework Python de gestion des tâches asynchrones, s'impose naturellement grâce à son intégration simple avec Django.

Celery permet de définir, planifier et exécuter des tâches en arrière-plan tout en offrant une grande flexibilité : prise en charge de plusieurs *backends de *courtiers et du stockage des résultats, gestion des files de priorité et monitoring avancé. Cette intégration native permet de limiter la complexité technique du projet et d'accélérer son développement en s'appuyant sur un outil mature et largement plébiscité dans l'écosystème Python.

Dans un premier temps, le courtier choisi pour Celery était Redis, en raison de sa simplicité d'installation et de sa légèreté. Redis fonctionne comme un stockage clé valeur en mémoire et permet de faire transiter efficacement les messages représentant les tâches à exécuter. Toutefois, cette solution a révélé certaines limites, notamment en matière de tolérance aux pannes et de robustesse : Redis ne supporte pas nativement toutes les fonctionnalités avancées de gestion des états de Celery, en particulier la capacité à détecter les échecs ou les déconnexions des « workers » en relançant automatiquement les tâches concernées.

Pour répondre à ces enjeux de fiabilité, le choix final s'est porté sur RabbitMQ comme courtier. RabbitMQ offre une communication plus avancée entre les producteurs (l'API) et les
consommateurs (les workers Celery), en permettant de surveiller en continu l'état des workers, de détecter leurs défaillances et de réattribuer automatiquement les tâches en cas de crash ou de déconnexion. Ce choix garantit une meilleure résilience et une exécution plus fiable des traitements asynchrones, en cohérence avec les exigences de robustesse du projet.

<figure><img src="image_8.png" /><figcaption>Figure 7: Diagramme de déploiement simplifié du Backend</figcaption></figure>

Nous pouvons retrouver ci-dessus un exemple simplifié du déploiement de l'application où nous pouvons observer les connexions entre les différents éléments ainsi que le potentiel de mise à l'échelle des analyses. Cependant ce n'est ici qu'un exemple simple du déploiement de cette application qui se voudra modulaire et dont toutes les briques pourront être mises à l'échelle horizontalement (comme évoqué précédemment pour l'api).
## 4.3 – Virtualisation de Grounded CLI

L'une des premières étapes du développement a consisté à virtualiser l'exécution de l'outil Grounded CLI afin de l'intégrer proprement en tant que service piloté par Celery. Cette étape était indispensable pour permettre son exécution automatisée et isolée au sein de l'architecture globale.

Pour construire une image Docker encapsulant la chaîne de traitement, je me suis appuyé sur la documentation de Grounded concernant l'installation de ses dépendances. Ces dépendances comprenaient :

* Des bibliothèques Python classiques (installables via pip)

* Mais aussi des outils logiciels externes comme CloudCompare ou MicMac.

La virtualisation s'est révélée particulièrement complexe en raison de ces dépendances logicielles externes, et notamment de CloudCompare. Bien que celui-ci fournisse un outil en ligne de commande capable de traiter des nuages de points, cet outil repose en interne sur une interface graphique issue du framework Qt. Dans un environnement Docker sans affichage, cette dépendance empêchait le bon fonctionnement de la CLI.

Pour résoudre ce problème, j'ai mené des recherches spécifiques sur Qt et ses mécanismes de gestion d'interface graphique. Cela m'a permis d'identifier la variable d'environnement :

```
QT_QPA_PLATFORM=offscreen
```

Cette variable configure Qt pour fonctionner en mode « offscreen », c'est-à-dire sans affichage à l'écran, ce qui permet d'exécuter les commandes dans un conteneur sans interface graphique.

En parallèle, j'ai également optimisé la taille finale de l'image Docker. L'image initiale, construite de manière monolithique, atteignait environ 9 Go du fait de l'ensemble des dépendances nécessaires à la compilation ou à l'installation des logiciels externes. Or, beaucoup de ces dépendances n'étaient plus utiles une fois la construction terminée.

Pour remédier à cela, j'ai restructuré le Dockerfile en deux étapes distinctes (multi-stage build) :
* **Stage de build**: incluant toutes les dépendances et outils nécessaires à l'installation et à la configuration des logiciels (par exemple les compilateurs, librairies de développement, packages temporaires).

* **Stage final**: ne conservant que les éléments réellement nécessaires à l'exécution (Grounded CLI et ses dépendances strictes).

Cette séparation a permis d'isoler les dépendances de construction et de ne pas les inclure dans l'image finale. Grâce à cette optimisation, la taille de l'image a pu être réduite à environ 2 Go, ce qui facilite son téléchargement, son déploiement et son utilisation sur des infrastructures cloud ou locales.

## 4.4 – Conception de l'API

### 4.4.1 – Présentation du framework Django

L'API a été développée en utilisant Django, un framework web écrit en Python qui suit le pattern architectural MTV (Model - Template - View). Ce pattern est comparable au pattern plus classique MVC (Model - View - Controller), mais avec une terminologie propre à Django.

Le tableau ci-dessous résume la correspondance entre ces deux approches :

<table><caption>Figure 8: Tableau de comparaison des patterns MVC et MTV</caption><thead><tr><td>MVC (ex : Symfony)</td><td>MTV (ex : Django)</td></tr></thead><tbody><tr><td>Model</td><td>Model</td></tr><tr><td>View</td><td>Template</td></tr><tr><td>Controller</td><td>View</td></tr></tbody></table>

Dans le pattern MTV de Django :

* **Model**: définit la structure des données et leur persistance

* **Template**: décrit la présentation des données

* **View**: contient la logique qui traite les requêtes HTTP, interagit avec les modèles et renvoie la réponse appropriée.
L'API, repose également sur Django Rest Framework (DRF), une extension de django visant
à faciliter de développement d'une API REST qui s'intègre avec Django pour fournir des
outils permettant d'exposer des routes REST. DRF offre notamment des classes génériques de
vues, des mécanismes de sérialisation des données et des outils de gestion des permissions.

Cette structure permet d'organiser le code en séparant les responsabilités principales :

* la définition des données et des schémas (Models),

• la gestion des requêtes et des règles métiers (Views),

* la production des réponses au format attendu (Serializers).

4.4.2 – Contexte et évolution de la structure de données

La structure de données du projet a été amenée à évoluer progressivement au fil du développement. Cette évolution visait à la fois à simplifier les premières itérations de l'implémentation, mais également à s'adapter aux ajustements fonctionnels intervenus durant le projet. Un aperçu global de cette structure est disponible dans le diagramme de classes joint en annexe 2.

4.4.3 – Implémentation de la modularité

Le projet repose sur l'intégration de Grounded CLI, une chaîne de traitement
modulaire composée de plusieurs types de modules ayant chacun leurs paramètres. Ces
modules, interchangeables selon le contexte d'analyse, ont nécessité une modélisation adaptée
de la structure de données, capable de représenter cette modularité tout en conservant un
couplage faible entre les composants. Pour répondre à ce besoin, un principe de
polymorphisme a été appliqué dans le modèle de données au sein du projet Django. Ce choix
permet d'encapsuler des comportements spécifiques à chaque outil tout en les unifiant sous
une interface commune.

La base de cette architecture repose sur une classe abstraite Tool, héritée de
PolymorphicModel, fournie par la bibliothèque « django-polymorphic ». Cette classe définit
une interface générique pour l'ensemble des outils utilisables dans la chaîne de traitement
(SfM, détecteurs, processeurs de nuages, etc.).
<figure><img src="image_9.png" /><figcaption>Figure 9: Classe abstraite Tool</figcaption></figure>

Chaque outil hérite d'une classe intermédiaire correspondant à son rôle fonctionnel (par exemple SFM, Detector ou CloudProcessor), puis d'une classe concrète correspondant à une implémentation précise (comme MicMac, CCTag ou CloudCompare). Chaque outil redéfinit les méthodes get_name(), get_attributes() et, si besoin, des méthodes spécifiques telles que les chemins d'accès aux fichiers générés.

Ce polymorphisme permet, entre autres :

* de générer dynamiquement des parties de la commande d'appel à Grounded cli nécessaires à l'exécution de chaque outil,

* d'exposer au niveau de l'API des champs spécifiques à chaque implémentation d'outil,

* de garantir une extensibilité future si de nouveaux modules doivent être intégrés.
Développement et mise en place d'un web service de calcul de la densité apparente des sols par photogrammétrie – Norman FRANÇOIS

Par exemple :

```python
class MicMac(SFM): 9 usages      Francois Norman
    distorsion_model = models.CharField(choices=DistorsionModel.choice, max_length=14,
                                         default=DistorsionModel.FRASER_BASIC)
    zoom_final = models.CharField(choices=ZoomFinal.choice, max_length=8, default=ZoomFinal.MIC MAC)
    tapioca_mode = models.CharField(choices=TapiocaMode.choice, max_length=8, default=TapiocaMode. ALL)
    tapioca_resolve = models.IntgerField(default=1000)
    tapioca_second_resolve = models.IntgerField(default=1000)

@staticmethod
@ Francois Norman
def get_name():
    return "micmac"

def get_attributes(self):      Francois Norman
    return {
        "distorsion_model": self.get_distorsion_model_display(),
        "zoom_final": self.get zoom_final_display(),
        "tapioca_mode": self.get_tapioca_mode_display(),
        "tapioca_resolve": self.tapioca_resolve,
        "tapioca_second_resolve": self.tapioca_second_resolve,
    }
```

<caption>Figure 10: Création du modèle du module MicMac dans l'API</caption>

## Intégration dans la configuration d'analyse

Les outils polymorphes sont regroupés dans un objet Configuration, qui représente un scénario complet d'analyse (c'est-à-dire une combinaison d'un SFM, d'un détecteur et d'un post-processeur). Cette configuration est ensuite rattachée à un utilisateur ou à une analyse.

Le modèle Configuration contient des relations vers les classes abstraites SFM, Detector et CloudProcessor, qui peuvent, selon les cas, référencer des instances concrètes comme MicMac, CCTag, ou CloudCompare.
<figure><img src="image_10.png" /><figcaption>Figure 11: Extrait simplifié du modèle Configuration</figcaption></figure>

## Sérialisation polymorphe

Pour garantir une compatibilité avec l'API REST de l'application, la sérialisation des objets polymorphes a été assurée grâce à l'utilisation de PolymorphicSerializer (provenant de drf-polymorphic). Cette structure permet de sérialiser et dés sérialiser dynamiquement les objets selon leur classe spécifique, tout en conservant une API homogène côté frontend.

Chaque groupe d'outils (SFM, détecteur, post-processeur) dispose de son propre serializer polymorphe, avec un champ « resource_type » permettant d'identifier dynamiquement la classe concernée.

<figure><img src="image_11.png" /><figcaption>Figure 12: Exemple de la création du serializer d'un module</figcaption></figure>

Nous pouvons ainsi voir ci-dessus, de quelle façon il est possible d'exposer via l'API un nouveau module en créant un serializer associé et en l'ajoutant au dictionnaire « model_serializer_mapping » du serializer de l'outil correspondant. Un utilisateur de l'API pourra ainsi lors de la création d'une configuration fournir la description des modules souhaités de telle façon :
<figure><img src="image_12.png" /></figure>

```json
"name": "Configuration de base",
"sfm": {
    "resource_type": "MicMac",
    "distortion_model": "RadialExtended",
    "zoom_final": "QuickMac",
    "tapioca_mode": "All",
    "tapioca_resolve": 1000,
    "tapioca_second_resolve": 1000
},
"cloud�processor": {
    "resource_type": "CloudCompare"
},
"detector": {
    "resource_type": "CCTag"
},
"scale_bars": [
    {
        "end": 0,
        "start": 1,
        "length": 0.22
    }
]
```

<figure><img src="image_13.png" /><figcaption>Figure 13: Exemple du contenu d'une requête de création d'une configuration</figcaption></figure>

### 4.4.4 – Gestion des fichiers

Comme évoqué précédemment, le stockage des fichiers a été externalisé vers un service cloud compatible avec l'API S3. Ce système est utilisé à la fois pour conserver les fichiers fournis par les utilisateurs et pour héberger ceux générés par l'application.

#### Accès aux fichiers par les utilisateurs

Afin de permettre aux utilisateurs d'accéder à ces fichiers, l'API met en place un mécanisme de génération d'URL pré-signées au moment où un utilisateur demande l'accès à une ressource. Ces URL pré-signées sont des liens temporaires qui autorisent le téléchargement direct du fichier concerné auprès du cloud, sans que l'utilisateur ait besoin de disposer d'identifiants ou d'autorisations spécifiques sur l'infrastructure de stockage.

Cette approche présente plusieurs avantages notables :

* **Sécurité renforcée** : Chaque URL pré-signée intègre une date d'expiration définie par l'API. Il est ainsi possible de restreindre la validité du lien à une durée précise, par exemple une heure, après laquelle l'accès au fichier devient impossible. Cela limite
considérablement les risques d'accès non autorisé, même si l'URL venait à être partagée ou interceptée.

* **Optimisation de la bande passante et des performances** : Le téléchargement des fichiers est effectué directement depuis le service cloud par l'utilisateur final, ce qui réduit la charge et le trafic réseau transitant par l'infrastructure principale. L'API n'a pas besoin de relayer les données, ce qui améliore la rapidité d'accès et contribue à la scalabilité de la plateforme, notamment en cas de volumes importants de fichiers ou de téléchargements simultanés.

En résumé, l'utilisation d'URL pré-signées constitue une solution à la fois sécurisée et performante pour la distribution des fichiers, en limitant les points d'exposition et en optimisant l'utilisation des ressources réseau.

## Envoie de fichiers par les utilisateurs

La question de l'envoi de fichiers par les utilisateurs est un sujet complexe, car les choix techniques et les bonnes pratiques dépendent fortement du contexte d'usage et du type de fichiers à transférer.

Dans le cas général des applications web, l'une des approches les plus courantes consiste à utiliser des requêtes HTTP de type multipart/form-data. Ce format permet de transmettre à la fois des fichiers et d'autres champs de formulaire dans une seule requête vers l'API. C'est un standard bien pris en charge par la plupart des navigateurs et des bibliothèques clientes.

Lors du développement du prototype de l'application, cette solution a été choisie pour l'envoi des photos à analyser vers l'API. Son principal avantage étant sa simplicité d'implémentation : côté frontend, un simple formulaire HTML ou une requête construite avec FormsData suffit ; côté backend, les frameworks comme Django REST Framework savent gérer nativement ces envois de fichiers. Cela a permis de démarrer rapidement et de valider le fonctionnement général de la chaîne de traitement.

Cependant, cette approche présente des limites importantes dès lors que l'on souhaite la généraliser à des volumes importants de fichiers ou de données :

* **Durée de la requête** : Le temps nécessaire pour envoyer plusieurs centaines de Mo voire plusieurs dizaines de Go pour certains des cas d'usages de Grounded, dépend fortement de la qualité de la connexion internet de l'utilisateur. Une connexion lente ou instable peut entraîner des délais très longs, voire des interruptions.
* **Timeout côté client** : Les navigateurs imposent souvent des limites de temps sur la durée des requêtes HTTP. Une requête trop longue peut être annulée automatiquement par le navigateur, ce qui oblige l'utilisateur à recommencer son envoi.

* **Limitations côté serveur** : Les API web sont conçues pour traiter de nombreuses requêtes simultanées. Mais une requête d'envoi de fichiers « bloquante » et très lourde mobilise des ressources serveur pendant toute sa durée. Par exemple, recevoir 600 Mo de fichiers en une seule requête monopolise un worker ou un *thread sur le serveur, limitant la capacité de l'API à répondre à d'autres requêtes en parallèle. Cela peut vite devenir un goulot d'étranglement si plusieurs utilisateurs effectuent des envois de fichiers simultanés.

C'est précisément pour contourner ces limitations liées aux envois de fichiers volumineux que, dans un second temps, j'ai proposé et conçu une solution adaptée pour gérer l'envoi de gros jeux de données.

Pour cela, je me suis appuyé sur une fonctionnalité particulièrement intéressante des URL pré-signées. Si, dans un premier temps, nous avons utilisé ces URL côté serveur pour autoriser des téléchargements sécurisés (c'est-à-dire permettre aux utilisateurs de récupérer des fichiers en respectant certaines règles d'accès et de durée de validité), il est tout aussi possible d'exploiter le même principe pour autoriser des envois directs vers le stockage distant.

Concrètement, l'idée consiste à générer côté serveur une URL d'envoi pré-signée : cette URL encadre l'envoi du fichier en imposant des contraintes précises (durée de validité limitée, taille maximale autorisée, *type MIME attendu, nom de fichier, etc.). Grâce à ce mécanisme, l'utilisateur peut transférer directement son fichier vers un service de stockage S3 (comme MinIO ou un équivalent), sans passer par le serveur d'application. Cela permet de soulager l'API, qui n'a plus à gérer elle-même le transfert des gros volumes de données, tout en gardant un contrôle fin et sécurisé sur ce qui est accepté.

Cependant, il est vite apparu qu'une telle solution, prise isolément, ne répondait pas pleinement à nos besoins. En effet, dans notre cas d'usage, il ne s'agit pas d'envoyer un seul gros fichier, mais un ensemble potentiellement très important de photos constituant un jeu de données complet. Pour garantir un flux de transfert efficace, fiable et adapté à la diversité des cas d'utilisation, il a donc fallu aller plus loin :

J'ai dû réfléchir et concevoir un protocole d'envoi spécifique permettant de gérer ces envois massifs de façon souple et robuste. L'objectif principal étant d'assurer une flexibilité maximale en permettre à l'utilisateur d'envoyer un grand nombre de fichiers tout en
bénéficiant d'un contrôle granulaire, d'une meilleure tolérance aux erreurs réseau, et d'une
expérience utilisateur plus fluide même sur des connexions moins stables. Pour cela, j'ai
dissocié la création d'un dataset de celle des photos qui lui sont associées. Chaque photo est
créée individuellement en fournissant à l'API les métadonnées du fichier concerné, ce qui
crée une requête d'envoi vers le cloud S3 spécifique à ce fichier. Le client est ensuite
responsable du transfert des données vers le cloud. Une fois l'envoi effectué, le client doit
 notifier l'API de la fin de ce transfert. Lorsque toutes les photos ont été envoyées, le client
informe l'API que l'envoi du dataset est complet.

<figure><img src="image_14.png" /><figcaption>Figure 14: Protocole
d'envoi d'un dataset</figcaption></figure>

4.4.5 – Tests unitaires

Afin de garantir la fiabilité et la stabilité de l'API développée, une batterie complète de
tests unitaires a été mise en place. Ces tests ont été conçus pour vérifier le bon déroulement
des principales fonctionnalités, notamment la gestion des jeux de données, la manipulation
des fichiers associés, ainsi que le respect des règles de sécurité et des permissions entre
utilisateurs.
Pour faciliter l'exécution des tests impliquant des fichiers, j'ai utilisé une méthode d'override du stockage. Cette technique permet de remplacer temporairement le système de stockage des fichiers par un système en mémoire lors des tests, évitant ainsi d'effectuer de réelles opérations d'entrée/sortie. Cette approche améliore significativement la rapidité des tests tout en maintenant leur pertinence fonctionnelle.

```java
@override_storage() = Francois Norman +1
@overrideSettings(ANALYSE_TASK="api/tasks.fake_analyse",
    CELERY_TASK_always_eager=True,
    CELERY_TASK_eagerpropagates=True)
class AnalysisViewSetTestCase(APITestCase):
```

<caption>Figure 15: Exemple de la modification dynamique des paramètres lors des tests</caption>

Les tests couvrent plusieurs axes :

* La création et la confirmation de jeux de données dans de nombreuses configurations, garantissant ainsi la cohérence des états et la gestion des erreurs.

* La gestion stricte des permissions d'un utilisateur, empêchant par exemple un utilisateur d'accéder ou de modifier les données appartenant à un autre utilisateur.

* La validation des opérations sur les analyses et configurations associées, incluant la création, la modification, et les restrictions de suppression selon les cas.

Pour automatiser et intégrer ces tests dans le cycle de développement, j'ai mis en place un pipeline GitLab CI/CD afin de garantir leur bonne exécution lors des développements ultérieurs. J'ai configuré la génération des rapports de tests au format JUnit XML en utilisant la bibliothèque « unittest-xml-reporting », ainsi qu'un fichier de configuration spécifique pour le pipeline GitLab. Cette configuration permet de collecter automatiquement les résultats comme rapports dans GitLab, offrant une visualisation claire des erreurs, échecs et succès directement dans l'interface de la plateforme, facilitant ainsi le suivi à chaque commit ou merge request (voir annexe 3 : Visualisation de l'exécution des tests dans un pipeline GitLab).

Cette démarche assure la qualité continue du code, tout en limitant les risques de régressions fonctionnelles lors d'évolutions futures du projet.
4.4.6 – Documentation

Pour faciliter le développement et la maintenance du projet, j'ai mis en place une documentation automatique des différentes routes de l'API à l'aide de la bibliothèque drf_spectacular. Cette solution permet de générer un schéma OpenAPI (Swagger) qui décrit clairement les points d'accès, les méthodes HTTP disponibles, les paramètres attendus et les réponses possibles.

L'objectif principal étant d'offrir un support clair et à jour aux développeurs qui seront amenés à utiliser ou à faire évoluer cette API. Pour aller plus loin qu'une simple génération automatique, j'ai pris soin d'enrichir la documentation grâce aux décorateurs fournis par la bibliothèque. Ces ajouts permettent notamment :

* de préciser les codes de réponse HTTP possibles ;

* de résumer et décrire le comportement des différentes actions ;

* de fournir des exemples concrets de requêtes ou de réponses, en particulier pour les routes les plus complexes.

J'ai également structuré les différentes vues de l'application afin que chaque route dispose d'explications adaptées à son usage, en utilisant les décorateurs « @extend_schema » et « @extend_schema_view ». Ces annotations rendent la documentation plus compréhensible et directement exploitable, en reflétant la logique réelle du projet.

En mettant cela en place, j'ai voulu m'assurer que l'API reste lisible et accessible même pour ceux qui n'ont pas participé à son développement initial, tout en respectant les standards de documentation d'API REST.
<figure><img src="image_15.png" /><figcaption>Figure 16: Extrait d'une partie de la documentation de l'api</figcaption></figure>

### 4.4.7 – Interface administrateur

Django intègre nativement un système d'interface d'administration puissant, qui permet de générer très rapidement une interface complète, fonctionnel et sécurisé. Cet outil facilite grandement la gestion des données métier d'un projet. La configuration de cette interface se fait dans un fichier dédié, admin.py, dans lequel chaque modèle doit être enregistré explicitement pour apparaître dans l'interface. Ce fichier permet également de personnaliser en profondeur l'affichage, les filtres, la navigation et les interactions entre objets.

Pour chaque modèle, Django offre plusieurs mécanismes de configuration qui améliorent l'expérience de gestion des données :

* Les colonnes à afficher en liste (list_display), pour voir immédiatement les champs les plus pertinents.

* Les filtres latéraux (list_filter), pour affiner rapidement la recherche sur des critères courants.
* Les champs de recherche (`search_fields`), permettant de retrouver facilement un enregistrement.

* L'ordre par défaut des résultats (`ordering`), pour organiser les listes de manière logique.

<figure><img src="image_16.png" /><figcaption>Figure 17: Exemple de la définition d'une page de l'interface administrateur</figcaption></figure>

## Expérience utilisateur

En plus de ces éléments, j'ai mis en place des inlines, qui sont des interfaces imbriquées permettant de modifier des objets liés directement depuis la page du modèle parent. Par exemple :

* Les photos d'un jeu de données peuvent être ajoutées ou modifiées directement depuis la fiche de ce jeu de données.

* Une analyse peut intégrer directement l'édition et la visualisation de sa configuration via une interface intégrée.

* Les fiches des utilisateurs affichent également les jeux de données et analyses associés, pour offrir une vue globale de leur activité.

Ce type d'intégration améliore considérablement la fluidité d'utilisation, en limitant les allers-retours entre écrans et en centralisant les opérations de gestion.

## Gestion des modules polymorphes

L'un des besoins spécifiques du projet a été de représenter dynamiquement différents types de traitements ou modules au sein d'une configuration, chacun ayant ses propres attributs. Pour cela, j'ai intégré la bibliothèque « `django-polymorphic` », qui permet de gérer proprement des hiérarchies de modèles hérités avec un seul point d'entrée.

Par exemple, une configuration peut embarquer un module de type `SFM`, dont une implémentation spécifique est `MicMac`, ou un module de `CloudProcessing`, basé sur
CloudCompare. Grâce à l'administration polymorphe, ces sous-modèles peuvent être gérés
via une interface commune tout en gardant leurs particularités.

```python
@admin.register(SFM)      = francois
class SFMParentAdmin(PolymorphicParentModelAdmin):
    base_model = SFM
    child_models = (MicMac,)

    def has_module permission(self, request): = francois
    return False

@admin.register(MicMac)    = francois
class MicMacAdmin(PolymorphicChildModelAdmin):
    base_model = MicMac

    def has_module permission(self, request): = francois
    return False
```

<caption>Figure 18: Intégration d'un module polymorphique dans l'interface d'administration</caption>

## Amélioration de l'interface

Dans le but de rendre l'interface d'administration plus agréable et moderne, j'ai mené des recherches sur les solutions existantes permettant d'améliorer l'apparence par défaut de Django Admin. En effet, l'interface native, bien que fonctionnelle, reste assez austère et peu intuitive pour certains utilisateurs.

À l'issue de cette exploration, j'ai choisi d'intégrer la bibliothèque « unfold ». Cette extension permet de moderniser visuellement l'administration Django sans altérer sa logique interne. Elle offre notamment :

* une interface plus esthétique et *responsive

* une meilleure hiérarchisation des sections et champs

* un affichage plus clair des inlines et des filtres

Grâce à unfold, j'ai pu structurer les écrans d'administration de façon plus ergonomique, avec des composants bien espacés, des onglets ou sections repliables, et une navigation facilitée. (voir Annexe 6)
## 4.5 – Conception du client web

### 4.5.1 – Présentation du framework Vue.js

Le client web du projet a été développé avec Vue.js, un framework JavaScript permettant la création d'interfaces utilisateur réactives reposant sur un système de composants permettant de structurer le code de façon modulaire et réutilisable.

Dans ce projet, j'ai utilisé Vue 3 ainsi que sa nouvelle API Composition, qui permet d'organiser la logique métier de manière plus claire et de la partager facilement entre composants. Par exemple, les appels à l'API backend ou la validation des formulaires sont définis dans des fonctions réutilisables. La gestion de l'état global ainsi que des services centraux de l'application est assurée par Pinia, la solution officielle pour Vue 3.

### 4.5.2 – Gestion de la communication avec l'API

Pour permettre à l'application web de communiquer avec le serveur, j'ai mis en place une couche dédiée, appelée API Store, qui centralise toutes les interactions entre le client et le backend.

Dans une application web moderne, le client doit souvent interroger un serveur pour récupérer ou envoyer des données : par exemple pour afficher la liste des utilisateurs, enregistrer un formulaire ou supprimer un élément. Ces échanges se font via des requêtes HTTP vers une API.

Pour rendre ce dialogue robuste et maintenable, j'ai choisi de regrouper la logique de communication en un seul module réutilisable. Dans mon projet, cette couche est réalisée sous la forme d'un store géré par Pinia.

Ceci permet de centraliser l'état et la logique métier de l'application. Au lieu de dupliquer la logique dans chaque composant, on la regroupe dans un store unique qui peut être utilisé partout.

Par exemple, on garde dans ce store :

* L'utilisateur actuellement connecté.

* L'état d'authentification.

* Les fonctions permettant de se connecter ou de se déconnecter.
* Les différentes fonctions permettant d'interagir avec les différentes ressources de l'api.

Pour l'envoi des requêtes HTTP au serveur, j'ai utilisé Axios, une bibliothèque JavaScript populaire simplifiant grandement la configuration des requêtes et leur gestion (par exemple l'envoi d'en-têtes ou la récupération de réponses JSON).

<figure><img src="image_17.png" /><figcaption>Figure 19: Configuration du client Axios</figcaption></figure>

Le store initialise un client Axios préconfiguré :

* `baseURL` est l'URL de l'API du serveur.

* `withCredentials` est activé pour gérer automatiquement les cookies (par exemple pour les sessions d'utilisateur).

* Les en-têtes sont configurés pour accepter le JSON

Ce client est ensuite utilisé au sein des différentes fonctions métier du store.
<figure><img src="image_18.png" /><figcaption>Figure 20: Exemple d'une fonction de l'apiStore</figcaption></figure>

Dans l'exemple ci-dessus, on peut voir la fonction « getById » du store API. Celle-ci met en
place une reconnexion automatique si les cookies d'authentification de l'utilisateur ont expiré,
et transforme également les erreurs renvoyées par l'API en un format standardisé plus facile à
exploiter par les autres modules de l'application.

Cette fonction est ensuite utilisée au sein des modules de cette façon :

<figure><img src="image_19.png" /><figcaption>Figure 21: Exemple d'utilisation de l'apiStore dans un module</figcaption></figure>
### 4.5.3 – Fonctionnalités principales

Le client web a été conçu dans le but d'accompagner aussi bien un utilisateur non expert qu'un utilisateur avancé dans l'usage de la plateforme Grounded Web. Il s'agit donc d'une interface pensée pour être accessible et simple de prime abord, tout en donnant accès à des fonctionnalités avancées via des menus. Ainsi des utilisateurs avancés peuvent pleinement exploiter l'outil, sans que les utilisateurs non experts ne soient noyés par des excès de choix de paramétrage (voir les différentes pages en annexe 5).

#### Création d'un jeu de données

La création d'un jeu de données est facilitée par un formulaire simple et intuitif. L'utilisateur renseigne les informations nécessaires et sélectionne les images à inclure dans le jeu de données. Une fois le formulaire validé, le client web se charge de l'envoi des fichiers vers le serveur en respectant le protocole d'authentification et de sérialisation mis en place précédemment (gestion des en-têtes, du token, et des éventuelles erreurs).

Par exemple, un utilisateur peut choisir une série de photos, renseigner un titre, puis lancer l'envoi en un seul clic. Le store API prend en charge la gestion des requêtes et des éventuelles erreurs réseau.

#### Lancement d'une analyse

Pour offrir une meilleure expérience utilisateur, le lancement d'une analyse se fait via un formulaire multi-étapes.

* **Première étape**: l'utilisateur sélectionne le jeu de données sur lequel il souhaite lancer l'analyse (ou le crée facilement via un bouton ; voir paragraphe « Création d'un jeu de données »). Cette étape intègre la récupération et l'affichage des jeux de données disponibles, grâce à des appels à l'API.

* **Seconde étape**: l'utilisateur configure les paramètres d'analyse. Cette configuration peut inclure des options telles que le choix des modules à activer ou les réglages utilisés lors de la prise de vue.

L'objectif est de guider l'utilisateur pas à pas et d'éviter les erreurs de configuration, même pour des utilisateurs n'ayant pas de compétences techniques avancées.
## Visualisation d'une analyse

La visualisation des résultats est une fonction clé du client web. Cette page a été conçue pour permettre d'explorer de manière ergonomique l'ensemble des fichiers produits par le traitement d'une analyse.

Elle offre :

* L'accès au fichier de résultats au format pdf ainsi que la visualisation dans un tableau de ces derniers.

* La visualisation du jeu de données initial.

* La visualisation des nuages de points générés au cours de l'analyse se fait dans une visionneuse 3D que j'ai mise en place à l'aide de la librairie Three.js.

* La visualisation des logs de l'analyse dans une interface ressemblant très fidèlement à un terminal et utilisant le même formatage couleur qu'un vrai terminal.

Cette partie a été particulièrement travaillée pour répondre aux besoins des utilisateurs avancés afin de continuer l'expérimentation de la méthode et ce tout en restant clair et compréhensible pour les profils moins techniques.

## Gestion des configurations

La gestion des configurations s'adresse avant tout aux utilisateurs avancés qui souhaitent personnaliser et affiner leurs analyses. Elle permet d'enregistrer, de modifier ou de supprimer des configurations d'analyse.

Une configuration d'analyse regroupant tous les paramètres liés l'exécution d'une analyse, le formulaire comprend la définition des réglets, le choix des modules utilisés dans la chaîne de traitement ainsi que leurs paramètres.

## Navigation parmi les analyses et les jeux de données

La navigation entre les analyses et les jeux de données se fait au moyen d'un tableau intégrant un mécanisme de défilement infini. Ce système permet de charger les résultats par lots successifs lorsque l'utilisateur fait défiler la page, ce qui évite de charger l'ensemble des données en une seule fois et améliore les temps de réponse.
Ces vues proposent des fonctionnalités de recherche textuelle permettant de retrouver des ressources spécifiques. Des options de filtrage et de tri sont également disponibles, afin de limiter les résultats à certains critères ou d'en modifier l'ordre d'affichage. L'ensemble de ces fonctionnalités vise à permettre la consultation et la gestion d'un grand nombre d'analyses ou de jeux de données de manière structurée et adaptée aux besoins de l'utilisateur.4.6 – Déploiement de l'application.

## 4.6 – Déploiement de l'application

### 4.6.1 – Environnement de développement

L'application GroundedWeb dispose d'un environnement de développement spécifiquement conçu pour simplifier et accélérer le travail des développeurs. Dans ce contexte, le mode DEBUG de Django est activé, ce qui permet d'obtenir un affichage détaillé des erreurs rencontrées et ainsi de diagnostiquer rapidement les problèmes. Les origines (CORS) sont autorisées sans restriction, facilitant les tests locaux sans configuration supplémentaire des hôtes. Le système d'envoi d'e-mails est quant à lui remplacé par un backend simplifié qui affiche les messages dans la console au lieu de les expédier réellement, réduisant ainsi les risques d'erreurs ou d'envois non souhaités pendant la phase de développement.

L'ensemble de l'environnement backend peut être lancé de façon homogène et standardisée sur toutes les machines des développeurs grâce à la commande :

```
>> docker compose up
```

Par ailleurs, le frontend développé avec Vue.js doit également être démarré séparément en mode développement afin de bénéficier du rechargement à chaud et des outils de débogage dédiés. Cela se fait via la commande suivante, exécutée dans le répertoire du projet front :

```
>> rpm run dev
```

Cette organisation permet d'assurer un cycle de développement fluide tout en rapprochant autant que possible les conditions locales de celles de production.

### 4.6.2 – Environnement d'intégration continue (CI)

L'environnement d'intégration continue est conçu pour automatiser la validation du code à chaque modification, en assurant un contrôle de qualité systématique. Son objectif
principal est de vérifier que les évolutions n'introduisent pas de régressions et que l'application reste fonctionnelle sur l'ensemble des branches actives du projet.

Dans le cadre de ce projet, le pipeline d'intégration continue est configuré sur GitLab CI. Il s'exécute automatiquement à chaque commit ou demande de fusion sur le dépôt. Le pipeline prévoit notamment une phase de tests automatisés, qui garantit que les fonctionnalités restent conformes aux attentes. Cette étape reproduit les conditions de l'application dans un environnement isolé et contrôlé, en simulant les services externes nécessaires (comme la base de données ou la file de messages) pour valider l'ensemble des composants.

En complément des tests, le pipeline intègre également une phase de construction des images Docker de l'application. Ces images, versionnées en fonction des branches ou des tags, sont ensuite poussées dans un registre de conteneurs. Cela facilite le déploiement dans les différents environnements, en garantissant que les versions construites et testées sont strictement celles qui seront utilisées en production.

### 4.6.3 – Environnement de production

L'environnement de production est configuré pour garantir la sécurité, la fiabilité et la performance de l'application une fois déployée auprès des utilisateurs finaux. Le mode DEBUG de Django est désactivé afin d'éviter toute divulgation d'informations techniques sensibles en cas d'erreur. Les hôtes autorisés sont définis explicitement pour restreindre l'accès au service aux seuls domaines souhaités, limitant ainsi le risque d'exposition involontaire. La sécurité des cookies est renforcée pour réduire les attaques potentielles (comme le vol de session), et l'envoi des e-mails est paramétré pour utiliser un serveur SMTP réel, afin de faire parvenir les notifications aux utilisateurs.

Le serveur d'application repose sur Gunicorn, un serveur WSGI performant conçu pour exécuter le code Python de Django de manière robuste en production. En amont de Gunicorn, Nginx est utilisé en tant que reverse proxy. Son rôle est d'intercepter les requêtes HTTP entrantes des clients et de les transmettre au serveur d'application approprié. Ce mécanisme permet notamment de masquer la complexité interne du service et d'offrir une couche supplémentaire de sécurité et de configuration fine (par exemple, en filtrant ou en réécrivant les requêtes).

Le principe même du reverse proxy permet à Nginx de jouer un rôle de load balancer si nécessaire : il peut répartir la charge entre plusieurs instances de Gunicorn ou de l'application, améliorant la scalabilité et la tolérance aux pannes. Cela permet d'adapter facilement le déploiement à un trafic plus important ou de garantir la haute disponibilité du service. Enfin,
le déploiement en production est facilité grâce à l'usage de fichiers Docker Compose spécifiques qui orchestrent la combinaison de tous ces services, que ce soit pour des tests en environnement local ou pour un déploiement sur un serveur distant.

Le déploiement en production s'appuie sur des fichiers Docker Compose qui orchestrent la combinaison de ces services, tant pour des tests locaux simulant la production que pour un déploiement sur un serveur distant. Concrètement, l'équipe peut lancer l'ensemble de la stack backend en production avec la commande suivante :

```
>> docker compose -f docker-compose.yml -f docker-compose.prod.yml up
```

Tandis que le déploiement du frontend, se trouvant dans un projet séparé, se fait facilement via la commande :

```
>> docker compose up
```

Pour aller plus loin vous pouvez retrouver en annexe 7 un guide détaillé de déploiement en production.

### 4.6.4 – Gestion des configurations et variables d'environnement de l'API

Pour organiser la configuration de manière claire et maintenable, le projet repose sur une architecture modulaire de fichiers Python hiérarchisés. Cette organisation permet de centraliser les paramètres communs à tous les environnements dans un fichier de base, tandis que chaque environnement (développement, CI, production, etc.) dispose d'un fichier dédié qui hérite de cette configuration de référence. Grâce à ce système d'héritage, il devient facile de personnaliser uniquement les éléments nécessaires pour un contexte donné sans dupliquer l'ensemble de la configuration.

Les paramètres sensibles ou spécifiques au contexte d'exécution tels que les mots de passe, les clés d'API, ou les URL de base de données ne sont jamais écrits en dur dans le code source. Ils sont injectés dynamiquement via des variables d'environnement définies dans des fichiers .env non versionnés. Cette pratique améliore considérablement la sécurité (en évitant toute fuite accidentelle) tout en rendant le déploiement plus flexible et adaptable à différents environnements.

Dans le cadre de ce projet, l'environnement de production est en réalité exécuté sur un réseau interne sans résolution DNS publique. Pour répondre à ce besoin particulier, une configuration spécifique a été prévue sous la forme d'un fichier production_local.py. Celui-ci hérite directement des paramètres de la configuration production.py, mais désactive certaines
contraintes de sécurité adaptées uniquement à un déploiement public (comme l'obligation de connexions sécurisées HTTPS pour les cookies ou les jetons JWT).

<figure><img src="image_20.png" /><figcaption>Figure 22: Contenu du fichier de configuration production_local.py</figcaption></figure>

Cette configuration permet de conserver les optimisations propres à l'environnement de production tout en tolérant certaines flexibilités utiles dans un contexte local contrôlé (par exemple : accès en HTTP simple en absence de certificat SSL). Elle est utilisée comme base par défaut dans les fichiers Docker Compose de production du projet, facilitant ainsi le déploiement sur un serveur interne ou en environnement de test avancé tout en conservant une séparation claire avec la configuration destinée à un déploiement public.

### 4.6.5 – Avantages de cette approche

Cette organisation des environnements et de la configuration permet de garantir une séparation claire des usages, d'assurer la sécurité des informations sensibles et de rendre le déploiement reproductible sur n'importe quel serveur ou machine. Elle facilite la collaboration entre développeurs en fournissant des commandes de lancement standardisées, tout en permettant aux futures équipes DevOps ou administrateurs système de déployer l'application de façon adaptée à leur environnement de production. Cette approche modulaire et conteneurisée contribue ainsi à la robustesse et à la maintenabilité du projet sur le long terme.
# V – Méthodologie

## 5.1 – Organisation du travail en entreprise

Le laboratoire ne dispose pas d'une hiérarchie formelle dédiée au développement logiciel : j'étais le seul développeur de métier affecté à ce projet, et donc également le seul en charge du développement du backend et du frontend. En l'absence de structure rigide ou d'équipe technique dédiée, je me suis fixé mes propres normes de travail et de qualité pour encadrer le développement. Nous avons malgré tout maintenu une organisation minimale et adaptée avec mon tuteur de stage mettant en place un tableau Trello pour suivre les demandes fonctionnelles, les bugs, les tâches en cours et les priorités. Cette forme légère de « \*backlog » nous a permis de classer les tâches par importance et de maintenir une vision partagée de l'avancement.

En termes de validation et prise de décision, nous avons fonctionné par réunions ponctuelles : j'ai participé à quatre réunions de projet plus larges, réunissant tous les membres de l'équipe, dont trois incluaient le prestataire externe chargé du développement de l'application mobile d'aide à la prise de vue. Ces échanges permettaient d'aligner les attentes et d'assurer la cohérence globale du projet. Pour les choix techniques spécifiques ou les arbitrages sur les fonctionnalités, je proposais à mon maître de stage différentes options, avec leurs avantages et inconvénients, pour décider ensemble de la meilleure approche.

Une version en cours de développement était continuellement disponible sur un des serveurs internes du laboratoire. Les utilisateurs pouvaient la tester et remonter des bugs ou des remarques. Cette boucle de retour utilisateur a contribué à affiner les priorités et corriger les problèmes au fur et à mesure sans démarche particulière d'installation de la part des utilisateurs.

## 5.2 – Gestion du code et du versionnement

Pour le contrôle de version, nous avons utilisé la forge GitLab de l'INRAE, organisée en deux dépôts : un pour le backend et un pour le frontend. La gestion suivait un GitLab Flow structuré avec :

* des branches principales (main et development),

* des branches de fonctionnalités ou de correctifs (feature/*, fix/*),
* un usage des tags pour marquer les versions.

Au fur et à mesure de mon développement, je faisais mes commits et créais des merge requests que j'acceptais moi-même, faute de collègues disponibles pour effectuer des revues de code.

Pour l'intégration continue, j'ai mis en place des pipelines GitLab CI automatisés dont la charge était :

* l'exécution des tests

* la création automatique les images Docker des projets ainsi que l'envoi sur le registre de conteneurs Gitlab associé

Les règles de déclenchement de la construction des images étaient :

* sur main : création de l'image latest

* sur development : création de l'image staging

* sur les tags : images versionnées correspondant au tag (ex. v1.0.0)

Cette approche a permis de fiabiliser le déploiement, de faciliter l'installation des mises à jour et d'assurer une traçabilité claire des versions livrées.

## 5.3 – Approche personnelle et autonomie

En tant que seul développeur sur le projet, j'ai travaillé avec un haut degré d'autonomie. Lors de blocages ou de problèmes techniques, je prenais systématiquement le temps de chercher des solutions par moi-même, en consultant la documentation officielle des frameworks utilisés, en parcourant des forums tels que Stack Overflow, ou en recourant à des outils d'intelligence artificielle pour générer des exemples ou approfondir certains concepts. J'ai également échangé avec Armel THÖNI, ingénieur d'étude développeur au sein du département OpenFLUID, qui m'a parfois orienté au cours de mon stage, notamment lors de réunions avec mon tuteur. J'ai pu lui poser des questions sur certaines bonnes pratiques et obtenir la validation de mes choix techniques, en particulier concernant l'utilisation du framework Django.
Tout au long du projet, j'ai veillé à appliquer les bonnes pratiques de développement, à les faire évoluer au fil de mes apprentissages et des besoins rencontrés. Cela s'est traduit par une amélioration progressive de l'architecture du code, une séparation claire des responsabilités entre les composants, ainsi qu'une structuration modulaire facilitant la lisibilité, la maintenance et l'évolution du projet. J'ai également fait preuve de proactivité en allant au-delà des attentes initiales du stage, en proposant et en mettant en œuvre plusieurs fonctionnalités ou orientations techniques non spécifiquement demandées. Parmi ces initiatives, on peut citer la mise en place d'une architecture modulaire pour la gestion des configurations, l'intégration d'un système de visualisation des nuages de points directement dans le navigateur, ou encore le choix de solutions techniques favorisant la maintenabilité du projet et simplifiant son déploiement.

En parallèle du développement principal, j'ai également pris en charge plusieurs aspects transverses essentiels au bon déroulement du projet. J'ai ainsi mené des démarches auprès des services internes de l'INRAE pour obtenir des hébergements informatiques, bénéficier d'accès SMTP ou encore demander un stockage cloud compatible S3, en rédigeant et formalisant les besoins techniques auprès des équipes support concernées via une plateforme interne nommée Ariane. J'ai assuré plusieurs présentations orales du projet : auprès de l'équipe projet élargie lors de réunions spécifiques, mais aussi à l'occasion de la journée de présentation des travaux des stagiaires, permettant de partager les avancées et les choix techniques réalisés. J'ai également participé aux échanges avec le prestataire externe chargé de l'application mobile, en apportant un regard technique et en clarifiant certains choix d'implémentation pour assurer la cohérence globale du projet.

Enfin, j'ai également assisté à la phase expérimentale en participant aux tests d'évaluation de la précision de la méthode, notamment par des mesures de volumes sur des étalons réalisés en un mélange de sable et de résine.
<figure><img src="image_21.png" /><figcaption>Figure 23: Mesure du volume des étalons par poussée d'Archimède</figcaption></figure>

<figure><img src="image_22.png" /><figcaption>Figure 24: Configuration d'expérimentation</figcaption></figure>
Conclusion

En arrivant au terme de ce stage, je peux dresser un bilan positif du projet Grounded tel qu'il a évolué cette année. Par rapport aux objectifs initiaux définis avec mon tuteur, j'ai livré un outil bien plus complet et opérationnel qu'attendu ce qui contribuera grandement à la maturation du projet. Grâce à l'architecture modulaire mise en place, à la séparation claire du frontend et du backend, ainsi qu'à la gestion rigoureuse des versions et déploiements via Docker et GitLab CI/CD, le projet est aujourd'hui parfaitement reprenable et maintenable. L'API sera utilisé par l'application mobile d'aide à la prise de vue, ainsi qu'à des fins d'expérimentation et de test de la méthode en association avec le client web, elle pourra éventuellement être aisément confiée à d'autres développeurs ou stagiaires pour la faire évoluer sur de nouvelles fonctionnalités ou adapter son interface aux besoins des utilisateurs.

Le principal apport au système d'information du laboratoire réside dans la centralisation et la simplification des traitements. L'application web offre un point d'entrée unique et ergonomique pour gérer la configuration des analyses, suivre les exécutions, répartir la puissance de calcul et visualiser les résultats. La mise en place d'un backend complet permet aux chercheurs de configurer et combiner facilement les modules, favorisant ainsi l'expérimentation scientifique et la reproductibilité des analyses pour des personnes non expertes. En permettant l'accès à ces traitements même pour des utilisateurs non spécialistes, le projet apporte une réelle valeur ajoutée et soutient la diffusion de la méthode de mesure de la densité apparente des sols par photogrammétrie au sein de la communauté scientifique et bien plus à terme.

Ce stage m'a également permis de développer de nombreuses compétences en lien avec le référentiel du BUT Informatique. J'ai travaillé l'analyse des besoins utilisateur ainsi que la formalisation des exigences, dans un contexte où aucun cahier des charges détaillé n'existait, en organisant des discussions régulières avec mon tuteur et parfois les autres membres de l'équipe. J'ai amélioré ma capacité à concevoir et développer des applications complètes et maintenables, en appliquant de bonnes pratiques de séparation des responsabilités et en documentant mes choix techniques. J'ai consolidé mes compétences en gestion de projet informatique, grâce à la mise en place de pipelines d'intégration continue, la gestion des branches et des versions sur GitLab, et l'automatisation des déploiements Docker. Enfin, j'ai développé ma compétence de communication professionnelle, en présentant le projet à plusieurs reprises devant l'équipe et en échangeant avec les différents services internes de l'INRAE pour organiser l'hébergement, l'accès à un serveur smtp ou les accès aux services cloud.
*Développement et mise en place d'un web service de calcul de la densité apparente des sols par photogrammétrie – Norman FRANÇOIS*

De nombreuses pistes d'amélioration demeurent pour la suite : enrichir la bibliothèque de modules d'analyse ou encore perfectionner l'ergonomie et le design de l'interface utilisateur pour la rendre plus professionnelle. Ces évolutions permettront de renforcer encore l'utilité de la plateforme Grounded, en l'adaptant au mieux aux besoins des chercheurs et aux exigences de la recherche.

Visa du tuteur de stage (vu le 18/07/2025):

<figure><img src="image_23.png" /></figure>
# Bibliographie

[1] G. Coulouma, D. Feurer, F. Vinatier, et O. Huttel, « Assessing new sensor-based volume measurement methods for high-throughput bulk density estimation in the field under various soil conditions », *European Journal of Soil Science*, vol. 72, n° 5, p. 2049-2061, 2021, doi: 10.1111/ejss.13115.

[2] « Celery - Distributed Task Queue — Celery 5.5.3 documentation ». [En ligne]. Disponible sur: https://docs.celeryq.dev/en/stable/ [Consulté le : 10-avril-2025]

[3] CodeUmwelt, « Django REST API with Custom User Model & JWT Cookie Authentication — Configure Authentication... », Medium. [En ligne]. Disponible sur: https://medium.com/@CodeUmwelt/django-rest-api-with-custom-user-model-jwt cookie-authentication-configure-authentication-2b33076c4b8e [Consulté le : 8-avril-2025]

[4] « Docker Compose », Docker Documentation. [En ligne]. Disponible sur: https://docs.docker.com/compose/ [Consulté le : 13-mai-2025]

[5] « Documentation de Django | Django documentation », Django Project. [En ligne]. Disponible sur: https://docs.djangoproject.com/fr/5.2/ [Consulté le : 22-mai-2025]

[6] « Home », Docker Documentation. [En ligne]. Disponible sur: https://docs.docker.com/ [Consulté le : 24-juin-2025]

« Home - Django REST framework ». [En ligne]. Disponible sur: https://www.djangorest-framework.org/ [Consulté le : 7-avril-2025]

[8] « Qt Documentation Feedback ». [En ligne]. Disponible sur: https://www.surveymonkey.com/r/8XKW76J?pagename=%2F [Consulté le : 25-avril-2025]
# Annexes

## Table des annexes

<table><tr><td>Annexe 1 : Offre de stage</td><td>III</td></tr><tr><td>Annexe 2 : Diagramme de classe de l'API</td><td>V</td></tr><tr><td>Annexe 3 : Visualisation de l'exécution des tests dans un pipeline gitlab</td><td>VI</td></tr><tr><td>Annexe 4 : Exemple de la documentation d'une route de l'API</td><td>VII</td></tr><tr><td>Annexe 5 : Aperçu des différentes page du client web</td><td>VIII</td></tr><tr><td>Annexe 6 : Interface administrateur</td><td>XIV</td></tr><tr><td>Annexe 7 : Guide de déploiement en prod de l'application GroundedWeb</td><td>XV</td></tr><tr><td>Annexe 8 : Bilan-critique/Perspectives</td><td>XIX</td></tr></table>
# Annexe 1 : Offre de stage

## Développement et mise en place d'un webservice de calcul de la densité apparente des sols par photogrammétrie

### Sujet Stage - 2024/2025

## Contexte

La densité apparente des sols est une mesure de premier ordre en science du sol. Elle est nécessaire aux calculs de stocks - en particulier les stocks de carbone qui constituent un enjeu majeur aujourd'hui, aux bilans de masse tels que le bilan hydrique, et à la paramétrisation de modèles de transferts dans le sol (eau, polluants). C'est une propriété difficile à mesurer et les méthodes existantes ne sont pas généralisables. C'est en particulier le cas pour les sols caillouteux et les sols très organiques de tourbière.

Une nouvelle méthode rapide de mesure in-situ de la densité apparente du sol basée sur la mesure du volume d'excavation par photogrammétrie a donc été développée au LISAH (Coulouma et al. 2021). La comparaison avec des méthodes standardisées a démontré une bonne précision de la mesure et une applicabilité à tout type de sol, en particulier pour les sols caillouteux. La méthode est aujourd'hui utilisée par d'autres équipes de recherche (Siegwart et al., 2023) et pourrait venir s'ajouter aux mesures de référence de la densité en sciences du sol.

En 2024 un script python de traitement automatisé des images photogrammétriques, appelé « grounded », a été développé. Ce script est désormais non seulement utilisé par l'équipe pour les traitements des images en opérationnel mais continue aussi à être développé pour améliorer ses fonctionnalités et la robustesse des algorithmes. Par ailleurs l'équipe d'accueil a obtenu le financement d'un projet de pré-maturation démarrant en 2025 et visant à développer un prototype d'application smartphone guidant les utilisateurs pour la prise d'images sur le terrain. Le guidage des utilisateurs via cette application assurera la qualité des jeux de données image pour le traitement photogrammétrique.

Dans la perspective d'avoir un prototype de cette application, il ne restera ainsi, pour avoir une chaîne complète du terrain au résultat, qu'à développer un webservice sur lequel l'appli enverra les photos et qui renverra en retour les estimations de volumes des échantillons de sol. Le LISAH souhaite créer ce webservice de manière à, en interne, pouvoir utiliser l'outil « grounded » sans connaissance informatique ni pré-requis ou installation locale et, en externe, pouvoir accueillir les images issues de la future application.

## Sujet de stage :

L'objectif de ce stage vise à développer, documenter et mettre en place un webservice de traitement des images basé sur le script « grounded » développé précédemment.
## Activités :

* Conteneurisation du logiciel existant (docker ou singularity)

* Détermination de la solution d'hébergement adaptée

* Mise en place d'un backend (proposition – non statué : flask ou Django)

* mise en place d'une API et tests

* Mise en place d'un frontend (proposition – non statué : Vue.js)

* fonctionnalité de dépôt de données et de configuration du calcul

* fonctionnalité d'interrogation de l'état d'avancement du calcul

* Mise en place de jeux de tests de non-régression de l'application et automatisation de l'exécution de ces derniers via les pipelines gitlab

## Attendus :

* Robustesse aux montées de version – gestion des dépendances

* Robustesse aux entrées
<figure><img src="image_24.png" /><figcaption>Annexe 2 : Diagramme de classe de l'API</figcaption></figure>
Annexe 3 : Visualisation de l'exécution des tests dans un pipeline gitlab

<figure><img src="image_25.png" /></figure>
<figure><img src="image_26.png" /><figcaption>Annexe 4 : Exemple de la documentation d'une route de l'API</figcaption></figure>
# Annexe 5 : Aperçu des différentes page du client web

## Page de détail d'une analyse

<figure><img src="image_27.png" /></figure>
<figure><img src="image_28.png" /><figcaption>Visualisation d'un nuage de point (3D)</figcaption></figure>
Visualisation des logs à l'issue d'une analyse

<figure><img src="image_29.png" /></figure>
## Formulaire multi-partie de lancement d'une analyse

<figure><img src="image_30.png" /></figure>

<figure><img src="image_31.png" /></figure>
## Gestion des configurations

<figure><img src="image_32.png" /></figure>
Visualisation de l'ensemble des jeux de données

<figure><img src="image_33.png" /></figure>
Annexe 6 : Interface administrateur

<figure><img src="image_34.png" /></figure>
# Annexe 7 : Guide de déploiement en prod de l'application GroundedWeb

Il est possible d'installer grounded web via docker et d'organiser son déploiement de façon à faciliter son export sur une machine externe.

## Étape 1 : Configuration du fichier .env de l'api

Commencez par copier le contenu du fichier « .env.example » dans un nouveau fichier nommé « .env » à la racine du projet.

Ensuite, personnalisiez ce fichier en modifiant les mots de passe, les adresses IP et autres paramètres pour les adapter à votre environnement. Par exemple :

```
AWS_S3_PUBLIC_HOST=http://localhost:9000
```

devient :

```
AWS_S3_PUBLIC_HOST=http://148.99.12.108:9000
```

**Attention particulière à la variable suivante :**

`CORS_ALLOWED_ORIGINS` définit les adresses des clients web autorisés à communiquer avec l'API. Veillez à y inscrire les URL correctes. Pour autoriser plusieurs clients, séparez les adresses par une virgule :

```
CORS_ALLOWED_ORIGINS=http://148.99.12.108:5173,http://148.99.12.108:5174
```

Ici, nous avons autorisé les clients accessibles depuis la machine, à l'adresse 148.99.12.108, sur le port 5173 (utilisé par défaut en développement avec Vue.js) ainsi que sur le port 5174 (notre convention pour la production).

Assurez-vous de ne laisser aucune erreur de syntaxe (pas d'espace inutile, bonne virgule de séparation) pour garantir le bon fonctionnement des requêtes entre l'API et les clients.

## Étape 2 : Génération d'un fichier de yaml de déploiement

Docker permet de résoudre et fusionner plusieurs fichiers **docker-compose**, ainsi que de prendre en compte les variables d'environnement du fichier .env. Le tout peut être exporté dans un fichier unique de déploiement (stack.yml).

```
>> docker compose -f docker-compose.yml -f docker-compose.prod.yml config > stack.yml
```

Ceci va enregistrer le résultat dans un fichier .yaml nommé `stack.yml`. La commande ci-dessus ne permet de déployer que le backend. Cependant il est possible d'inclure le frontend avec cette commande :
```
>> docker compose -f docker-compose.yml -f docker-compose.prod.yml -f ../path/to/frontend/docker-compose.yml config > stack.yml
```

Si le déploiement est destiné à un réseau local sans certificat SSL (connexion en HTTP au lieu de HTTPS), vous pouvez ajouter le fichier « docker-compose.prod.local.yml ». Cela implique d'utiliser l'une des commandes suivantes, selon que vous déployiez uniquement le backend ou le backend avec le frontend.

Backend seul :

```
>> docker compose -f docker-compose.yml -f docker-compose.prod.yml -f docker-compose.prod.local.yml config > stack.yml
```

Backend + frontend :

```
>> docker compose -f docker-compose.yml -f docker-compose.prod.yml -f docker-compose.prod.local.yml -f ../path/to/frontend/docker-compose.yml config > stack.yml
```

## Étape 3 : Ajout des fichiers de configuration

Le frontend et le backend reposent sur des fichiers de configuration partagés avec leurs conteneurs respectifs, permettant d'adapter et de personnaliser l'architecture de déploiement.

### 1) Configuration de nginx

Le premier fichier, nginx_config, correspond à la configuration du serveur nginx utilisé comme reverse proxy pour l'API.

* Une version minimale est fournie dans le projet de l'API sous le nom « nginx.conf ».

* Vous pouvez la modifier selon vos besoins, par exemple pour exposer une seconde API en cas de montée en charge.

### 2) Configuration du frontend

Le second fichier, frontend_config, est un fichier JSON qui définit les paramètres du client web.

* Il inclut l'URL de l'API ainsi que la configuration par défaut proposée aux utilisateurs.

* Une version minimale est disponible à la racine du projet du client web (frontend) sous le nom « config-prod.json ».

### 3) Transfert des fichiers sur le serveur cible
Une fois ces fichiers configurés selon vos besoins, transférez-les sur la machine cible, dans le répertoire de votre choix. Par exemple : `~/groundedweb/`

### 4) Mise à jour du fichier stack.yml

Avant de transférer le fichier de déploiement, pensez à mettre à jour la section `configs` de votre fichier `stack.yml` afin d'y définir le chemin des fichiers de configuration.

Exemple de la section `configs` adaptée :

```yaml
configs:
  frontend_config:
    name: groundedweb_frontend_config
    file: ~/groundedweb/config-prod.json
  nginx_config:
    name: groundedweb_nginx_config
    file: ~/groundedweb/nginx.conf
```

### 5) Transfert du fichier de déploiement

Enfin, transférez le fichier `stack.yml` sur le serveur de déploiement, idéalement dans le même répertoire que les fichiers de configuration.

## Étape 4 : Déploiement et mise à jour

Vous pouvez maintenant déployer la stack grounded web !

Vous pouvez récupérer les dernières modifications de l'image avec cette commande sur votre serveur distant :

* `docker compose -f stack.yml pull # Récupération des dernières images`

* `docker compose -f stack.yml down # Suppression des conteneurs`

* `docker compose -f stack.yml up # Lancement des conteneurs`

Et déployer la stack via la commande :

* `docker compose -f stack.yml up -d`

<footnote n="1">1. Par défaut, la commande `docker compose` recherche un fichier nommé `docker-compose.yml`. Renommer le fichier `stack.yml` avec ce nom permet donc de simplifier la commande en enlevant `-f stack.yml`.</footnote>
Si vous souhaitez déployer la stack sur un cluster docker swarm et que la machine cible est le nœud maître, vous pouvez utiliser la commande :

```
>> docker stack deploy --resolve-image=always --with-registry-auth -c docker-compose.yml groundedweb
```

En réutilisant la même commande, vous pouvez mettre à jour l'ensemble des images docker de l'application.
# Annexe 8 : Bilan-critique/Perspectives

## 1. Bilan critique de la solution actuelle

Au cours de mon stage, j'ai participé au développement d'une part importante du projet Grounded, en mettant en place une base logicielle solide sur laquelle les futures évolutions pourront s'appuyer. Cette première version de l'application est globalement opérationnelle et apporte une réelle valeur ajoutée au projet. Toutefois, plusieurs limites techniques et fonctionnelles sont apparues au fil du développement et des tests, ce qui laisse entrevoir des pistes claires d'amélioration.

Tout d'abord, le modèle de données actuel est très orienté métier, mais ne permet pas une visualisation agrégée des résultats issus de plusieurs jeux de données. Cela complique l'analyse globale des informations collectées sur le terrain. Pour remédier à cela, il serait pertinent d'introduire un nouveau modèle regroupant ces jeux de données sous une même entité : les fosses pédologiques. Cette structure permettrait de centraliser les informations communes (comme la localisation), de simplifier la visualisation des résultats et d'améliorer la cohérence du modèle, notamment en préparation de l'intégration de l'application mobile.

La chaîne de traitement automatisée (Grounded CLI) constitue un autre point central du projet, autour duquel l'API est construite. L'un des enjeux est de garantir que cette CLI reste facilement extensible pour accompagner les évolutions du projet. Actuellement, la création de l'image Docker est longue (environ 10 minutes) et pourrait devenir un frein à terme. Une optimisation du Dockerfile — par exemple en utilisant des images de base plus légères, un système de build multi-stage ou un meilleur usage du cache — permettrait de réduire le temps de build et de simplifier l'ajout de nouvelles dépendances. Bien que non bloquant à ce stade, ce point mérite attention pour fluidifier les futurs développements.

Le déploiement en production représente l'un des points les plus structurants mais reste aujourd'hui incomplet. Grâce à une collaboration avec l'INRAE, un accès au cloud Orion (OpenStack) a été obtenu, offrant une infrastructure dédiée pour héberger l'application. Toutefois, par manque de temps et d'expertise DevOps, le déploiement n'a pas pu être entièrement finalisé. Ce déploiement manuel présente des risques en termes de maintenabilité. Il serait donc judicieux de mettre en œuvre une infrastructure as code avec Terraform, afin de rendre le déploiement reproductible et automatisé. À terme, une migration vers Kubernetes est recommandée pour assurer une meilleure scalabilité et résilience, notamment si l'application évolue vers une utilisation professionnelle.

Sur le plan fonctionnel et visuel, l'interface web est pleinement utilisable mais reste perfectible. Certaines fonctionnalités de base, telles que la modification du mot de passe par l'utilisateur, ne sont pas encore disponibles dans le client web, alors qu'elles existent dans
l'API. De plus, l'interface gagnerait à être modernisée visuellement pour améliorer l'expérience utilisateur. L'ajout de préférences utilisateurs stockées localement pourrait également enrichir la personnalisation de l'interface. Par ailleurs, le système d'envoi de fichiers montre des limites en cas de connexion instable ou de transferts volumineux. L'intégration d'un outil tel qu'Uppy, qui gère la reprise automatique des envois interrompus, améliorerait la fiabilité de cette fonctionnalité essentielle.

Un autre point de vigilance concerne la sécurité du processus d'inscription. Actuellement, aucune vérification d'email n'est réalisée, ce qui expose l'application à des inscriptions frauduleuses ou automatisées si un jour celle-ci est amenée à être exposé au grand public. L'intégration de la bibliothèque django-allauth, en complément de dj-rest-auth, permettrait de combler ce manque de manière simple, en ajoutant des étapes de confirmation et de validation à la création de compte.

Enfin, bien que l'API soit correctement documentée via OpenAPI, aucun SDK<fnref n="2" /> client n'a encore été développé. Cela peut freiner l'adoption du projet par des développeurs ou des chercheurs souhaitant interagir facilement avec l'API. Le développement d'une bibliothèque Python dédiée, avec une documentation claire et des exemples d'usage, faciliterait grandement l'intégration de l'API dans d'autres outils ou projets, et contribuerait à élargir la communauté autour de Grounded. Voici ci-dessous un exemple probable d'utilisation de ce futur SDK.

```python
client = GroundedWebClient("http://localhost:8000/api")
client.login("user@mail.com", "password")
dataset = client dataset.create(
    photos_before_dir="path/to/photos_before"
    photos_after_dir="path/to/photos_after"
)

config = Configuration(
    sfm = MicMac()
    cloud� ssor = CloudCompare()
    detector = CCTag()
    scale_bars = [
        ScaleBar(start=0, end=1, length=0.22),
        ScaleBar(start=1, end=2, length=0.22)
    ]
)

analysis = client .analysis.create= dataset, configuration= config)
while (analysis.status not in [Analysis.status.COMPLETED, Analysis.status .FAILED]):
    time.sleep(10)
    analysis.refresh()
print("Votre analyse s'est terminée avec le statut :", analysis.status)
```

<footnote n="2">2 SDK signifie Software Development Kit : il s'agit d'un ensemble d'outils permettant de développer des applications pour une plateforme spécifique.</footnote>
## 2. Perspectives pour la suite du projet

Dans le cadre de la continuité du projet Grounded, plusieurs axes d'amélioration ont été identifiés et mériteraient d'être approfondis par les équipes futures. Voici les perspectives principales, classées par ordre de priorité, accompagnées pour chacune d'un état des lieux des difficultés prévisibles, des ressources nécessaires, des points de blocage actuels et de premières idées de solutions.

### 1. Développement d'un SDK Python pour l'API

* **Importance**: Très élevée

* **Difficultés attendues**: Moyennes

* **Ressources nécessaires**: Un développeur Python connaissant le fonctionnement des API REST

* **Points bloquants**: Aucun blocage majeur, mais nécessite du temps dédié

* **Solutions envisagées**: Création d'une bibliothèque Python (packagée pour PyPI) facilitant les appels aux principaux endpoints de l'API (authentification, gestion des jeux de données, upload de fichiers, etc.). L'objectif est d'encourager l'adoption du projet par des tiers, notamment chercheurs et développeurs extérieurs.

### 2. Finalisation du déploiement en production (Terraform, OpenStack, Kubernetes)

* **Importance**: Très élevée

* **Difficultés attendues**: Élevées

* **Ressources nécessaires**: Un développeur DevOps ayant des affinités avec Django

* **Points bloquants**: Le déploiement actuel se base sur des machines déjà préconfigurés et utilise une connexion HTTP

* **Solutions envisagées**: Création d'une infrastructure as code avec Terraform pour automatiser le déploiement sur le cloud Orion (OpenStack). Une fois cette base stabilisée, initier une transition progressive vers Kubernetes afin de se rapprocher des standards de production actuels.
### 3. Introduction du modèle "fosses pédologiques" pour structurer les données

* **Importance** : Élevée

* **Difficultés attendues** : Moyennes

* **Ressources nécessaires** : Développeurs backend et frontend pour la mise à jour des modèles, de l'API et de l'interface

* **Points bloquants** : Modèle inexistant à ce jour dont l'implémentation demandera un changement de gestion des données via l'API et qui devra être réimplémenté au niveau du client.

* **Solutions envisagées** : Définir un nouveau modèle regroupant les jeux de données par fosse. Adapter les vues de l'API et les composants frontend pour afficher les données regroupées. Cette structuration préparera aussi le terrain pour l'intégration de l'application mobile.

### 4. Amélioration de l'interface frontend

* **Importance** : Moyenne

* **Difficultés attendues** : Moyennes

* **Ressources nécessaires** : Un développeur frontend

* **Points bloquants** : Interface fonctionnelle mais incomplète et visuellement perfectible

* **Solutions envisagées** : Ajouter les fonctionnalités manquantes (modification de mot de passe, préférences utilisateur via le stockage local), améliorer l'ergonomie visuelle, et intégrer une solution comme Uppy pour fiabiliser les transferts de fichiers (reprendre un envoi en cas de coupure).

### 5. Mise en place d'une vérification d'e-mail à l'inscription

* **Importance** : Moyenne à élevée

* **Difficultés attendues** : Faibles

* **Ressources nécessaires** : Un développeur ayant une bonne maîtrise de Django

* **Points bloquants** : Aucune vérification d'e-mail présente à ce jour
* **Solutions envisagées** : Intégration de la bibliothèque « django-allauth » en complément de « dj-rest-auth » pour gérer la confirmation d'inscription par e-mail et la validation des comptes utilisateurs.

**3. Conclusion**

Le projet Grounded, dans sa version actuelle, représente selon moi une base solide et maintenable sur laquelle les futures équipes pourront s'appuyer pour construire les prochaines évolutions. L'architecture mise en place, bien que très fonctionnelle, présente encore plusieurs axes d'amélioration. Ce bilan critique met en évidence les points clés à renforcer : la structuration des données, la professionnalisation du déploiement, l'accessibilité, l'amélioration de l'expérience utilisateur, ainsi que la sécurisation du processus d'inscription.

Les perspectives proposées visent à consolider et pérenniser l'application en vue d'un usage plus large et plus professionnel. Ces pistes identifiées s'inscrivent dans une logique d'amélioration continue, adaptée aux ressources du projet. Je pense qu'à l'aide de ces éléments, cela pourra faciliter la prise en main du projet par la prochaine personne qui en aura la charge, tout en assurant une continuité dans la qualité et la vision technique du développement de Grounded.