2010-11-21 7 views
5

Burada "applyDCT" ve "applyIDCT" yöntemleriyle DCT algoritma sınıfım var. Teknik olarak, 0 ile 255 arasında bir 2x2 rastgele tamsayı tablosunda ileri bir DCT (ayrık kosinüs dönüşümü) yaptıktan sonra, bu sayılar üzerinde hemen bir ters DCT yaptıktan sonra, ilk etapta sahip olduğumuz orijinal tamsayı numaralarına geri dönmeliyiz. Benim durumumda öyle değil. Burada neyi yanlış yapıyorum? göstermiyor "Geri f için",java'da DCT ve IDCT algoritması ile ilgili sorunlar

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] 

yukarıda gösterildiği gibi: İşte

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+"]"); 
      } 
     } 
    } 
} 

sonuçların örnektir:

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; 
    } 
} 

Ve burada onunla birlikte gider ana sınıftır başlangıçta f aynı değerler ...

+2

giriş böyleydi Ne beklenen sonuç ve ne fiili Sonuç ne oldu? Hangisinin hatalı olduğunu bulmak için her girişinizi önemsiz giriş durumlarında (örneğin, [1 0; 0 0]) çalıştırmayı denediniz mi? –

+0

Orijinal tam sayılarınızı geri almadığınızı söylerken ne sonuç alırsınız? Bazı kayan nokta yuvarlama hataları tanıtılabilir. – rsp

+0

DCT'nin kendisi zararlıdır. Kayıpsız (geri alınabilir) işlem yapmak için değiştirilmiş DCT'ye (kayıpsız DCT) ihtiyacınız vardır. – osgx

cevap

8

Bu sorunu çözdüm, sorunum açık değilse üzgünüm ama E doğru değildi budur:

public double[][] applyIDCT(double[][] F) { 
     double[][] f = new double[N][N]; 
     for (int i=0;i<N;i++) { 
      for (int j=0;j<N;j++) { 
      double sum = 0.0; 
      for (int u=0;u<N;u++) { 
       for (int v=0;v<N;v++) { 
       sum+=(c[u]*c[v])/4.0*Math.cos(((2*i+1)/(2.0*N))*u*Math.PI)*Math.cos(((2*j+1)/(2.0*N))*v*Math.PI)*F[u][v]; 
       } 
      } 
      f[i][j]=Math.round(sum); 
      } 
     } 
     return f; 
    } 

Bu yalnızca bir veri 8x8 blok açısından eserler, yoksa bunu değiştirmek zorunda kalacak: IDCT yöntemi döngüler için i içine katsayısı ve j olması gerekiyordu

böyle bir şey haline
(c[u]*c[v])/4.0) 

:

(2*c[u]*c[v])/Math.sqrt(M*N) 
M ve N tablonun boyutları olan

...

İşte bir veri 2x2 bloğu ile sonuçlar şöyle:

Original values 
--------------- 
54.0 => f[0][0] 
35.0 => f[0][1] 
128.0 => f[1][0] 
185.0 => f[1][1] 

From f to F 
----------- 
200.99999999999994 => F[0][0] 
-18.99999999999997 => F[0][1] 
-111.99999999999997 => F[1][0] 
37.99999999999999 => F[1][1] 

Back to f 
--------- 
54.0 => f[0][0] 
35.0 => f[0][1] 
128.0 => f[1][0] 
185.0 => f[1][1]