Tous les articles

Dans les coulisses de Kansumi : comment un plan devient un graphe de scène

Une plongée technique dans le graphe de scène JSON de chaque rendu Kansumi, et ce que mesurent vraiment ses scores de confiance.

The Kansumi Team4 min
Sur cette page

La plupart des outils de décoration par IA traitent votre plan comme une simple image. Kansumi le traite comme des données. Dès que l’extraction est terminée, votre plan cesse d’être des pixels et devient un document JSON versionné que nous appelons le graphe de scène, et chaque mur que vous déplacez, chaque porte que vous bougez, chaque rendu que vous générez lit et écrit dans ce document, jamais dans l’image.

Cet article explore le fonctionnement de ce système, et pourquoi il rend les rendus fiables.

Le pipeline Kansumi, de l’import des plans jusqu’aux rendus, avec le graphe de scène comme source unique de vérité
Le pipeline Kansumi, de l’import des plans jusqu’aux rendus, avec le graphe de scène comme source unique de vérité

Pourquoi les images sont de mauvaises sources de vérité

Une image de plan ne sait rien. Elle ne peut pas vous dire la longueur d’un mur, si une porte s’ouvre vers l’intérieur, ou si le canapé que vous avez demandé rentre bien dans la pièce. Les outils qui modifient l’image doivent tout redeviner à chaque changement, c’est ainsi qu’on se retrouve avec des rendus où la pièce a silencieusement gagné un mètre.

Si la géométrie n’est stockée nulle part, chaque modification devient un nouvel acte d’imagination.

Alors nous la stockons. Intégralement.

Le graphe de scène, en millimètres

Chaque projet possède un document scene.v1.json. Toutes les coordonnées et longueurs sont des entiers exprimés en millimètres réels, plus aucune unité en pixels après l’extraction. Voici un extrait raccourci d’une scène réelle :

scene.v1.json (excerpt)
{
  "schema_version": "v1",
  "units": "mm",
  "scale": {
    "confirmed": true,
    "reference": { "type": "wall_length", "element_id": "wall_a", "value_mm": 4200 }
  },
  "walls": [
    {
      "id": "wall_a",
      "start": { "x": 0, "y": 0 },
      "end": { "x": 4200, "y": 0 },
      "thickness_mm": 120,
      "confidence": 0.94,
      "user_confirmed": true
    }
  ],
  "openings": [
    {
      "id": "door_1",
      "kind": "door",
      "host_wall_id": "wall_a",
      "offset_mm_from_start": 2050,
      "width_mm": 900,
      "swing": "left",
      "swing_direction": "in",
      "confidence": 0.81,
      "user_confirmed": false
    }
  ]
}

Deux détails de cet extrait comptent plus que les autres.

Les ouvertures se rattachent aux murs de façon paramétrique

Une porte n’est pas stockée à une position (x, y). Elle est stockée comme « sur wall_a, à 2050 mm de son début, large de 900 mm ». Quand vous déplacez un mur, le divisez ou le redressez dans l’éditeur, la porte se réancre de façon déterministe. Elle ne peut pas dériver au milieu d’une pièce.

Une ouverture de porte définie par son mur hôte, son décalage depuis le début du mur, et sa largeur : le tout en millimètres
Une ouverture de porte définie par son mur hôte, son décalage depuis le début du mur, et sa largeur : le tout en millimètres

L’échelle, une donnée à part entière

L’extraction estime un ratio provisoire pixels-millimètres, mais la scène enregistre si un humain l’a confirmé, et par rapport à quelle référence : une longueur de mur connue, une cote lue par OCR, ou une largeur de porte standard. Tant que scale.confirmed n’est pas vrai, l’éditeur l’affiche, honnêtement, comme une estimation.

Ce que mesurent vraiment les scores de confiance

Chaque élément extrait porte un confidence compris entre 0 et 1. Ce n’est pas un simple ornement : l’éditeur trie sa file de révision en fonction de cette valeur, et le pipeline refuse de générer un rendu à partir d’une géométrie à la fois peu fiable et non révisée.

ÉlémentSource de confianceSous le seuil, nous…
MursConsensus du modèle de vision sur plusieurs passesLes signalons pour révision dans l’éditeur
OuverturesScore de détection × confiance du mur hôteVous demandons de confirmer le sens d’ouverture et la largeur
PiècesFermeture du polygone + concordance de l’étiquette OCRLaissons le type de pièce non défini
CotesQualité OCR de l’étiquette impriméeIgnorons l’étiquette pour la mise à l’échelle

Modifier sans casser la géométrie

Comme le graphe de scène fait office de registre, les opérations de l’éditeur sont de petites fonctions pures qui s’appliquent dessus. Diviser un mur, par exemple, réancre chaque ouverture par simple calcul arithmétique : pas par une nouvelle détection :

wall-split (simplified)
function splitWall(scene: SceneV1, wallId: string, at_mm: number): SceneV1 {
  const wall = scene.walls.find((w) => w.id === wallId);
  if (!wall) throw new Error(`unknown wall: ${wallId}`);

  const [left, right] = divideSegment(wall, at_mm);

  const openings = scene.openings.map((o) => {
    if (o.host_wall_id !== wallId) return o;
    // An opening before the cut stays on the left piece with its offset
    // untouched; one after the cut moves to the right piece, offset shifted.
    return o.offset_mm_from_start < at_mm
      ? { ...o, host_wall_id: left.id }
      : { ...o, host_wall_id: right.id, offset_mm_from_start: o.offset_mm_from_start - at_mm };
  });

  return { ...scene, walls: replaceWall(scene.walls, wallId, [left, right]), openings };
}

Annuler et rétablir (undo/redo) viennent gratuitement : chaque modification produit un nouveau document de scène, l’historique n’est donc qu’une simple pile de ces documents.

Les rendus sont des preuves, pas des suppositions

Quand vous générez des concepts, le moteur de rendu ne regarde absolument pas votre image importée. Il construit une image de contrôle à partir du graphe de scène (murs, ouvertures et emprises du mobilier projetés depuis la caméra canonique de la pièce) puis conditionne le modèle de diffusion sur celle-ci. Le rendu respecte vos dimensions parce qu’on ne lui a jamais rien montré d’autre.

C’est aussi pour cela que l’éditeur conversationnel peut dire « le canapé de 1,6 m ne tient pas sur le mur de 1,4 m » plutôt que de générer discrètement une pièce impossible : la vérification tient en un simple calcul entier sur des millimètres, effectué avant même qu’un seul pixel ne soit généré.

À retenir

  • La géométrie vit à un seul endroit : un graphe de scène JSON versionné, en millimètres, jamais en pixels.
  • Les relations sont paramétriques : les ouvertures appartiennent aux murs, les caméras appartiennent aux pièces, si bien que les modifications s’enchaînent sans risque.
  • L’incertitude est explicite : les scores de confiance et les indicateurs user_confirmed conditionnent ce que le pipeline accepte de rendre.
  • Les rendus découlent du graphe : c’est pourquoi ils correspondent à votre mètre ruban.

Si vous ne l’avez pas encore essayé, importez un plan et regardez le graphe de scène se construire sous vos yeux.

À lire ensuite