algorithme de conversion RGB>YUV - C++ - Programmation
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...
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)
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.
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 :
|
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)
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.
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 : |
à 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 : |
ok.
donc à priori la routine converti bien un RGB 24 bits en YUV 24bits....
faudrait regarder si le YUV 411 colle avec ça...
Marsh Posté le 08-09-2003 à 19:44:38
http://www.microsoft.com/Developer [...] edia_Types
Citation : |
Marsh Posté le 09-09-2003 à 09:14:24
ok merci beaucoup je vais vérifier tout ça... je te tiens au courant.
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.
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...
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).
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)
Marsh Posté le 09-09-2003 à 11:31:48
ce qui semble bon !!!!
et (255,255,0) donne bien 16....
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)
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.
Marsh Posté le 09-09-2003 à 11:39:52
en fait on est retombé sur l'équation initiale, mais avec U & V inversés....
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,...) ?
Marsh Posté le 09-09-2003 à 11:42:51
ensuite le 411 est expliqué dans la doc philips "4:1:1 YCbCr (orthogonal)
sampling"
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...
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).
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 )
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....
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....
Marsh Posté le 09-09-2003 à 12:07:00
sinon il se peut que tu ayes un buffer à Y et un buffer à U+V....
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...)
Marsh Posté le 10-09-2003 à 16:12:22
bizarre
si l'ordre des octets était mauvais, on aurait une image shootée
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....
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;
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. |
OK merci par contre que signifie le >> 8 ?
Marsh Posté le 11-09-2003 à 11:00:08
Rody83 a écrit : |
décalage de 8 bits vers la droite ce qui revient a diviser par 256.
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.
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...
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 :.