Search code examples
imagematlabimage-processingrangegamma

Matlab range - gamma correction


Could you tell me how to take a range of an image? I want to do a gamma correction of "cameraman.tif" for pixels in range 0:120 gamma = 1.8, for pixels in range 120:255 gamma = 0.5

But all pixels go to first if statement so I am unable to apply second gamma.

a = imread('cameraman.tif');
gamma1 = 2;
gamma2 = 0.5;
N =size(a);
out = zeros(N);
for i=1:N
  for j=1:N
    temp=a(i,j);
    if temp>0&temp<120
       out(i,j)=temp.^2;
    end
    if temp>120&temp<=255
       out(kx,ky)=temp.^0.5;
    end
 end
end
imshow(out)

Solution

  • Your second if statement uses access variables kx and ky.... I'm assuming you wanted to use i and j:

    out(i,j)=temp.^0.5;
    

    You also must make sure that the intensity is double precision for the square root to work. Therefore make sure that the intensity read in per location is cast to double, then convert back to uint8 when you're done. Actually, do the conversion after you sweep through the whole image.

    for i=1:N
      for j=1:N
        temp=double(a(i,j)); % Change
        if temp>0&temp<120
           out(i,j)=temp.^2;
        end
        if temp>120&temp<=255
           out(i,j)=temp.^0.5; % Change
        end
     end
    end
    
    out = uint8(out); % Change
    

    kx and ky were set somewhere else in your code and are never changing, so this means that if and when the second if statement does happen, the setting of the gamma only happens at one spot only defined at kx and ky. My advice to you would be to write an actual function so that you aren't cross-contaminating variables in different workspaces. Encompassing this in a function would have given you an error immediately telling you that kx and ky are not defined.

    BTW, I would rather you do this more efficiently without loops. You can very easily perform the same operations vectorized. However, this requires that you convert the image to double as the default type is uint8 for the Cameraman image. Therefore, use double to convert an image to double, do the gamma correction, then convert back using uint8:

    a = double(imread('cameraman.tif'));
    out = zeros(size(a));
    out(a > 0 & a < 120) = a(a > 0 & a < 120).^2;
    out(a >= 120 & a <= 255) = a((a >= 120 & a <= 255).^0.5;
    out = uint8(out);
    

    The first and second line of code are of course familiar. The third line of code finds a logical mask where we search for intensities between 0 and 120 exclusive. Once we find those values, we use the same logical mask to index into the original image and only access those values, square each value and set them in the same spatial locations at the output. The same can be said for the last line of code where you're searching between 120 and 255 but you are taking the square root instead. We finally convert to uint8 for display.