Search code examples
imagematlabimage-processingdct

Change image brightness and contrast using DCT coefficients


I'm trying to perform some image transformations in the frequency domain (using dct coeff) such as adjusting the brightness and contrast of a grayscale image. What I know so far is that adjusting the brightness implies adding an offset to the pixel intensity and adjusting the contrast is multiplying each pixel with a value. My question is if this is still available in the frequency domain?

img = image("lena.bmp")
img= double(img)-128;
blKsz = 8;
coef = blkproc(I,[block_size block_size],'dct2');

new_coef = coef - 0.3;
% IDCT
new_img = blkproc(new_coef,[block_size block_size],'idct2');
new_img = new_img+128;

When I do this there is no visible difference to the image, even though the values are a bit higher. But if instead of doing by blocks I perform on the coef of full image

coef = dct2(img); % or blKsz=512; %full image

the difference is noticeable.

What am I doing wrong? Is it the way I choose the values I add and multiply (which are totally random)? I would also like to mention that if I add an offset artifacts from idct are present in the output (the first 3 top left pixels of each block are way different than the others).

I know that the top left value of each dct block has the brightness average of the block. Should I modify only this one and not the other values? How does the block size influence the result?


Solution

  • Adjusting the brightness and contrast of your image in the frequency domain is certainly possible, but the practical implications behind it are questionable. Mainly, I am not sure why you would want to go through all of the computational burden of calculating each DCT block. Contrast and brightness enhancement in this particular case in the spatial domain is of worst case O(n) where n is the total number of pixels in the image. Going to the frequency domain will incur additional computational cost.

    In any case, as you mentioned in your post, you can increase brightness by adding a constant to all of the intensity values, and to increase contrast you can scale each pixel by a constant factor. It is analogous to the frequency domain like so:

    Contrast Enhancement

    By taking a look at the spatial domain, if you multiply every pixel by a constant, all of the DCT coefficients will also get multiplied by a constant as well as the DCT is a (relatively) invertible transform. As such, if you want to achieve contrast enhancement, you can take every single value for every DCT block that you have and multiply by this constant.

    Brightness Enhancement

    By taking a look at the spatial domain, if you take every pixel and add a constant to it, you are essentially increasing the overall "power" of the image. If you were to take a look at the frequency spectrum between any image and an image with a constant value added to each pixel, for the DCT blocks the coefficients would be the same except for the DC value (top left corner of each block). As such, if you wanted to increase brightness in the frequency domain, you would add a constant value to each of the DC values in each of the DCT blocks. However, I am not sure what the numerical correlation is between adding a value to the DC term in each block in comparison to adding a constant value to each pixel in the spatial domain. What I mean to say is adding a value of... let's say... 5 for example... in the spatial domain does not mean that if you add a value of 5 to each of the DC values, you will get the same results. There will definitely be an increase in brightness, but I'm not sure how to quantify how much brightness increase you will get once you take the inverse DCT.

    A caveat that you should take a note of is that if you try to add a value to every DCT coefficient, you would essentially be simulating additive white Gaussian noise. The higher the value, the more noise that gets introduced into your image. As such, if you were to take the inverse DCT, the results may not be favourable to your liking. Therefore, make sure you only add a constant to the DC value (i.e. the top left corner of a DCT block)


    Long story short, theoretically it is possible to do this in the frequency domain, but practically speaking I don't see a point.