In this example, we will use a photograph of me, to try and reduce the red eye effect. In order to be able to use this tool in other photographs as well, we should make it as generic as possible.
RedEyeReduction.m
):function output = RedEyeReduction(input, thresh)
% Function for red eye reduction in input image
% Inputs:
% input - Input image
% thresh – Threshold value in channel a*
% Output:
% output - Output image (after red-eye reduction)
cform = makecform('srgb2lab'), % Make the transform structureimg_lab = applycform(input,cform); % Apply transform to L*a*b*
eyes = roipoly(input); % Select area of eyes
mask = (img_lab(:,:,2) > thresh) & (eyes > 0); % Red pixels in eyes
% Split the three color channels
R=input(:,:,1);
G=input(:,:,2);
B=input(:,:,3);
R(mask) = round((G(mask)+B(mask))/2); % Replace R value with (G+B)/2
output = cat(3,R,G,B); % Join color channels to form output image
>> img = imread('my_red_eyes.bmp'), >> output = RedEyeReduction(img, 150);
>> subplot(1,2,1),imshow(img),title('Original image') >> subplot(1,2,2),imshow(output),title('Image after red-eye correction')
>> output = RedEyeReduction(img, 170); % Picking a very high threshold >> output2 = RedEyeReduction(img, 120); % Picking a very low threshold >> figure,subplot(1,2,1),imshow(output),title('Very high threshold') >> subplot(1,2,2),imshow(output2),title('Very low threshold')
>> output3 = RedEyeReduction(img, 150); % Picking a very large area
When choosing the right threshold, the results achieved in this example are very satisfying, given that we have only written less than 10 lines of functional code. The process described above was followed, that is, transforming the image to CIE-L*a*b*, choosing the area containing the eyes, combining it with our threshold to generate a mask, and then using the mask to replace R values with the average values of G and B. You should note that in order to get the average, we performed addition of the two channels, followed by division by two. This could lead to a non-integer result, so we converted it to integer using the function round
, which rounds the result to the nearest integer value. In the last two steps, we revealed the ugly truth; our function relies too much on a proper selection of the color threshold and the eyes area from the user.