Problems implementing my own 2d DCT function. Smearing effect
41 views (last 30 days)
Show older comments
Hi, I'm trying to implement my own Discrete Cosine transform and inverse transform functions. I have all the code written however the output images from the fuction seem to have a blurring effect.
EX:
Here is my code :
function dct = my_dct_2d(image)
%% Calculate the cosine coefficients
image = double(image);
N = length(image);
dct = zeros(N);
for u=0: N-1
for v=0: N-1
if u==0
cu = 1/sqrt(N);
else
cu = sqrt(2/N);
end
if v==0
cv = 1/sqrt(N);
else
cv = sqrt(2/N);
end
mysum = 0;
for x=0:N-1
for y=0:N-1
temp = image(x+1,y+1)*cos(pi*u*(2*x+1)/(2*N))*cos(pi*v*(2*y+1)/(2*N));
%temp = image(k,l)*cos(((2*(k-1)+1)*i*pi)/(2*n))*cos(((2*(l-1)+1)*j*pi)/(2*n));
mysum = mysum+ temp;
end
end
dct(u+1,v+1) = cu*cv*mysum;
end
end
end
function idct = my_idct_2d(image)
%% Calculate the cosine coefficients
N = length(image);
idct = zeros(N);
for u=0: N-1
for v=0: N-1
if u==0
cu = 1/sqrt(N);
else
cu = sqrt(2/N);
end
if v==0
cv = 1/sqrt(N);
else
cv = sqrt(2/N);
end
mysum = 0;
for x=0:N-1
for y=0:N-1
temp = cu*cv*image(x+1,y+1)*cos(pi*u*(2*x+1)/(2*N))*cos(pi*v*(2*y+1)/(2*N));
%temp = image(k,l)*cos(((2*(k-1)+1)*i*pi)/(2*n))*cos(((2*(l-1)+1)*j*pi)/(2*n));
mysum = mysum+ temp;
end
end
idct(u+1,v+1) = mysum;
end
end
idct = uint8(idct);
end
Please let me know if you see an error or I am implementing the functions incorectly.
Thanks
-Matt
Edit: Here is the code that generated the images posted as an example:
I = imread('cameraman.tif');
temp = my_dct_2d(I);
newImage = my_idct_2d(temp);
imshow([I newImage]);
2 Comments
Accepted Answer
Matt J
on 7 Jun 2019
Edited: Matt J
on 7 Jun 2019
Your forward and inverse DCT code look identical. In other words, you appear to be performing the forward DCT where you intended to do the inverse.
2 Comments
Matt J
on 7 Jun 2019
Edited: Matt J
on 7 Jun 2019
Your code is also quite slow, making testing difficult. There are opportunities here to exploit vectorization and separability. Below is how I would implement it. You could probably do even better by writing it in terms of FFTs.
I = imread('cameraman.tif');
temp = my_dct_2d(I);
newImage = uint8( my_idct_2d(temp));
imshow([I newImage]);
function A=dctmatrix_1d(N)
c(1:N,1)=sqrt(2/N); c(1)=c(1)/sqrt(2);
e=(0:N-1);
A=c.*cos( e(:) * (pi*(2*e+1)/(2*N)) );
end
function dct = my_dct_2d(image)
image = double(image);
N = length(image);
A=dctmatrix_1d(N);
dct=A*image*A.';
end
function idct = my_idct_2d(image)
image = double(image);
N = length(image);
A=dctmatrix_1d(N);
idct=A\image/A.';
end
Matt J
on 7 Jun 2019
Edited: Matt J
on 7 Jun 2019
I = double(imread('cameraman.tif'));
K=dct_kronprod(length(I)); %This can be re-used later on images of the same size
tic
temp = K*I;
newImage = uint8( K\temp );
toc %Elapsed time is 0.005276 seconds.
imshow([I newImage]);
function K=dct_kronprod(N)
c(1:N,1)=sqrt(2/N); c(1)=c(1)/sqrt(2);
e=(0:N-1);
A=c.*cos( e(:) * (pi*(2*e+1)/(2*N)) );
K=KronProd({A},[1,1]);
end
More Answers (0)
See Also
Products
Community Treasure Hunt
Find the treasures in MATLAB Central and discover how the community can help you!
Start Hunting!