Increase the contrast of an image using lookup table in MATLAB
I am trying to do some image processing for which I am assigned an 8-bit grayscale image. I have to change the contrast of the image by creating a lookup table that increases the contrast for pixel values between 50 and 205. I have created a lookup table using the following MATLAB code.
a = 2;
x = 0:255;
lut = 255 ./ (1+exp(-a*(x-127)/32));
When I draw lut
, I get the graph shown below:
So far so good, but how can I increase the contrast for pixel values between 50 and 205? The final conversion conversion graph should be something like this:
source to share
From your comments, you just want a linear map , where intensity values are < 50
displayed at 0, intensities that are > 205
displayed at 255, and everything else is linear mapping between them. You can simply do this:
slope = 255 / (205 - 50); % // Generate equation of the line -
% // y = mx + b - Solve for m
intercept = -50*slope; %// Solve for b --> b = y - m*x, y = 0, x = 50
LUT = uint8(slope*(0:255) + intercept); %// Generate points
LUT(1:51) = 0; %// Anything < intensity 50 set to 0
LUT(206:end) = 255; %// Anything > intensity 205 set to 255
The LUT now looks like this:
plot(0:255, LUT);
axis tight;
grid;
Notice how I trimmed the intensities when they are < 50
and > 205
. MATLAB starts indexing at index 1, so we need to offset the intensities by 1 so that they correctly display pixel intensities that start at 0.
To finally apply this to your image, all you need to do is:
out = LUT(img + 1);
It is assumed to be img
your input image. Note also that we had to compensate for the input with +1
, since MATLAB starts indexing at location 1, while the intensity starts at 0.
Minor note
You can easily do this using imadjust
what basically does it for you under the hood. You call it like this:
outAdjust = imadjust(in, [low_in; high_in], [low_out; high_out]);
low_in
and high_in
represent the minimum and maximum intensities of the input signals that exist in your image. Note that they are normalized between [0,1]
. low_out
and high_out
adjust the intensities of your image so that it low_in
maps to low_out
, high_in
maps to high_out
, and everything else contrasts in between. For your case, you would do:
outAdjust = imadjust(img, [0; 1], [50/255; 205/255]);
This should stretch the contrast so that the input intensity 50
maps to the output intensity 0
and the input intensity 205
maps to the output intensity 255
. Any intensities < 50
and > 205
are automatically saturated to 0
and 255
respectively.
source to share
You need to take every pixel in the image and replace it with the corresponding value in the lookup table. This can be done with some nested loops for
, but this is not the most idiomatic way to do it. I would recommend using arrayfun
with a function that replaces a pixel.
new_image = arrayfun(@(pixel) lut(pixel), image);
It might be more efficient to use code that generates lut
directly on the image. If performance is an issue and you don't need to use a lookup table, try comparing both methods.
new_image = 255 ./ (1 + exp(-image * (x-127) / 32));
Note that the variable new_image
will no longer have a type uint8
. If you need to display it again (say with imshow
), you will need to return it by writing uint8(new_image)
.
source to share