How to set Image contrast using slider?

18 views (last 30 days)
Naor t
Naor t on 4 Jan 2022
Commented: DGM on 7 Jan 2022
I have this button, when clicking im searcing for image in the computer, then i want to change the brightness and contrast. brightness does work for me, but i dont understand how to do it with contrast (should be in slider 2) help please?
and how can i set another button for changing the image to black and white? (i added what i tried)
function pushbutton1_Callback(hObject, eventdata, handles)
i = uigetfile({'*.png';});
img = imread(i);
axes(handles.axes1);
imshow(img);
handles.im_ax1=imagesc(img,'Parent',handles.axes1);
guidata(hObject,handles)
% --- Executes on slider movement.
function slider1_Callback(hObject, eventdata, handles)
valor=get(hObject, 'value');
new_image=get(handles.im_ax1,'CData')+valor;
set(handles.im_ax1,'CData',new_image)
% --- Executes during object creation, after setting all properties.
function slider1_CreateFcn(hObject, eventdata, handles)
% Hint: slider controls usually have a light gray background.
if isequal(get(hObject,'BackgroundColor'), get(0,'defaultUicontrolBackgroundColor'))
set(hObject,'BackgroundColor',[.9 .9 .9]);
end
set(hObject,'Max',100,'Min',-100,'Value',0)
% --- Executes on slider movement.
function slider2_Callback(hObject, eventdata, handles)
% --- Executes during object creation, after setting all properties.
function slider2_CreateFcn(hObject, eventdata, handles)
% Hint: slider controls usually have a light gray background.
if isequal(get(hObject,'BackgroundColor'), get(0,'defaultUicontrolBackgroundColor'))
set(hObject,'BackgroundColor',[.9 .9 .9]);
end
function pushbutton2_Callback(hObject, eventdata, handles)
% hObject handle to pushbutton2 (see GCBO)
% eventdata reserved - to be defined in a future version of MATLAB
% handles structure with handles and user data (see GUIDATA)
I = rgb2gray(img);
imshow(I)

Answers (1)

DGM
DGM on 4 Jan 2022
Edited: DGM on 4 Jan 2022
Personally, I find simple two-parameter linear brightness/contrast adjustment to be frustratingly inflexible, but it's popular in image editing software for the simplicity.
This is basically how GIMP/GEGL does it:
% A is expected to be floating point, in the range [0 1]
A = im2double(imread('pout.tif'));
% the nominal range of these parameters is [-1 1]
% get these values from your sliders
brightness = -0.1;
contrast = 0.3;
B = A;
if brightness < 0
B = B*(1+brightness);
else
B = B + (1-B)*brightness;
end
th = tan((contrast+1)*pi/4);
B = (B - 0.5)*th + 0.5;
imshow([A B])
You will note that this implements a simple linear curve. This will push values below 0 or above 1. If those values don't need to be retained for further processing (e.g. if the image is to be exported), it may be a good idea to clamp the results.
In other words, with the above parameters, the transfer curve between A and B looks like this. Note supramaximal and subminimal values on the output:
But applying a simple clamping routine gives something like this.
B = min(max(B,0),1);
There may be other ways to come up with two-parameter methods. For graphical work, slope discontinuities like those in the above curve are often undesirable, as they create noticeable banding in smooth images. I'm more used to doing this with arbitrary curves instead of endpoints or brightness/contrast. When in MATLAB, I tend to use a levels + gamma + contrast approach which often can be further reduced to a two-parameter nonlinear method if I'm feeling lazy.
% A is expected to be floating point, in the range [0 1]
A = im2double(imread('pout.tif'));
% both of these are exponents; their null value is 1;
% their range is [0 +inf], but a practical range may be [0 3] or so
gamma = 1.2;
contrast = 1.2;
B = A.^gamma; % apply gamma
B = applycontrast(B,contrast); % apply smooth contrast
imshow([A B])
function R = applycontrast(I,k)
if k==1
R = I;
return;
end
c = 0.5;
mk = abs(k)<1;
mc = c<0.5;
if ~xor(mk,mc)
pp = k; kk = k*c/(1-c);
else
kk = k; pp = (1-c)*k/c;
end
hi = I>c; lo = ~hi;
R = zeros(size(I));
R(lo) = 0.5*((1/c)*I(lo)).^kk;
R(hi) = 1-0.5*((1-I(hi))*(1/(1-c))).^pp;
end
The above operation has a smooth transfer curve and keeps values in-range.
As I mentioned, I tend to do contrast/brightness adjustment via a combination of input/output levels adjustment (linear) plus the above nonlinear gamma/contrast parameters. This is a 6-parameter approach and is the core of the MIMT tool imlnc() and the corresponding functionality of immodify(). The same can be done simply by using the above contrast function in addition to imadjust().
% these are null values
inlevels = [0 1]; % x-coordinates of transfer curve endpoints
outlevels = [0 1]; % y-coordinates of same
gamma = 1;
contrast = 1;
B = imadjust(A,inlevels,outlevels,gamma);
B = applycontrast(B,contrast);
If no nonlinear contrast behavior is desired, imadjust() should suffice by itself.
Aside from all of these methods, it's worth noting that your use of imagesc() implicitly performs a linear transformation equivalent to a contrast adjustment before the user adjusts anything. To be clear, this transformation doesn't change the image in CData, but it changes the displayed image, altering what the user sees. If your goal is to allow the user to arbitrarily adjust the contrast of an image, why would you start from anything other than the original, unaltered image? You're probably better off using imshow() or image(), though you may need to set certain options.
As far as your last question, it depends what you mean by "black & white". If you mean to convert a color image to grayscale, rgb2gray() should work. If you want to convert it to a binary image (containing only black or white, with no gray levels between), then you can try to use imbinarize(), but you're going to have trouble getting practical results unless you allow for a means to configure the optional arguments used by imbinarize().
Either way, it's unclear if your button callback is going to target the intended axes when it calls imshow(). If you intend for it to be displayed in the same axes as the other image, you'll have to do what needs to be done to do so.
  2 Comments
Naor t
Naor t on 6 Jan 2022
Hey thanks you for the very detailed answer.
about your question "why would you start from anything other than the original, unaltered image?"
i don't fully understand what do you mean by that? i have a picture, that i added to the axes
then i want to do some change to this picture, like brithness, contrast, change the color, what do you mean by "unaltered image"?
DGM
DGM on 7 Jan 2022
I mean the image as represented by the numeric array values in memory -- with respect to the nominal black and white values implied by the data class. That sounds picky, but the point is that when you're using imagesc(), the image on the screen is an altered representation of the image that's actually in CData.
Let's say I have a really low-contrast image that needs to be edited.
A = im2double(imread('pout.tif'))*0.6+0.2; % same image, but even worse contrast
If that image is displayed with imshow() with default scaling, it's displayed just how it should be expected. The brightest and darkest pixels are both some medium grays.
imshow(A)
However, if it's displayed with imagesc() or with the displayrange option in imshow(), the displayed image will appear to have higher contrast than it really does. Even though A and CData contain no black or white content, the displayed image does.
imagesc(A)
colormap(gray)
axis image
imshow(A,[])
This would be misleading to the user when they're trying to adjust the contrast, since they're not looking at the image directly.
If the images are technical data on some arbitrary scale and it's required to normalize them before beginning the editing task, that can be done using mat2gray().
A = mat2gray(A); % normalize to data extrema
% or
A = mat2gray(A,[lowerlimit upperlimit]); % normalize to some nominal range
If so, it's worth deciding which one of the two above examples is most appropriate for the data.

Sign in to comment.

Categories

Find more on Images in Help Center and File Exchange

Tags

Community Treasure Hunt

Find the treasures in MATLAB Central and discover how the community can help you!

Start Hunting!