JavaでDCTとIDCTアルゴリズムの問題
質問
ここで私は、「applyDCT」と「applyIDCT」方法と私のDCTアルゴリズムのクラスを持っています。技術的には0から255までのランダムな整数の2×2のテーブルの上に順方向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に含まれている同じ値を示していない...
、上記のように解決
私は、この問題を解決してきた、私は私の質問は不明であった場合は申し訳ありませんが、ここでは右ではなかったものです:IDCT方法は、ループのiとj内の係数を持っていた。
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;
}
このデータのみの8×8ブロックのために働くか、あるいはあなたがこれを変更する必要があります:
(c[u]*c[v])/4.0)
このようなものに
(2*c[u]*c[v])/Math.sqrt(M*N)
MとNは、テーブルのdimentionsある場合...
ここでは、データの2×2ブロックを用いた結果である
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]
所属していません StackOverflow