Perte d'information avec une DCT !!!

La question :

salut.
J'expérimente actuellement la compression JPEG.

J'ai codé pour tester une DCT et une iDCT.
Sauf que voila, l'exécution successive des deux algo ne me redonne pas
(et de loin) la matrice originale.

Voila le source (en PHP) qui est assez simple finalement.

$pixel = array(
array(139, 144, 149, 153, 155, 155, 155, 155),
array(144, 151, 153, 156, 159, 156, 156, 156),
array(150, 155, 160, 163, 158, 156, 156, 156),
array(159, 161, 162, 160, 160, 159, 159, 159),
array(159, 160, 161, 162, 162, 155, 155, 155),
array(161, 161, 161, 161, 160, 157, 157, 157),
array(162, 162, 161, 163, 162, 157, 157, 157),
array(162, 162, 161, 161, 163, 158, 158, 158));

/* DCT */

for ($i = 0 ; $i < 8 ; $i++)
for ($j = 0 ; $j < 8 ; $j++)
{
$s = 0.0;
for ($x = 0 ; $x < 8; $x++)
for ($y = 0 ; $y < 8; $y++)
{
if (($i == 0) && ($j == 0))
$c = 0.25 / (sqrt(2) * sqrt(2));
else if (($i == 0) || ($j == 0))
$c = 0.25 / sqrt(2);
else if (($i == 0) || ($j == 0))
$c = 0.25;

$coef = $c * cos(((2*$x+1)*$i*M_PI) / 16) *
cos(((2*$y+1)*$j*M_PI) / 16);
$value = $coef * $pixel[$x][$y];
$s += $value;
}
$dct[$i][$j] = $s;
}

/* iDCT */

for ($i = 0 ; $i < 8 ; $i++)
for ($j = 0 ; $j < 8 ; $j++)
{
$s = 0.0;
for ($x = 0 ; $x < 8; $x++)
for ($y = 0 ; $y < 8; $y++)
{
if (($x == 0) && ($y == 0))
$c = 0.25 / (sqrt(2) * sqrt(2));
else if (($x == 0) || ($y == 0))
$c = 0.25 / sqrt(2);
else if (($x == 0) || ($y == 0))
$c = 0.25;

$coef = $c * cos(((2*$x+1)*$i*M_PI) / 16) *
cos(((2*$y+1)*$j*M_PI) / 16);
$value = $coef * $dct[$x][$y];
$s += $value;
}
$idct[$i][$j] = $s;
}

J'ai utilisé la table exemple fournie par sur
http://fr.wikipedia.org/wiki/JPEG

La matrice de départ etait
139 144 149 153 155 155 155 155
144 151 153 156 159 156 156 156
150 155 160 163 158 156 156 156
159 161 162 160 160 159 159 159
159 160 161 162 162 155 155 155
161 161 161 161 160 157 157 157
162 162 161 163 162 157 157 157
162 162 161 161 163 158 158 158

Le résultat obtenu est
142 142 139 129 110 85 58 30
143 144 140 127 111 85 58 30
140 141 136 125 104 78 54 28
135 133 126 113 95 73 50 26
116 113 107 95 81 59 41 21
91 89 84 75 63 48 33 17
64 63 58 52 45 33 23 12
33 32 30 26 23 17 12 6

Alors évidement:
- je n'ai rien arrondi (tous les calcul en float)
- je n'ai pas utilisé de quantization.

Bref, j'ai juste appliqué le DCT et l'iDCT et je suis très surpris des
écart obtenus !!!

Les pertes sont-elles dues aux flottants 32 bits?
Ou dois chercher un bug dans mon iDCT (encore que bon j'ai déjà pas mal
cherché)
PS: le problème ne dois pas venir de la DCT sinon je ne trouverai pas
des valeurs identiques à celles présente sur Wikipedia.

Etienne

Poser votre question sur le forum Programmation

Les 7 réponses :

Le 08/12/2010 12:25, Etienne a écrit :

Oups.
Je viens juste de me rendre compte de l'écart énnnnnorme entre la
matrice originale et celle de destination.

J'ai du faire une modif dans mon iDCT, car si les écarts était grand, il
ne l'était pas autant.

Faut que je remette mon iDCT originale est que je repost !!!

Désolé pour la boulette.
Etienne


La matrice de départ etait
139 144 149 153 155 155 155 155
144 151 153 156 159 156 156 156
150 155 160 163 158 156 156 156
159 161 162 160 160 159 159 159
159 160 161 162 162 155 155 155
161 161 161 161 160 157 157 157
162 162 161 163 162 157 157 157
162 162 161 161 163 158 158 158

Le résultat obtenu est
142 142 139 129 110 85 58 30
143 144 140 127 111 85 58 30
140 141 136 125 104 78 54 28
135 133 126 113 95 73 50 26
116 113 107 95 81 59 41 21
91 89 84 75 63 48 33 17
64 63 58 52 45 33 23 12
33 32 30 26 23 17 12 6

Le 08/12/2010 12:31, Etienne a écrit :


Le 08/12/2010 12:25, Etienne a écrit :

Oups.


Ok voila la formule de l'iDCT

for ($i = 0 ; $i < 8; $i++)
for ($j = 0 ; $j < 8; $j++)
{
$s = 0.0;
for ($u = 0 ; $u < 8 ; $u++)
for ($v = 0 ; $v < 8 ; $v++)
{
if (($u == 0) && ($v == 0))
$c = 0.25 / (sqrt(2) * sqrt(2));
else if (($u == 0) || ($v == 0))
$c = 0.25 / sqrt(2);
else if (($u == 0) || ($v == 0))
$c = 0.25;

$coef = $c * cos(((2*$i+1)*$u*M_PI) / 16) *
cos(((2*$j+1)*$v*M_PI) / 16);
$value = $coef * $dct[$u][$v];
$s += $value;
}
$idct[$i][$j] = $s;
}

La matrice de départ était
139 144 149 153 155 155 155 155
144 151 153 156 159 156 156 156
150 155 160 163 158 156 156 156
159 161 162 160 160 159 159 159
159 160 161 162 162 155 155 155
161 161 161 161 160 157 157 157
162 162 161 163 162 157 157 157
162 162 161 161 163 158 158 158

Le résultat obtenu est
143 147 150 153 154 152 152 152
147 152 154 156 158 155 155 155
152 156 159 161 159 156 156 156
158 160 161 161 161 159 159 159
157 159 160 162 162 156 156 156
159 160 161 161 161 158 158 158
160 161 161 163 162 158 158 158
160 161 161 162 163 159 159 159

Donc des ecart quand meme assez important...

Etienne a écrit :


Le 08/12/2010 12:31, Etienne a écrit :


Le 08/12/2010 12:25, Etienne a écrit :

Oups.


Ok voila la formule de l'iDCT

for ($i = 0 ; $i < 8; $i++)
for ($j = 0 ; $j < 8; $j++)
{
$s = 0.0;
for ($u = 0 ; $u < 8 ; $u++)
for ($v = 0 ; $v < 8 ; $v++)
{
if (($u == 0) && ($v == 0))
$c = 0.25 / (sqrt(2) * sqrt(2));
else if (($u == 0) || ($v == 0))
$c = 0.25 / sqrt(2);
else if (($u == 0) || ($v == 0))
$c = 0.25;

$coef = $c * cos(((2*$i+1)*$u*M_PI) / 16) *
cos(((2*$j+1)*$v*M_PI) / 16);
$value = $coef * $dct[$u][$v];
$s += $value;
}
$idct[$i][$j] = $s;
}


Non, elle est encore fausse...


Donc des ecart quand meme assez important...


Pas étonnant.

--
__Pascal Bourguignon__ http://www.informatimago.com/
A bad day in () is better than a good day in {}.

Le 08/12/2010 15:17, Pascal J. Bourguignon a écrit :


Non, elle est encore fausse...


Donc des ecart quand meme assez important...


Pas étonnant.


Comment ca elle est encore fausse.

J'ai pris la formule ici

http://xavier.chassagneux.free.fr/tipe/tipe.htm

A l'origine j'avais mis en place l'algorithme de chen
que j'avais pris ici

http://fr.wikipedia.org/wiki/DCT

Et c'est à cause des erreurs que j'ai codé l'idct brut de fonderie.
l'algorithme de chen et mon idct donne quasiment le même résultat.

Ce qui me laissait à penser que l'idct était juste !!!

Non ???

Etienne

Le Wed, 08 Dec 2010 13:53:43 +0100, Etienne a écrit
(dans <news:4cff7f37$0$30332$>, posté
dans fr.comp.algorithmes) :


if (($u == 0) && ($v == 0))
$c = 0.25 / (sqrt(2) * sqrt(2));
else if (($u == 0) || ($v == 0))
$c = 0.25 / sqrt(2);
else if (($u == 0) || ($v == 0))
$c = 0.25;


Il y a un lézard dans les conditions?

--
___________
_/ _ \_`_`_`_) Serge PACCALIN -- sp ad mailclub.net
\ \_L_) Il faut donc que les hommes commencent
-'(__) par n'être pas fanatiques pour mériter
_/___(_) la tolérance. -- Voltaire, 1763

Poser votre question sur le forum Programmation

Questions similaires :

Information : VB6 à vendre

Hello, Juste pour info, comme je sais que c'est une demande récurrente ici : Il y a en ce moment des Visual Studio 6.0 et des Visual Basic 6.0 à vendre en ce moment sur eBay, à de très bonnes conditions: Ce sont des versions Pro, à partir de $250 frais de livraison inclus (170...

Compression avec perte

Bonjour, Je voudrais faire de la compression d'un signal, qui comprend plusieurs contraintes, tous en autorisant certains type de differences entre signal codé, signal décodé. Je sais que je ne peux pas avoir moins de 2 '1' d'affilé, et plus de 8 '1' d'affilé. Je n'ai pas le droit d'avoir un seul...