2d DCT程序不能正常工作
我必须为我的项目执行此图像的2d DCT。 我翻译了编码的权利。从逻辑上看,这一切似乎都很好,但它并没有给出所需的结果。我已经用matlab函数来检查3x3矩阵的结果,但它们不正确。2d DCT程序不能正常工作
此外,我编码的内容和方式给出了大量的循环,因此实际的图像操作需要数小时来计算。
任何减少循环和指出程序错误的建议都会很好。 谢谢。
这是我的代码。所有的
double alpha_p, alpha_q;
double pi = Math.atan(1.0) * 4.0;
//dct begins
System.out.println("it begins");
for (int p = 0; p < M; p++) {
for (int q = 0; q < N; q++) {
if (p == 0)
alpha_p = 1/sqrt(M);
else
alpha_p = sqrt(2/M);
if (q == 0)
alpha_q = 1/sqrt(N);
else
alpha_q = sqrt(2/N);
double toreturn = 0;
for (int m = 0; m < M; m++) {
for (int n = 0; n < N; n++) {
toreturn = toreturn + img[m][n]
* cos(((2 * m + 1) * p * pi)/2 * M)
* cos(((2 * n + 1) * q * pi)/2 * N);
}
}
dctimg[p][q] = alpha_p * alpha_q * toreturn;
System.out.println("euta");
}
}
// dct over
System.out.println("its over");
//inverse dct begins
for (int m = 0; m < M; m++) {
for (int n = 0; n < N; n++) {
double toreturn = 0;
for (int p = 0; p < M; p++) {
for (int q = 0; q < N; q++) {
if (p == 0)
alpha_p = 1/sqrt(M);
else
alpha_p = sqrt(2/M);
if (q == 0)
alpha_q = 1/sqrt(N);
else
alpha_q = sqrt(2/N);
toreturn = toreturn + alpha_p * alpha_q * dctimg[p][q]
* cos(((2 * m + 1) * p * pi)/2 * M)
* cos(((2 * n + 1) * q * pi)/2 * N);
}
}
finalimg[m][n] = toreturn;
}
}
//inverse dct over
首先,DCT公式中的cos
分母是2 * M
。这是一个典型的错误。 4/2 * 2 = 4
不1
cos(((2 * m + 1) * p * pi)/2 * M)
应该cos(((2 * m + 1) * p * pi)/(2 * M))
括号都需要在所有四种情况。
我想提的另一个时刻是sqrt(2/M)
。如果M
具有整数类型(您的代码不清楚)并且它大于2
,则表达式2/M
等于0
。因为两个操作数都具有整数类型,并且/
只给出整数部分。要修复它,请添加一个像这样的浮点数sqrt(2.0/M)
。
正如你已经注意到了,有很多循环,换句话说,该二维DCT II的复杂性是O(n^4)
。
在现实生活中,没有人将DCT应用于整个实际图像。图像被分割成大小为8x8的块,每个块由DCT处理。这种方法允许保持较低并且复杂度变得可接受。
为了降低算法复杂度,我想链接here,其中使用1D DCT和FFT的方法很好解释。
谢谢你,先生,请您解释清楚的答复。我意识到了错误。我会尝试通过应用8x8块来减少复杂性。一件好事是,现在我在连续的DCT和IDCT之后获得原始像素值。但是,DCT系数与matlab测试结果并不匹配。我为这个测试尝试了一个3x3矩阵。将不得不整理出来。你知道matlab使用什么块大小作为标准吗? – user8311562
@ user8311562,我[实施](https://gist.github.com/Ka6aSH/7594671a4d60aef7a12b0077e002d6a1)从头开始描述DST2 [这里](https://www.mathworks.com/help/images/ref/dct2 .html)并在MathLab online'J = dct2([11 12 13; 14 15 16; 17 18 19]);''的相同输入上对其进行测试。结果是一样的,也许我们错过了另一个错误。 我不确定,但我认为函数dst2不使用块,它是一个纯粹的转换。另一个问题是为什么它如此之快?答案是MathLab针对矩阵运算进行了高度优化,并且很难达到这样的性能。 – Enegue
谢谢Enegue。全部整理出来。 – user8311562
'double pi = Math.atan(1.0)* 4.0' ..或者你可以使用'Math.PI' – harold
感谢分享知识。 “Math.PI”嗯。 – user8311562
参见[使用DFFT计算DFCT](https://stackoverflow.com/a/22779268/2521214)和[如何计算DFT/DFFT](https://stackoverflow.com/a/26355569/2521214)。确保你使用的是兼容的DCT ......如果我的记忆效果很好,其中有4个...... – Spektre