I started this post with a attempt to show the difference between RGB and YCbCr. but that was easy enough so i added one round of dct/idct to see the effects on grey scale(if any).

Link to heading

The main difference between RGB and YCbCr is that instead using Red/green/blue, YCbCr is using gray(luminance) and Red/Blue differences. It’s mainly due to the fact human eye detects gray scale better than color scale which allows more aggressive compression for color components.

The equation to convert from RGB to YCbCr is from wiki Example image

With that out the way, I thought it would be fun to do DCT then IDCT to see if DCT/IDCT makes visible change in the image. I found dct2 and idct2 from SO (for 2-D DCT based on scipy 1-D DCT).

And there are no visible differences between original gray scale and final image after DCT/IDCT. I did subtract them and differences are mostly 1.42108547e-14.

Example image

import numpy as np
from scipy.fftpack import dct, idct
import imageio.v2 as imageio
import matplotlib.pyplot as plt

def rgb2ycbcr(image):
    R = image[:, :, 0]
    G = image[:, :, 1]
    B = image[:, :, 2]

    Y  = 0                          + .299     *  R + .587      * G  + 0.114   * B
    #Cb = np.ones[image.shape] * 128 - 0.168736 *  R - 0.331264  * G  + 0.5      *
B
    #Cr = np.ones[image.shape] * 128 + 0.5      *  R - 0.0.418688* G  - 0.081312 *
B
    return Y

rgb = imageio.imread('./Lenna.png')
ycbcr = rgb2ycbcr(rgb)

# DCT/IDCT
gray = ycbcr
def dct2(a):
    return dct(dct(a.T, norm='ortho').T, norm='ortho')
def idct2(a):
    return idct(idct(a.T, norm='ortho').T, norm='ortho')

dct_im = dct2(gray)
idct_im = idct2(dct_im)

_, plots = plt.subplots(2)
plots[0].imshow(gray, cmap="gray")
plots[1].imshow(idct_im, cmap="gray")
plt.show()