代码之家  ›  专栏  ›  技术社区  ›  Jean-François Beaulieu

Java中DCT和IDCT算法存在的问题

  •  6
  • Jean-François Beaulieu  · 技术社区  · 15 年前

    这里我有一个DCT算法类,它有“applyDCT”和“applyDCT”方法。技术上,在对2x2的0到255之间的随机整数表执行正向DCT(离散余弦变换)之后,然后立即对这些数字执行反向DCT,我们应该回到我们最初拥有的整数。在我看来,情况并非如此。我在这里做错什么了?

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

    下面是主要的课程:

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

    以下是结果示例:

    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]
    

    如上图所示,“返回F”并没有显示最初包含在F中的相同值…

    1 回复  |  直到 11 年前
        1
  •  9
  •   Jean-François Beaulieu    15 年前

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

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

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

    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]
    
    推荐文章