Convertir une couleur RGB en YUV

Convertir une couleur RGB en YUV - Programmation

Marsh Posté le 17-05-2001 à 18:56:19    

Salut,
Quelqu'un saurait comment convertir une couleur RGB en YUV et inversement.
 
Car en fait j'ai une couleur RGB et je veux augmenter la luminosité, donc j'ai pensé la convertir en YUV, augmenter la luminance, puis reconvertir en RGB.
 
Quelles sont les fonctions ou les formules mathématiques qui permettent cette conversions?
 
Merci

Reply

Marsh Posté le 17-05-2001 à 18:56:19   

Reply

Marsh Posté le 17-05-2001 à 18:58:59    

Reply

Marsh Posté le 17-05-2001 à 19:04:20    

merci!

Reply

Marsh Posté le 17-05-2001 à 19:08:17    

si ca marche pas, tu peux toujours jeter un oeil ici:
http://www.efg2.com/Lab/
ils ont un exemple pour changer la luminosite/contraste d'une image:
http://www.efg2.com/Lab/ImageProce [...] lettes.htm


---------------
www.alliancefrancophone.org ... Home is where the heart is
Reply

Marsh Posté le 18-05-2001 à 05:04:02    

Desole de pourrir le topic :) mais j'ai deux questions a la con :)
 
Quelle est la difference entre augmenter/diminuer les channels d'une image en RGB(A) et augmenter/diminuer les channels en YUV ?
L'une des methodes augmente la luminosite (RGB?) et l'autre ??
 
Que se passe-t-il avec un algo comme ca:
- On test si le channel Red est inferieur a 255
  et on l'augmente
- On test si le channel Green est inferieur a 255
  et on l'augmente
- On test si le channel Blue est inferieur a 255
  et on l'augmente
 
Si l'un des channels d'un pixel est deja sature, on ne l'augmente donc pas mais on augmente les autres....L'image est-elle deformee ??

 

[edit]--Message édité par Willythekid--[/edit]


---------------
Si t'es pas net, reste a la buvette
Reply

Marsh Posté le 18-05-2001 à 09:59:22    

Les composantes RGB n'ont pas la même luminosité.
Le Green est beaucoups plus lumineux que le Red qui est plus lumineux que le Blue.
Si tu veux modifier la luminosité en RGB il faut tenir compte de ces différences et modifier les composantes en fonction de leur contribution à la luminosité.
C'est ce qui est fait en YUV ou Y represente en gros la luminosité et UV les couleurs.
Y=(0.257 * R) + (0.504 * G) + (0.098 * B) + 16

Reply

Marsh Posté le 18-05-2001 à 10:24:24    

ok ok merci pour cette precision!!
Ma curiosite est comblee :)
 
En fait, il est inutile de se faire chier a converir tout en YUV pour augmenter la luminosite...l'application de cette formule suffit...
 
Au fait a quoi sert le 16 dans ta formule ?
(les couleurs ca a jamais ete mon truc!!)


---------------
Si t'es pas net, reste a la buvette
Reply

Marsh Posté le 18-05-2001 à 10:31:19    

Gnoof,
 
Une fois convertie en YUV et la luminosité augmentée comment tu fais pour reconvertir en RGB,
et quel est la plage de valeur de Y (0 à 255) ?

Reply

Marsh Posté le 18-05-2001 à 14:45:44    

Voilà les formules complètes
Y=(0.257 * R) + (0.504 * G) + (0.098 * B) + 16;
U=(0.439 * R) - (0.368 * G) - (0.071 * B) + 128;
V=-(0.148 * R) - (0.291 * G) + (0.439 * B) + 128;
 
R=1.164*(Y - 16) + 1.596*(U- 128);
G=1.164*(Y - 16) - 0.813*(U- 128) - 0.391*(V- 128);
B=1.164*(Y - 16)+ 2.018*(V - 128);
 
Il faut clamper les valeurs entre 0 et 255 et lors de la conversion float(ou double)--> int ne pas oublier d'ajouter 0.5 avant de faire floor(..)

Reply

Marsh Posté le 18-05-2001 à 14:55:51    

Merci beaucoup!
 
(mais qu'est ce que t'entends par clamper les valeurs entre 0 et 255 et est-ce que je clampe avant ou après la conversion) ?

Reply

Marsh Posté le 18-05-2001 à 14:55:51   

Reply

Marsh Posté le 18-05-2001 à 15:14:07    

Voila, j'ai écrit ces deux fonctions avec tes formules:
 
void Rgb2Yuv(ColorYUV *yuv,char r,char g,char b)
{
 double y,u,v;
 
 y=(0.257 * r) + (0.504 * g) + (0.098 * b) + 16 + 0.5;
 u=(0.439 * r) - (0.368 * g) - (0.071 * b) + 128 + 0.5;
 v=-(0.148 * r) - (0.291 * g) + (0.439 * b) + 128 +0.5;
 
 if (y>255) y=255;
 if (u>255) u=255;
 if (v>255) v=255;
 
 yuv->y=(char) floor(y);
 yuv->u=(char) floor(u);
 yuv->v=(char) floor(v);
}
 
void Yuv2Rgb(ColorRGB *rgb,char y,char u,char v)
{
 double r,g,b;
 
 r=1.164*(y - 16) + 1.596*(u - 128) + 0.5;
 g=1.164*(y - 16) - 0.813*(u - 128) - 0.391 * (v - 128) + 0.5;
 b=1.164*(y - 16) + 2.018*(v - 128) + 0.5;
 
 if (r>255) r=255;
 if (g>255) g=255;
 if (b>255) b=255;
 
 rgb->r=(char) floor(r);
 rgb->g=(char) floor(g);
 rgb->b=(char) floor(b);
}
 
Mon problème est le suivant:
Quand je convertis une couleur RGB en YUV et que je la reconvertis immédiatement après en RGB, la couleur d'arrivée est complètement différente de la couleur de départ...
Comment ça se fait, on devrait obtenir la même couleur après une conversion RGB->YUV->RGB.

Reply

Marsh Posté le 18-05-2001 à 18:00:30    

up

Reply

Marsh Posté le 18-05-2001 à 19:37:35    

UP Urgent SVP... :)

Reply

Marsh Posté le 19-05-2001 à 11:13:32    

Ben exactement, non.
Vu que a travaille en flottant et qu'en plus il y a des floors.
 
M'enfin ca devrait pas être "complètement différent" juste à quelques arrondis près.
 
Essaye avec du noir, du blanc, du gris, du bleu, du rouge, du vert et tu verras déjà si t'arrives à avoir la même chose...

Reply

Marsh Posté le 19-05-2001 à 11:16:04    

D'autres part, dans l'algo au dessus moi j'aurai fait le test de >255 avec des int, c'est plus rapide, surtout que juste après il y a une "traduction" de double en int...

Reply

Marsh Posté le 19-05-2001 à 12:17:23    

Heu...
Le noir me donne du blanc, le blanc reste blanc
le rouge donne du blanc, enfin ça dépend des teintes des composantes de départ, mais en gros ça rend n'importe quoi...
 
Personne n'a un algo complet qui marche pour conversion dans les deux sens???

Reply

Marsh Posté le 19-05-2001 à 12:19:01    

Au fait maintenant l'algo ressemble à ça:
 
PS: pour l'instant je me fiche de l'optimisation, je veux juste un algo qui marche :) merci
 
void Rgb2Yuv(ColorYUV *yuv,int r,int g,int b)
{
 double y,u,v;
 
 if (r>255) r=255;
 if (g>255) g=255;
 if (b>255) b=255;
 
 y=(0.257 * r) + (0.504 * g) + (0.098 * b) + 16;
 u=(0.439 * r) - (0.368 * g) - (0.071 * b) + 128;
 v=-(0.148 * r) - (0.291 * g) + (0.439 * b) + 128;
 
 yuv->y=(int) floor(y);
 yuv->u=(int) floor(u);
 yuv->v=(int) floor(v);
}
 
void Yuv2Rgb(ColorRGB *rgb,int y,int u,int v)
{
 double r,g,b;
 
 if (y>255) y=255;
 if (u>255) u=255;
 if (v>255) v=255;
 
 r=1.164*(y - 16) + 1.596*(u - 128);
 g=1.164*(y - 16) - 0.813*(u - 128) - 0.391 * (v - 128);
 b=1.164*(y - 16) + 2.018*(v - 128);
 
 rgb->r=(int) floor(r);
 rgb->g=(int) floor(g);
 rgb->b=(int) floor(b);
}

Reply

Marsh Posté le 19-05-2001 à 14:00:40    

le premier merdait

Citation :


void Yuv2Rgb(ColorRGB *rgb,char y,char u,char v)  


 
merdait certainement à cause du fait que yuv, étaient interprété en signé -128..127 & pas 0...255 (d'ou les couleurs qui partent en couille)

Reply

Marsh Posté le 19-05-2001 à 14:16:21    

N'empeche que ça marche toujours pas cet algo, les couleurs deviennent n'importe quoi quand je fais une conversion RGB->YUV->RGB.
 
Les formules mathématiques sont peut être fausses...

Reply

Marsh Posté le 20-05-2001 à 11:59:28    

Ben c'est vrai qu'en prenant noir (0,0,0) aucune des 2 formules ne donne 0.
 
Pour le YUV->RGB, j'ai (source MeuhMeuhTV)
nB = (116*(nY-16)                + 202*(nU-128)) / 100;
nG = (116*(nY-16) -  81*(nV-128) -  39*(nU-128)) / 100;
nR = (116*(nY-16) + 160*(nV-128)               ) / 100;
 
3 equations, 3 inconnues, tu peux retrouver la formule inverse :D
 
Par contre il y a des tests autour pour remettre 0 quand c'est négatif ou au dessus de 255

Reply

Marsh Posté le 20-05-2001 à 12:18:24    

Merci, je vais essayer de voir avec ces formules, on va bien voir...

Reply

Marsh Posté le 21-05-2001 à 10:09:08    

Enfin je voulais dire qu'au dessus de 255 ca remet à 255 ;)
D'ou l'interet de travailler en int et pas en char.
Ca surcharge la pile de 3*4 octets, c'est pas la mort.

Reply

Marsh Posté le    

Reply

Sujets relatifs:

Leave a Replay

Make sure you enter the(*)required information where indicate.HTML code is not allowed