algorithme de conversion RGB>YUV

algorithme de conversion RGB>YUV - C++ - Programmation

Marsh Posté le 08-09-2003 à 16:26:54    

Salut.
 
J'ai un programme qui (entre autres) convertit un flux vidéo du format RGB en format YUV 411 planar. Or j'ai un problème, en sortie la vidéo est en noir et blanc...
J'ai cherché un peu partout sur le net et les équations que j'utilise sont les suivantes :
 
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
 
sachant que j'en ai essayé d'autres qui me donnent le même résultat. J'ai l'impression que j'ai seulement la luminance (composante Y)... Quelqu'un a-t'il déjà eu ce problème ? Si oui pourrait-il m'aider ? Merci d'avance.
 
NB : j'ai posté dans C++ car le programme est fait dans ce langage...


---------------
.: Passions | Galerie | Blog :.
Reply

Marsh Posté le 08-09-2003 à 16:26:54   

Reply

Marsh Posté le 08-09-2003 à 16:53:53    

bah déjà vérifies que tout est flottant, car si tu stoques dans des entiers, la partie fractionnaire peut sauter...

Reply

Marsh Posté le 08-09-2003 à 17:06:59    

sinon ta matrice a l'air bonne, hormis les +16/+128.
 
en fait la question est (sont):
 
qu'est-ce que tu as en entrée, un truc entre 0 et 1 flottant, ou 0 et 255 entier ?
 
qu'est-ce que tu veux en sortie ? (flottant entre 0 et 1 ou entier entre 0 et 255)

Reply

Marsh Posté le 08-09-2003 à 17:30:32    

En fait c'est prog qui a été fait avant que je commence mon stage (par un autre stagiaire, justement) et il est fonctionnel à part ce problème de noir et blanc que j'ai pour tâche de corriger...
Il faut que je continue à regarder ce qui s'y fait, mais au niveau des équations j'en ai trouvées pas mal, et toutes reviennent au même ; comme mon prédécesseur avait fait pas mal de recherches sur le sujet, je pense qu'il a trouvé les meilleures...
Sinon concernant la partie entière, j'ai des warning à la compilation qui m'avertissent à propos d'une conversion de "double" à "unsigned char" : ça peut venir de là mon problème ?
Enfin en sortie il me semble que c'est compris entre 0 et 255, et un e fonction se charge de corriger les dépassements...idem pour l'entrée.


---------------
.: Passions | Galerie | Blog :.
Reply

Marsh Posté le 08-09-2003 à 18:25:46    

c'est là le problème...
 
concernant la "matrice" de passage du RVB au YUV, elle est normalisée, donc tu devrais toujours trouver les même coefficients sur le net, le problème est donc:
 

Code :
  1. Y = 0.257*R + 0.504*G + 0.098*B + 16
  2. U = 0.439*R - 0.368*G - 0.071*B + 128
  3. V = -0.148*R - 0.291*G + 0.439*B + 128


 
a) format de l'entrée
b) format de sortie
c) les constantes sont elles bonne et sont peut être là à cause du a) & b)

Reply

Marsh Posté le 08-09-2003 à 18:27:26    

donc maintenant, autre astuce (Taz devrait passer par là)
 
si tes Y,U,V sont des unsigned char, j'ai peur qu'il fasse des vielles troncations dans le calcul...
 
alors attends je me fais à truc à la con pour tester la routine.

Reply

Marsh Posté le 08-09-2003 à 18:49:41    

bon si t'y mets un (255,255,255) , tu as en sortie (235.045,128,128)
 
http://www.globalmediapro.com/av/messages/82880.html
 

Citation :


Here's what's happening. Broadcast YUV runs in the range 16-235. RGB runs in 0-255. There are legitimate YUV values below 16 and above 235 for short periods (sometimes known as superblack and superwhite).
 
When we move RGB to YUV and back, we do clamp YUV values in the 0-15 and 236 to 255 to equal 'black' and 'white' respectively.
 
This is a clamping artifact visible on a vectorscope (Not FCP's software vectorscope, since it works in RGB space, but a real vectorscope.) This occurs only on render, since we do need to reach legitimate RGB values, and place them legitimately into YUV space.


 
à priori au niveau encodage en YUV, il faut clamper le 0-15 et le 236-255.
 
vu le comportement de la routine, ça semble attendre le R,V,B entre 0 et 255, donc l'octet de chaque canal...
 
avec le rouge à fond uniquement (255,0,0), on a ~(81,240,90) et pour le bleu à fond on obtiens ~(41,110,240).
 
ce qui semble cohérent.... (enfin chui pas sûr)
 
-------
 
buh, un lien sympa: (mais qui complique l'affaire)
 
http://www.nalanda.nitc.ac.in/indu [...] LORSPC.PDF
 
----------
 
bon ça s'éclairci:
 
pour le Y, ton équation et celle de philips "coincident":
 
la routine attends bien des valeurs entre 0 et 255.
elle cherche à produire un Y entre 16 et 235.
si tu prends l'équation de philips pour le Y:
 
Y=0.299*R + 0.587*G + 0.114*B
 
et que tu  considères que tu veux ramener ta plage non pas sur 255 niveaux mais 219 (235 max - 16 min), tu prémultiplies les coefs par 219/255, et tu ajoutes 16:  
 
0.299*(219/255)=>0.2567
0.587*(219/255)=>0.5041
0.114 => 0.0979
 
ce qui fait que Y semble cohérent.
après voir si ça colle pour l'encode en YUV 411 planar...
 
 
---------------------------------------------
 
de la doc philips:
 

Citation :


The color
difference signals Cb and Cr are coded in
offset binary, which ?offsets? the ?no color?
point into the middle of the number range to
code 128 (80 hex). 100% color saturation
uses the codes from 16 (10 hex) to 240 (F0
hex).


 
ok.
 
donc à priori la routine converti bien un RGB 24 bits en YUV 24bits....
 
faudrait regarder si le YUV 411 colle avec ça...


Message édité par bjone le 08-09-2003 à 19:16:50
Reply

Marsh Posté le 08-09-2003 à 19:44:38    

http://www.microsoft.com/Developer [...] edia_Types
 

Citation :


MEDIASUBTYPE_Y411  
 
YUV 411 format data. Same as Y41P.  
 
MEDIASUBTYPE_Y41P
 
Y41P format data.  
 
A packed YUV format. A Y sample at every pixel, a U and V sample at every fourth pixel horizontally on each line; every vertical line sampled. Byte ordering (lowest first) is U0, Y0, V0, Y1, U4, Y2, V4, Y3, Y4, Y5, Y6, Y7, where the suffix 0 is the leftmost pixel and increasing numbers are pixels increasing left to right. Each 12-byte block is 8 image pixels.  
 

Reply

Marsh Posté le 09-09-2003 à 09:14:24    

ok merci beaucoup je vais vérifier tout ça... je te tiens au courant. :hello:
 
EDIT : j'ai essayé l'équation de Philips pour le Y et ça donne la même chose... il faut donc creuser du côté des U et V, ce sont eux qui doivent foirer.


Message édité par rody83 le 09-09-2003 à 10:10:44

---------------
.: Passions | Galerie | Blog :.
Reply

Marsh Posté le 09-09-2003 à 11:06:36    

bon essayé les équations de Philips pour les U et V, mais si j'ajoute pas 128 à la fin, ça me donne n'importe quoi comme image (avec des couleurs, certes, mais crados) ; c'est trop bizarre en plus c'est pas moi qui ait codé le prog, donc c'est chaud de comprendre ce qui a été fait...
par contre j'ai aussi essayé de faire la transformation inverse sur les U et V (enlever 128 et multiplier les coeffs par 255/127) et ça marche pas mieux...


---------------
.: Passions | Galerie | Blog :.
Reply

Marsh Posté le 09-09-2003 à 11:06:36   

Reply

Marsh Posté le 09-09-2003 à 11:17:10    

le 128 est là, car c'est l'encodage est non-signé mais avec offset. en gros U & V sont signés, MAIS dans l'octet le 0 correspond à 128. (il faut donc décaller le bourdel avec un +128).

Reply

Marsh Posté le 09-09-2003 à 11:29:39    

yep, quand je remets +128 ça revient "normal" (en N&B quoi)... je sais plus où chercher ; je me demande si ça vient pas d'ailleurs  :??:


---------------
.: Passions | Galerie | Blog :.
Reply

Marsh Posté le 09-09-2003 à 11:31:38    

ensuite si tu prends l'équation de phillips U & V peuvent être négatifs.
 
donc U et V prennent un delta de 224 et non 219 comme Y (d'après philips)
 
donc la normalisation de plage serait 224/255 (pour faire un truc symétrique comme pour Y)...
 
donc si prends l'équation philips:  
 
U = - 0.169 * R - 0.331 * G + 0.500 * B
 
donc:
 
U = - 0.1484*R - 0.29*G + 0.4392*B (+ 128)

Reply

Marsh Posté le 09-09-2003 à 11:31:48    

ce qui semble bon !!!!
 
et (255,255,0) donne bien 16....


Message édité par bjone le 09-09-2003 à 11:32:50
Reply

Marsh Posté le 09-09-2003 à 11:35:10    

c la même chose pour Y ? ou le delta diffère ?
 
EDIT : dsl tu as déjà répondu à ça... ;)


Message édité par rody83 le 09-09-2003 à 11:35:47

---------------
.: Passions | Galerie | Blog :.
Reply

Marsh Posté le 09-09-2003 à 11:35:28    

on va faire pareil pour V:
 
V=0.500 * R - 0.419 * G - 0.081 * B
 
=> 0.4392*R - 0.368 * G - 0.07115 *B (+128)

Reply

Marsh Posté le 09-09-2003 à 11:36:52    

j'essaie ça de suite...
 
EDIT : ça donne la même chose, toujours en N&B ; je vais voir si ça vient pas d'ailleurs pk là les équations sont bonnes a priori.


Message édité par rody83 le 09-09-2003 à 11:38:45

---------------
.: Passions | Galerie | Blog :.
Reply

Marsh Posté le 09-09-2003 à 11:38:10    

pareil, on obtient bien un bon comportement avec (255,0,0) qui donne 240 et (0,255,255) qui donne 16.
 
donc le matrice final est donc:
 
Y = 0.257*R + 0.504*G + 0.098*B + 16;
U = - 0.1484*R - 0.29*G + 0.4392*B + 128 ;  
V = 0.4392*R - 0.368 * G - 0.07115 *B + 128;
 
après il faudrait vérifier que l'encodage YUV 411 est correct, mais si tu as bien le noir et blanc sur toute l'image, c'est que le placement des octets est correct.

Reply

Marsh Posté le 09-09-2003 à 11:39:52    

en fait on est retombé sur l'équation initiale, mais avec U & V inversés....

Reply

Marsh Posté le 09-09-2003 à 11:42:50    

au niveau des octets c'est impec... par contre je me demandais un truc : pour chaque U et V de calculés on a 4 composantes RGB (puisqu'on a YYYYUV) ; donc comment savoir lors du calcul de U et V quelles composantes prendre (R1G1B1, R2G2B2,...) ?


---------------
.: Passions | Galerie | Blog :.
Reply

Marsh Posté le 09-09-2003 à 11:42:51    

ensuite le 411 est expliqué dans la doc philips "4:1:1 YCbCr (orthogonal)
sampling"

Reply

Marsh Posté le 09-09-2003 à 11:44:30    

BJOne a écrit :

en fait on est retombé sur l'équation initiale, mais avec U & V inversés....


 
ce qui ne change rien au résultat final...


---------------
.: Passions | Galerie | Blog :.
Reply

Marsh Posté le 09-09-2003 à 11:45:27    

Rody83 a écrit :

au niveau des octets c'est impec... par contre je me demandais un truc : pour chaque U et V de calculés on a 4 composantes RGB (puisqu'on a YYYYUV) ; donc comment savoir lors du calcul de U et V quelles composantes prendre (R1G1B1, R2G2B2,...) ?


 
pour chaque pixel, du fais ta conversion RGB 24 bits => YUV 24 bits (8 bits/composante).
 
en YUV 411, pour un paquet de 4 pixels, tu émets le YUV du premier pixel, et ensuite uniquement le Y de chaque pixel (pour les 3 suivants).

Reply

Marsh Posté le 09-09-2003 à 11:46:58    

donc le calcul est bon, vu que c'est le premier pixel qui est pris en compte... j'avais essayé de faire la moyenne des 4 pixels, mais ça changeait pas grand chose.


---------------
.: Passions | Galerie | Blog :.
Reply

Marsh Posté le 09-09-2003 à 11:48:43    

par contre le truc qui me chiffonne c'est l'ordonnencement...
 
en prennant le truc de philips directement, on a:
 
Y0 U0 V0 | Y1 | Y2 | Y3 | Y4 U4 V4 | Y5 | Y6 | Y7 .....
 
(enfin c'est l'interprétation que j'en fais hein ;) )


Message édité par bjone le 09-09-2003 à 11:55:03
Reply

Marsh Posté le 09-09-2003 à 11:52:00    

alors que le format 41P  (411 packed) decrit pas grosspft c'est:
 
Y0 U0 V0 | Y1  U4 | Y2  V4 | Y3 | Y4 | Y5 | Y6 | Y7 ......
 
pas blocs de 12 octets répétitifs.... :??:


Message édité par bjone le 09-09-2003 à 11:52:27
Reply

Marsh Posté le 09-09-2003 à 12:00:46    

moi c'est du 4.1.1 planar que je veux ; à priori c'est Y1Y2Y3Y4U1V1


---------------
.: Passions | Galerie | Blog :.
Reply

Marsh Posté le 09-09-2003 à 12:02:05    

enfin attention ça l'interprétation que j'en fais....
 
ça se trouve je me plantes....
 

Reply

Marsh Posté le 09-09-2003 à 12:07:00    

sinon il se peut que tu ayes un buffer à Y et un buffer à U+V....

Reply

Marsh Posté le 09-09-2003 à 12:09:25    

http://www.efg2.com/Lab/Graphics/Colors/YUV.htm#411
 
et eux le format YUV 411 planar
 
c'est 4 Y + un couple UV (ce qui est ptet plus correct...)

Reply

Marsh Posté le 10-09-2003 à 14:35:08    

apparemment le problème doit venir d'ailleurs ; je vais en discuter avec mon tuteur de stage cet apr...
 
EDIT voilà l'image une fois encodée puis décodée :
 
http://r.lourd.free.fr/divers/capture.jpg


Message édité par rody83 le 10-09-2003 à 14:52:59

---------------
.: Passions | Galerie | Blog :.
Reply

Marsh Posté le 10-09-2003 à 16:12:22    

bizarre :/
 
si l'ordre des octets était mauvais, on aurait une image shootée :??:

Reply

Marsh Posté le 10-09-2003 à 16:13:55    

ce que tu peux faire pour débugguer le bordel:
 
ajoute un bout de code ou tu émets le premier pixel de chaque image dans un fichier .txt
 
puis tu teste avec une image noire, blanche, rouge, bleu, et tu regardes les résultats....
 

Reply

Marsh Posté le 10-09-2003 à 16:41:05    

je vais essayer ça... thx


---------------
.: Passions | Galerie | Blog :.
Reply

Marsh Posté le 11-09-2003 à 10:00:09    

si t'as besoin d'avoir de bonnes perfs pour ta routine de conversion, voici une astuce : tu ramènes tous tes coeffs sur 256.
Y = 0.299f*R + 0.587f*G + 0.114f*B;
Y = (76*R + 150*G + 30*B) >> 8;

Reply

Marsh Posté le 11-09-2003 à 10:48:30    

hellbilly a écrit :

si t'as besoin d'avoir de bonnes perfs pour ta routine de conversion, voici une astuce : tu ramènes tous tes coeffs sur 256.
Y = 0.299f*R + 0.587f*G + 0.114f*B;
Y = (76*R + 150*G + 30*B) >> 8;
 


 
OK merci par contre que signifie le >> 8 ?


---------------
.: Passions | Galerie | Blog :.
Reply

Marsh Posté le 11-09-2003 à 11:00:08    

Rody83 a écrit :


 
OK merci par contre que signifie le >> 8 ?


décalage de 8 bits vers la droite ce qui revient a diviser par 256.

Reply

Marsh Posté le 11-09-2003 à 11:29:14    

oki d'acc...


---------------
.: Passions | Galerie | Blog :.
Reply

Marsh Posté le 11-09-2003 à 21:01:17    

oui mais bon avant de passer en virgule fixe, fodrait déjà que ce qui soit sorti soit bon ;)
 
pi à la limite autant passer en virgule fixe 16:16.


Message édité par bjone le 11-09-2003 à 21:01:51
Reply

Marsh Posté le 12-09-2003 à 10:54:07    

en fait je vais appliquer la tactique suivante :
 
- prendre deux images identiques existantes, l'un en rgb et l'autre en yuv
- encoder puis décoder la même image à partir de rgb
- comparer l'original en yuv (le bon) et celle que j'obtiens, voir les différences qu'il y a
 
l'ennui c'est que j'arrive pas à trouver une image rgb et sa transformée en yuv...


---------------
.: Passions | Galerie | Blog :.
Reply

Marsh Posté le    

Reply

Sujets relatifs:

Leave a Replay

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