2
$\begingroup$

As I understand it from this video, in a JPEG image an 8x8-pixel block is made up of weighted cosine waves, calculated using DCTII. There are lots of visualizations of these waves, such as this one from the Wikipedia article on JPEG compression:

Visualization of DCTII cosine waves

I'd like to be able to visualize each of the waves for a given 8x8-pixel block in an image, weighted with values calculated by DCTII.

Where can I find (or how can I calculate) the 64 cosine functions used in JPEG compression?

$\endgroup$
  • $\begingroup$ Any more needed? $\endgroup$ – Laurent Duval Dec 8 '19 at 15:09
2
$\begingroup$

Those 2D cosine functions are independent of your input image. They are just "cosine waves", or the 64 basis functions that yield 64 coefficients when transforming "$8\times 8$" blocks. Given a $D$ $8\times 8$ matrix for the DCT-II, and a $8\times 8$ image patch $I$, you'll get $64$ coefficients $C$ by:

$$C=DID^T$$

[EDIT] If you want to display the 2D DCT-II functions only, you have to create 2D arrays $D_{h,v}(m,n)$ ($0\le m< M$ and $0\le n< N$) for each couple of horizontal/vertical integer indices $(h,v)$, with $0\le h< H$ and $0\le v< V$, with $H=M$ and $V=N$. Classically for JPEG, $M=N=8$. A formula is (up to a transposition, and possibly a scale factor):

$$D_{h,v}(m,n) = 2\sum_{m=0}^{M-1}\sum_{n=0}^{N-1} \frac{1}{\sqrt{M}}\frac{1}{\sqrt{N}}\eta_h \eta_v \cos\left(\frac{\pi h}{2M}(2m+1)\right)\cos\left(\frac{\pi v}{2N}(2n+1)\right)$$

with $\eta_x = \frac{1}{\sqrt{2}}$ if $x=0$, $\eta_x = 1$ if $x\neq0$. There are a lot of clever implementations, I'll provide the most straightforward. The goal is to get a picture like the following:

8x8 DCT-II bases

A pseudo-code version (from Matlab) could be (with the issue of 0-based or 1-based indices):

nRow = 8;nCol = 8;
nFreqHoriz = 8;
nFreqVerti = 8;
for iFreqH = 1:nFreqHoriz
    for iFreqV = 1:nFreqVerti
        iFreqHoriz = iFreqH-1;
        iFreqVerti = iFreqV-1;
        normFreqDC = 1/sqrt(2);
        matFreq2D = zeros(nRow,nCol);
        for iRow = 1:nRow
            for iCol = 1:nCol
                iRow0 = iRow-1;
                iCol0 = iCol-1;
                matFreq2D(iRow,iCol) = 2/(sqrt(nFreqHoriz)*sqrt(nFreqVerti))*cos(pi*iFreqHoriz*(2*iRow0+1)/(2*nRow))*cos(pi*iFreqVerti*(2*iCol0+1)/(2*nCol));
                if ~iFreqHoriz ,  matFreq2D(iRow,iCol) =  matFreq2D(iRow,iCol)*normFreqDC;end
                if ~iFreqVerti ,  matFreq2D(iRow,iCol) =  matFreq2D(iRow,iCol)*normFreqDC;end
            end
        end
        sum(matFreq2D(:).^2)
        subplot(nFreqHoriz,nFreqVerti,8*(iFreqV-1)+iFreqH)
        imagesc(matFreq2D);axis off;axis square;colormap gray
    end
end
| improve this answer | |
$\endgroup$
  • 1
    $\begingroup$ Maybe the SE format is not the most evident ; k is an index for each frequency component (see dsp.stackexchange.com/a/58599/15892). You can more or less iuse the formula after "The general equation for a 2D (N by M image) DCT is defined by the following equation:" in users.cs.cf.ac.uk/Dave.Marshall/Multimedia/node231.html $\endgroup$ – Laurent Duval Jun 1 '19 at 14:24
  • 1
    $\begingroup$ PS maybe I didn't explain my question well: I just want the functions used to create the visualization above, not calculating the weights for a particular 8x8-pixel block. $\endgroup$ – JeffThompson Jun 6 '19 at 14:35
  • 1
    $\begingroup$ So, OK, let's do it $\endgroup$ – Laurent Duval Jun 6 '19 at 20:28
  • 1
    $\begingroup$ Of course, I just wanted to share the code used to run the picture, and in some case, it can help to understand how to implement the formula in another language $\endgroup$ – Laurent Duval Jun 7 '19 at 15:08
  • 1
    $\begingroup$ Code is much easier to understand for me than a formula :) $\endgroup$ – JeffThompson Jun 7 '19 at 15:17

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.