For an project I have to demonstrate JPEG compression and therefore the conversion with DCTII and IDCT. I have no idea how to implement this formula. But I found an website that provides the Java code and online IDE for testing.
https://ide.geeksforgeeks.org/FnC3bRJEAr here you can see the code.
(formulas from Wikipedia/JPEG)
So, what changes have to be made to the code?
I tried switching the for-loops and the variables in the formula but the values I got were definitely wrong, other tries lead to error messages.
The only difference between the DCT and IDCT is where coefficient are taken into account.
You should replace line 46 in your code by
sum = sum + ck*cl*dct1;
where ck and cl are computed as in lines 24-34, but for k and l
And suppress ci*cj in line 49
BTW, this java code is exceptionally inefficient. Precompute Math.sqrt(2), Math.sqrt(n) and put your cosine in a table and it will be at least 3 times faster.
Your summations are doing a matrix multiplication. Your a multiplying an 8x8 data matrix by an 8x8 DCT matrix.
The DCT matrix is orthonormal so its inverse is its transpose.
You should therefore be able to invert by exchanging u and v.
Related
Within a java project I've developed I need to calculate the inverse of a matrix. In order to align with other projects and other developers I'm using the Efficient Java Matrix Library (orj.ejml).
For inverting the Matrix I'm using invert from org.ejml.ops.CommonOps, and I has worked fine until now that I'm getting a unexpected result
I've isolated the case that doesn't work to be:
DenseMatrix64F X = new DenseMatrix64F(3, 3);
X.setData(new double[]{77.44000335693366,-24.64000011444091,-8.800000190734865, -24.640000114440916,7.839999732971196,2.799999952316285, -8.800000190734865,2.799999952316285,1.0000000000000004});
DenseMatrix64F invX = new DenseMatrix64F(3, 3);
boolean completed = CommonOps.invert(X, invX);
System.out.println(X);
System.out.println(invX);
System.out.println(completed);
The output I get from this test is:
Type = dense , numRows = 3 , numCols = 3
77.440 -24.640 -8.800
-24.640 7.840 2.800
-8.800 2.800 1.000
Type = dense , numRows = 3 , numCols = 3
NaN -Infinity Infinity
NaN Infinity -Infinity
NaN -Infinity Infinity
true
My first thought was that it could be a singular matrix and therefore not invertible, but after testing the same matrix with a different calculation tool I've found that it is not singular.
So I went back to the EJML documentation and found out the following information for this particular function.
If the algorithm could not invert the matrix then false is returned. If it returns true that just means the algorithm finished. The results could still be bad because the matrix is singular or nearly singular.
And, in this particular case the matrix is not singular but we could say it is near singular.
The only solution I could think off was to search the inverted matrix for NaN or Infinites after calculating it, and if I find something funny in there I just replace the inverted matrix with the original matrix, although it doesn't seem a very clean practice it yields reasonable results.
My question is:
Could you think of any solution for this situation? Something smarter and wiser than just using the original matrix as its own inverse matrix.
In case there is no way around it, do you know of any other Java Matrix library that has some solution to this situation, I'm not looking forward to introduce a new library but it may be the only solution if this becomes a real problem.
Regards and thanks for your inputs!
You should try using SVD if you have to have an inverse. Also consider a pseudo inverse instead. Basically any library using LU decomposition will have serious issues. Here's the output from Octave. Note how two of the singular values are almost zero. Octave will give you an inverse with real numbers, but it's a poor one...
octave:7> cond(B)
ans = 8.5768e+17
octave:8> svd(B)
ans =
8.6280e+01
3.7146e-15
1.0060e-16
inv(B)*B
warning: inverse: matrix singular to machine precision, rcond = 4.97813e-19
ans =
0.62500 0.06250 0.03125
0.00000 0.00000 0.00000
0.00000 0.00000 4.00000
I am using Java + Jblas (first time user) and am trying to multiply two matrices. One is a 163x4 and the other is 4x1 matrix. I would expect the result of such a multiplication to be a 163x1 matrix. However using:
FloatMatrix a = b.mmuli(c);
I am getting the error:
Matrices must have same length (is: 652 and 4)
Now while I assume, that makes perfect sense for the program I am confused. The same multiplication worked fine in Octave (which of course applies some magic). But now for getting this to work I would need to know what kind of sorcery this is?
EDIT
So here is what the Octave Documentation says about broadcasting (the sorcery):
In case all dimensions are equal, no broadcasting occurs and ordinary
element-by-element arithmetic takes place. For arrays of higher
dimensions, if the number of dimensions isn’t the same, then missing
trailing dimensions are treated as 1. When one of the dimensions is 1,
the array with that singleton dimension gets copied along that
dimension until it matches the dimension of the other array.
So this means I just copy the 4x1 matrix 163 times. Then I can execute the multiplication, but instead of the 163x1 matrix I wanted, I now have a 163x4 matrix. Which for me is strange. What is my solution now?
So I finally figured it out. And it's one of those mistakes... It has to be
FloatMatrix a = b.mmul(c);
The element wise multiplication was the error here.
I have been reading the DSP Guide for what seems like a good 3 years now. Only until recently getting comfortable enough with programming did I decide to start experimenting around with FFT based convolution, 1D to be exact, one real in, a complex out.
I stumbled across some code for getting the FFT and IFFT and got it to work, I am getting a correct DFT in the complex frequency domain which after a little bit of bit manipulation (separating the complex array back into two separate real and imaginary arrays) and running it back through the IFFT followed by again more bit manipulation yeilds the original input like expected.
Now maybe I have the concept of Convolution all wrong but simply multiplying like elements of the complex arrays and then running the result back through the IFFT is giving bogus numbers. To test I am simply making a ramping kernel, and a dirac delta function as the input and plugging the result into the IFFT, the code is not giving the original kernel as expected.
public void convolution(double [] xReal, double [] xImag,
double [] hReal, double [] hImag){
for (int i = 0; i < n; i++){
xReal[i] *= hReal[i];
xImag[i] *= hImag[i];
}
}
My question is: is this code for multiplying the elements of the complex DFT correct.
I have been looking for simple convolution code or simply the math behind it but have had no such luck. Everything I have found has just been "multiplication in the frequency domain equals convolution in the time domain".
Multiplication in the frequency domain does a circular convolution, not a straight linear convolution, unless you zero pad out the FFTs and IFFT to longer than the sum of the length of the time domain signal and the full time domain impulse response. (Zero-pad, because a circular wrap/around of all zeros is the same as no wrap around).
Also, for convolution, you need to multiply by the transform (FFT) of the zero-padded impulse response (its frequency response), not the impulse response itself.
Also, the multiplication has to be a complex multiply, not a multiply of just the 2 separated component vectors.
Several months ago I had to implement a two-dimensional Fourier transformation in Java. While the results seemed sane for a few manual checks I wondered how a good test-driven approach would look like.
Basically what I did was that I looked at reasonable values of the DC components and compared the AC components if they roughly match the Mathematica output.
My question is: Which unit tests would you implement for a discrete Fourier transformation? How would you validate results returned by your calculation?
As for other unit-tests, you should consider small fixed input test-vectors for which results can easily be computed manually and compared against. For the more involved input test-vectors, a direct DFT implementation should be easy enough to implement and used to cross-validate results (possibly on top of your own manual computations).
As far as specific test vectors for one-dimensional FFT, you can start with the following from dsprelated, which they selected to exercise common flaws:
Single FFT tests - N inputs and N outputs
Input random data
Inputs are all zeros
Inputs are all ones (or some other nonzero value)
Inputs alternate between +1 and -1.
Input is e^(8*j*2*pi*i/N) for i = 0,1,2, ...,N-1. (j = sqrt(-1))
Input is cos(8*2*pi*i/N) for i = 0,1,2, ...,N-1.
Input is e^((43/7)*j*2*pi*i/N) for i = 0,1,2, ...,N-1. (j sqrt(-1))
Input is cos((43/7)*2*pi*i/N) for i = 0,1,2, ...,N-1.
Multi FFT tests - run continuous sets of random data
Data sets start at times 0, N, 2N, 3N, 4N, ....
Data sets start at times 0, N+1, 2N+2, 3N+3, 4N+4, ....
For two-dimensional FFT, you can then build on the above. The first three cases are still directly applicable (random data, all zeros, all ones). Others require a bit more work but are still manageable for small input sizes.
Finally google searches should yield some reference images (before and after transform) for a few common cases such as black & white squares, rectangle, circles which are can be used as reference (see for example http://www.fmwconcepts.com/misc_tests/FFT_tests/).
99.9% of the numerical and coding issues you will likely find will be found by testing with a random complex vectors and comparing with a direct DFT to a tolerance on the order of floating point precision.
Zero, constant, or sinusoidal vectors may help understand a failure by allowing your eye to catch issues like initialization, clipping, folding, scaling. But they will not typically find anything that the random case does not.
My kissfft library does a few extra tests related to fixed point issues -- not an issue if you are working in floating point.
I'm trying to sort d-dimensional data vectors by their Hilbert order, for bulk-loading a spatial index.
However, I do not want to compute the Hilbert value for each point explicitly, which in particular requires setting a particular precision. In high-dimensional data, this involves a precision such as 32*d bits, which becomes quite messy to do efficiently. When the data is distributed unevenly, some of these calculations are unnecessary, and extra precision for parts of the data set are necessary.
Instead, I'm trying to do a partitioning approach. When you look at the 2D first order hilbert curve
1 4
| |
2---3
I'd split the data along the x-axis first, so that the first part (not necessarily containing half of the objects!) will consist of 1 and 2 (not yet sorted) and the second part will have objects from 3 and 4 only. Next, I'd split each half again, on the Y axis, but reverse the order in 3-4.
So essentially, I want to perform a divide-and-conquer strategy (closely related to QuickSort - on evenly distributed data this should even be optimal!), and only compute the necessary "bits" of the hilbert index as needed. So assuming there is a single object in "1", then there is no need to compute the full representation of it; and if the objects are evenly distributed, partition sizes will drop quickly.
I do know the usual textbook approach of converting to long, gray-coding, dimension interleaving. This is not what I'm looking for (there are plenty of examples of this available). I explicitly want a lazy divide-and-conquer sorting only. Plus, I need more than 2D.
Does anyone know of an article or hilbert-sorting algorithm that works this way? Or a key idea how to get the "rotations" right, which representation to choose for this? In particular in higher dimensionalities... in 2D it is trivial; 1 is rotated +y, +x, while 4 is -y,-x (rotated and flipped). But in higher dimensionalities this gets more tricky, I guess.
(The result should of course be the same as when sorting the objects by their hilbert order with a sufficiently large precision right away; I'm just trying to save the time computing the full representation when not needed, and having to manage it. Many people keep a hashmap "object to hilbert number" that is rather expensive.)
Similar approaches should be possible for Peano curves and Z-curve, and probably a bit easier to implement... I should probably try these first (Z-curve is already working - it indeed boils down to something closely resembling a QuickSort, using the appropriate mean/grid value as virtual pivot and cycling through dimensions for each iteration).
Edit: see below for how I solved it for Z and peano curves. It is also working for 2D Hilbert curves already. But I do not have the rotations and inversion right yet for Hilbert curves.
Use radix sort. Split each 1-dimensional index to d .. 32 parts, each of size 1 .. 32/d bits. Then (from high-order bits to low-order bits) for each index piece compute its Hilbert value and shuffle objects to proper bins.
This should work well with both evenly and unevenly distributed data, both Hilbert ordering or Z-order. And no multi-precision calculations needed.
One detail about converting index pieces to Hilbert order:
first extract necessary bits,
then interleave bits from all dimensions,
then convert 1-dimensional indexes to inverse Gray code.
If the indexes are stored in doubles:
If indexes may be negative, add some value to make everything positive and thus simplify the task.
Determine the smallest integer power of 2, which is greater than all the indexes and divide all indexes to this value
Multiply the index to 2^(necessary number of bits for current sorting step).
Truncate the result, convert it to integer, and use it for Hilbert ordering (interleave and compute the inverse Gray code)
Subtract the result, truncated on previous step, from the index: index = index - i
Coming to your variant of radix sort, i'd suggest to extend zsort (to make hilbertsort out of zsort) with two binary arrays of size d (one used mostly as a stack, other is used to invert index bits) and the rotation value (used to rearrange dimensions).
If top value in the stack is 1, change pivotize(... ascending) to pivotize(... descending), and then for the first part of the recursion, push this top value to the stack, for second one - push the inverse of this value. This stack should be restored after each recursion. It contains the "decision tree" of last d recursions of radix sort procedure (in inverse Gray code).
After d recursions this "decision tree" stack should be used to recalculate both the rotation value and the array of inversions. The exact way how to do it is non-trivial. It may be found in the following links: hilbert.c or hilbert.c.
You can compute the hilbert curve from f(x)=y directly without using recursion or L-systems or divide and conquer. Basically it's a gray code or hamiltonian path traversal. You can find a good description at Nick's spatial index hilbert curve quadtree blog or from the book hacker's delight. Or take a look at monotonic n-ary gray code. I've written an implementation in php including a moore curve.
I already answered this question (and others) but my answer(s) mysteriously disappeared. The Compact Hilbert Index implemention from http://code.google.com/p/uzaygezen/source/browse/trunk/core/src/main/java/com/google/uzaygezen/core/CompactHilbertCurve.java (method index()) already allows one to limit the number of hilbert index bits computed up to a given level. Each iteration of the loop from the mentioned method computes a number of bits equal to the dimensionality of the space. You can easily refactor the for loop to compute just one level (i.e., a number of bits equal to the dimensionality of the space) at a time, going only as deeply as needed to compare lexicographically two numbers by their Compact Hilbert Index.