IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

Calcul scientifique Python Discussion :

numpyArray trouver certaines valeurs et les modifier [Python 2.X]


Sujet :

Calcul scientifique Python

Vue hybride

Message précédent Message précédent   Message suivant Message suivant
  1. #1
    Membre confirmé Avatar de Flaherty Mc Coillean
    Homme Profil pro
    Ingénieur de Recherche
    Inscrit en
    Décembre 2007
    Messages
    108
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 39
    Localisation : France, Puy de Dôme (Auvergne)

    Informations professionnelles :
    Activité : Ingénieur de Recherche
    Secteur : Aéronautique - Marine - Espace - Armement

    Informations forums :
    Inscription : Décembre 2007
    Messages : 108
    Par défaut numpyArray trouver certaines valeurs et les modifier
    Bonjour à tous =)

    Je débute en python et me voilà confronté à un petit problème... Je vous explique le contexte : mon objectif est de faire l'équivalent d'imagesc (fonction MATLAB) en python, c'est à dire à partir d'un numpyArray réétaler la dynamique entre 0 et 255 puis lui appliquer une 'colorbar' (lue à partir d'une image tiff faisant 256*1 pixels) pour récupérer 3 numpyArray (un pour le rouge, un pour le vert et un pour le bleu) me permettant d'enregistrer mon résultat sous forme d'une image. J'ai réussi une première version mais le temps de calcul est bien trop long à mon goût et j'essaye maintenant d'optimiser mon code.

    Dans un premier temps voici mon code non optimisé qui fonctionne :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    from PIL import Image
    import numpy
     
    def imagesc(data, nb_col, nb_lig, col)
       """ """
       PATH_COLOR = '/home/chemin/vers/colorbar/'
       colorbar = Image.open(PATH_COLOR+col+'.tiff', 'r'
       colorbar = colorbar.getdata()
     
       R = G = B = data
     
       min_data = numpy.ma.min(data)
       max_data = numpy.ma.max(data)
     
       j=0
       while j < nb_lig:
          k = 0
          while k < nb_col:
             i = 0
             if min_data < max_data:
                i = ((data[j][k] - min_data)/(max_data-min_data))*255
             else:
                i = 0
             i = int(numpy.around(i, decimals = 0))
     
             R[j][k] = colorbar[i][0]
             G[j][k] = colorbar[i][0]
             B[j][k] = colorbar[i][0]
             k += 1
          j += 1
     
       numpy.ma.masked_where(numpy.ma.getmask(data) == True, R)
       numpy.ma.masked_where(numpy.ma.getmask(data) == True, G)
       numpy.ma.masked_where(numpy.ma.getmask(data) == True, B)
     
       RGB = []
       RGB.append(R)
       RGB.append(G)
       RGB.append(B)
    Et ma tentative d'optimisation qui ne fonctionne pas... Où j'ai essayé au maximum de mes maigres capacités de supprimer les boucles car c'est une plaie pour les temps de calcul.
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    from PIL import Image
    import numpy
     
    def imagesc(data, col)
       """ """
       PATH_COLOR = '/home/chemin/vers/colorbar/'
       colorbar = Image.open(PATH_COLOR+col+'.tiff', 'r'
       colorbar = colorbar.getdata()
     
       min_data = numpy.ma.min(data)
       max_data = numpy.ma.max(data)
     
       if min_data < max_data:
          index = numpy.around((((data - min_data)/(max_data - min_data))*255), decimals = 0)
          index = index.astype(int)
       else:
          index = data * 0.0
          index = index.astype(int)
     
       R = G = B = index
     
       for i in range(0, 256):
          R[numpy.ma.where(index == i)] = colorbar[i][0]
          G[numpy.ma.where(index == i)] = colorbar[i][1]
          B[numpy.ma.where(index == i)] = colorbar[i][2]
     
       RGB = []
       RGB.append(R)
       RGB.append(G)
       RGB.append(B)
    Quand je test ça 'à la main' directement sous idle en tapant genre "i = 16" puis "R[numpy.ma.where(index == i)] = colorbar[i][0]" j'obtiens ce que je veux mais dès que je le passe dans la boucle for ça ne fonctionne plus... Je ne comprends pas pourquoi ça me modifie mon numpyArray 'index' et je me retrouve au final avec 4 array (index, R, G, et B) identique et qui ne correspondent en rien à ce que je devrais avoir.

    j'ai alors essayé une autre variante que voici:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
       for i in range(0, 256):
          numpy.ma.put(R, numpy.ma.where(index == i), colorbar[i][0])
          numpy.ma.put(G, numpy.ma.where(index == i), colorbar[i][1])
          numpy.ma.put(B, numpy.ma.where(index == i), colorbar[i][2])
    mais là ça ne fonctionne pas non plus, ça me modifie la première de mes numpyArray (sans obtenir le résultat souhaité puisque j'obtiens la valeur 128 partout) et ça ne touche pas au reste.

    Je suis persuadé que la solution n'est pas loin et assez évidente, mais je manque de pratique en Python et pour le moment elle m'échappe et ça m’énerve XD, c'est pourquoi j'attends avec impatience vos conseils avisés !

    Merci d'avance ! En espérant avoir posé mon problème suffisamment clairement.

  2. #2
    Membre émérite
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Janvier 2013
    Messages
    388
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Ingénieur développement logiciels
    Secteur : Conseil

    Informations forums :
    Inscription : Janvier 2013
    Messages : 388
    Par défaut
    Salut,
    Je ne connais pas imagesc de Matlab. Et je comprends difficilement ce que tu veux obtenir.
    Si c'est pour afficher l'image, matplotlib.pyplot.imshow permet de renormer.
    Il est sûrement possible de factoriser les opérations avec les tableaux numpy mais il faut donner plus de détails.
    Pour supprimer les méchantes boucles dans le code qui fonctionne, je ferais :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    import itertools
    ...
     
    def imagesc(data, nb_col, nb_lig, col)
        ...
        R = data
        min_data = numpy.ma.min(data)
        max_data = numpy.ma.max(data)
        delta = max_data - min_data
        factor = 255 / delta if delta else 0
        for j, k in itertools.product(range(nb_lig), range(nb_col)):
            i = (data[j, k] - min_data) * factor
            R[j, k] = colorbar[round(i), 0]
        G = B[:,:] = R[:,:]
        ...

  3. #3
    Membre confirmé Avatar de Flaherty Mc Coillean
    Homme Profil pro
    Ingénieur de Recherche
    Inscrit en
    Décembre 2007
    Messages
    108
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 39
    Localisation : France, Puy de Dôme (Auvergne)

    Informations professionnelles :
    Activité : Ingénieur de Recherche
    Secteur : Aéronautique - Marine - Espace - Armement

    Informations forums :
    Inscription : Décembre 2007
    Messages : 108
    Par défaut
    Tout d'abord merci pour ta réponse, ta solution alternative me fait effectivement gagner un peu de temps de calcul mais pas encore assez à mon goût et je suis persuadé qu'en factorisant les calculs avec numpy.Aray j'obtiendrais un temps de calcul décent pour l'utilisation que j'aurais de ce bout de code (traitement en temps réel d'images satellites).

    Donc tout d'abord le contexte : Je travaille sur des images satellites, et plus particulièrement sur les données d'un satellite météorologique géostationnaire. Toutes les 15 minutes je reçois une nouvelle image, mon objectif est de faire tous mes traitements et calculs scientifiques et sur l'ensemble des cibles qui m’intéresse en moins de 15 minutes (histoire de pouvoir traiter les données suivantes). Pour traiter mes données j'utilise des librairies python spécialement conçues pour : mipp, pyresample et mpop. Ce que je cherche à faire une fois ma petite tambouille scientifique appliquée sur mes données c'est à sortir ces images en géotiffs (tiff géo-référencé et reprojeté ce qui permet de l'afficher sur une google map).

    En gros je pars de mes données qui sont sous la forme d'un numpy.Array de flottants ce peut être par exemple des températures en degré Kelvin (genre 273.15, 312.68, etc...). Ce genre de données je peux directement l'enregistrer en géotiff à l'aide de la librairie mpop mais seulement en noir et blanc genre comme ça :



    Ce que je cherche à faire c'est passer cette image en couleur (pourquoi ? Principalement pas soucis d’esthétisme on va dire XD). Mon code couleur est défini par une petite image PNG qui fait 1 pixel de large pour 256 pixels de haut genre ça : Nom : hotvolc.png
Affichages : 170
Taille : 249 octets


    Alors comment faire ? Première étape ré-étaler la dynamique de mes données pour que cette dernière colle avec ma 'colorbar' (mon fichier png). En effet mes données sont des flottants qui font la java sur une gamme de valeurs à la mord moi le noeud. Ce ré-étalement de la dynamique c'est ce que je fais quand je calcul mon array appelé index. Une fois le calcul d'index terminé, je me retrouve avec un array dont les valeurs vont de 0 (pour la plus petite valeurs de mes données) à 255 (pour la plus haute valeur de mes données).

    Une fois que j'ai index, il ne me reste plus qu'à dire pour chaque pixel tu vas récupérer dans ma colorbar la valeur de rouge, la valeur de vert et la valeur de bleu correspondant à ce pixel indexé.. Sauf qu'une double itération 'pour chaque ligne, pour chaque colonne' c'est trop long... Et là ce que je cherche à faire c'est à le faire dans l'autre sens, plutôt que de le faire case par case, je veux le faire degré de couleur par degré de couleur. En gros je veux dire trouve moi sur mon image tous les pixels indexé à 0, à ce moment là dans mon tableau R place la valeur de rouge adéquate au niveau des pixels concernés, idem pour le tableau G avec les valeurs de vert, et B avec les valeurs de bleu, et puis hop maintenant trouve moi tous les pixels indexés à 1 et ainsi de suite jusqu'à 255. Une itération sur 256 valeurs et bien plus courte vu la taille de mes images.

    Une fois que j'ai mes tableaux R, G et B je peux les repasser dans la babasse de mpop pour obtenir ce genre de chose :


    J'espère avoir été plus clair...

    Dans mon code quand j’exécute cette partie :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
       if min_data < max_data:
          index = numpy.around((((data - min_data)/(max_data - min_data))*255), decimals = 0)
          index = index.astype(int)
       else:
          index = data * 0.0
          index = index.astype(int)
    J'obtiens bien mes données avec une dynamique ré-étalée entre 0 et 255. J'ai vérifié le résultat obtenu est cohérent avec ce que je cherche à obtenir.

    Là ou ça ce complique c'est quand se bout de code s’exécute :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
       for i in range(0, 256):
          R[numpy.ma.where(index == i)] = colorbar[i][0]
          G[numpy.ma.where(index == i)] = colorbar[i][1]
          B[numpy.ma.where(index == i)] = colorbar[i][2]
    Dans ma tête avec ce bout de code je fais varier i de 0 à 255 (ce qui correspond à la dynamique de ma colorbar), pour chaque valeur de i (donc chaque palier de couleur) je récupère les positions de tous les pixels qui ont été indexé à ce dit palier, puis je leur attribut la valeur de couleur correspondant avant de passer au palier de couleur suivant. Sauf que... Je ne sais pas pourquoi mais lors de l'exécution de ce code mon array Index est modifié ! Comment est ce possible ? Et étrangement à la fin je me retrouve avec 4 array (index, R, G et B) identiques alors que colorbar[i][0], colorbar[i][1] et colorbar[i][2] donne des valeurs différentes. A nouveau je me pose la question de savoir pourquoi, et comment cela est-il possible !

    En espérant que vous pourrez m'aider merci =)

  4. #4
    Membre émérite
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Janvier 2013
    Messages
    388
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Ingénieur développement logiciels
    Secteur : Conseil

    Informations forums :
    Inscription : Janvier 2013
    Messages : 388
    Par défaut
    Ok. C'est plus clair.
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
       R = G = B = index
     
       for i in range(0, 256):
          R[numpy.ma.where(index == i)] = colorbar[i][0]
          G[numpy.ma.where(index == i)] = colorbar[i][1]
          B[numpy.ma.where(index == i)] = colorbar[i][2]
    De cette façon, les R, G et B sont des alias de index. Ils pointent tous sur le même objet, c'est pourquoi il sont tous identiques au final. Pour faire une copie, tu peux faire par exemple :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
        R = G[:,:] = B[:,:] = index[:,:]
    Ou encore :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
        R = np.zeros_like(index)
        G = np.zeros_like(index)
        B = np.zeros_like(index)
        for c in range(256):
            idx = index == c
            R[idx] = colorbar[c,0]
            G[idx] = colorbar[c,1]
            B[idx] = colorbar[c,2]

  5. #5
    Membre confirmé Avatar de Flaherty Mc Coillean
    Homme Profil pro
    Ingénieur de Recherche
    Inscrit en
    Décembre 2007
    Messages
    108
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 39
    Localisation : France, Puy de Dôme (Auvergne)

    Informations professionnelles :
    Activité : Ingénieur de Recherche
    Secteur : Aéronautique - Marine - Espace - Armement

    Informations forums :
    Inscription : Décembre 2007
    Messages : 108
    Par défaut
    Merci beaucoup problème résolu donc, et y a pas à dire je gagne en temps de calcul avec cette méthode ! Je m'en doutais que c'était un truc tout bête... La point positif c'est que je ne ferais plus cette erreur des alias. Encore merci =)

+ Répondre à la discussion
Cette discussion est résolue.

Discussions similaires

  1. [Débutant] Trouver le nombre d'éléments supérieurs à une certaine valeur
    Par IFREMER dans le forum MATLAB
    Réponses: 2
    Dernier message: 07/05/2009, 14h32
  2. Réponses: 16
    Dernier message: 15/08/2008, 11h08
  3. Comment rechercher dans les tables une valeur puis la modifier ?
    Par arnaudperfect dans le forum Requêtes
    Réponses: 5
    Dernier message: 01/07/2008, 10h28
  4. Réponses: 6
    Dernier message: 15/02/2008, 11h10
  5. Réponses: 3
    Dernier message: 05/03/2007, 12h54

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo