Retour sur Expérience de Data Visualisation 3D avec Blender

Fixons tout de suite le contexte. Dans cet article, Blender ne désigne bien sûr pas un robot mixeur pour la cuisine, mais le logiciel libre de modélisation 3D.

Blender propose des fonctions avancées de modélisation et d’animation. D’autres logiciels pourraient être considérés tel que 3DS max, maya, ou Cinema 4D parmi les plus connus, mais la différence pour ces expérimentations est que Blender est disponible gratuitement. Il est donc possible d’essayer sans plus attendre. L’objet n’est pas ici de faire une présentation de Blender (la chaîne youtube Blender Guru le fait très bien si le sujet vous intéresse et que vous maîtrisez l’anglaismais plutôt de le mettre en regard avec notre activité : travailler avec la donnée.

En effet le monde de la donnée et de la 3D sont tous deux des domaines au coeur de l’actualité du numérique et les interactions entre ces deux domaines ne sont pas nouvelles. Le Big data VR challenge, était par exemple un concours organisé notamment par Epic Games (société éditrice du moteur Unreal Engine) au cours duquel des projets de visualisation de données en VR étaient développés. Aussi, il paraissait intéressant de proposer une initiation (sans prétention) et des technologies possibles.

Dans un premier temps, nous nous intéressons à Blender qui propose un langage de script embarqué qui n’est autre que Python. Le logiciel en lui-même n’est pas écrit en python, mais embarque, dans la version 2.79, sous linux 64 bit (sous Windows 10 64 bit également et vraisemblablement pour mac également) un interpréteur de python 3.5. Il est ainsi possible, par l’intermédiaire d’une fenêtre de scripting d’écrire et compiler du code python dans l’interface de Blender, et même de faire interagir les 2 en utilisant notamment une librairie dédiée bpy (pour Blender/Python API).

Pour avoir le retour console, il suffit de lancer Blender depuis la console. Celle-ci affichera alors les sorties une fois le script compilé dans Blender. Voici les différentes étapes afin d’installer des modules tiers fonctionnant dans Blender :

  1. Installation de Blender
  2. Vérification de la commande python (et ajout d’un alias éventuel dans .bashrc, par exemple : pythonb)
    path.../blender-2.79a-linux-glibc219-x86_64/2.79/python/bin/python3.5m
  3. Compiler le script get-pip.py avec cet interpréteur si pip n’est pas déjà installé.
  4. Lancement de pip pour installer vos librairies préférées (vous noterez que je ne passe pas par un virtualenv puisque j’utilise l’interpréteur de Blender, les packages sont installés pour cet interpréteur et non pas pour le système). Attention, il faut bien ajouter -m pour lancer pip. Par exemple :
    pythonb -m pip install pandas

Félicitations, votre interpréteur Python est prêt à accueillir vos modules python préférés ! (Une installation similaire fonctionne également sous Windows 10 avec Blender 2.79).

Pour interagir avec Blender, il est possible d’utiliser BPY (Blender PYthon module) préinstallé avec l’interpréteur. Il permet notamment d’accéder aux éléments de la scène 3D, de créer/manipuler des objets dans la scène, de simuler des entrées utilisateurs… (Voici également une vidéo d’introduction en anglais présentant des exemples de code simples desquels le code suivant s’inspire.)

Voici également un très petit  jeu de données issu du projet Mister Isidor retravaillé assez rapidement.
Il permet de connaître la répartition des appartements en vente ou location ces derniers mois dans différentes villes en fonction de leur nombre de pièces.

"city",1,2,3,4,5,6,7,8,9,10,11,12,14,16
"lyon",482,714,1161,887,419,73,13,9,1,3,0,4,1,0
"nantes",413,707,686,334,119,38,9,10,3,1,0,0,0,1
"strasbourg",137,365,590,378,144,29,17,7,4,0,2,0,0,0
data_for_blender.csv

L’idée ici est simplement de visualiser par ville (axe des x) et par type d’appartement (axe des y) le nombre d’appartement étudiés (axe des z).
Ci-après le code utilisé pour le rendu :

import bpy
import csv
from math import radians

bpy.context.space_data.font_size = 12
fPath   = '~/Documents/data_for_blender.csv'
csvFile = csv.reader( open( fPath ) )
data    = [ row for row in csvFile ][1:]

totalAppt = 0
for k in range(1,14):
    totalAppt += sum([ int( row[k] ) for row in data ])

for i, row in enumerate( data ): # enumeration of cities
    print(i)
    city = row[0]
    for j in range(1,len(row)): # enumeration of nb of rooms
        current_criterium_appt = row[j]

        # compute an appropriate ratio to display the height of the cube
        current_height = ( int( current_criterium_appt ) / totalAppt ) * 10
        
        # create the cube to represent the current city and type of appt
        bpy.ops.mesh.primitive_cube_add( 
            radius   = 0.5,      # Set base size
            location = ( 
                i * 1.1,         # 1.1 to live a small space between the cubes    
                j * 1.1,         # 1.1 to live a small space between the cubes 
                current_height/2   # the half of height, indeed it's the position of the center of the cube
            )
        )
           
        cube = bpy.context.object
        cube.dimensions.z = current_height # the height that we have computed
        if i == 0 : # so only once per type of appt
               # Add type of appt
                bpy.ops.object.text_add(
                    location = ( -1, j * 1.1-0.25, current_height)
                )
                bpy.context.scene.objects.active.scale = (0.5,0.5, 0)    
                text = bpy.context.object
                text.rotation_euler.z = radians(90) # Rotate text by 90 degrees along Z axis
                text.rotation_euler.x = radians(90) # Rotate text by 90 degrees along X axis
                text.data.extrude     = 0.05        # depth of the text
                text.data.bevel_depth = 0.01        # bevel effect that smoothes text's edges
                text.data.body        = "T"+str(j)  # the current type of appt

        # Add the number of appts
        bpy.ops.object.text_add(
            location = ( i * 1.1 + 0.25, j * 1.1-0.25, current_height + 0.2)
        )
        bpy.context.scene.objects.active.scale = (0.3,0.3, 0)    
        text = bpy.context.object
        text.rotation_euler.z = radians(90)                 
        text.data.extrude     = 0.05                        
        text.data.bevel_depth = 0.01                        
        text.data.body        = str(current_criterium_appt) # total number
        activeObject = bpy.context.active_object            # set active object to variable
        mat = bpy.data.materials.new(name="red_mat")        # set new material to variable
        mat.diffuse_color = (1, 0, 0)                       # change color
        text.data.materials.append(mat)                     # add the material to the object
        
    # add name of the city
    bpy.ops.object.text_add(
        location = ( i * 1.1+0.2, -5, 0 )
    )
                    
    text = bpy.context.object
    text.rotation_euler.z = radians(90)
    text.data.extrude     = 0.05        
    text.data.bevel_depth = 0.01        
    text.data.body        = city        # the city name
script_blender.py


On obtient donc une représentation hybride entre la heat matrix et l’histogramme. 
Ci-après vous trouverez un rendu Gif du model 3d (le rendu est peu travaillé).
A noter que, par rapport au script précédent, une camera, une lumière et des images clés de rotation ont été ajoutées de manière à réaliser cet export.

L’idée serait bien sûr de pousser le concept plus loin pour arriver à un rendu à la fois pédagogique, scientifiquement juste mais s’adressant plus efficacement au ressenti de chacun, voire captant plus facilement l’intérêt via des animations.

Dans les idées futures, il serait notamment intéressant de :

  • Monter en compétences en modélisation et scripting pour proposer des visualisation plus pédagogiques/attrayantes.
  • Proposer des vidéos de visualisation 3D
  • Proposer des rendus 3D dans la page web en utilisant blend4Web ou opengl voire en intégrant les graphiques obtenus dans des moteurs de jeux pour les explorer en temps réels ou dans des expériences VR

 

par Nicolas DAVID, Ingénieur R&D et Data Scientist chez Verteego