tracé 3d à partir d'une matrice

leodisjonct

tracé 3d à partir d'une matrice

Message par leodisjonct » 15 déc. 2015 18:52

Bonsoir !
J'ai besoin d'aide pour coder un algo qui me permettrait de tracer une courbe en 3d à partir d'une image en nuance de gris.
Seulement je n'ai pas étudié les fonctions plot3d, et je n'arrive pas à trouver un moyen simple.
J'ai créé une fonction qui renvoie un tableau avec les valeurs des nuances. Ainsi à chaque coordonnées x et y correspondrait une valeur de gris, et donc une certaine côte.
Il s'agit là d'une première approche pour tenter de modéliser en 3d une image obtenue au microscope électronique. Je pourrai complexifier une fois que j'en saurai plus sur les modules :P

Ici, il me suffirait de renvoyer chaque élément de la matrice M.
Seulement, python me renvoie une erreur d'indexage :
j'écris M[x][y], ce qui apparemment est une erreur d'argument de la fonction "ax.plot_surface". Du coup j'ai essayé de vectoriser la fonction, mais ça change rien !!
Y a-t-il un moyen de s'en sortir ?

from __future__ import division
from scipy import *
from pylab import *
from PIL import Image
import numpy as np


#utilisation de PIL :

i=Image.open("M:/tipe/image.jpg")
(lo,la)=i.size
i.show()

# Matrice des nuances de gris :

def matrice(lo,la):
L=np.array(i.getdata())
M=[]
P=np.zeros(lo)
for k in range(la):
for j in range(lo):
P[j]=L[j]
M.append(np.array(P))
return M


#tracé altitude > nuance de gris :

from mpl_toolkits.mplot3d import Axes3D
from matplotlib import cm
import matplotlib.pyplot as plt


M=matrice(lo,la)

x=np.arange(la)
y=np.arange(lo)
X,Y=np.meshgrid(x,y)

def z(x,y):
return M[x][y]


Z=vectorize(z(x,y))

fig = plt.figure()
ax = fig.gca(projection='3d')
surf = ax.plot_surface(X, Y, Z,rstride=2,cstride=2,cmap=cm.RdPu,linewidth=1,antialiased=True)

Messages : 13

Inscription : 27 févr. 2013 16:45

Profil de l'utilisateur : Élève de lycée

Re: tracé 3d à partir d'une matrice

Message par loupi » 15 déc. 2015 23:39

Si je comprends bien ce que tu veux faire, tu veux tracer le niveau de gris sur la coordonnée Z, donc une valeur comprise entre 0 et 255.
Alors, il me semble que ta matrice M n'est pas correcte.
Je verrais plutôt un truc du genre dans ta fonction matrice :

Code : Tout sélectionner

def matrice(lo,la):
    L=np.array(i.getdata())
    M=[]
    for k in range(lo):
        P=[]
        for j in range(la):
            P.append(L[k*la+j][0])
        M.append(np.array(P))
    return M
La liste L est une liste de lo*la pixels, il faut construire une matrice M[lo][la]
Ensuite, il doit suffire de passer directement M au lieu de ton Z dans le plot_surface

Pour une image, il vaudrait mieux parler de largeur/hauteur plutôt que de longueur/largeur

abouMPSI

Re: tracé 3d à partir d'une matrice

Message par abouMPSI » 16 déc. 2015 11:51

c'est pour tracer à l'écran,
ou pour fraiser dans un FabLab in fine ? :)

leodisjonct

Re: tracé 3d à partir d'une matrice

Message par leodisjonct » 16 déc. 2015 13:48

Merci Loupi ! :D
Sinon, pour le tracé as tu une idée ? Comment je peux contourner l'erreur d'argument pour le plot ? existe-t-il un plot qui trace directement la côte à partir d'une matrice ?

Abou, je vois pas trop l'intérêt d'utiliser un meb pour fraiser :lol:

*mettre M dans le plot directement induit une erreur d'argument

Messages : 13

Inscription : 27 févr. 2013 16:45

Profil de l'utilisateur : Élève de lycée

Re: tracé 3d à partir d'une matrice

Message par loupi » 16 déc. 2015 18:18

leodisjonct a écrit :*mettre M dans le plot directement induit une erreur d'argument
Est-ce que tu as vu que j'avais inversé les 2 boucles imbriquées dans la fonction matrice ?

Je viens d'essayer, sur ma config ça trace bien l'image en "3D". J'ai essayé avec 3 images ( carrée, portrait, paysage) et ça semble ok pour les 3 formats.
Par contre pour tester, prends une image pas trop grosse (genre 200x200) et pas trop complexe en niveaux de gris.

Ci-dessous le code complet qui fonctionne.

Code : Tout sélectionner

from __future__ import division
from scipy import *
from pylab import *
from PIL import Image
import numpy as np

#utilisation de PIL :

i=Image.open("M:/tipe/image.jpg")
(lo,la)=i.size
#i.show()

# Matrice des nuances de gris :


def matrice(lo,la):
    L=np.array(i.getdata())
    M=[]
    for k in range(lo):
        P=[]
        for j in range(la):
            P.append(L[k*la+j][0])
        M.append(np.array(P))
    return M

#tracé altitude > nuance de gris :

from mpl_toolkits.mplot3d import Axes3D
from matplotlib import cm
import matplotlib.pyplot as plt

M=matrice(lo,la)

x=np.arange(la)
y=np.arange(lo)
X,Y=np.meshgrid(x,y)

fig = plt.figure()
ax = fig.gca(projection='3d')
surf = ax.plot_surface(X, Y, M,rstride=2,cstride=2,cmap=cm.RdPu,linewidth=1,antialiased=True)

leodisjonct

Re: tracé 3d à partir d'une matrice

Message par leodisjonct » 16 déc. 2015 22:24

Merci beaucoup !
En effet ça marche parfaitement !

Bon pour les grosses images, ça lag vachement. Du coup je vais tenter d'améliorer le prg en concentrant sur une zone recherchée (j'imagine que ça se fait simplement avec la fct getpixel() ).
Ensuite il faudra que je prenne en compte l'angle du scintillateur par rapport à la zone bombardée, mais ça me parait hard ! :twisted:

Répondre