Changer couleur image

Résolu
cs_roro69 Messages postés 70 Date d'inscription vendredi 27 décembre 2002 Statut Membre Dernière intervention 29 septembre 2018 - 30 déc. 2017 à 21:46
vb95 Messages postés 3472 Date d'inscription samedi 11 janvier 2014 Statut Contributeur Dernière intervention 13 avril 2024 - 14 janv. 2018 à 16:05
Bonsoir et Merci pour le temps consacré et l'aide apporté
Voilà ce que je souhaiterais:
Dans mon programme je charge de petite image 100 pixel par 100 pixel;
Avec le code je récupère la couleurs du pixels:

For i = 0 To monImage.Width - 1
For j = 0 To MonImage.Height - 1
LaCouleur = monImage.GetPixel(i, j)
Next i
Next j


A partir de là je souhaiterais changer la couleur de chaque pixel avec une palette que j'ai crée donc je charge ces couleurs dans une liste comme ceci:

Private MaPalette As New List(Of Color) From {Color.FromArgb(236, 237, 237), Color.FromArgb(240, 232, 185), Color.FromArgb(240, 185, 1), Color.FromArgb(230, 79, 39), Color.FromArgb(182, 49, 54), Color.FromArgb(225, 136, 159), Color.FromArgb(105, 74, 130), Color.FromArgb(44, 70, 144), Color.FromArgb(48, 92, 176), Color.FromArgb(37, 104, 71)}


Donc à partir de là je voudrais que mon programme compare chaque pixel et le remplace avec la couleur la plus proche de ma palette

Voilà ce que j'ai déjà tenté ;mais j'ai une erreur de dépassement de capacité.
Voici le code:
For i = 0 To monImage.Width - 1
                For j = 0 To monImage.Height - 1
                    LaCouleur = monImage.GetPixel(i, j)
                    Dim lememe As Integer = 0
                    Dim oldmeme As Integer = 0
                Dim oldval As Double = 0
                Dim val As Double= Math.Sqrt((LaCouleur.A - MaPalette(0).A) * (LaCouleur.A - MaPalette(0).A) + (LaCouleur.G - MaPalette(0).G) * (LaCouleur.G - MaPalette(0).G) + (LaCouleur.B - MaPalette(0).B) * (LaCouleur.B - MaPalette(0).B) + (LaCouleur.R - MaPalette(0).R) * (LaCouleur.R - MaPalette(0).R))
                For idx As Integer = 0 To MaPalette.Count - 1
                    Dim val2 As Double = Math.Sqrt((LaCouleur.A - MaPalette(idx).A) * (LaCouleur.A - MaPalette(idx).A) + (LaCouleur.G - MaPalette(idx).G) * (LaCouleur.G - MaPalette(idx).G) + (LaCouleur.B - MaPalette(idx).B) * (LaCouleur.B - MaPalette(idx).B) + (LaCouleur.R - MaPalette(idx).R) * (LaCouleur.R - MaPalette(idx).R))
                    If val2 <= val Then
                            oldval = val
                            val = val2
                            oldmeme= meme
                            meme = idx
                        End If
                    Next idx
                    monimage2.SetPixel(i, j, MaPalette(meme))
                Next j
            Next i

Voilà à partir de là je suis bloqué ;et je ne sais pas pourquoi j'ai un dépassement de capacité
je vous remercie d'avance pour l'aide apporté et les conseils donnés

2 réponses

vb95 Messages postés 3472 Date d'inscription samedi 11 janvier 2014 Statut Contributeur Dernière intervention 13 avril 2024 169
Modifié le 31 déc. 2017 à 17:01
Bonjour


Private MaPalette As New List(Of Color) From {Color.FromArgb(236, 237, 237), Color.FromArgb(240, 232, 185), Color.FromArgb(240, 185, 1), Color.FromArgb(230, 79, 39), Color.FromArgb(182, 49, 54), Color.FromArgb(225, 136, 159), Color.FromArgb(105, 74, 130), Color.FromArgb(44, 70, 144), Color.FromArgb(48, 92, 176), Color.FromArgb(37, 104, 71)}


Dans la déclaration de ta palette tu ne précises pas le paramètre A : donc celui est implicitement égal à 255 ( soit le plus opaque)

Chaque couleur est définie par 4 paramètres : A , R G et B ( chacun de ces paramètres est sur 8 bits( de 0 à 255 comme plage de valeurs)
Avant d'aller plus loin peux-tu expliquer la formule avec Math.Sqrt : tu fais l'addition de 4 valeurs et chacune de ces valeurs serait l'élévation au carré d'une composante de la couleur - la même composante de la palette

Math.Sqrt( ( (Acouleur - Apalette) ^2) + ( (Rcouleur - Rpalette) ^2) + ( (Gcouleur - Gpalette) ^2) + ( (Bcouleur - Bpalette) ^2) )



La théorie, c'est quand on sait tout et que rien ne fonctionne. La pratique, c'est quand tout fonctionne et que personne ne sait pourquoi. 
0
cs_roro69 Messages postés 70 Date d'inscription vendredi 27 décembre 2002 Statut Membre Dernière intervention 29 septembre 2018
31 déc. 2017 à 18:19
Bonjour vb95 ;merci pour ta réponses.
Je vais essayer d'expliquer ce que je tente de faire:
Pour commencer voici ce que je voudrais c'est réaliser un programme pour faire de patrons de perles hama que ma filles à eu pour son noël.
Donc la liste de couleur est la liste de toute les couleurs de perles hama; ainsi avec cette palette je voudrais changer les couleurs d'une image avec la palettes des couleurs hama.
Pour la formule :
A chaque passage d'un pixel ;je calcule une valeur la plus élevé pour un pixel en comparant les composante argb de l'image avec la première couleurs de ma palette ;
ensuite au même passage de ce pixel je parcours mes couleurs de palette et je calcule la valeur qui doit correspondre a la valeur ci dessus; de là je récupère la couleur et injecte le pixel dans un nouveau bitmap.

Voilà merci beaucoup vb 95 de ton temps consacré et de l'aide apporté
0
cs_roro69 Messages postés 70 Date d'inscription vendredi 27 décembre 2002 Statut Membre Dernière intervention 29 septembre 2018
31 déc. 2017 à 20:39
0
vb95 Messages postés 3472 Date d'inscription samedi 11 janvier 2014 Statut Contributeur Dernière intervention 13 avril 2024 169 > cs_roro69 Messages postés 70 Date d'inscription vendredi 27 décembre 2002 Statut Membre Dernière intervention 29 septembre 2018
2 janv. 2018 à 23:58
Bonsoir
Si je comprends pas tu prends la couleur d'un pixel de l'image d'origine et tu recherches dans ta palette des couleurs des perles hama la couleur la plus approchée .
J'ai été sur le site où tu as pris les infos .
Quand à la valeur la plus élevée pour un pixel ( la couleur blanche ) c'est les 4 composantes A, R , G et B mises à la valeur 255 alors que la plus basse ( la couleur noire ) a ses 4 composantes à 0 .
Donc je ne vois pas pourquoi tu fais le premier calcul !
Quand au calcul avec la racine carrée j'ai un petit doute : dans les couleurs de la palette hama tu ne précises pas la composante A de le couleur ( donc celle est à 255 par défaut)
Dans ton code
 LaCouleur = monImage.GetPixel(i, j)
récupères-tu des valeurs positives ou négatives ?
0
cs_roro69 Messages postés 70 Date d'inscription vendredi 27 décembre 2002 Statut Membre Dernière intervention 29 septembre 2018
3 janv. 2018 à 18:55
Bonjour Vb95 Merci pour ta réponse
J'ai trouvé une solution : c'est un peu lent mais bon çà marche

Public Function BonneCouleur(ByVal imgg As Bitmap) As Bitmap
Dim i As Integer = 0
Do While i < imgg.Height
Dim j As Integer = 0
Do While j < imgg.Width
Dim bestindex As Integer = 0
Dim val As Integer = 255 * 255 + 255 * 255 + 255 * 255 + 1
For k As Integer = 0 To MesCouleurs.Count - 1
Dim mycolor As Color = imgg.GetPixel(j, i)
Dim Rdiff As Integer = mycolor.R
Dim Gdiff As Integer = mycolor.G
Dim Bdiff As Integer = mycolor.B

If Rdiff < MesCouleurs(k).R Then
Rdiff = MesCouleurs(k).R - Rdiff
Else
Rdiff = Rdiff - MesCouleurs(k).R
End If

If Gdiff < MesCouleurs(k).G Then
Gdiff = MesCouleurs(k).G - Gdiff
Else
Gdiff = Gdiff - MesCouleurs(k).G
End If

If Bdiff < MesCouleurs(k).B Then
Bdiff = MesCouleurs(k).B - Bdiff
Else
Bdiff = Bdiff - MesCouleurs(k).B
End If

Dim val1 As Integer = Rdiff * Rdiff + Gdiff * Gdiff + Bdiff * Bdiff

If val1 < val Then
val = val1
bestindex = k
End If
Next k
imgg.SetPixel(j, i, MesCouleurs(bestindex))
j += 1
Loop
i += 1
Loop
Return imgg
End Function

Donc je t'explique ce que je souhaite faire:
1) je charge une image.
2)Je redimensionne mon image suivant le cadre qui va être utilisé
(1 pixel = 1 perle)
2)je crée des palettes avec les couleurs de perles hama ; il y a 46 couleurs non transparente ; je mets dans une liste les couleurs en fonctions de l'image.(Maximum 10)
3)Je parcours mon image pour incorporer ces couleurs au plus proches.
4) je quadrille mon image 1 X 1 pixel
Voilà Merci de ton aide et de tes réponses toujours aussi bien détaillé
0
vb95 Messages postés 3472 Date d'inscription samedi 11 janvier 2014 Statut Contributeur Dernière intervention 13 avril 2024 169 > cs_roro69 Messages postés 70 Date d'inscription vendredi 27 décembre 2002 Statut Membre Dernière intervention 29 septembre 2018
3 janv. 2018 à 19:19
Bonsoir cs_roro69
Il y a surement moyen d'optimiser et d'accélérer tout ceci !
Déjà sortir les Dim des boucles For : cela évite de redimensionner la variable

For k As Integer = 0 To MesCouleurs.Count - 1
Dim mycolor As Color = imgg.GetPixel(j, i)
Dim Rdiff As Integer = mycolor.R
Dim Gdiff As Integer = mycolor.G
Dim Bdiff As Integer = mycolor.B
' La suite du code
Next k

Dans le cas au-dessus à chaque tour de boucle tu crées les 4 variables qui sont détruites à la fin de chaque tour de boucle et tu les recrées à nouveau au tour suivant


Dim mycolor As Color
Dim Rdiff As Integer
Dim Gdiff As Integer
Dim Bdiff As Integer
For k As Integer = 0 To MesCouleurs.Count - 1
mycolor = imgg.GetPixel(j, i)
Rdiff = mycolor.R
Gdiff = mycolor.G
Bdiff = mycolor.B
' La suite du code
Next k


Il y a d'autres optimisations à faire aussi au niveau des 3 tests suivants


If Rdiff < MesCouleurs(k).R Then
Rdiff = MesCouleurs(k).R - Rdiff
Else
Rdiff = Rdiff - MesCouleurs(k).R
End If


Je regarderais dès que j'aurais un moment !
Meilleurs vœux à vous pour 2018 !
0
cs_roro69 Messages postés 70 Date d'inscription vendredi 27 décembre 2002 Statut Membre Dernière intervention 29 septembre 2018
9 janv. 2018 à 15:53
Bonjour CGSI3
Super code ;j'ai mis dans mon application c'est excellent .
Plus qu'a finaliser mon application de perle (un peu plus compliqué que je ne pensais ; difficile de travailler des images )
Merci beaucoup a toi et a vb95
Meric pour votre aide et votre temps consacré
--
0
vb95 Messages postés 3472 Date d'inscription samedi 11 janvier 2014 Statut Contributeur Dernière intervention 13 avril 2024 169
14 janv. 2018 à 16:05
Bonjour !
Si nos réponses t'ont satisfait utilises la roue dentée en haut de ton message pour mettre le sujet en résolu !
Merci
0
Rejoignez-nous