| [C++] Approximation entière d'un produit avec un float | |
|
|
Auteur | Message |
---|
Mass *Excellent utilisateur*
Messages : 3351 Localisation : Dans une canonnière wookie. Projet Actuel : Monter des trucs et des machins
| Sujet: [C++] Approximation entière d'un produit avec un float Mar 4 Nov 2014 - 16:43 | |
| Salut tout le monde Je m'intéressait il y a peu au traitement/compression du signal vidéo et j'ai eu à convertir un signal RGB en un signal YUV. La formule "classique" donnée notamment par Wikipédia est la suivante : - Code:
-
Y = 0,299 * R + 0,587 * G + 0,114 * B U = −0,14713 * R − 0,28886 * G + 0,436 * B V = 0,615 * R − 0,51498 * G - 0,10001 * B Cela marche très bien mais il s'agit de multiplier chaque composante RGB (un entier non signé de 8 bits) par un float, donc c'est un calcul beaucoup plus lent pour le CPU. J'ai donc trouvé un code similaire qui me fait le même calcul mais avec une approximation utilisant des entiers : - Code:
-
#define CLIP(X) ( (X) > 255 ? 255 : (X) < 0 ? 0 : X)
#define RGB2Y(R, G, B) CLIP(( ( 66 * (R) + 129 * (G) + 25 * (B) + 128) >> 8) + 16) #define RGB2U(R, G, B) CLIP(( ( -38 * (R) - 74 * (G) + 112 * (B) + 128) >> 8) + 128) #define RGB2V(R, G, B) CLIP(( ( 112 * (R) - 94 * (G) - 18 * (B) + 128) >> 8) + 128) Ici CLIP est une simple fonction empêchant l'overflow, mais comme vous pouvez le constater, l'intégralité du calcul se fait au moyen d'entiers, ce qui est beaucoup beaucoup beaucoup plus rapide (testé et approuvé). Le soucis, c'est que je ne comprend pas le fonctionnement de ce code. J'aimerai comprendre comment il fonctionne, et j'aimerai surtout établir une façon de faire de même pour n'importe quel produit utilisant des flottants ! Quelqu'un pourrait me donner des pistes pour y parvenir ? Merci de votre aide |
|
| |
onilink_ Modérateur
Messages : 9180 Localisation : Montpellier Projet Actuel : Planet Centauri
OniDev
| Sujet: Re: [C++] Approximation entière d'un produit avec un float Mar 4 Nov 2014 - 17:34 | |
| Bah en fait tu changes juste de repère, donc de base c'est [0.0, 1.0] vers un repère entier. Du coup tous les trucs a virgule, tu multiplies par X, ce qui donne:
[0.0, 1.0] Y = 0.299 * R + 0.587 * G + 0.114 * B
[0, 220] Y = 0.299 * 220 * R + 0.587 * 220 * G + 0.114 * 220 * B Y = 66 * R + 129 * G + 25 * B
Par contre, le (X + 128) >> 8, je sais pas trop a quoi ça correspond la... |
|
| |
Mass *Excellent utilisateur*
Messages : 3351 Localisation : Dans une canonnière wookie. Projet Actuel : Monter des trucs et des machins
| Sujet: Re: [C++] Approximation entière d'un produit avec un float Mar 4 Nov 2014 - 21:51 | |
| Comment tu détermines X ? |
|
| |
onilink_ Modérateur
Messages : 9180 Localisation : Montpellier Projet Actuel : Planet Centauri
OniDev
| Sujet: Re: [C++] Approximation entière d'un produit avec un float Mar 4 Nov 2014 - 22:44 | |
| Bah perso j'aurais choisis 255, du coup je sais pas trop comment ils ont déterminé 220. C'est peut être lié aux autres trucs que je capte pas trop |
|
| |
ombre Utilisateur confirmé: Rang ***
Messages : 689 Localisation : Dans sa batcave.
| Sujet: Re: [C++] Approximation entière d'un produit avec un float Mar 4 Nov 2014 - 23:52 | |
| C'est que des histoires de % est malheureusement ça marche qu'avec les multiples de 2 ! Petite astuce de développeur pour faire une division (sans virgule of course) avec un multiple de 2 c'est l'opérateur >> Par exemple, diviser par 2, c'est >> 1 diviser par 4 c'est >> 2 ... DONC diviser par 256 ça équivaut à >> 8 << x ; c'est multiplier par 2^x.
Je prends un le 1er code : Y = 0,299 * R + 0,587 * G + 0,114 * B En faites c'est : 29.9% de rouge + 58,7% de vert + 11,4% de bleu en gros : Y = (29,9 * R + 58,7 * G + 11,4 * B) / 100 Sauf qu'on sait là, que le max c'est 256 (2^8 ), donc plutôt que faire un ratio 100, il fait un ratio 255 : ~= (environ égale) 0.299 * 255 ~= 66 0.587 * 255 ~= 129 0.114 * 255 ~= 25 Après son calcul c'est : (66 * R + 129 * G + 25 * B) / 255
Le +128, c'est parce que je penses que c'est des nombres "négatifs" (donc de -128 à 128) et il passe ça à 0 à 256. Le + 16 c'est l'anguille de l'histoire, mais j'ai tendance à penser que c'est ce qui manque pour faire 256 (66 + 129 + 25 + 16).
En gros, si tu veux faire la même méthode, c'est pour faire des calculs de %, et au lieu d'utiliser une base 100, faut utiliser une base 256. |
|
| |
onilink_ Modérateur
Messages : 9180 Localisation : Montpellier Projet Actuel : Planet Centauri
OniDev
| Sujet: Re: [C++] Approximation entière d'un produit avec un float Mer 5 Nov 2014 - 10:17 | |
| Ouai bah justement, dans le calcul ci dessus pour Y il utilise 220 et pas 256. Et après être passé d'un domaine flottant a un domaine entier, je vois toujours pas l’intérêt de faire un >> 8 perso |
|
| |
Mass *Excellent utilisateur*
Messages : 3351 Localisation : Dans une canonnière wookie. Projet Actuel : Monter des trucs et des machins
| Sujet: Re: [C++] Approximation entière d'un produit avec un float Jeu 6 Nov 2014 - 21:15 | |
| ben parce que il faut repasser sur 8 bits après, donc diviser par 256 vu qu'il a multiplié par 220 (au lieu de 256) avant, du coup |
|
| |
onilink_ Modérateur
Messages : 9180 Localisation : Montpellier Projet Actuel : Planet Centauri
OniDev
| Sujet: Re: [C++] Approximation entière d'un produit avec un float Jeu 6 Nov 2014 - 21:27 | |
| Ah ouai c'est vrai que la valeur en entrée est entière... Reste juste a comprendre le 220 du coup |
|
| |
Mass *Excellent utilisateur*
Messages : 3351 Localisation : Dans une canonnière wookie. Projet Actuel : Monter des trucs et des machins
| Sujet: Re: [C++] Approximation entière d'un produit avec un float Jeu 6 Nov 2014 - 21:54 | |
| Peut-être une erreur ? Ou une approximation spécifique à la conversion YUV ? C'est embêtant j'espérais que cette méthode me permettrait de transformer un bon nombre de calculs flottants en approximation avec des entiers, mais elle est moins miracle que ce que je pensais |
|
| |
onilink_ Modérateur
Messages : 9180 Localisation : Montpellier Projet Actuel : Planet Centauri
OniDev
| Sujet: Re: [C++] Approximation entière d'un produit avec un float Jeu 6 Nov 2014 - 22:09 | |
| Bah elle est pas utile dans n'importe quel cas imaginable ouai, mais sinon ça permet de faire des optis assez cool en général surtout quand tu bidouilles des images.
|
|
| |
[TheDarkTiger] Modérateur
Messages : 7420 Localisation : Essonne
| Sujet: Re: [C++] Approximation entière d'un produit avec un float Lun 24 Nov 2014 - 1:44 | |
| C'est dû aux niveaux électriques du signal. Le 'Noir' 'studio' n'est pas le même que le 'noir' 'PC'. Ainsi, pour le Y (la luminosité), sur PC, elle est dans l'intervalle [0-255], parce qu'on peut stoquer tout ça, mais en 'studio', (donc avant l'avènement numérique), les signaux ne pouvaient pas aller au vrai 0 électrique ni au niveau maximum (1V de mémoire). Donc, en numérisant ces signaux, on tombait à peu près sur [16-235]. Les valeurs ont don été normalisées pour les données studio : le Y aura un niveau minimal de 16 et une amplitude de 220, soit l'intervalle [16-235]. Bref, un reliquat d'un temps ancien où l'on est passé au MPEG. Edit : L'article wikipedia en anglais sur le YUV est plutôt bien fait. https://en.wikipedia.org/wiki/YUVLe paragraphe "Numerical approximations" corrobore à peu près ce que je disait. aparement, c'est plutôt qu'avec les erreurs d'arrondi, on arrivait à 16 de différence, et qu'ils ont juste recentré le tout pour être sûrs de pas déborder. _________________ Bonne chance pour vos projets actuels ! Prêt à aider ceux qui en ont besoin ^^ l'antiqueBienvenue au 2629eme utilisateur : Mike Jones ! |
|
| |
Contenu sponsorisé
| Sujet: Re: [C++] Approximation entière d'un produit avec un float | |
| |
|
| |
| [C++] Approximation entière d'un produit avec un float | |
|