Ici, j'ai ma classe d'algorithme DCT avec les méthodes "applyDCT" et "applyIDCT". Techniquement, après avoir fait une DCT directe (transformée en cosinus discrète) sur une table 2x2 d'entiers aléatoires entre 0 et 255, puis en effectuant immédiatement une DCT inverse sur ces nombres, nous devrions revenir aux nombres entiers originaux que nous avions en premier lieu. Dans mon cas, ce n'est pas le cas. Qu'est-ce que je fais mal ici?Problèmes avec l'algorithme DCT et IDCT dans java
public class DCT {
private static final int N = 2;
private double[] c = new double[N];
public DCT() {
this.initializeCoefficients();
}
private void initializeCoefficients() {
for (int i=1;i<N;i++) {
c[i]=1;
}
c[0]=1/Math.sqrt(2.0);
}
public double[][] applyDCT(double[][] f) {
double[][] F = new double[N][N];
for (int u=0;u<N;u++) {
for (int v=0;v<N;v++) {
double sum = 0.0;
for (int i=0;i<N;i++) {
for (int j=0;j<N;j++) {
sum+=Math.cos(((2*i+1)/(2.0*N))*u*Math.PI)*Math.cos(((2*j+1)/(2.0*N))*v*Math.PI)*f[i][j];
}
}
sum*=((c[u]*c[v])/4.0);
F[u][v]=sum;
}
}
return F;
}
public double[][] applyIDCT(double[][] F) {
double[][] f = new double[N][N];
for (int u=0;u<N;u++) {
for (int v=0;v<N;v++) {
double sum = 0.0;
for (int i=0;i<N;i++) {
for (int j=0;j<N;j++) {
sum+=((c[u]*c[v]))*Math.cos(((2*i+1)/(2.0*N))*u*Math.PI)*Math.cos(((2*j+1)/(2.0*N))*v*Math.PI)*F[i][j];
}
}
sum/=4.0;
//sum*=((c[u]*c[v])/4.0);
f[u][v]=sum;
}
}
return f;
}
}
Et voici la classe principale qui va avec:
public class Main {
private static final int N = 2;
private static double[][] f = new double[N][N];
private static Random generator = new Random();
public static void main(String[] args) {
// Generate random integers between 0 and 255
int value;
for (int x=0;x<N;x++) {
for (int y=0;y<N;y++) {
value = generator.nextInt(255);
f[x][y] = value;
System.out.println(f[x][y]+" => f["+x+"]["+y+"]");
}
}
DCT dctApplied = new DCT();
double[][] F = dctApplied.applyDCT(f);
System.out.println("From f to F");
System.out.println("-----------");
for (int x=0;x<N;x++) {
for (int y=0;y<N;y++) {
try {
System.out.println(F[x][y]+" => F["+x+"]["+y+"]");
} catch (Exception e) {
System.out.println(e);
}
}
}
double f[][] = dctApplied.applyIDCT(F);
System.out.println("Back to f");
System.out.println("---------");
for (int y=0;y<N;y++) {
for (int z=0;z<N;z++) {
System.out.println(f[y][z]+" => f["+y+"]["+z+"]");
}
}
}
}
Voici par exemple des résultats:
149.0 => f[0][0]
237.0 => f[0][1]
122.0 => f[1][0]
147.0 => f[1][1]
From f to F
-----------
81.87499999999999 => F[0][0]
-14.124999999999993 => F[0][1]
14.62500000000001 => F[1][0]
-7.875 => F[1][1]
Back to f
---------
9.3125 => f[0][0]
14.812499999999998 => f[0][1]
7.624999999999999 => f[1][0]
9.187499999999998 => f[1][1]
Comme indiqué ci-dessus, "Retour à f" ne montre pas les mêmes valeurs contenues dans f initialement ...
Quel a été le cas d'entrée, ce qui était le résultat attendu, et ce que le résultat réel? Avez-vous essayé d'exécuter chacune de vos routines sur des cas d'entrée triviaux (par exemple, [1 0; 0 0]) pour savoir lequel était incorrect? –
Quels résultats obtenez-vous lorsque vous dites que vous ne récupérez pas vos entiers originaux? Certaines erreurs d'arrondi à virgule flottante peuvent être introduites. – rsp
DCT lui-même est lossy. Vous avez besoin d'un DCT modifié (DCT sans perte) pour obtenir un fonctionnement sans perte (réversible). – osgx