################################ Transformations ################################ Discrete Cosine Transform (DCT) =============================== This section demonstrates the *Discrete Cosine Transform* of an image. As in the Jpeg standard the DCT is performed blockwise. The entire image is partitioned into non-overlapping blocks of size *(8x8)* pixels. The transformed image is backtransformed by applying the *Inverse Discrete Cosine Transform (IDCT)*. The reconstructed image is identical to the original image. Moreover, this Python program allows the user to select an arbitrary block in the image (by clicking into the image). The selected block as well as the DCT of this block are plotted into a Matplotlib figure. The following packages are applied by this program.:: import cv2 import numpy as np from matplotlib import pyplot as plt from matplotlib.colors import Normalize import matplotlib.cm as cm The height and width of the blocks is *B=8*. An image is imported and transformed to a grayscale image. Moreover, the image is cropped, such that its height and width is a multiple of the blocksize *B*.:: B=8 #blocksize fn3= 'tria.jpg' img1 = cv2.imread(fn3, cv2.CV_LOAD_IMAGE_GRAYSCALE) h,w=np.array(img1.shape[:2])/B * B print h print w img1=img1[:h,:w] For each block in the image the DCT is applied. The transformed image is stored in the variable *Trans* and it is saved to the file *Transformed.jpg*:: blocksV=h/B blocksH=w/B vis0 = np.zeros((h,w), np.float32) Trans = np.zeros((h,w), np.float32) vis0[:h, :w] = img1 for row in range(blocksV): for col in range(blocksH): currentblock = cv2.dct(vis0[row*B:(row+1)*B,col*B:(col+1)*B]) Trans[row*B:(row+1)*B,col*B:(col+1)*B]=currentblock cv2.cv.SaveImage('Transformed.jpg', cv2.cv.fromarray(Trans)) Next, the user is asked to mark a region in the displayed image, by clicking into the image. The block around the clicked position is highlighted by a blue box:: plt.imshow(img1,cmap="gray") point=plt.ginput(1) block=np.floor(np.array(point)/B) #first component is col, second component is row print block col=block[0,0] row=block[0,1] plt.plot([B*col,B*col+B,B*col+B,B*col,B*col],[B*row,B*row,B*row+B,B*row+B,B*row]) plt.axis([0,w,h,0]) plt.title("Original Image") .. figure:: triahighlight.png :scale: 60 % :align: center :alt: x The selected block and its DCT-transform are then plotted into a second Matplotlib-figure:: plt.figure() plt.subplot(1,2,1) selectedImg=img1[row*B:(row+1)*B,col*B:(col+1)*B] N255=Normalize(0,255) #Normalization object, used by imshow() plt.imshow(selectedImg,cmap="gray",norm=N255,interpolation='nearest') plt.title("Image in selected Region") plt.subplot(1,2,2) selectedTrans=Trans[row*B:(row+1)*B,col*B:(col+1)*B] plt.imshow(selectedTrans,cmap=cm.jet,interpolation='nearest') plt.colorbar(shrink=0.5) plt.title("DCT transform of selected Region") .. figure:: triablock.png :scale: 80 % :align: center :alt: x Then the *IDCT* is applied to reconstruct the original image from the transformed representation. The reconstructed image is stored in the variable *back0* and it is saved to the file *BackTransformed.jpg*:: back0 = np.zeros((h,w), np.float32) for row in range(blocksV): for col in range(blocksH): currentblock = cv2.idct(Trans[row*B:(row+1)*B,col*B:(col+1)*B]) back0[row*B:(row+1)*B,col*B:(col+1)*B]=currentblock cv2.cv.SaveImage('BackTransformed.jpg', cv2.cv.fromarray(back0)) In order to verify that *DCT* and *IDCT* are lossless, the *Mean Absolute Difference (MAD)* between the original and the reconstructed image is calculated and printed to the console. The reconstructed image is plotted into a Matplotlib-figure.:: diff=back0-img1 print diff.max() print diff.min() MAD=np.sum(np.abs(diff))/float(h*w) print "Mean Absolute Difference: ",MAD plt.figure() plt.imshow(back0,cmap="gray") plt.title("Backtransformed Image") plt.show() .. figure:: triaback.png :scale: 60 % :align: center :alt: x