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 :

Modifier bandes RGB - module PIL


Sujet :

Python

Vue hybride

Message précédent Message précédent   Message suivant Message suivant
  1. #1
    Futur Membre du Club
    Homme Profil pro
    Taupin MP
    Inscrit en
    Juin 2021
    Messages
    4
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 24
    Localisation : France, Marne (Champagne Ardenne)

    Informations professionnelles :
    Activité : Taupin MP

    Informations forums :
    Inscription : Juin 2021
    Messages : 4
    Par défaut Modifier bandes RGB - module PIL
    Bonjour,

    Je travaille sur un petit projet qui consiste à créer une mosaïque à partir d'une banque d'image : l'image formée au finale est constituée de plein de petites images qui forment les pixels de la grande image.
    Voici une illustration que j'ai réalisée :
    Nom : exemple..jpg
Affichages : 174
Taille : 2,07 Mo

    Pour cela, j'ai créé un dictionnaire (enregistré en .json) dont les clés sont les triplets "(R, G, B)" et les valeurs sont les noms des images dont la couleur moyenne correspond au code RGB.
    Je parcours les pixels de ma grande image, et pour chacun, je cherche la couleur la plus proche dans le dictionnaire (j'utilise pour l'instant la méthode un peu améliorée de la distance euclidienne en sRGB, disponible ici (wiki).

    Maintenant, je souhaite améliorer le rendu final en modifiant légèrement chaque petite image formant les "pixels" de ma grande image pour se rapprocher davantage de la couleur voulue.
    Pour ce faire, j'ai calculé la différence entre le code RGB du pixel courant de la grande image et le code RGB de l'image la plus proche (dans le dictionnaire) : j'obtiens Dr, Dg, Db (les différences correspondant au rouge, vert et bleu). Puis, j'ai séparé les bandes R, G, B de ma petite image (qui remplacera le pixel) avec img.split(), que j'ai transformé en 3 tableaux numpy avec numpy.array(img), et auxquels j'ai ajouté les différences divisées par deux Dr//2, Dg//2 et Db//2.
    Le résultat est décevant. J'ignore pourquoi, mais à certains endroits, les couleurs sont très forcées :
    Nom : exemple2.jpg
Affichages : 144
Taille : 822,1 Ko

    Je m'y prend peut-être mal.

    Quelqu'un pourrait-il m'aider à résoudre mon problème ?

  2. #2
    Membre Expert

    Homme Profil pro
    Ingénieur calcul scientifique
    Inscrit en
    Mars 2013
    Messages
    1 229
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Alpes Maritimes (Provence Alpes Côte d'Azur)

    Informations professionnelles :
    Activité : Ingénieur calcul scientifique

    Informations forums :
    Inscription : Mars 2013
    Messages : 1 229
    Par défaut
    Bonjour

    Citation Envoyé par Mentalink Voir le message
    Le résultat est décevant. J'ignore pourquoi, mais à certains endroits, les couleurs sont très forcées
    Oui, c'est sûr que si vous corriger 50% de l'erreur, alors forcément les traits de vos petites images vont être très forcés, à moins que l'erreur de base ne soit pas très grande. Et si vous corrigez 100% de l'erreur, alors normalement chacune de vos petites images va être un aplat unicolore (faire des test en montant dans les %, pour voir si cela est validé).
    Vous pourriez :
    1- diminuer le ratio que vous ajouter
    2- vous pourriez ajouter à chaque canal, l'erreur moyenne commise sur la petite image. Car en gommant un certain % de l'erreur pixel par pixel, et bien vous aller plus dénaturer les pixels sur lesquels il y a beaucoup d'erreurs que les autres. Alors que si vous corriger votre petite image par un ajout constant sur toute l'image, alors vous aller rapprocher le niveau RGB moyen de la petite image, du niveau RGB attendu, mais cela, sans dénaturé le contraste que votre image pourrait avoir. (Attention à ce que cette modif ne fasse pas des pixel négatif, ou bien au dessus de 255)

  3. #3
    Futur Membre du Club
    Homme Profil pro
    Taupin MP
    Inscrit en
    Juin 2021
    Messages
    4
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 24
    Localisation : France, Marne (Champagne Ardenne)

    Informations professionnelles :
    Activité : Taupin MP

    Informations forums :
    Inscription : Juin 2021
    Messages : 4
    Par défaut
    Bonsoir,

    Merci pour votre réponse. Il est vrai que si l'erreur commise est grande, la correction apportée modifierait l'image fortement. Je m'en suis aperçu en imprimant pour chaque petite image la correction ajoutée pour chaque couleur : on atteint parfois des écarts de 30 à 40 (sur 255 : c'est beaucoup). Cependant, je n'arrive pas à bien saisir pourquoi certaines zones des petites images sont plus dénaturées que d'autres, car la correction porte bien sur toute l'image : je fait la différence, pour chaque couleur (R, G et B) entre le code RGB du pixel désiré et le code RGB correspondant à la couleur moyenne de la petite image. Ensuite, pour chaque bande de la petite image (et non pour chaque pixel : c'est la bande de l'image toute entière que je modifie !), j'ajoute la moitié de la différence correspondante.

    J'aimerais réagir maintenant à vos propositions :
    1- Diminuer le ratio comme vous le préconisez semble adapté au vu de l'écart important, même si avec une banque plus grande d'image, l'écart sera sans doute moindre. Ajouter un écrêtage serait l'idéal, je pense. Cette solution me semble peu satisfaisante puisqu'elle ne permettrait pas une correction si importante de l'image.
    2 - Je ne pense pas avoir correctement saisi la solution que vous proposez : peut-être avez-vous mal compris ce que je fais ? Comme je l'ai dit, la correction de la petite image se fait sur chacun des trois canaux, et non pixel par pixel. Pour être plus précis, je récupère les canaux de la petite image dans des tableaux où chaque case correspond à un pixel, et j'ajoute à toutes les cases la moitié de la différence dont le calcul est expliqué précédemment. M'y prendrais-je mal ?
    2' - Je ne m'étais pas posé la question des bornes du pixel : il se peut en effet qu'avec cette méthode, j'obtienne des pixels négatifs ou supérieurs à 255. Que se passe-t-il ? La couleur est-elle définie d'une manière modulaire ? Devrais-je écrêter les valeurs à 0 et 255 lorsqu'un pixel dépasse ces bornes :
    a) sur toute la bande ?
    b) sur le pixel concerné uniquement ?

    Enfin, après réflexion, ne serait-ce pas le caractère non linéaire du codage RGB qui ferait apparaître un tel défaut ? Concrètement, peut-être qu'ajouter 10 à la composante rouge du code correspondant à une couleur cyan modifie davantage la couleur qu'en faisant de même sur un code de couleur saumon. Si cette explication est la bonne, il faudrait trouver un moyen de corriger le ton moyen de l'image sans avoir de tels écarts sur certains pixels : existe-t-il une fonction du module ImageFilter ?


    Je tiens à vous remercier à nouveau pour votre réponse : ce projet me tient à coeur et j'aimerais pouvoir avancer.


    EDIT :
    J'ai limité pour chaque pixel des petites images les valeurs RGB entre 0 et 255 (solution 2')b)) : rien n'y fait, le problème demeure.

  4. #4
    Membre Expert

    Homme Profil pro
    Ingénieur calcul scientifique
    Inscrit en
    Mars 2013
    Messages
    1 229
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Alpes Maritimes (Provence Alpes Côte d'Azur)

    Informations professionnelles :
    Activité : Ingénieur calcul scientifique

    Informations forums :
    Inscription : Mars 2013
    Messages : 1 229
    Par défaut
    Sur le calcul d'erreur, si je peux mieux m'exprimer, voici un petit exemple. Disons qu'il n'y a qu'un seul canal pour simplifier (une image en niveau de gris)

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    valeur_cible = 100
     
    ma_petite_image = np.array([[120,120,110],[95,87,101],[98,107,99]])
     
    ### option 1
    err1 = ma_petite_image - valeur_cible
    print(err1)
    ma_nouvelle_petite_image1 = ma_petite_image + 0.5*err1
     
    ### option 2
    err2 = np.mean(ma_petite_image) - valeur_cible
    print(err2)
    ma_nouvelle_petite_image2 = ma_petite_image + 0.5*err2
    Je pense que vous faites l'option 1 (dans laquelle err1 est du coup un tableau, qui a la même taille que l'image, et dont les valeurs varient d'un pixel à un autre), et je suggère de faire plutot l'option 2, où la correction appliquée est exactement la meme sur toute la petite image et non variable d'un pixel à un autre de cette petite image.


    Pour le reste si ca dépasse les bornes 0;255 oui je pense que le rendu va être bizarre, donc mieux vaut faire un min/max pour ramener les valeurs supérieurs à 255 à juste 255 et idem pour les valeurs négatives, les ramener à 0.

  5. #5
    Futur Membre du Club
    Homme Profil pro
    Taupin MP
    Inscrit en
    Juin 2021
    Messages
    4
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 24
    Localisation : France, Marne (Champagne Ardenne)

    Informations professionnelles :
    Activité : Taupin MP

    Informations forums :
    Inscription : Juin 2021
    Messages : 4
    Par défaut
    Bonjour,
    Merci pour votre réactivité et votre temps dédié à fournir des exemples clairs.

    J'ai trois points sur lesquels m'exprimer :

    — Et non, vous vous trompez, c'est bien l'option 2 que je fais depuis le début ! Je n'ai peut-être pas été assez clair là-dessus, excusez-moi en. C'est ce que je voulais dire par :
    Citation Envoyé par Mentalink Voir le message
    je fais la différence, pour chaque couleur (R, G et B) entre le code RGB du pixel désiré et le code RGB correspondant à la couleur moyenne de la petite image
    Donc le problème n'est pas celui-ci : cela aurait été tout de même une bonne explication.

    — J'ajoute que j'ai écrêté les valeurs à 0 et 255 pour chaque pixel mais que ça ne règle pas le problème non plus (même si cela ne semble pas se voir sur le rendu final, c'est une amélioration : merci).

    — Je me permet de citer ci-dessous ce que j'avais écrit : est-ce pertinent ?
    Enfin, après réflexion, ne serait-ce pas le caractère non linéaire du codage RGB qui ferait apparaître un tel défaut ? Concrètement, peut-être qu'ajouter 10 à la composante rouge du code correspondant à une couleur cyan modifie davantage la couleur qu'en faisant de même sur un code de couleur saumon. Si cette explication est la bonne, il faudrait trouver un moyen de corriger le ton moyen de l'image sans avoir de tels écarts sur certains pixels : existe-t-il une fonction du module ImageFilter ?

  6. #6
    Membre Expert

    Homme Profil pro
    Ingénieur calcul scientifique
    Inscrit en
    Mars 2013
    Messages
    1 229
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Alpes Maritimes (Provence Alpes Côte d'Azur)

    Informations professionnelles :
    Activité : Ingénieur calcul scientifique

    Informations forums :
    Inscription : Mars 2013
    Messages : 1 229
    Par défaut
    Citation Envoyé par Mentalink Voir le message
    — Je me permet de citer ci-dessous ce que j'avais écrit : est-ce pertinent ? [...]
    Oui je n'ai volontairement pas répondu sur ce point, car les autres points venant suplanter celui là, il me fallait éclaircir les précédents points. D'autant que l'idée que vous amenez ici, peut se défendre, mais en fait conduit à beaucoup d'autres questions. Comme :
    - Par exemple, si vous considérer que le rouge à plus d'importance, ok, alors vous allez mettre une correction un peu moindre sur ce canal pour ne pas trop dénaturer l'image d'origine. Mais tenant compte du fait que la correction soit pondérée sur les canaux, peut etre qu'une autre petite image aurait mieux convenue, car plus proche de la valeur voulue sur le canal rouge. Donc ca voudrait dire que pour rester consistant, il faudrait peut etre intégrer cette pondération dans la norme d'erreur.
    - comment choisir intelligemment les poids de chaque canal ? Prendre ceux de la luminance ? Ou bien finalement peut-être qu'une conversion dans un système HSV serait mieux, car là, les canaux ont chacun une sémantique, et peut être que là vous allez pouvoir tuner les poids de sorte à mieux traduire mathématiquement ce que veut dire "ne pas trop dénaturer l'image".

    Dans tous les cas, vous construire un petit set de 3-4 petites images avec des valeurs cibles, et avec une correction qui selon vous dénature l'image, vous permettra de faire plus de test de tout ça.

  7. #7
    Futur Membre du Club
    Homme Profil pro
    Taupin MP
    Inscrit en
    Juin 2021
    Messages
    4
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 24
    Localisation : France, Marne (Champagne Ardenne)

    Informations professionnelles :
    Activité : Taupin MP

    Informations forums :
    Inscription : Juin 2021
    Messages : 4
    Par défaut
    Je suis tout à fait d'accord avec vos remarques, et je pense tout de suite pour le premier point à la méthode de Monte Carlo, qui permettrait de s'autoriser à revenir un peu en arrière pour prendre la meilleure image. Mais avant cela, il faudrait trouver un moyen de traduire la perception humaine (ce que vous évoquez après). J'ai pour cela fait quelques recherches (sur wikipédia essentiellement) pour comprendre les systèmes de codages existant puis les différentes méthodes et améliorations historiques aux formules proposées (surtout ici).
    Je ne suis pas du tout familier ni à l'aise avec ces notions très nouvelles pour moi. Il me reste donc à me documenter (peut-être avez-vous des sources utiles ?) sur tout cela, y compris la luminance et le système HSV.

    Je reviendrai sans doute plus tard vers vous, que ce soit pour régler un autre problème - si cela ne vous dérange pas - ou pour donner la solution pour laquelle j'aurais opté.
    J'ai en ce moment des oraux à préparer, donc l'avancement de mon projet se trouve retardé.

    Merci pour toutes vos réponses,
    Antoine.

Discussions similaires

  1. Probleme module PIL python 3.4
    Par Mima19 dans le forum Général Python
    Réponses: 2
    Dernier message: 23/04/2015, 18h55
  2. Module PIL et python 3
    Par Grye300 dans le forum Programmation multimédia/Jeux
    Réponses: 4
    Dernier message: 23/04/2014, 20h49
  3. pbs module PIL avec py2exe
    Par claude 64 dans le forum Général Python
    Réponses: 5
    Dernier message: 09/01/2013, 21h10
  4. Python et le module PIL
    Par figarojuju dans le forum Debian
    Réponses: 2
    Dernier message: 21/04/2008, 08h46
  5. [py2exe] module PIL
    Par jbjweb dans le forum Py2exe
    Réponses: 1
    Dernier message: 26/10/2006, 08h21

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