2010-11-21 30 views
5

Ở đây tôi có lớp thuật toán DCT của mình với các phương thức "applyDCT" và "applyIDCT". Về mặt kỹ thuật sau khi thực hiện một DCT chuyển tiếp (biến đổi cosin rời rạc) trên một bảng 2x2 các số nguyên ngẫu nhiên từ 0 đến 255, và sau đó ngay lập tức thực hiện một DCT đảo ngược trên các số này, chúng ta nên quay trở lại số nguyên ban đầu mà chúng ta có ở vị trí đầu tiên. Trong trường hợp của tôi, điều này không phải như vậy. Tôi làm gì sai ở đây?Các vấn đề với thuật toán DCT và IDCT trong 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; 
    } 
} 

Và đây là những lớp học chính mà đi với nó:

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

Dưới đây là ví dụ về kết quả:

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] 

Như đã trình bày ở trên, "Back to f" không hiển thị các giá trị tương tự có trong f ban đầu ...

+2

trường hợp đầu vào là bao nhiêu, kết quả mong đợi, và những gì các kết quả thực tế là gì? Bạn có cố gắng chạy từng thói quen của mình trên các trường hợp nhập liệu tầm thường (ví dụ: [1 0; 0 0]) để tìm ra trường hợp nào không chính xác? –

+0

Bạn nhận được kết quả gì khi nói rằng bạn không lấy lại số nguyên gốc? Một số lỗi làm tròn dấu phẩy động có thể được giới thiệu. – rsp

+0

DCT chính nó là mất mát. Bạn cần DCT được sửa đổi (DCT không mất dữ liệu) để hoạt động không bị mất (có thể đảo ngược). – osgx

Trả lời

8

Tôi đã giải quyết vấn đề này, tôi xin lỗi nếu câu hỏi của tôi không rõ ràng nhưng e là những gì là không đúng: Phương pháp IDCT phải có hệ số bên trong i và j cho vòng:

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

này chỉ làm việc cho một khối 8x8 của dữ liệu, nếu không bạn sẽ phải thay đổi điều này:

(c[u]*c[v])/4.0) 

vào một cái gì đó như thế này:

(2*c[u]*c[v])/Math.sqrt(M*N) 

đâu M và N là kích thước của bảng ...

Sau đây là các kết quả với một khối 2x2 dữ liệu:

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] 
Các vấn đề liên quan