Reputation: 262
I am using the scipy.fftpack.dct and scipy.fftpack.idct to an image array in python. I don't however want to apply it to the entire image, but to individual 8x8 blocks in the image. This is the simple class I wrote to for testing this
from PIL import Image
import numpy as np
from scipy.fftpack import dct, idct
class ImageController():
def __init__(self, image_name):
im = np.asarray(Image.open(image_name))
self.origional_size = im.shape
im_x_dim, im_y_dim = self.origional_size
self.image = im
if not self.image.flags.writeable:
self.image.flags.writeable = True
def get(self):
return self.image
def display(self):
Image.fromarray(self.image).show()
return self
def apply_dct(self):
# self.image = dct(self.image, norm='ortho')
self.loop_through_8_x_8(dct)
return self
def apply_idct(self):
# self.image = idct(self.image, norm='ortho')
self.loop_through_8_x_8(idct)
return self
def loop_through_8_x_8(self, appyFunc):
print appyFunc
row = 0
while row < len(self.image):
col = 0
while col < len(self.image[row]):
self.image[row:row+8, self.get_list(col)] = appyFunc(self.image[row:row+8, self.get_list(col)] , norm='ortho')
col += 8
row += 8
print row, col
return self;
def get_list(self, index):
x = []
for i in range(index, index + 8):
x.append(i)
return x
The issue I am having is that when I apply DCT to the 8x8 blocks, then IDCT right afterwards all the information is lost and the image looks like a mess. All I am calling is
ImageController('lena.jpg').apply_dct().apply_idct().display()
When I run this, the image is all just noise. However if you see in apply_dct() and apply_idct() I have something commented out which is where I tried DCT and IDCT on the entire image instead of on the 8x8 blocks. When I do this it works perfectly, It just doesn't work when I try on the 8x8 blocks, and I need to apply it to the 8x8 blocks and not the entire image.
Extra information if needed, the images are in grey scale so there is only 1 channel.
Upvotes: 1
Views: 1335
Reputation: 114841
Check the data type of your image array (self.image.dtype
). It is probably 8 bit unsigned integers. The DCT will be floating point values, but when you assign the result of the DCT to the 8x8 block in place, the floating point values are cast to 8 bit integers. Then the same thing happens when you apply the IDCT.
One option to avoid the problem is to convert the image to 64 bit floating point in __init__()
, e.g, im = np.asarray(Image.open(image_name), dtype=np.float64)
. Whether that makes sense depends on what else you are going to do with the array.
Upvotes: 2