P.Bisoyi
P.Bisoyi

Reputation: 133

DCT of an image

I work on a function in Matlab that calculates the DCT (discrete cosine transform) of an image. I don't know what is not working in my code,which is used in image compression.please help me. Any ideas please.

   clc;close all;clear all;
   image=('cameraman.tif');
    [h w] = size(image);
    image = double(image) - 128;
    b=8;
    block = zeros(b,b);

 image_t=zeros(size(image));
 for k=1:b:h
     for l=1:b:w
        image_t(k:k+b-1,l:l+b-1)= image(k:k+b-1,l:l+b-1);
        for u=1:b
            for v=1:b
                if u == 0
                    Cu = 1/sqrt(2);
                else
                    Cu = 1;
                end
                if v == 0
                    Cv = 1/sqrt(2);
                else
                    Cv = 1;
                end
                Res_sum=0;
                for x=1:b;
                    for y=1:b
                        Res_sum = Res_sum + ((image_t(x,y))*cos(((2*x)+1)*u*pi/(2*b))*cos(((2*y)+1)*v*pi/(2*b)));  
                    end
                end
                dct= (1/4)*Cu*Cv*Res_sum;
                block(u,v) = dct;

            end
        end
        image_comp(k:k+b-1,l:l+b-1)=block(u,v);
     end
 end
end

Upvotes: 0

Views: 1595

Answers (1)

hbaderts
hbaderts

Reputation: 14326

I assume you implement the following formula for the DCT:

dct

with

c(x)

And I guess you need to divide the image into blocks of 8x8 and do the DCT on each of these blocks.

  1. Please comment your code! It helps you and others understand it much better!
  2. You can never reach the part inside if u == 0 or if v == 0, as you go through u and v in for loops which run through 1:b. The underlying problem is that MATLAB starts indexing at 1, while the frequencies in the DCT start at 0. My hint: Use u and v as frequency as in the formula, not like index, i.e. for u=0:b-1 and use u+1 when indexing.
  3. The same for x and y.
  4. image_t should only contain the current block (i thus renamed it to current_block) and not the whole image. That's current_block = image(k:k+b-1,l:l+b-1);
  5. In the line dct= (1/4)*Cu*Cv*Res_sum;, it should not be 1/4 but rather 1/sqrt(2*N) where N is your block size (you call it b), thus 1/sqrt(2*b). For a block size of 8, as in your example, this is of course 1/4.
  6. image is the name of a MATLAB function. It is advisable not to use it as a function name. Consider changing it e.g. to input_image.
  7. I am not sure why you subtract 128 from the input image, please overthink why you are doing that.

That leads to the code below. I don't know if that solves all your problem, but you should be much closer to that now ;-)

PS: Consider vectorization of the code for improved performance.

function image_comp = dctII(input_image, b)
    [h, w] = size(input_image);
    input_image = double(input_image);
    block_dct = zeros(b);

    % Loop through all blocks
    for k=1:b:h
      for l=1:b:w

        % Save true image of block
        current_block = input_image(k:k+b-1,l:l+b-1);

        % Loop through all cos frequencies (u,v)
        for u=0:b-1
          for v=0:b-1
            if u == 0
                Cu = 1/sqrt(2);
            else
                Cu = 1;
            end
            if v == 0
                Cv = 1/sqrt(2);
            else
                Cv = 1;
            end

            Res_sum = 0;

            % Loop through all pixel values
            for x=0:b-1
              for y=0:b-1
                Res_sum = Res_sum + ((current_block(x+1,y+1))*cos(((2*x)+1)*u*pi/(2*b))*cos(((2*y)+1)*v*pi/(2*b)));  
              end
            end

            % Calculate DCT value at frequency (u,v)
            dct = 1/sqrt(2*b) * Cu * Cv * Res_sum;
            block_dct(u+1,v+1) = dct;
          end
        end

        image_comp(k:k+b-1,l:l+b-1) = block_dct(u+1,v+1);

      end
    end
end         % of function

Upvotes: 1

Related Questions