Ở đâ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 ...
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? –
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
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