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

Python Discussion :

[PIL ou numpy]Correction de couleur sur une image


Sujet :

Python

  1. #1
    Membre éclairé
    Avatar de airod
    Homme Profil pro
    Gérant Associé, DMP Santé et Directeur technique
    Inscrit en
    Août 2004
    Messages
    767
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 49
    Localisation : France, Essonne (Île de France)

    Informations professionnelles :
    Activité : Gérant Associé, DMP Santé et Directeur technique
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Août 2004
    Messages : 767
    Par défaut [PIL ou numpy]Correction de couleur sur une image
    Bonjour,

    Malgré mes recherches je n'ai pas encore trouvé comment faire.

    Voilà, c'est assez simple, je cherche a appliquer une correction de couleur sur une image, tel une courbe photoshop.

    l'idée est de passer par une courbe de bézier, mais PIL ne permet pas de le faire directement.

    Avez vous des solutions a me proposer.
    Merci d'avance.

  2. #2
    Membre éclairé
    Avatar de airod
    Homme Profil pro
    Gérant Associé, DMP Santé et Directeur technique
    Inscrit en
    Août 2004
    Messages
    767
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 49
    Localisation : France, Essonne (Île de France)

    Informations professionnelles :
    Activité : Gérant Associé, DMP Santé et Directeur technique
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Août 2004
    Messages : 767
    Par défaut Première solution mais trop, beaucoup trop lente...
    Bonjour,

    j'ai réussi a obtenir ce que je veux en créant une liste représentant mon bezier, mais si le traitement est assez rapide sur une petite image, il est beaucoup trop long sur une image haute definition (3000px x2000 px). Auriez vous une idée pour optimiser le temps de traitement, l'objectif étant de l'intégrer dans un serveur de traitement d'image.

    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
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
    88
    89
    90
    factor=2 #facteur de correction pour retrouver les corrections de photoshop
     
    def make_bezier(xys):
        # xys should be a sequence of 2-tuples (Bezier control points)
        n = len(xys)
        combinations = pascal_row(n-1)
        def bezier(ts):
            # This uses the generalized formula for bezier curves
            # http://en.wikipedia.org/wiki/B%C3%A9zier_curve#Generalization
            result = []
            for t in ts:
                tpowers = (t**i for i in range(n))
                upowers = reversed([(1-t)**i for i in range(n)])
                coefs = [c*a*b for c, a, b in zip(combinations, tpowers, upowers)]
                result.append(
                    tuple(sum([coef*p for coef, p in zip(coefs, ps)]) for ps in zip(*xys)))
            return result
        return bezier
     
    def pascal_row(n):
        # This returns the nth row of Pascal's Triangle
        result = [1]
        x, numerator = 1, n
        for denominator in range(1, n//2+1):
            # print(numerator,denominator,x)
            x *= numerator
            x /= denominator
            result.append(x)
            numerator -= 1
        if n&1 == 0:
            # n is even
            result.extend(reversed(result[:-1]))
        else:
            result.extend(reversed(result))
        return result
     
    def bezierRGB(r,g,b):
        ts = [t/100.0 for t in range(101)]
        dcouches={}
        dcorr={'R':r,'G':g,'B':b}
        for c in dcorr :
            xys = [(0, 0), (128,128+(dcorr[c]*factor)), (255, 255)]
            bezier = make_bezier(xys)
            points = bezier(ts)
            dcouches[c]=points
        return [dcouches['R'],dcouches['G'],dcouches['B']]
     
    def newPoint(pt,bezier):
        #return (pt,bezier)
        a=0
        while pt > bezier[a][0] :
            a+=1
     
        if a>0 : npt = int(bezier[a][1])
        else : npt = int(bezier[0][1])
     
        return (pt,npt,bezier)
     
    def colorAdjustement(im,r,g,b):
        lbezierRGB=bezierRGB(r,g,b)
        width, height = im.size
        colortuples = im.getcolors(maxcolors=17000000)
        pix = im.load()
        u=max(len(lbezierRGB[0]),len(lbezierRGB[1]),len(lbezierRGB[2])) #longueur max des points de courbes
        print u
        for x in range(0, width):
            for y in range(0, height):
                ro,go,bo=list(pix[x,y])
                color=(ro,go,bo)
     
     
                if y==100 and x==100:
                    print newPoint(ro,lbezierRGB[0])
                if r !=0 :
                    ro = newPoint(ro,lbezierRGB[0])[1]
                if g !=0 :
                    go = newPoint(go,lbezierRGB[1])[1]
                if b !=0 :
                    bo = newPoint(bo,lbezierRGB[2])[1]
     
     
                im.putpixel((x, y), (ro,go,bo))
     
        return im
     
    if __name__ == '__main__':
        import Image
        im = Image.open("0002.JPG")
        im = colorAdjustement(im,30,10,0)
        im.save('0002_CorrectionBezier.JPG')
    Merci d'avance

  3. #3
    Membre confirmé

    Homme Profil pro
    Lycéen
    Inscrit en
    Avril 2015
    Messages
    19
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 26
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : Lycéen

    Informations forums :
    Inscription : Avril 2015
    Messages : 19
    Par défaut
    Bonjour,

    Je suggère numpy pour construire une courbe de bézier.

    Un petit exemple avec numpy. La fonction adjust_colors prend en entrée une image couleur (np.array de taille (longueur, largeur, 3)), et quatre autres tableaux de taille (256,) qui correspondent à des courbes (bézier par exemple). Ces courbes vont être appliquées sur chaque canaux, rouge, vert, bleu, et les trois en même temps (changement de contraste).

    L'indice d'une valeur d'un tableau numpy correspond à l'abscisse d'un point de la courbe bézier, la valeur associée à cet indice correspond à l'ordonnée de ce point. Dès lors, il suffit, en travaillant sur un canal, de changer la valeur V d'un pixel par la valeur d'indice V de ce tableau.

    Un exemple plutôt rapide pour une photo couleur de taille 768x1024 (7-8 secondes) :

    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
    40
    41
    42
    import scipy.misc
    import numpy as np
    import matplotlib.pyplot as plt
     
    def adjust_colors(image, red, green, blue, value):
        for i in xrange(image.shape[0]):
            for j in xrange(image.shape[1]):
                image[i, j, 0] = red[image[i, j, 0]]
                image[i, j, 1] = green[image[i, j, 1]]
                image[i, j, 2] = blue[image[i, j, 2]]
                for x in xrange(image[i, j].shape[0]):
                    image[i, j, x] = value[image[i, j, x]]
     
    # load image
    photo = scipy.misc.face()
     
    # manipulation des canaux rgb l'image
    # courbe de couleur pour chaque canal
    # .
    #    .
    #      .
    #         .
    #            .
    # 0  50%  100%
    r = g = b = np.arange(0, 256)[::-1]
     
    # manipulation du contraste de l'image
    # courbe de contraste
    # .       .
    #  .     .
    #   .   .
    #    . .
    #     .
    # 0  50%  100%
    v0 = np.linspace(0, 255, 128)
    v1 = v0.copy()[::-1]
    v = np.concatenate((v1, v0))
    adjust_colors(photo, r, g, b, v)
     
    # affichage de l'image
    plt.imshow(photo)
    plt.show()

  4. #4
    Membre éclairé
    Avatar de airod
    Homme Profil pro
    Gérant Associé, DMP Santé et Directeur technique
    Inscrit en
    Août 2004
    Messages
    767
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 49
    Localisation : France, Essonne (Île de France)

    Informations professionnelles :
    Activité : Gérant Associé, DMP Santé et Directeur technique
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Août 2004
    Messages : 767
    Par défaut
    merci,

    j'ai testé votre code from scratch, mis a par que j'ai été obligé de changer
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
     
    photo = scipy.misc.face()
    par
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    photo = scipy.misc.imread('0002.JPG')
    car scipy.misc.face n'existe pas dans la version mise à ma disposition.

    Malgré tout, mon image fait 3888x2592, et c'est la taille minimum des images que je vais devoir traiter et le temps d'exécution est encore trop long (cependant les corrections ne sont pas les même). Je pense que l'on est au même niveau que mon code.
    Je pense que tout se passe au niveau des doubles boucles.

    une lecture de time donne 97.8 pour votre code contre 113.6 pour le mien. Mieux mais il faudrait que j'arrive a tomber sous les 50 pour être bon.

    Je vais décortiquer votre code pour bien comprendre, car c'est un peu flou pour l'instant.

    Merci.

  5. #5
    Membre confirmé

    Homme Profil pro
    Lycéen
    Inscrit en
    Avril 2015
    Messages
    19
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 26
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : Lycéen

    Informations forums :
    Inscription : Avril 2015
    Messages : 19
    Par défaut
    Autant pour moi.
    Maintenant, je te défie de faire mieux !

    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
    40
    import scipy.misc
    import numpy as np
    import matplotlib.pyplot as plt
     
    def adjust_colors(image, red, green, blue, value):
        image[:, :, 0] = red[image[:, :, 0]]
        image[:, :, 1] = green[image[:, :, 1]]
        image[:, :, 2] = blue[image[:, :, 2]]         
        for i in xrange(image.shape[2]):
             image[:, :, i] = value[image[:, :, i]]
     
    # load image
    photo = scipy.misc.face()
     
    # manipulation des canaux rgb l'image
    # courbe de couleur pour chaque canal
    # .
    #    .
    #      .
    #         .
    #            .
    # 0  50%  100%
    r = g = b = np.arange(0, 256)[::-1]
     
    # manipulation du contraste de l'image
    # courbe de contraste
    # .       .
    #  .     .
    #   .   .
    #    . .
    #     .
    # 0  50%  100%
    v0 = np.linspace(0, 255, 128)
    v1 = v0.copy()[::-1]
    v = np.concatenate((v1, v0))
    adjust_colors(photo, r, g, b, v)
     
    # affichage de l'image
    plt.imshow(photo)
    plt.show()

  6. #6
    Membre éclairé
    Avatar de airod
    Homme Profil pro
    Gérant Associé, DMP Santé et Directeur technique
    Inscrit en
    Août 2004
    Messages
    767
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 49
    Localisation : France, Essonne (Île de France)

    Informations professionnelles :
    Activité : Gérant Associé, DMP Santé et Directeur technique
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Août 2004
    Messages : 767
    Par défaut
    Pas mieux

    Mais j'ai besoin d'explication de texte. Pouvez vous m'expliquer le code. et comment passer les paramètres pour obtenir le type de correction juste RGB, comme le fait mon code.

    Merci d'avance.

  7. #7
    Membre confirmé

    Homme Profil pro
    Lycéen
    Inscrit en
    Avril 2015
    Messages
    19
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 26
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : Lycéen

    Informations forums :
    Inscription : Avril 2015
    Messages : 19
    Par défaut
    Pour combien ?

    Je te fais cadeaux de l'utilitaire complet, amplement commenté, avec un exemple.

  8. #8
    Membre éclairé
    Avatar de airod
    Homme Profil pro
    Gérant Associé, DMP Santé et Directeur technique
    Inscrit en
    Août 2004
    Messages
    767
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 49
    Localisation : France, Essonne (Île de France)

    Informations professionnelles :
    Activité : Gérant Associé, DMP Santé et Directeur technique
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Août 2004
    Messages : 767
    Par défaut
    Mille merci.

    Je décortique.

  9. #9
    Membre éclairé
    Avatar de airod
    Homme Profil pro
    Gérant Associé, DMP Santé et Directeur technique
    Inscrit en
    Août 2004
    Messages
    767
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 49
    Localisation : France, Essonne (Île de France)

    Informations professionnelles :
    Activité : Gérant Associé, DMP Santé et Directeur technique
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Août 2004
    Messages : 767
    Par défaut
    Voilà donc le code terminé.
    Un grand merci a he2lo pour sa précieuse aide.

    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
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
    88
    89
    90
    91
    92
    93
    94
    95
    96
    97
    98
    99
    100
    101
    102
    103
    104
    105
    106
    107
    108
    109
    110
    111
    112
    113
    114
    115
    116
    117
    118
    119
    120
    121
    122
    123
    124
    125
    126
    127
    128
    129
    130
    131
    132
    133
    134
    135
    136
    137
    138
    139
    140
    141
    142
    143
    144
    145
    146
    147
    148
    149
    150
    151
    152
    153
    154
    155
    156
    157
    158
    159
    160
    161
    162
    163
    164
    165
    166
    167
    168
    169
    170
    171
    import scipy.misc
    import numpy as np
    import matplotlib.pyplot as plt
    from scipy.interpolate import interp1d
    from PIL import Image
    import time
     
     
    factor=2 #facteur de correction pour retrouver les corrections de photoshop
     
    def make_bezier(xys):
        # xys should be a sequence of 2-tuples (Bezier control points)
        n = len(xys)
        combinations = pascal_row(n-1)
        def bezier(ts):
            # This uses the generalized formula for bezier curves
            # http://en.wikipedia.org/wiki/B%C3%A9zier_curve#Generalization
            result = []
            for t in ts:
                tpowers = (t**i for i in range(n))
                upowers = reversed([(1-t)**i for i in range(n)])
                coefs = [c*a*b for c, a, b in zip(combinations, tpowers, upowers)]
                result.append(
                    tuple(sum([coef*p for coef, p in zip(coefs, ps)]) for ps in zip(*xys)))
            return result
        return bezier
     
    def pascal_row(n):
        # This returns the nth row of Pascal's Triangle
        result = [1]
        x, numerator = 1, n
        for denominator in range(1, n//2+1):
            # print(numerator,denominator,x)
            x *= numerator
            x /= denominator
            result.append(x)
            numerator -= 1
        if n&1 == 0:
            # n is even
            result.extend(reversed(result[:-1]))
        else:
            result.extend(reversed(result))
        return result
     
    def bezierRGB(r,g,b):
        ts = [t/100.0 for t in range(101)]
        dcouches={}
        dcorr={'R':r,'G':g,'B':b}
        for c in dcorr :
            xys = [(0, 0), (128,128+(dcorr[c]*factor)), (255, 255)]
            bezier = make_bezier(xys)
            points = bezier(ts)
            dcouches[c]=points
        return [dcouches['R'],dcouches['G'],dcouches['B']]
     
    def splitBezier(bezier):
        """retourne un tuple de liste (x,y) des points contenu dans make_bezier"""
        x,y=[],[]
        for p in bezier :
            x.append(p[0])
            y.append(p[1])
        return (x,y)
     
    """
        Small utility which is dealing with rgbv curves
        to do some color corrections on a coloured image
    """
     
    def color_curve(x, y, kind):
        """
            Create a color curve given a set of points and a kind of interpolation
     
            Parameters
            ----------
            x : numpy 1d array
                The x-coordinates of your points (must be between 0 and 255
                                    included and stored in increasing order).
            y : numpy 1d array
                The y-coordinates of your points (values ranging from 0 to 255).
            kind: string
                The kind of interpolation : linear, cubic (for at least 4 points),
                quadratic (for at least 3 points).
     
            Returns
            -------
            out : numpy 1d array
                The y-coordinates of the curve, the indices being their x-coords.
                Beware: All negative values are set to zero !
     
            Examples
            --------
            >>> x = np.array([0, 50, 128, 200, 255])
            >>> y = np.array([255, 0, 125, 0, 255])
            >>> plt.plot(np.arange(256), color_curve(x, y, 'quadratic'))
            >>> plt.show()
        """
        return interp1d(x, y, kind)(np.arange(256)).clip(min=0)
     
     
    def adjust_colors_contrast(image, red, green, blue, contrast):
        """
            Apply color curves on the color channels of an image
     
            Parameters
            ----------
            image : numpy array of shape (width, height, 3)
                A coloured image.
            red, green, blue, contrast : numpy 1d arrays (256 values
                                                ranging from 0 to 255)
                The color curves that are applied on the color channels.
     
            Returns
            -------
            out : numpy array of shape (width, height, 3)
                The resulting image.
        """
        image[:, :, 0] = red[image[:, :, 0]]
        image[:, :, 1] = green[image[:, :, 1]]
        image[:, :, 2] = blue[image[:, :, 2]]
        # Apply the color curves on each channels
        for i in xrange(image.shape[2]):
             image[:, :, i] = contrast[image[:, :, i]]
             # Apply the contrast curve on each channels
     
    def adjust_colors(image, red, green, blue):
        """
            Apply color curves on the color channels of an image
     
            Parameters
            ----------
            image : numpy array of shape (width, height, 3)
                A coloured image.
            red, green, blue, contrast : numpy 1d arrays (256 values
                                                ranging from 0 to 255)
                The color curves that are applied on the color channels.
     
            Returns
            -------
            out : numpy array of shape (width, height, 3)
                The resulting image.
        """
        image[:, :, 0] = red[image[:, :, 0]]
        image[:, :, 1] = green[image[:, :, 1]]
        image[:, :, 2] = blue[image[:, :, 2]]
        # Apply the color curves on each channels
     
    def ajustColorImage(im,r,g,b):
        image=scipy.misc.fromimage(im)
        beziers=bezierRGB(r,g,b)
        rbezier=splitBezier(beziers[0])
        r = color_curve(rbezier[0], rbezier[1], 'quadratic')
        # The color curve which correspond to the quadratic interpolation of points
        # (0, 255), (128, 0), (255, 255) is applied on the red color channel.
        gbezier=splitBezier(beziers[1])
        g = color_curve(gbezier[0], gbezier[1], 'quadratic')
        # The color curve which correspond to the straight line passing through
        # the points (0, 255), (255, 0) is applied on the green color channel.
        bbezier=splitBezier(beziers[2])
        b = color_curve(bbezier[0], bbezier[1], 'quadratic')
        # The color curve which correspond to the straight line passing through
        # the points (0, 0), (255, 255) is applied on the blue color channel.
        # Doing this will not apply a color correction on this channel
        adjust_colors(image, r, g, b)
        return image
     
    if __name__ == '__main__':
        a=time.time()
        im=Image.open("0002.JPG")
        im=Image.fromarray( ajustColorImage(im,30,10,0))
        print time.time() - a
        im.save('0002_colorCorrectionScipy.JPG')
    si ca intéresse quelqu'un

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

Discussions similaires

  1. Réponses: 9
    Dernier message: 03/03/2015, 14h57
  2. [Débutant] Fleche, Texte, Cadre et Choix des couleurs sur une image
    Par niepoc dans le forum MATLAB
    Réponses: 10
    Dernier message: 16/07/2008, 16h44
  3. placer un filtre de couleur sur une image
    Par mm2405 dans le forum Traitement d'images
    Réponses: 2
    Dernier message: 06/12/2007, 11h25
  4. [Pygame]Supprimer/masquer les pixels d'une même couleur sur une image
    Par Mysti¢ dans le forum Programmation multimédia/Jeux
    Réponses: 2
    Dernier message: 10/05/2007, 13h40
  5. [CSS]Supprimer couleur sur une image en lien
    Par Nasky dans le forum Mise en page CSS
    Réponses: 4
    Dernier message: 10/06/2006, 14h22

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